feat:update form
This commit is contained in:
@@ -61,6 +61,12 @@ import {
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
FieldGroup,
|
||||
FieldLabel,
|
||||
} from "@/components/ui/field";
|
||||
|
||||
interface Question {
|
||||
id: string;
|
||||
@@ -72,6 +78,7 @@ interface Question {
|
||||
required: boolean;
|
||||
options: string[] | null;
|
||||
allowOther: boolean;
|
||||
imageAnswerMode: "none" | "optional" | "required";
|
||||
}
|
||||
|
||||
interface FormEditorClientProps {
|
||||
@@ -80,6 +87,7 @@ interface FormEditorClientProps {
|
||||
title: string;
|
||||
description: string | null;
|
||||
isOpen: boolean;
|
||||
allowMultipleSubmissions: boolean;
|
||||
};
|
||||
initialQuestions: Question[];
|
||||
}
|
||||
@@ -89,6 +97,9 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
const [formTitle, setFormTitle] = useState(form.title);
|
||||
const [formDescription, setFormDescription] = useState(form.description || "");
|
||||
const [formIsOpen, setFormIsOpen] = useState(form.isOpen);
|
||||
const [allowMultipleSubmissions, setAllowMultipleSubmissions] = useState(
|
||||
form.allowMultipleSubmissions
|
||||
);
|
||||
const [questions, setQuestions] = useState<Question[]>(initialQuestions);
|
||||
const [uploadingId, setUploadingId] = useState<string | null>(null);
|
||||
const [addingQuestion, setAddingQuestion] = useState(false);
|
||||
@@ -97,14 +108,16 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
const formTitleRef = useRef(formTitle);
|
||||
const formDescriptionRef = useRef(formDescription);
|
||||
const formIsOpenRef = useRef(formIsOpen);
|
||||
const allowMultipleSubmissionsRef = useRef(allowMultipleSubmissions);
|
||||
const questionsRef = useRef(questions);
|
||||
|
||||
useEffect(() => {
|
||||
formTitleRef.current = formTitle;
|
||||
formDescriptionRef.current = formDescription;
|
||||
formIsOpenRef.current = formIsOpen;
|
||||
allowMultipleSubmissionsRef.current = allowMultipleSubmissions;
|
||||
questionsRef.current = questions;
|
||||
}, [formDescription, formIsOpen, formTitle, questions]);
|
||||
}, [allowMultipleSubmissions, formDescription, formIsOpen, formTitle, questions]);
|
||||
|
||||
const saveForm = useCallback(async () => {
|
||||
const title = formTitleRef.current;
|
||||
@@ -115,6 +128,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
title: title.trim(),
|
||||
description: formDescriptionRef.current,
|
||||
isOpen: formIsOpenRef.current,
|
||||
allowMultipleSubmissions: allowMultipleSubmissionsRef.current,
|
||||
});
|
||||
router.refresh();
|
||||
}, [form.id, router]);
|
||||
@@ -125,6 +139,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
...q,
|
||||
options: q.options === null ? [] : q.options,
|
||||
allowOther: q.allowOther,
|
||||
imageAnswerMode: q.imageAnswerMode,
|
||||
}));
|
||||
await bulkUpdateQuestions(form.id, formattedUpdates);
|
||||
router.refresh();
|
||||
@@ -154,6 +169,12 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
formAutoSave.schedule();
|
||||
};
|
||||
|
||||
const handleAllowMultipleSubmissionsChange = (val: boolean) => {
|
||||
allowMultipleSubmissionsRef.current = val;
|
||||
setAllowMultipleSubmissions(val);
|
||||
formAutoSave.schedule();
|
||||
};
|
||||
|
||||
const handleAddQuestion = async () => {
|
||||
setAddingQuestion(true);
|
||||
try {
|
||||
@@ -334,9 +355,10 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
/>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="form-title">Form Title</Label>
|
||||
<CardContent>
|
||||
<FieldGroup>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="form-title">Form Title</FieldLabel>
|
||||
<Input
|
||||
id="form-title"
|
||||
value={formTitle}
|
||||
@@ -347,26 +369,42 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
{!formTitle.trim() && (
|
||||
<p className="text-sm text-destructive">Form title is required.</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="form-description">Description</Label>
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="form-description">Description</FieldLabel>
|
||||
<RichTextEditor
|
||||
value={formDescription}
|
||||
onChange={(html) => handleFormDescriptionChange(html)}
|
||||
placeholder="Provide a description..."
|
||||
className="min-h-20 w-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 pt-2">
|
||||
</Field>
|
||||
<Field orientation="horizontal">
|
||||
<Switch
|
||||
id="form-is-open"
|
||||
checked={formIsOpen}
|
||||
onCheckedChange={handleFormIsOpenChange}
|
||||
/>
|
||||
<Label htmlFor="form-is-open" className="text-sm font-normal text-muted-foreground">
|
||||
<FieldLabel htmlFor="form-is-open" className="font-normal">
|
||||
Accepting Submissions
|
||||
</Label>
|
||||
</div>
|
||||
</FieldLabel>
|
||||
</Field>
|
||||
<Field orientation="horizontal">
|
||||
<Switch
|
||||
id="allow-multiple-submissions"
|
||||
checked={allowMultipleSubmissions}
|
||||
onCheckedChange={handleAllowMultipleSubmissionsChange}
|
||||
/>
|
||||
<div className="flex flex-col gap-1">
|
||||
<FieldLabel htmlFor="allow-multiple-submissions" className="font-normal">
|
||||
Allow multiple submissions
|
||||
</FieldLabel>
|
||||
<FieldDescription>
|
||||
Users can create separate responses instead of only editing their current response.
|
||||
</FieldDescription>
|
||||
</div>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -566,6 +604,28 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
Required
|
||||
</Label>
|
||||
</div>
|
||||
<Field className="w-full max-w-xs">
|
||||
<FieldLabel>Answer image</FieldLabel>
|
||||
<Select
|
||||
value={q.imageAnswerMode}
|
||||
onValueChange={(val) =>
|
||||
handleUpdateQuestion(q.id, {
|
||||
imageAnswerMode: val as Question["imageAnswerMode"],
|
||||
})
|
||||
}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="none">Off</SelectItem>
|
||||
<SelectItem value="optional">Optional</SelectItem>
|
||||
<SelectItem value="required">Required</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
{(q.type === "radio" || q.type === "checkbox") && (
|
||||
|
||||
Reference in New Issue
Block a user