Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: user reply design #46

Merged
merged 6 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,24 @@
.form-input {
@apply placeholder:text-gray-500;
}

.reply-input {
@apply shadow-sm h-10 rounded-md block w-full;
}

.reply-block {
@apply flex flex-col justify-start items-center h-screen space-y-2 mx-auto;
}

.reply-field {
@apply rounded-md bg-white flex flex-col px-4 w-full shadow-md py-2;
}

.reply-field-item {
@apply flex justify-between items-center space-y-1 py-4;
}

.reply-text {
@apply block text-sm font-medium capitalize;
}
}
1 change: 1 addition & 0 deletions src/operations/forms/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { FormEdit } from "./create/FormEdit";
export { FormList } from "./list/FormList";
export { FormReply } from "./reply/FormReply";
10 changes: 10 additions & 0 deletions src/operations/forms/reply/FormReply.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { ReplyFormHeader, ReplyFormBody } from "./components";

export function FormReply() {
return (
<div className="w-full mx-auto max-w-[900px]">
<ReplyFormHeader />
<ReplyFormBody />
</div>
);
}
147 changes: 147 additions & 0 deletions src/operations/forms/reply/components/ReplyFormBody.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { useState } from "react";
import { Button } from "@material-tailwind/react";

const camelize = (str) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put some comment to explain this

return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function (match, index) {
if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
return index === 0 ? match.toLowerCase() : match.toUpperCase();
});
};

export function ReplyFormBody() {
const [formContent] = useState([
{
id: 0,
name: "0",
label: "what is your name ?",
required: false,
question_type: "short_answer",
list: [],
},
{
id: 1,
name: "1",
label: "Describe yourself ?",
required: false,
question_type: "paragraph",
list: [],
},
{
id: 3,
name: "3",
label: "Select your hobbies",
required: false,
question_type: "checkbox",
list: ["Reading", "Gardening", "Cooking"],
},
{
id: 4,
name: "4",
label: "Select your preferred payment method",
required: false,
question_type: "radio",
list: ["Credit Card", "PayPal", "Bitcoin"],
},
]);

const submitForm = (e) => {
e.preventDefault();

//loop through our questions & get values based on the element name
const formTargets = e.target;
const data = [];
formContent.map((content) => {
const element = camelize(content.label);
if (content.question_type === "checkbox") {
const checkboxes = formTargets[element];
const selectedOptions = Array.from(checkboxes)
.filter((checkbox) => checkbox.checked)
.map((checkbox) => checkbox.value);
data.push({
question: content.label,
answer: selectedOptions,
});
} else {
data.push({
question: content.label,
answer: formTargets[element].value,
});
}
});

console.log("form data", data);
};

return (
<form onSubmit={submitForm} className="reply-block">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there will be a bounce of questions with reply so I mean, create state or store or something else to handle them :

{questionId: "uuid",
answer: ""}

{formContent.map((field) => (
<div key={field.id} className="reply-field">
<div className="reply-field-item">
<div key={field.name} className="reply-text text-black-700">
<label>{field.label}</label>
</div>
</div>

<div className="my-4">
{field.question_type === "short_answer" && (
<input
type="text"
className="reply-input"
placeholder={field.label}
name={camelize(field.label)}
/>
)}
{field.question_type === "paragraph" && (
<input
className="reply-input"
placeholder={field.label}
name={camelize(field.label)}
/>
)}

{field.question_type === "checkbox" && (
<>
{field.list.map((option) => (
<div key={option}>
<input
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use material tailwind CheckBox

type="checkbox"
id={camelize(option)}
name={camelize(field.label)}
value={option}
/>
<label className="px-5" htmlFor={camelize(option)}>
{option}
</label>
</div>
))}
</>
)}
{field.question_type === "radio" && (
<>
{field.list.map((option) => (
<div key={option}>
<input
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if exist, use Radio from material tailwind

type="radio"
id={camelize(option)}
name={camelize(field.label)}
value={option}
/>
<label className="px-5" htmlFor={camelize(option)}>
{option}
</label>
</div>
))}
</>
)}
</div>
</div>
))}

<div className="flex mt-5 w-full gap-3 justify-end items-center">
<Button size="sm" type="submit">
Submit
</Button>
</div>
</form>
);
}
32 changes: 32 additions & 0 deletions src/operations/forms/reply/components/ReplyFormHeader.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useCreateFormStore } from "../../../../stores";

function NumberOfQuestion() {
const numberOfQuestion = useCreateFormStore(
(state) => state.questions.length
);
return (
<p className="text-bgray mt-5 text-[14px]">
Number of questions: {numberOfQuestion}
</p>
);
}

export function ReplyFormHeader() {
const { config } = useCreateFormStore((state) => ({
config: state.config,
}));

return (
<div
className="border-t-[10px] form-block"
style={{ borderTopColor: config.color }}
>
<h1 className="form-input font-bold text-[16px] py-2">Form Header</h1>
<p className="form-input max-h-[50px] focus:border-none terxt-[14px]">
Form Description
</p>

<NumberOfQuestion />
</div>
);
}
2 changes: 2 additions & 0 deletions src/operations/forms/reply/components/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./ReplyFormBody";
export * from "./ReplyFormHeader";