"use client"; import { useState, useEffect, useRef } from "react"; import { minsToTime } from "@/app/(main)/dashboard/components/block-timeline"; import type { AccessMode, ChannelResponse, LogoPosition, ProgrammingBlock, MediaFilter, RecyclePolicy, } from "@/lib/types"; export const WEBHOOK_PRESETS = { discord: `{ "embeds": [{ "title": "📺 {{event}}", "description": "{{#if data.item.title}}Now playing: **{{data.item.title}}**{{else}}No signal{{/if}}", "color": 3447003, "timestamp": "{{timestamp}}" }] }`, slack: `{ "text": "📺 *{{event}}*{{#if data.item.title}} — {{data.item.title}}{{/if}}" }`, } as const; export type WebhookFormat = "default" | "discord" | "slack" | "custom"; export function defaultFilter(): MediaFilter { return { content_type: null, genres: [], decade: null, tags: [], min_duration_secs: null, max_duration_secs: null, collections: [], series_names: [], search_term: null, }; } export function defaultBlock(startMins = 20 * 60, durationMins = 60): ProgrammingBlock { return { id: crypto.randomUUID(), name: "", start_time: minsToTime(startMins), duration_mins: durationMins, content: { type: "algorithmic", filter: defaultFilter(), strategy: "random" }, loop_on_finish: true, ignore_recycle_policy: false, access_mode: "public", }; } export function useChannelForm(channel: ChannelResponse | null) { const [name, setName] = useState(""); const [description, setDescription] = useState(""); const [timezone, setTimezone] = useState("UTC"); const [blocks, setBlocks] = useState([]); const [recyclePolicy, setRecyclePolicy] = useState({ cooldown_days: null, cooldown_generations: null, min_available_ratio: 0.1, }); const [autoSchedule, setAutoSchedule] = useState(false); const [accessMode, setAccessMode] = useState("public"); const [accessPassword, setAccessPassword] = useState(""); const [logo, setLogo] = useState(null); const [logoPosition, setLogoPosition] = useState("top_right"); const [logoOpacity, setLogoOpacity] = useState(100); const [webhookUrl, setWebhookUrl] = useState(""); const [webhookPollInterval, setWebhookPollInterval] = useState(5); const [webhookFormat, setWebhookFormat] = useState("default"); const [webhookBodyTemplate, setWebhookBodyTemplate] = useState(""); const [webhookHeaders, setWebhookHeaders] = useState(""); const [selectedBlockId, setSelectedBlockId] = useState(null); const fileInputRef = useRef(null); // Reset form when channel changes useEffect(() => { if (channel) { setName(channel.name); setDescription(channel.description ?? ""); setTimezone(channel.timezone); setBlocks(channel.schedule_config.day_blocks['monday'] ?? []); setRecyclePolicy(channel.recycle_policy); setAutoSchedule(channel.auto_schedule); setAccessMode(channel.access_mode ?? "public"); setAccessPassword(""); setLogo(channel.logo ?? null); setLogoPosition(channel.logo_position ?? "top_right"); setLogoOpacity(Math.round((channel.logo_opacity ?? 1) * 100)); setWebhookUrl(channel.webhook_url ?? ""); setWebhookPollInterval(channel.webhook_poll_interval_secs ?? 5); const tmpl = channel.webhook_body_template ?? ""; setWebhookBodyTemplate(tmpl); setWebhookHeaders(channel.webhook_headers ?? ""); if (!tmpl) { setWebhookFormat("default"); } else if (tmpl === WEBHOOK_PRESETS.discord) { setWebhookFormat("discord"); } else if (tmpl === WEBHOOK_PRESETS.slack) { setWebhookFormat("slack"); } else { setWebhookFormat("custom"); } setSelectedBlockId(null); } }, [channel]); const addBlock = (startMins = 20 * 60, durationMins = 60) => { const block = defaultBlock(startMins, durationMins); setBlocks((prev) => [...prev, block]); setSelectedBlockId(block.id); }; const updateBlock = (idx: number, block: ProgrammingBlock) => setBlocks((prev) => prev.map((b, i) => (i === idx ? block : b))); const removeBlock = (idx: number) => { setBlocks((prev) => { const next = prev.filter((_, i) => i !== idx); if (selectedBlockId === prev[idx].id) setSelectedBlockId(null); return next; }); }; return { // Basic info name, setName, description, setDescription, timezone, setTimezone, autoSchedule, setAutoSchedule, // Access accessMode, setAccessMode, accessPassword, setAccessPassword, // Logo logo, setLogo, logoPosition, setLogoPosition, logoOpacity, setLogoOpacity, fileInputRef, // Webhook webhookUrl, setWebhookUrl, webhookPollInterval, setWebhookPollInterval, webhookFormat, setWebhookFormat, webhookBodyTemplate, setWebhookBodyTemplate, webhookHeaders, setWebhookHeaders, // Blocks blocks, setBlocks, selectedBlockId, setSelectedBlockId, recyclePolicy, setRecyclePolicy, addBlock, updateBlock, removeBlock, }; }