diff --git a/apps/dashboard/modules/shop-timings/shop-timing-form.tsx b/apps/dashboard/modules/shop-timings/shop-timing-form.tsx index 879b2e4..7fcd7a9 100644 --- a/apps/dashboard/modules/shop-timings/shop-timing-form.tsx +++ b/apps/dashboard/modules/shop-timings/shop-timing-form.tsx @@ -8,6 +8,7 @@ import { FieldGroup } from "@/shared/components/ui/field" import { Rhform, RhfTextField, + RhfSelectField, RhfCheckboxField, } from "@/shared/components/form" import { toast } from "sonner" @@ -17,6 +18,7 @@ import { useFormMutation } from "@/shared/hooks/use-form-mutation" import { shopTimingFormSchema, + DAY_OF_WEEK_VALUES, type ShopTimingFormValues, } from "./shop-timing.schema" import { SHOP_TIMING_ROUTES } from "@garage/api" @@ -29,10 +31,19 @@ export type ShopTimingFormProps = { onSuccess?: () => void } +// ── Options ── + +const DAY_OPTIONS = DAY_OF_WEEK_VALUES.map((day) => ({ + value: day, + label: day.charAt(0).toUpperCase() + day.slice(1), +})) + // ── Default values ── const DEFAULT_VALUES: ShopTimingFormValues = { title: "", + day_of_week: "", + is_closed: false, in_time: "", out_time: "", full_day_hours: "", @@ -51,6 +62,8 @@ function mapToFormValues(data: unknown): ShopTimingFormValues { return { title: d.title ?? "", + day_of_week: d.day_of_week ?? "", + is_closed: d.is_closed ?? false, in_time: d.in_time ?? "", out_time: d.out_time ?? "", full_day_hours: d.full_day_hours ?? "", @@ -64,10 +77,15 @@ function mapToFormValues(data: unknown): ShopTimingFormValues { } function mapFormToPayload(values: ShopTimingFormValues) { + const closed = values.is_closed + return { title: values.title, - in_time: values.in_time, - out_time: values.out_time, + day_of_week: values.day_of_week || undefined, + is_closed: closed, + // Closed days carry no opening hours. + in_time: closed ? undefined : values.in_time, + out_time: closed ? undefined : values.out_time, full_day_hours: values.full_day_hours || undefined, half_day_hours: values.half_day_hours || undefined, punch_in: values.punch_in || undefined, @@ -93,6 +111,8 @@ export function ShopTimingForm({ resourceId, initialData, onSuccess }: ShopTimin mapToFormValues: mapToFormValues, }) + const isClosed = form.watch("is_closed") + const { mutate, error, isPending } = useFormMutation(form, { mutationFn: (values: ShopTimingFormValues) => { const payload = mapFormToPayload(values) @@ -128,8 +148,13 @@ export function ShopTimingForm({ resourceId, initialData, onSuccess }: ShopTimin
- - + + +
+ +
+ +
diff --git a/apps/dashboard/modules/shop-timings/shop-timing.schema.ts b/apps/dashboard/modules/shop-timings/shop-timing.schema.ts index 4f35103..1eca4f0 100644 --- a/apps/dashboard/modules/shop-timings/shop-timing.schema.ts +++ b/apps/dashboard/modules/shop-timings/shop-timing.schema.ts @@ -6,18 +6,43 @@ const optionalTimeFormat = z .optional() .refine((v) => !v || timeRegex.test(v), "Time must be in HH:MM:SS format") -const shopTimingFormSchema = z.object({ - title: z.string().min(1, "Title is required").max(255, "Title cannot exceed 255 characters"), - in_time: z.string().min(1, "In time is required").regex(timeRegex, "In time must be in HH:MM:SS format"), - out_time: z.string().min(1, "Out time is required").regex(timeRegex, "Out time must be in HH:MM:SS format"), - full_day_hours: optionalTimeFormat, - half_day_hours: optionalTimeFormat, - punch_in: optionalTimeFormat, - punch_out: optionalTimeFormat, - before_time: optionalTimeFormat, - after_time: optionalTimeFormat, - is_default: z.boolean().default(false), -}) +export const DAY_OF_WEEK_VALUES = [ + "saturday", + "sunday", + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", +] as const + +const shopTimingFormSchema = z + .object({ + title: z.string().min(1, "Title is required").max(255, "Title cannot exceed 255 characters"), + day_of_week: z.string().optional(), + is_closed: z.boolean().default(false), + // Optional at the field level; required below only when the day is open. + in_time: optionalTimeFormat, + out_time: optionalTimeFormat, + full_day_hours: optionalTimeFormat, + half_day_hours: optionalTimeFormat, + punch_in: optionalTimeFormat, + punch_out: optionalTimeFormat, + before_time: optionalTimeFormat, + after_time: optionalTimeFormat, + is_default: z.boolean().default(false), + }) + .superRefine((values, ctx) => { + // When the shop is open, in/out times are mandatory. + if (!values.is_closed) { + if (!values.in_time) { + ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["in_time"], message: "In time is required" }) + } + if (!values.out_time) { + ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["out_time"], message: "Out time is required" }) + } + } + }) type ShopTimingFormValues = z.infer