"use client"; import { useEffect, useState } from "react"; import { createClient, waitForRealtimeAuth } from "@/lib/supabase/client"; import { DayCard, type DayRow } from "./day-card"; import { PANTHEON_PRESETS, getGodPreset } from "@/lib/pantheon"; import { IconPlus } from "@/components/icons"; import { formatCountdown } from "@/lib/tribunal-date"; export function CalendrierView({ isJudge, initialDays, initialTribunalDate, }: { isJudge: boolean; initialDays: DayRow[]; initialTribunalDate: string | null; }) { const [days, setDays] = useState(initialDays); const [tribunalDate, setTribunalDate] = useState(initialTribunalDate); const [editingTribunalDate, setEditingTribunalDate] = useState(false); const [tribunalInput, setTribunalInput] = useState( initialTribunalDate ? initialTribunalDate.slice(0, 16) : "", ); const [addingDay, setAddingDay] = useState(false); const [newDate, setNewDate] = useState(""); const [newGod, setNewGod] = useState(PANTHEON_PRESETS[0].name); const [newGodDomain, setNewGodDomain] = useState(PANTHEON_PRESETS[0].domain); const [customGod, setCustomGod] = useState(false); const [error, setError] = useState(null); async function refetch() { const supabase = createClient(); const { data } = await supabase .from("days") .select("id, date, god_name, god_domain, description, events(*)") .order("date", { ascending: true }); if (data) { setDays( data.map((day) => ({ ...day, events: [...day.events].sort((a, b) => (a.start_time ?? "99:99").localeCompare(b.start_time ?? "99:99"), ), })), ); } const { data: settingsRow } = await supabase .from("settings") .select("tribunal_date") .eq("id", true) .single(); setTribunalDate(settingsRow?.tribunal_date ?? null); } useEffect(() => { const supabase = createClient(); let channel: ReturnType | null = null; let cancelled = false; waitForRealtimeAuth(supabase).then(() => { if (cancelled) return; channel = supabase .channel("calendrier-changes") .on("postgres_changes", { event: "*", schema: "public", table: "days" }, refetch) .on("postgres_changes", { event: "*", schema: "public", table: "events" }, refetch) .on("postgres_changes", { event: "*", schema: "public", table: "settings" }, refetch) .subscribe(); }); return () => { cancelled = true; if (channel) supabase.removeChannel(channel); }; }, []); async function handleSaveTribunalDate() { const supabase = createClient(); const isoValue = tribunalInput ? new Date(tribunalInput).toISOString() : null; const { error: updateError } = await supabase .from("settings") .update({ tribunal_date: isoValue }) .eq("id", true); if (!updateError) { setTribunalDate(isoValue); setEditingTribunalDate(false); } } async function handleAddDay(event: React.FormEvent) { event.preventDefault(); setError(null); if (!newDate) { setError("Choisis une date."); return; } const supabase = createClient(); const { error: insertError } = await supabase.from("days").insert({ date: newDate, god_name: newGod, god_domain: newGodDomain, }); if (insertError) { setError( insertError.message.includes("duplicate key") ? "Une journée existe déjà à cette date." : "Une erreur est survenue.", ); return; } setAddingDay(false); setNewDate(""); setNewGod(PANTHEON_PRESETS[0].name); setNewGodDomain(PANTHEON_PRESETS[0].domain); setCustomGod(false); refetch(); } return (

{formatCountdown(tribunalDate)}

{tribunalDate && (

{new Date(tribunalDate).toLocaleString("fr-FR", { dateStyle: "full", timeStyle: "short", timeZone: "Europe/Paris", })}

)} {isJudge && (
{editingTribunalDate ? (
setTribunalInput(e.target.value)} className="rounded-md border border-gold/30 bg-white/50 px-2 py-1 text-sm text-text-marble" />
) : ( )}
)}
{days.length === 0 && !addingDay && (

Aucune journée n'a encore été inscrite au calendrier.

)}
{days.map((day) => ( ))}
{isJudge && (
{addingDay ? (
setNewDate(e.target.value)} required className="rounded-md border border-gold/30 bg-white/50 px-2 py-1.5 text-sm text-text-marble" />
{customGod && (
setNewGod(e.target.value)} required className="rounded-md border border-gold/30 bg-white/50 px-2 py-1.5 text-sm text-text-marble" />
)}
setNewGodDomain(e.target.value)} required className="rounded-md border border-gold/30 bg-white/50 px-2 py-1.5 text-sm text-text-marble" />
{error &&

{error}

}
) : ( )}
)}
); }