import React, { useEffect, useMemo, useRef, useState } from 'react'; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { DropdownMenuItem, DropdownMenuSeparator } from '@/components/ui/dropdown-menu'; import { type Event } from '@/features/event/api/eventService'; import { ArrowLeft, LayoutGrid } from 'lucide-react'; import { useHeader } from '@/contexts/HeaderContext'; import EventFormInline from './EventFormInline'; const EVENT_WIZARD_STATE_KEY = 'kgb.eventWizard.state'; interface EventWizardProps { onComplete: () => void; onBackToOverview: () => void; events: Event[]; loading: boolean; error: string | null; onReload: () => void; } const EventWizard: React.FC = ({ onComplete, onBackToOverview, events, loading, error, onReload }) => { const [showForm, setShowForm] = useState(false); const [activeEventId, setActiveEventId] = useState(null); const { setHeader, resetHeader } = useHeader(); useEffect(() => { try { const raw = sessionStorage.getItem(EVENT_WIZARD_STATE_KEY); if (!raw) return; const parsed = JSON.parse(raw) as { showForm?: boolean; activeEventId?: string | number | null }; if (typeof parsed.showForm === 'boolean') setShowForm(parsed.showForm); if (parsed.activeEventId !== undefined) setActiveEventId(parsed.activeEventId); } catch { // ignore } // only on mount // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { try { sessionStorage.setItem( EVENT_WIZARD_STATE_KEY, JSON.stringify({ showForm, activeEventId: activeEventId ?? null }) ); } catch { // ignore } }, [activeEventId, showForm]); const activeEvent = useMemo(() => { if (!activeEventId) return null; return events.find((e) => String(e.id) === String(activeEventId)) || null; }, [activeEventId, events]); const canGoTimeline = showForm; const handleBackToTimeline = () => { setShowForm(false); setActiveEventId(null); }; useEffect(() => { onReload(); }, [onReload]); useEffect(() => { const eventName = (activeEvent as any)?.title || (activeEvent as any)?.name || null; const title = showForm ? activeEventId ? (
Event bearbeiten
{eventName ?
{eventName}
: null}
) : 'Event erstellen' : 'Veranstaltungen'; setHeader({ title, left: ( <> {showForm && ( )} ), mobileMenu: ( <> Zurück zum Dashboard {showForm ? : null} {showForm && ( Zurück zur Timeline )} ), }); return () => { resetHeader(); }; }, [activeEvent, activeEventId, onBackToOverview, resetHeader, setHeader, showForm]); const sortedEvents = useMemo(() => { if (!events.length) return [] as Event[]; return [...events].sort((a, b) => { const aDate = a?.eventDate || a?.event_date || a?.begin_date; const bDate = b?.eventDate || b?.event_date || b?.begin_date; const aTime = aDate ? new Date(aDate).getTime() : 0; const bTime = bDate ? new Date(bDate).getTime() : 0; return aTime - bTime; }); }, [events]); const activeRef = useRef(null); const todayIndex = useMemo(() => { if (!sortedEvents.length) return -1; const today = new Date(); today.setHours(0, 0, 0, 0); // Finde das erste Event mit Datum heute oder in der Zukunft const upcomingIndex = sortedEvents.findIndex((event) => { const baseDate = event?.eventDate || event?.event_date || event?.begin_date; if (!baseDate) return false; const date = new Date(baseDate); if (Number.isNaN(date.getTime())) return false; date.setHours(0, 0, 0, 0); return date.getTime() >= today.getTime(); }); // Wenn nichts in der Zukunft liegt, scrolle zum letzten Event (jüngstes vergangenes) if (upcomingIndex === -1) { return sortedEvents.length - 1; } return upcomingIndex; }, [sortedEvents]); useEffect(() => { if (todayIndex === -1) return; if (!activeRef.current) return; activeRef.current.scrollIntoView({ behavior: 'smooth', inline: 'center', block: 'nearest' }); }, [todayIndex, sortedEvents]); const formatDate = (dateString?: string) => { if (!dateString) return ''; const date = new Date(dateString); if (Number.isNaN(date.getTime())) return dateString; return date.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' }); }; return ( {showForm ? (
{ setShowForm(false); setActiveEventId(null); onReload(); }} onCancel={() => { setShowForm(false); setActiveEventId(null); }} />
) : loading ? (
Events werden geladen...
) : error ? (
{error}
) : (
{sortedEvents.length} Veranstaltung{sortedEvents.length === 1 ? '' : 'en'} geladen
{sortedEvents.map((event, index) => { const isToday = index === todayIndex && todayIndex !== -1; const title = (event as any).title || event.name || 'Unbenanntes Event'; const singleDate = (event as any).eventDate || (event as any).event_date || event.begin_date; const status = ((event as any).status || (event as any).overall_status) as 'PENDING' | 'ON_AIR' | undefined; // Status nur für heutige oder zukünftige Events anzeigen let statusToShow: 'PENDING' | 'ON_AIR' | undefined = status; if (singleDate) { const d = new Date(singleDate); if (!Number.isNaN(d.getTime())) { const today = new Date(); today.setHours(0, 0, 0, 0); d.setHours(0, 0, 0, 0); if (d.getTime() < today.getTime()) { statusToShow = undefined; } } } const statusLabel = statusToShow === 'ON_AIR' ? 'On Air' : 'Pending'; const statusClass = statusToShow === 'ON_AIR' ? 'bg-emerald-100 text-emerald-700' : 'bg-amber-100 text-amber-700'; return (
{ const eid = event.id ?? `${event.name || 'event'}-${index}`; setActiveEventId(eid as any); setShowForm(true); }} >
{title}
{statusToShow && ( {statusLabel} )}
{formatDate(singleDate)}
); })}
)} ); }; export default EventWizard;