import { z } from "zod";
export const ScheduledTodoTitleSchema = z
.string()
.trim()
.min(1, "Title is required")
.max(100, "Title must be 100 characters or fewer");
export const ScheduledTodoDetailsSchema = z.string().max(5_000).optional();
// "HH:MM", 24-hour -- exactly what an gives back, so
// the client never needs to reformat before sending it.
export const ScheduledTodoTimeDueSchema = z
.string()
.regex(/^([01]\d|2[0-3]):[0-5]\d$/, "Invalid time");
// Minutes of lead time before timeDue -- 0 ("When due") up to a week.
export const ScheduledTodoRemindMinutesBeforeSchema = z.number().int().min(0).max(10_080);
const DateStringSchema = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Invalid date");
const RecurrenceEndSchema = z.discriminatedUnion("type", [
z.object({ type: z.literal("never") }),
z.object({ type: z.literal("until"), date: DateStringSchema }),
z.object({ type: z.literal("count"), count: z.number().int().min(1).max(999) }),
]);
/**
* What the "Add/Edit Scheduled To-Do" dialog submits for the recurring
* case -- validated here and only here turned into an RFC 5545 RRULE
* string (see lib/rrule-utils.ts). Never trust a client-supplied RRULE
* string directly.
*/
export const RecurrenceInputSchema = z
.object({
frequency: z.enum(["DAILY", "WEEKLY", "MONTHLY", "YEARLY"]),
interval: z.number().int().min(1).max(365),
// 0 = Sunday .. 6 = Saturday, matching Date#getUTCDay().
daysOfWeek: z.array(z.number().int().min(0).max(6)).max(7).optional(),
dayOfMonth: z.number().int().min(1).max(31).optional(),
month: z.number().int().min(1).max(12).optional(),
end: RecurrenceEndSchema,
})
.superRefine((value, ctx) => {
if (value.frequency === "WEEKLY" && !value.daysOfWeek?.length) {
ctx.addIssue({
code: "custom",
path: ["daysOfWeek"],
message: "Pick at least one day of the week",
});
}
if ((value.frequency === "MONTHLY" || value.frequency === "YEARLY") && !value.dayOfMonth) {
ctx.addIssue({ code: "custom", path: ["dayOfMonth"], message: "Day of month is required" });
}
if (value.frequency === "YEARLY" && !value.month) {
ctx.addIssue({ code: "custom", path: ["month"], message: "Month is required" });
}
});
export type RecurrenceInput = z.infer;