Harden form auth and submission handling
This commit is contained in:
@@ -39,6 +39,7 @@ import { RichTextEditor } from "@/components/rich-text-editor";
|
||||
import { FormattedText } from "@/components/formatted-text";
|
||||
import { ThemeToggle } from "@/components/theme-toggle";
|
||||
import { DropdownMenuAvatar, DiscordMemberProfile } from "@/components/dropdown-menu-avatar";
|
||||
import { getErrorMessage } from "@/lib/errors";
|
||||
|
||||
interface Question {
|
||||
id: string;
|
||||
@@ -84,10 +85,12 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
const formIsOpenRef = useRef(formIsOpen);
|
||||
const questionsRef = useRef(questions);
|
||||
|
||||
formTitleRef.current = formTitle;
|
||||
formDescriptionRef.current = formDescription;
|
||||
formIsOpenRef.current = formIsOpen;
|
||||
questionsRef.current = questions;
|
||||
useEffect(() => {
|
||||
formTitleRef.current = formTitle;
|
||||
formDescriptionRef.current = formDescription;
|
||||
formIsOpenRef.current = formIsOpen;
|
||||
questionsRef.current = questions;
|
||||
}, [formDescription, formIsOpen, formTitle, questions]);
|
||||
|
||||
const autoSaveForm = useCallback(() => {
|
||||
if (formTimerRef.current) clearTimeout(formTimerRef.current);
|
||||
@@ -170,7 +173,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
options: [],
|
||||
});
|
||||
router.refresh();
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
console.error("Failed to add question:", err);
|
||||
}
|
||||
};
|
||||
@@ -186,7 +189,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
try {
|
||||
await deleteQuestion(id, form.id);
|
||||
router.refresh();
|
||||
} catch (err: any) {
|
||||
} catch (err: unknown) {
|
||||
console.error("Failed to delete question:", err);
|
||||
}
|
||||
};
|
||||
@@ -243,7 +246,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
{
|
||||
loading: "Uploading image...",
|
||||
success: "Image uploaded!",
|
||||
error: (err: any) => err.message || "Failed to upload image.",
|
||||
error: (err: unknown) => getErrorMessage(err, "Failed to upload image."),
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -259,7 +262,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
{
|
||||
loading: "Removing image...",
|
||||
success: "Image removed.",
|
||||
error: (err: any) => err.message || "Failed to remove image.",
|
||||
error: (err: unknown) => getErrorMessage(err, "Failed to remove image."),
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -283,8 +286,9 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
handleUpdateQuestion(question.id, { options });
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
setQuestions(initialQuestions);
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => setQuestions(initialQuestions), 0);
|
||||
return () => clearTimeout(timeout);
|
||||
}, [initialQuestions]);
|
||||
|
||||
return (
|
||||
@@ -360,7 +364,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
<div className="flex items-center gap-2 self-end sm:self-auto">
|
||||
<Select
|
||||
value={q.type}
|
||||
onValueChange={(val: any) => handleUpdateQuestion(q.id, { type: val })}
|
||||
onValueChange={(val) => handleUpdateQuestion(q.id, { type: val as Question["type"] })}
|
||||
>
|
||||
<SelectTrigger className="w-36">
|
||||
<SelectValue />
|
||||
@@ -499,7 +503,7 @@ export default function FormEditorClient({ form, initialQuestions }: FormEditorC
|
||||
onCheckedChange={(checked) => handleUpdateQuestion(q.id, { allowOther: checked })}
|
||||
/>
|
||||
<Label htmlFor={`allowOther-${q.id}`} className="text-sm font-normal text-muted-foreground">
|
||||
Add 'Other' option
|
||||
Add 'Other' option
|
||||
</Label>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user