fix: address code review issues from Task 4 (onSubmit, AiDraftBanner, STEP_FIELDS)

This commit is contained in:
2026-05-24 22:42:50 -04:00
parent de03f9129b
commit ab3b32f419

View File

@@ -36,6 +36,12 @@ import {
} from "@/lib/event-form";
import { parseRecurrenceRule, validateRecurrence } from "@/lib/recurrence";
const STEP_FIELDS: Record<1 | 2 | 3, (keyof EventFormValues)[]> = {
1: ["title", "url"],
2: ["start", "end"],
3: ["recurrenceRule"],
};
interface EventDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
@@ -96,12 +102,6 @@ export const EventDialog = ({
onOpenChange(nextOpen);
};
const STEP_FIELDS: Record<1 | 2 | 3, (keyof EventFormValues)[]> = {
1: ["title", "url"],
2: ["start", "end"],
3: ["recurrenceRule"],
};
const handleNext = async () => {
const valid = await trigger(STEP_FIELDS[step]);
if (valid) advanceStep();
@@ -148,41 +148,42 @@ export const EventDialog = ({
reset(getDefaultEventFormValues());
});
const onSubmit = handleSubmit((values) => {
const result = validateEventFormValues(values);
if (!result.success) {
const fieldErrors = result.error.flatten().fieldErrors;
for (const [fieldName, messages] of Object.entries(fieldErrors)) {
const firstMessage = messages?.[0];
if (firstMessage) {
setError(fieldName as keyof EventFormValues, {
message: firstMessage,
});
}
}
return;
}
if (values.recurrenceRule) {
const recurrenceValidation = validateRecurrence(parseRecurrenceRule(values.recurrenceRule));
if (!recurrenceValidation.isValid) {
setError("recurrenceRule", {
message:
recurrenceValidation.errors.rule ||
recurrenceValidation.errors.count ||
recurrenceValidation.errors.until ||
"Invalid recurrence.",
});
return;
}
}
onSave(result.data);
reset(getDefaultEventFormValues());
});
const stepProps = { control, register, errors, watch, setValue, isAiDraft };
if (!isMobile) {
return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent className="max-w-2xl rounded-[10px] bg-card p-0 shadow-xl">
<DialogHeader className="px-6 py-5 shadow-[inset_0_-1px_0_0_var(--color-border)]">
<DialogTitle className="text-[28px] tracking-[-0.06em]">{titleText}</DialogTitle>
<DialogDescription>{descriptionText}</DialogDescription>
</DialogHeader>
<form className="grid gap-6 px-6 py-5" onSubmit={handleSave}>
{isAiDraft && <AiDraftBanner />}
<section className="grid gap-3">
<p className="font-mono text-[11px] uppercase text-muted-foreground">Event details</p>
<DetailsStep {...stepProps} isAiDraft={false} />
</section>
<section className="grid gap-3">
<p className="font-mono text-[11px] uppercase text-muted-foreground">Schedule</p>
<ScheduleStep {...stepProps} isAiDraft={false} />
</section>
<section className="grid gap-3">
<p className="font-mono text-[11px] uppercase text-muted-foreground">Recurrence</p>
<RecurrenceStep {...stepProps} isAiDraft={false} />
</section>
<DialogFooter>
<Button type="button" variant="ghost" onClick={() => handleOpenChange(false)}>
Cancel
</Button>
<Button type="submit">{saveLabel}</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
}
const progressBars = (
<div className="grid grid-cols-3 gap-1.5 px-4 pt-2 pb-3">
{([1, 2, 3] as const).map((n) => (
@@ -203,40 +204,6 @@ export const EventDialog = ({
3: "Recurrence",
};
if (!isMobile) {
return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent className="max-w-2xl rounded-[10px] bg-card p-0 shadow-xl">
<DialogHeader className="px-6 py-5 shadow-[inset_0_-1px_0_0_var(--color-border)]">
<DialogTitle className="text-[28px] tracking-[-0.06em]">{titleText}</DialogTitle>
<DialogDescription>{descriptionText}</DialogDescription>
</DialogHeader>
<form className="grid gap-6 px-6 py-5" onSubmit={onSubmit}>
{isAiDraft && <AiDraftBanner />}
<section className="grid gap-3">
<p className="font-mono text-[11px] uppercase text-muted-foreground">Event details</p>
<DetailsStep {...stepProps} />
</section>
<section className="grid gap-3">
<p className="font-mono text-[11px] uppercase text-muted-foreground">Schedule</p>
<ScheduleStep {...stepProps} />
</section>
<section className="grid gap-3">
<p className="font-mono text-[11px] uppercase text-muted-foreground">Recurrence</p>
<RecurrenceStep {...stepProps} />
</section>
<DialogFooter>
<Button type="button" variant="ghost" onClick={() => handleOpenChange(false)}>
Cancel
</Button>
<Button type="submit">{saveLabel}</Button>
</DialogFooter>
</form>
</DialogContent>
</Dialog>
);
}
return (
<Drawer open={open} onOpenChange={handleOpenChange}>
<DrawerContent>