refactor: centralize event dialog form state
This commit is contained in:
84
src/lib/event-form.ts
Normal file
84
src/lib/event-form.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import { isAfter, parseISO } from "date-fns";
|
||||
import { z } from "zod";
|
||||
import type { CalendarEvent } from "@/lib/types";
|
||||
|
||||
export interface EventFormValues {
|
||||
title: string;
|
||||
description: string;
|
||||
location: string;
|
||||
url: string;
|
||||
start: string;
|
||||
end: string;
|
||||
allDay: boolean;
|
||||
recurrenceRule?: string;
|
||||
}
|
||||
|
||||
const eventFormSchema = z
|
||||
.object({
|
||||
title: z.string().trim().min(1, "Title is required."),
|
||||
description: z.string(),
|
||||
location: z.string(),
|
||||
url: z.preprocess((value) => value ?? "", z.string().trim()),
|
||||
start: z.string().trim().min(1, "Start date is required."),
|
||||
end: z.string(),
|
||||
allDay: z.boolean(),
|
||||
recurrenceRule: z.string().optional(),
|
||||
})
|
||||
.superRefine((value, ctx) => {
|
||||
if (value.url) {
|
||||
const urlValidation = z.string().url().safeParse(value.url);
|
||||
if (!urlValidation.success) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["url"],
|
||||
message: "Enter a valid URL.",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (value.end) {
|
||||
const startDate = parseISO(value.start);
|
||||
const endDate = parseISO(value.end);
|
||||
if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["end"],
|
||||
message: "End date must be valid.",
|
||||
});
|
||||
} else if (!isAfter(endDate, startDate)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["end"],
|
||||
message: "End date must be after the start date.",
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const getDefaultEventFormValues = (): EventFormValues => ({
|
||||
title: "",
|
||||
description: "",
|
||||
location: "",
|
||||
url: "",
|
||||
start: "",
|
||||
end: "",
|
||||
allDay: false,
|
||||
recurrenceRule: undefined,
|
||||
});
|
||||
|
||||
export const getEventFormValuesFromEvent = (
|
||||
event?: Partial<CalendarEvent>,
|
||||
): EventFormValues => ({
|
||||
...getDefaultEventFormValues(),
|
||||
title: event?.title || "",
|
||||
description: event?.description || "",
|
||||
location: event?.location || "",
|
||||
url: event?.url || "",
|
||||
start: event?.start || "",
|
||||
end: event?.end || "",
|
||||
allDay: event?.allDay || false,
|
||||
recurrenceRule: event?.recurrenceRule || undefined,
|
||||
});
|
||||
|
||||
export const validateEventFormValues = (values: EventFormValues) =>
|
||||
eventFormSchema.safeParse(values);
|
||||
Reference in New Issue
Block a user