'use client'; import Card from '@/components/ui/Card'; import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId'; import type { LeagueAdminScheduleViewModel } from '@/lib/view-models/LeagueAdminScheduleViewModel'; import type { LeagueSeasonSummaryViewModel } from '@/lib/view-models/LeagueSeasonSummaryViewModel'; import { useServices } from '@/lib/services/ServiceProvider'; import { LeagueRoleUtility } from '@/lib/utilities/LeagueRoleUtility'; import { useParams } from 'next/navigation'; import { useEffect, useMemo, useState } from 'react'; export default function LeagueAdminSchedulePage() { const params = useParams(); const leagueId = params.id as string; const currentDriverId = useEffectiveDriverId(); const { leagueService, leagueMembershipService } = useServices(); const [isAdmin, setIsAdmin] = useState(false); const [membershipLoading, setMembershipLoading] = useState(true); const [seasons, setSeasons] = useState([]); const [seasonId, setSeasonId] = useState(''); const [schedule, setSchedule] = useState(null); const [loading, setLoading] = useState(false); const [track, setTrack] = useState(''); const [car, setCar] = useState(''); const [scheduledAtIso, setScheduledAtIso] = useState(''); const [editingRaceId, setEditingRaceId] = useState(null); const isEditing = editingRaceId !== null; const publishedLabel = schedule?.published ? 'Published' : 'Unpublished'; const selectedSeasonLabel = useMemo(() => { const selected = seasons.find((s) => s.seasonId === seasonId); return selected?.name ?? seasonId; }, [seasons, seasonId]); const loadSchedule = async (leagueIdToLoad: string, seasonIdToLoad: string) => { setLoading(true); try { const vm = await leagueService.getAdminSchedule(leagueIdToLoad, seasonIdToLoad); setSchedule(vm); } finally { setLoading(false); } }; useEffect(() => { async function checkAdmin() { setMembershipLoading(true); try { await leagueMembershipService.fetchLeagueMemberships(leagueId); } finally { const membership = leagueMembershipService.getMembership(leagueId, currentDriverId); setIsAdmin(membership ? LeagueRoleUtility.isLeagueAdminOrHigherRole(membership.role) : false); setMembershipLoading(false); } } checkAdmin(); }, [leagueId, currentDriverId, leagueMembershipService]); useEffect(() => { async function loadSeasons() { const loaded = await leagueService.getLeagueSeasonSummaries(leagueId); setSeasons(loaded); if (loaded.length > 0) { const active = loaded.find((s) => s.status === 'active') ?? loaded[0]; setSeasonId(active?.seasonId ?? ''); } } if (isAdmin) { loadSeasons(); } }, [leagueId, isAdmin, leagueService]); useEffect(() => { if (!isAdmin) return; if (!seasonId) return; loadSchedule(leagueId, seasonId); // eslint-disable-next-line react-hooks/exhaustive-deps }, [leagueId, seasonId, isAdmin]); const handlePublishToggle = async () => { if (!schedule) return; if (schedule.published) { const vm = await leagueService.unpublishAdminSchedule(leagueId, seasonId); setSchedule(vm); return; } const vm = await leagueService.publishAdminSchedule(leagueId, seasonId); setSchedule(vm); }; const handleAddOrSave = async () => { if (!seasonId) return; if (!scheduledAtIso) return; if (!isEditing) { const vm = await leagueService.createAdminScheduleRace(leagueId, seasonId, { track, car, scheduledAtIso, }); setSchedule(vm); setTrack(''); setCar(''); setScheduledAtIso(''); return; } const vm = await leagueService.updateAdminScheduleRace(leagueId, seasonId, editingRaceId, { ...(track ? { track } : {}), ...(car ? { car } : {}), ...(scheduledAtIso ? { scheduledAtIso } : {}), }); setSchedule(vm); setEditingRaceId(null); }; const handleEdit = (raceId: string) => { if (!schedule) return; const race = schedule.races.find((r) => r.id === raceId); if (!race) return; setEditingRaceId(raceId); setTrack(''); setCar(''); setScheduledAtIso(race.scheduledAt.toISOString()); }; const handleDelete = async (raceId: string) => { const confirmed = window.confirm('Delete this race?'); if (!confirmed) return; const vm = await leagueService.deleteAdminScheduleRace(leagueId, seasonId, raceId); setSchedule(vm); }; if (membershipLoading) { return (
Loading…
); } if (!isAdmin) { return (

Admin Access Required

Only league admins can manage the schedule.

); } return (

Schedule Admin

Create, edit, and publish season races.

{seasons.length > 0 ? ( ) : ( setSeasonId(e.target.value)} className="bg-iron-gray text-white px-3 py-2 rounded" placeholder="season-id" /> )}

Selected: {selectedSeasonLabel}

Status: {publishedLabel}

{isEditing ? 'Edit race' : 'Add race'}

setTrack(e.target.value)} className="bg-iron-gray text-white px-3 py-2 rounded" />
setCar(e.target.value)} className="bg-iron-gray text-white px-3 py-2 rounded" />
setScheduledAtIso(e.target.value)} className="bg-iron-gray text-white px-3 py-2 rounded" placeholder="2025-01-01T12:00:00.000Z" />
{isEditing && ( )}

Races

{loading ? (
Loading schedule…
) : schedule?.races.length ? (
{schedule.races.map((race) => (

{race.name}

{race.scheduledAt.toISOString()}

))}
) : (
No races yet.
)}
); }