205 lines
6.4 KiB
TypeScript
205 lines
6.4 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { useParams } from 'next/navigation';
|
|
import { PageWrapper } from '@/components/shared/state/PageWrapper';
|
|
import { LeagueAdminScheduleTemplate } from '@/templates/LeagueAdminScheduleTemplate';
|
|
import {
|
|
useLeagueAdminStatus,
|
|
useLeagueSeasons,
|
|
useLeagueAdminSchedule
|
|
} from "@/lib/hooks/league/useLeagueScheduleAdminPageData";
|
|
import { useEffectiveDriverId } from "@/lib/hooks/useEffectiveDriverId";
|
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { useInject } from '@/lib/di/hooks/useInject';
|
|
import { LEAGUE_SERVICE_TOKEN } from '@/lib/di/tokens';
|
|
|
|
export default function LeagueAdminSchedulePage() {
|
|
const params = useParams();
|
|
const leagueId = params.id as string;
|
|
const currentDriverId = useEffectiveDriverId() || '';
|
|
const queryClient = useQueryClient();
|
|
|
|
const leagueService = useInject(LEAGUE_SERVICE_TOKEN);
|
|
|
|
// Form state
|
|
const [seasonId, setSeasonId] = useState<string>('');
|
|
const [track, setTrack] = useState('');
|
|
const [car, setCar] = useState('');
|
|
const [scheduledAtIso, setScheduledAtIso] = useState('');
|
|
const [editingRaceId, setEditingRaceId] = useState<string | null>(null);
|
|
|
|
// Check admin status using domain hook
|
|
const { data: isAdmin, isLoading: isAdminLoading } = useLeagueAdminStatus(leagueId, currentDriverId);
|
|
|
|
// Load seasons using domain hook
|
|
const { data: seasonsData, isLoading: seasonsLoading } = useLeagueSeasons(leagueId, !!isAdmin);
|
|
|
|
// Auto-select season
|
|
const selectedSeasonId = seasonId || (seasonsData && seasonsData.length > 0
|
|
? (seasonsData.find((s) => s.status === 'active') ?? seasonsData[0])?.seasonId
|
|
: '');
|
|
|
|
// Load schedule using domain hook
|
|
const { data: schedule, isLoading: scheduleLoading, refetch: refetchSchedule } = useLeagueAdminSchedule(leagueId, selectedSeasonId, !!isAdmin);
|
|
|
|
// Mutations
|
|
const publishMutation = useMutation({
|
|
mutationFn: async () => {
|
|
if (!schedule || !selectedSeasonId) return null;
|
|
return schedule.published
|
|
? await leagueService.unpublishAdminSchedule(leagueId, selectedSeasonId)
|
|
: await leagueService.publishAdminSchedule(leagueId, selectedSeasonId);
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['adminSchedule', leagueId, selectedSeasonId] });
|
|
},
|
|
});
|
|
|
|
const saveMutation = useMutation({
|
|
mutationFn: async () => {
|
|
if (!selectedSeasonId || !scheduledAtIso) return null;
|
|
|
|
if (!editingRaceId) {
|
|
return await leagueService.createAdminScheduleRace(leagueId, selectedSeasonId, {
|
|
track,
|
|
car,
|
|
scheduledAtIso,
|
|
});
|
|
} else {
|
|
return await leagueService.updateAdminScheduleRace(leagueId, selectedSeasonId, editingRaceId, {
|
|
...(track ? { track } : {}),
|
|
...(car ? { car } : {}),
|
|
...(scheduledAtIso ? { scheduledAtIso } : {}),
|
|
});
|
|
}
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['adminSchedule', leagueId, selectedSeasonId] });
|
|
// Reset form
|
|
setTrack('');
|
|
setCar('');
|
|
setScheduledAtIso('');
|
|
setEditingRaceId(null);
|
|
},
|
|
});
|
|
|
|
const deleteMutation = useMutation({
|
|
mutationFn: async (raceId: string) => {
|
|
return await leagueService.deleteAdminScheduleRace(leagueId, selectedSeasonId, raceId);
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['adminSchedule', leagueId, selectedSeasonId] });
|
|
},
|
|
});
|
|
|
|
// Derived states
|
|
const isLoading = isAdminLoading || seasonsLoading || scheduleLoading;
|
|
const isPublishing = publishMutation.isPending;
|
|
const isSaving = saveMutation.isPending;
|
|
const isDeleting = deleteMutation.variables || null;
|
|
|
|
// Handlers
|
|
const handleSeasonChange = (newSeasonId: string) => {
|
|
setSeasonId(newSeasonId);
|
|
setEditingRaceId(null);
|
|
setTrack('');
|
|
setCar('');
|
|
setScheduledAtIso('');
|
|
};
|
|
|
|
const handlePublishToggle = () => {
|
|
publishMutation.mutate();
|
|
};
|
|
|
|
const handleAddOrSave = () => {
|
|
if (!scheduledAtIso) return;
|
|
saveMutation.mutate();
|
|
};
|
|
|
|
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 = (raceId: string) => {
|
|
const confirmed = window.confirm('Delete this race?');
|
|
if (!confirmed) return;
|
|
deleteMutation.mutate(raceId);
|
|
};
|
|
|
|
const handleCancelEdit = () => {
|
|
setEditingRaceId(null);
|
|
setTrack('');
|
|
setCar('');
|
|
setScheduledAtIso('');
|
|
};
|
|
|
|
// Prepare template data
|
|
const templateData = schedule && seasonsData && selectedSeasonId
|
|
? {
|
|
schedule,
|
|
seasons: seasonsData,
|
|
seasonId: selectedSeasonId,
|
|
}
|
|
: undefined;
|
|
|
|
// Render admin access required if not admin
|
|
if (!isLoading && !isAdmin) {
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="bg-deep-graphite border border-charcoal-outline rounded-lg p-6 text-center">
|
|
<h3 className="text-lg font-medium text-white mb-2">Admin Access Required</h3>
|
|
<p className="text-sm text-gray-400">Only league admins can manage the schedule.</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Template component that wraps the actual template with all props
|
|
const TemplateWrapper = ({ data }: { data: typeof templateData }) => {
|
|
if (!data) return null;
|
|
|
|
return (
|
|
<LeagueAdminScheduleTemplate
|
|
data={data}
|
|
onSeasonChange={handleSeasonChange}
|
|
onPublishToggle={handlePublishToggle}
|
|
onAddOrSave={handleAddOrSave}
|
|
onEdit={handleEdit}
|
|
onDelete={handleDelete}
|
|
onCancelEdit={handleCancelEdit}
|
|
track={track}
|
|
car={car}
|
|
scheduledAtIso={scheduledAtIso}
|
|
editingRaceId={editingRaceId}
|
|
isPublishing={isPublishing}
|
|
isSaving={isSaving}
|
|
isDeleting={isDeleting}
|
|
setTrack={setTrack}
|
|
setCar={setCar}
|
|
setScheduledAtIso={setScheduledAtIso}
|
|
/>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<PageWrapper
|
|
data={templateData}
|
|
isLoading={isLoading}
|
|
error={null}
|
|
Template={TemplateWrapper}
|
|
loading={{ variant: 'full-screen', message: 'Loading schedule admin...' }}
|
|
empty={{
|
|
title: 'No schedule data available',
|
|
description: 'Unable to load schedule administration data',
|
|
}}
|
|
/>
|
|
);
|
|
} |