feat(web): disable submit while saving + Save & create another + Cmd/Ctrl+Enter (#46)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,7 +54,7 @@ export function ObjectForm({
|
||||
}: {
|
||||
mode: "create" | "edit";
|
||||
defaults?: { core: ObjectCore; fields: Record<string, unknown> };
|
||||
onSubmit: (values: ObjectFormValues) => void;
|
||||
onSubmit: (values: ObjectFormValues, opts?: { createAnother?: boolean }) => Promise<boolean> | boolean;
|
||||
onCancel: () => void;
|
||||
formError?: string | null;
|
||||
fieldErrorKey?: string | null;
|
||||
@@ -76,7 +76,7 @@ export function ObjectForm({
|
||||
},
|
||||
});
|
||||
|
||||
const { register, handleSubmit, formState: { errors } } = form;
|
||||
const { register, handleSubmit, formState: { errors, isSubmitting } } = form;
|
||||
|
||||
useEffect(() => {
|
||||
if (fieldErrorKey) {
|
||||
@@ -87,15 +87,21 @@ export function ObjectForm({
|
||||
}
|
||||
}, [fieldErrorKey, form, t]);
|
||||
|
||||
const submit = handleSubmit((data) => {
|
||||
const fields = pruneFields(data.fields, localizedTextKeys, default_language);
|
||||
const runSubmit = (createAnother: boolean) =>
|
||||
handleSubmit(async (data) => {
|
||||
const fields = pruneFields(data.fields, localizedTextKeys, default_language);
|
||||
const values =
|
||||
mode === "create"
|
||||
? { core: data.core, visibility: data.visibility, fields }
|
||||
: { core: data.core, fields };
|
||||
const ok = await onSubmit(values, { createAnother });
|
||||
if (ok && createAnother) {
|
||||
form.reset({ core: EMPTY_CORE, visibility: "draft", fields: {} });
|
||||
document.getElementById("object_number")?.focus();
|
||||
}
|
||||
});
|
||||
|
||||
onSubmit(
|
||||
mode === "create"
|
||||
? { core: data.core, visibility: data.visibility, fields }
|
||||
: { core: data.core, fields },
|
||||
);
|
||||
});
|
||||
const submit = runSubmit(false);
|
||||
|
||||
const coreField = (
|
||||
key: keyof ObjectCore,
|
||||
@@ -125,7 +131,16 @@ export function ObjectForm({
|
||||
);
|
||||
|
||||
return (
|
||||
<form onSubmit={submit} className="space-y-4 overflow-auto p-4">
|
||||
<form
|
||||
onSubmit={submit}
|
||||
onKeyDown={(e) => {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
void submit();
|
||||
}
|
||||
}}
|
||||
className="space-y-4 overflow-auto p-4"
|
||||
>
|
||||
{formError && (
|
||||
<p role="alert" className="text-sm text-destructive">
|
||||
{formError}
|
||||
@@ -177,11 +192,22 @@ export function ObjectForm({
|
||||
)}
|
||||
|
||||
<div className="flex gap-2 pt-2">
|
||||
<Button type="submit">
|
||||
{mode === "create" ? t("form.create") : t("form.save")}
|
||||
<Button type="submit" disabled={isSubmitting}>
|
||||
{isSubmitting ? t("form.saving") : mode === "create" ? t("form.create") : t("form.save")}
|
||||
</Button>
|
||||
|
||||
<Button type="button" variant="ghost" onClick={onCancel}>
|
||||
{mode === "create" && (
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
disabled={isSubmitting}
|
||||
onClick={() => void runSubmit(true)()}
|
||||
>
|
||||
{t("form.createAnother")}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<Button type="button" variant="ghost" disabled={isSubmitting} onClick={onCancel}>
|
||||
{t("form.cancel")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user