89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
import { z } from "zod";
|
|
import { WEEKDAYS } from "@/lib/types";
|
|
import type { Weekday } from "@/lib/types";
|
|
|
|
const weekdaySchema = z.enum([
|
|
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
|
|
]);
|
|
|
|
export const mediaFilterSchema = z.object({
|
|
content_type: z.enum(["movie", "episode", "short"]).nullable().optional(),
|
|
genres: z.array(z.string()),
|
|
decade: z
|
|
.number()
|
|
.int()
|
|
.min(1900, "Decade must be ≥ 1900")
|
|
.max(2099, "Decade must be ≤ 2090")
|
|
.nullable()
|
|
.optional(),
|
|
tags: z.array(z.string()),
|
|
min_duration_secs: z.number().min(0, "Must be ≥ 0").nullable().optional(),
|
|
max_duration_secs: z.number().min(0, "Must be ≥ 0").nullable().optional(),
|
|
collections: z.array(z.string()),
|
|
series_names: z.array(z.string()),
|
|
search_term: z.string().nullable().optional(),
|
|
});
|
|
|
|
export const accessModeSchema = z.enum([
|
|
"public",
|
|
"password_protected",
|
|
"account_required",
|
|
"owner_only",
|
|
]);
|
|
|
|
export const blockSchema = z.object({
|
|
id: z.string(),
|
|
name: z.string().min(1, "Block name is required"),
|
|
start_time: z.string(),
|
|
duration_mins: z.number().int().min(1, "Must be at least 1 minute"),
|
|
content: z.discriminatedUnion("type", [
|
|
z.object({
|
|
type: z.literal("algorithmic"),
|
|
filter: mediaFilterSchema,
|
|
strategy: z.enum(["best_fit", "sequential", "random"]),
|
|
provider_id: z.string().optional(),
|
|
}),
|
|
z.object({
|
|
type: z.literal("manual"),
|
|
items: z.array(z.string()),
|
|
provider_id: z.string().optional(),
|
|
}),
|
|
]),
|
|
loop_on_finish: z.boolean().optional(),
|
|
ignore_recycle_policy: z.boolean().optional(),
|
|
access_mode: accessModeSchema.optional(),
|
|
access_password: z.string().optional(),
|
|
});
|
|
|
|
export const channelFormSchema = z.object({
|
|
name: z.string().min(1, "Name is required"),
|
|
timezone: z.string().min(1, "Timezone is required"),
|
|
description: z.string().optional(),
|
|
day_blocks: z.record(weekdaySchema, z.array(blockSchema))
|
|
.default(() =>
|
|
Object.fromEntries(WEEKDAYS.map(d => [d, []])) as unknown as Record<Weekday, z.infer<typeof blockSchema>[]>
|
|
),
|
|
recycle_policy: z.object({
|
|
cooldown_days: z.number().int().min(0).nullable().optional(),
|
|
cooldown_generations: z.number().int().min(0).nullable().optional(),
|
|
min_available_ratio: z
|
|
.number()
|
|
.min(0, "Must be ≥ 0")
|
|
.max(1, "Must be ≤ 1"),
|
|
}),
|
|
auto_schedule: z.boolean(),
|
|
access_mode: accessModeSchema.optional(),
|
|
access_password: z.string().optional(),
|
|
});
|
|
|
|
export type FieldErrors = Record<string, string | undefined>;
|
|
|
|
export function extractErrors(err: z.ZodError): FieldErrors {
|
|
const map: FieldErrors = {};
|
|
for (const issue of err.issues) {
|
|
const key = issue.path.join(".");
|
|
if (!map[key]) map[key] = issue.message;
|
|
}
|
|
return map;
|
|
}
|