feat(frontend): ScheduleConfig V2 types, weekday schema, export update
This commit is contained in:
@@ -71,7 +71,9 @@ export function ChannelCard({
|
||||
onMoveDown,
|
||||
}: ChannelCardProps) {
|
||||
const [confirmOpen, setConfirmOpen] = useState(false);
|
||||
const blockCount = channel.schedule_config.blocks.length;
|
||||
const blockCount = Object.values(channel.schedule_config.day_blocks).reduce(
|
||||
(sum, blocks) => sum + blocks.length, 0
|
||||
);
|
||||
const { status, label } = useScheduleStatus(channel.id);
|
||||
|
||||
const scheduleColor =
|
||||
|
||||
@@ -27,7 +27,9 @@ import type {
|
||||
MediaFilter,
|
||||
ProviderInfo,
|
||||
RecyclePolicy,
|
||||
Weekday,
|
||||
} from "@/lib/types";
|
||||
import { WEEKDAYS } from "@/lib/types";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Local shared primitives (only used inside this file)
|
||||
@@ -334,7 +336,7 @@ interface EditChannelSheetProps {
|
||||
name: string;
|
||||
description: string;
|
||||
timezone: string;
|
||||
schedule_config: { blocks: ProgrammingBlock[] };
|
||||
schedule_config: { day_blocks: Record<Weekday, ProgrammingBlock[]> };
|
||||
recycle_policy: RecyclePolicy;
|
||||
auto_schedule: boolean;
|
||||
access_mode?: AccessMode;
|
||||
@@ -373,7 +375,9 @@ export function EditChannelSheet({
|
||||
name: form.name,
|
||||
description: form.description,
|
||||
timezone: form.timezone,
|
||||
blocks: form.blocks,
|
||||
day_blocks: Object.fromEntries(
|
||||
WEEKDAYS.map(d => [d, d === 'monday' ? form.blocks : []])
|
||||
) as Record<Weekday, ProgrammingBlock[]>,
|
||||
recycle_policy: form.recyclePolicy,
|
||||
auto_schedule: form.autoSchedule,
|
||||
access_mode: form.accessMode,
|
||||
@@ -390,7 +394,11 @@ export function EditChannelSheet({
|
||||
name: form.name,
|
||||
description: form.description,
|
||||
timezone: form.timezone,
|
||||
schedule_config: { blocks: form.blocks },
|
||||
schedule_config: {
|
||||
day_blocks: Object.fromEntries(
|
||||
WEEKDAYS.map(d => [d, d === 'monday' ? form.blocks : []])
|
||||
) as Record<Weekday, ProgrammingBlock[]>,
|
||||
},
|
||||
recycle_policy: form.recyclePolicy,
|
||||
auto_schedule: form.autoSchedule,
|
||||
access_mode: form.accessMode !== "public" ? form.accessMode : "public",
|
||||
|
||||
@@ -32,6 +32,7 @@ import type {
|
||||
ChannelResponse,
|
||||
ProgrammingBlock,
|
||||
RecyclePolicy,
|
||||
Weekday,
|
||||
} from "@/lib/types";
|
||||
|
||||
export default function DashboardPage() {
|
||||
@@ -84,7 +85,7 @@ export default function DashboardPage() {
|
||||
name: string;
|
||||
description: string;
|
||||
timezone: string;
|
||||
schedule_config: { blocks: ProgrammingBlock[] };
|
||||
schedule_config: { day_blocks: Record<Weekday, ProgrammingBlock[]> };
|
||||
recycle_policy: RecyclePolicy;
|
||||
auto_schedule: boolean;
|
||||
access_mode?: import("@/lib/types").AccessMode;
|
||||
|
||||
@@ -84,7 +84,7 @@ export function useChannelForm(channel: ChannelResponse | null) {
|
||||
setName(channel.name);
|
||||
setDescription(channel.description ?? "");
|
||||
setTimezone(channel.timezone);
|
||||
setBlocks(channel.schedule_config.blocks);
|
||||
setBlocks(channel.schedule_config.day_blocks['monday'] ?? []);
|
||||
setRecyclePolicy(channel.recycle_policy);
|
||||
setAutoSchedule(channel.auto_schedule);
|
||||
setAccessMode(channel.access_mode ?? "public");
|
||||
|
||||
@@ -4,6 +4,8 @@ import { useState } from "react";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { api } from "@/lib/api";
|
||||
import type { ChannelImportData } from "@/app/(main)/dashboard/components/import-channel-dialog";
|
||||
import { WEEKDAYS } from "@/lib/types";
|
||||
import type { Weekday } from "@/lib/types";
|
||||
|
||||
export function useImportChannel(token: string | null) {
|
||||
const queryClient = useQueryClient();
|
||||
@@ -26,7 +28,11 @@ export function useImportChannel(token: string | null) {
|
||||
await api.channels.update(
|
||||
created.id,
|
||||
{
|
||||
schedule_config: { blocks: data.blocks },
|
||||
schedule_config: {
|
||||
day_blocks: Object.fromEntries(
|
||||
WEEKDAYS.map(d => [d, d === 'monday' ? data.blocks : []])
|
||||
) as Record<Weekday, typeof data.blocks>,
|
||||
},
|
||||
recycle_policy: data.recycle_policy,
|
||||
},
|
||||
token,
|
||||
|
||||
@@ -5,7 +5,7 @@ export function exportChannel(channel: ChannelResponse): void {
|
||||
name: channel.name,
|
||||
description: channel.description ?? undefined,
|
||||
timezone: channel.timezone,
|
||||
blocks: channel.schedule_config.blocks,
|
||||
day_blocks: channel.schedule_config.day_blocks,
|
||||
recycle_policy: channel.recycle_policy,
|
||||
};
|
||||
const blob = new Blob([JSON.stringify(payload, null, 2)], {
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
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(),
|
||||
@@ -53,7 +59,10 @@ 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(),
|
||||
blocks: z.array(blockSchema),
|
||||
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(),
|
||||
|
||||
@@ -91,8 +91,35 @@ export interface ProgrammingBlock {
|
||||
access_password?: string;
|
||||
}
|
||||
|
||||
export type Weekday =
|
||||
| 'monday' | 'tuesday' | 'wednesday' | 'thursday'
|
||||
| 'friday' | 'saturday' | 'sunday'
|
||||
|
||||
export const WEEKDAYS: Weekday[] = [
|
||||
'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday',
|
||||
]
|
||||
|
||||
export const WEEKDAY_LABELS: Record<Weekday, string> = {
|
||||
monday: 'Mon', tuesday: 'Tue', wednesday: 'Wed', thursday: 'Thu',
|
||||
friday: 'Fri', saturday: 'Sat', sunday: 'Sun',
|
||||
}
|
||||
|
||||
export interface ScheduleConfig {
|
||||
blocks: ProgrammingBlock[];
|
||||
day_blocks: Record<Weekday, ProgrammingBlock[]>
|
||||
}
|
||||
|
||||
export interface ConfigSnapshot {
|
||||
id: string
|
||||
version_num: number
|
||||
label: string | null
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export interface ScheduleHistoryEntry {
|
||||
id: string
|
||||
generation: number
|
||||
valid_from: string
|
||||
valid_until: string
|
||||
}
|
||||
|
||||
// Config
|
||||
|
||||
Reference in New Issue
Block a user