website cleanup
This commit is contained in:
@@ -11,6 +11,8 @@ import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId';
|
||||
import { useRaceDetail, useRegisterForRace, useWithdrawFromRace, useCancelRace, useCompleteRace, useReopenRace } from '@/hooks/useRaceService';
|
||||
import { useLeagueMembership } from '@/hooks/useLeagueMembershipService';
|
||||
import { LeagueMembershipUtility } from '@/lib/utilities/LeagueMembershipUtility';
|
||||
import { RaceDetailEntryViewModel } from '@/lib/view-models/RaceDetailEntryViewModel';
|
||||
import { RaceDetailUserResultViewModel } from '@/lib/view-models/RaceDetailUserResultViewModel';
|
||||
import {
|
||||
AlertTriangle,
|
||||
ArrowLeft,
|
||||
@@ -95,14 +97,10 @@ export default function RaceDetailPage() {
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
setCancelling(true);
|
||||
try {
|
||||
await raceService.cancelRace(race.id);
|
||||
await loadRaceData();
|
||||
await cancelMutation.mutateAsync(race.id);
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : 'Failed to cancel race');
|
||||
} finally {
|
||||
setCancelling(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,14 +115,10 @@ export default function RaceDetailPage() {
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
setRegistering(true);
|
||||
try {
|
||||
await raceService.registerForRace(race.id, league.id, currentDriverId);
|
||||
await loadRaceData();
|
||||
await registerMutation.mutateAsync({ raceId: race.id, leagueId: league.id, driverId: currentDriverId });
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : 'Failed to register for race');
|
||||
} finally {
|
||||
setRegistering(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -139,14 +133,10 @@ export default function RaceDetailPage() {
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
setRegistering(true);
|
||||
try {
|
||||
await raceService.withdrawFromRace(race.id, currentDriverId);
|
||||
await loadRaceData();
|
||||
await withdrawMutation.mutateAsync({ raceId: race.id, driverId: currentDriverId });
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : 'Failed to withdraw from race');
|
||||
} finally {
|
||||
setRegistering(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -160,14 +150,10 @@ export default function RaceDetailPage() {
|
||||
|
||||
if (!confirmed) return;
|
||||
|
||||
setReopening(true);
|
||||
try {
|
||||
await raceService.reopenRace(race.id);
|
||||
await loadRaceData();
|
||||
await reopenMutation.mutateAsync(race.id);
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : 'Failed to re-open race');
|
||||
} finally {
|
||||
setReopening(false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -268,7 +254,7 @@ export default function RaceDetailPage() {
|
||||
<AlertTriangle className="w-8 h-8 text-warning-amber" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-white font-medium mb-1">{error || 'Race not found'}</p>
|
||||
<p className="text-white font-medium mb-1">{error instanceof Error ? error.message : error || 'Race not found'}</p>
|
||||
<p className="text-sm text-gray-500">
|
||||
The race you're looking for doesn't exist or has been removed.
|
||||
</p>
|
||||
@@ -292,9 +278,9 @@ export default function RaceDetailPage() {
|
||||
const entryList: RaceDetailEntryViewModel[] = viewModel.entryList;
|
||||
const registration = viewModel.registration;
|
||||
const userResult: RaceDetailUserResultViewModel | null = viewModel.userResult;
|
||||
const raceSOF = race.strengthOfField;
|
||||
const raceSOF = null; // TODO: Add strengthOfField to RaceDetailRaceDTO
|
||||
|
||||
const config = statusConfig[race.status];
|
||||
const config = statusConfig[race.status as keyof typeof statusConfig];
|
||||
const StatusIcon = config.icon;
|
||||
const timeUntil = race.status === 'scheduled' ? getTimeUntil(new Date(race.scheduledAt)) : null;
|
||||
|
||||
@@ -322,7 +308,7 @@ export default function RaceDetailPage() {
|
||||
const raceMetrics = [
|
||||
MetricBuilders.views(entryList.length * 12),
|
||||
MetricBuilders.engagement(78),
|
||||
{ label: 'SOF', value: raceSOF != null ? raceSOF.toString() : '—', icon: Zap, color: 'text-warning-amber' as const },
|
||||
{ label: 'SOF', value: raceSOF != null ? String(raceSOF) : '—', icon: Zap, color: 'text-warning-amber' as const },
|
||||
MetricBuilders.reach(entryList.length * 45),
|
||||
];
|
||||
|
||||
@@ -650,7 +636,8 @@ export default function RaceDetailPage() {
|
||||
{raceSOF ?? '—'}
|
||||
</p>
|
||||
</div>
|
||||
{race.registeredCount !== undefined && (
|
||||
{/* TODO: Add registeredCount and maxParticipants to RaceDetailRaceDTO */}
|
||||
{/* {race.registeredCount !== undefined && (
|
||||
<div className="p-4 bg-deep-graphite rounded-lg">
|
||||
<p className="text-xs text-gray-500 uppercase tracking-wide mb-1">Registered</p>
|
||||
<p className="text-white font-medium">
|
||||
@@ -658,7 +645,7 @@ export default function RaceDetailPage() {
|
||||
{race.maxParticipants && ` / ${race.maxParticipants}`}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
)} */}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
@@ -797,12 +784,12 @@ export default function RaceDetailPage() {
|
||||
<div className="grid grid-cols-2 gap-3 mb-4">
|
||||
<div className="p-3 rounded-lg bg-deep-graphite">
|
||||
<p className="text-xs text-gray-500 mb-1">Max Drivers</p>
|
||||
<p className="text-white font-medium">{league.settings.maxDrivers ?? 32}</p>
|
||||
<p className="text-white font-medium">{(league.settings as any).maxDrivers ?? 32}</p>
|
||||
</div>
|
||||
<div className="p-3 rounded-lg bg-deep-graphite">
|
||||
<p className="text-xs text-gray-500 mb-1">Format</p>
|
||||
<p className="text-white font-medium capitalize">
|
||||
{league.settings.qualifyingFormat ?? 'Open'}
|
||||
{(league.settings as any).qualifyingFormat ?? 'Open'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -828,10 +815,10 @@ export default function RaceDetailPage() {
|
||||
variant="primary"
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
onClick={handleRegister}
|
||||
disabled={registering}
|
||||
disabled={registerMutation.isPending}
|
||||
>
|
||||
<UserPlus className="w-4 h-4" />
|
||||
{registering ? 'Registering...' : 'Register for Race'}
|
||||
{registerMutation.isPending ? 'Registering...' : 'Register for Race'}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -845,10 +832,10 @@ export default function RaceDetailPage() {
|
||||
variant="secondary"
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
onClick={handleWithdraw}
|
||||
disabled={registering}
|
||||
disabled={withdrawMutation.isPending}
|
||||
>
|
||||
<UserMinus className="w-4 h-4" />
|
||||
{registering ? 'Withdrawing...' : 'Withdraw'}
|
||||
{withdrawMutation.isPending ? 'Withdrawing...' : 'Withdraw'}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
@@ -856,13 +843,13 @@ export default function RaceDetailPage() {
|
||||
{viewModel.canReopenRace &&
|
||||
LeagueMembershipUtility.isOwnerOrAdmin(viewModel.league?.id || '', currentDriverId) && (
|
||||
<Button
|
||||
variant="outline"
|
||||
variant="secondary"
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
onClick={handleReopenRace}
|
||||
disabled={reopening}
|
||||
disabled={reopenMutation.isPending}
|
||||
>
|
||||
<PlayCircle className="w-4 h-4" />
|
||||
{reopening ? 'Re-opening...' : 'Re-open Race'}
|
||||
{reopenMutation.isPending ? 'Re-opening...' : 'Re-open Race'}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -900,13 +887,13 @@ export default function RaceDetailPage() {
|
||||
{viewModel.canReopenRace &&
|
||||
LeagueMembershipUtility.isOwnerOrAdmin(viewModel.league?.id || '', currentDriverId) && (
|
||||
<Button
|
||||
variant="outline"
|
||||
variant="secondary"
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
onClick={handleReopenRace}
|
||||
disabled={reopening}
|
||||
disabled={reopenMutation.isPending}
|
||||
>
|
||||
<PlayCircle className="w-4 h-4" />
|
||||
{reopening ? 'Re-opening...' : 'Re-open Race'}
|
||||
{reopenMutation.isPending ? 'Re-opening...' : 'Re-open Race'}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -926,10 +913,10 @@ export default function RaceDetailPage() {
|
||||
variant="secondary"
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
onClick={handleCancelRace}
|
||||
disabled={cancelling}
|
||||
disabled={cancelMutation.isPending}
|
||||
>
|
||||
<XCircle className="w-4 h-4" />
|
||||
{cancelling ? 'Cancelling...' : 'Cancel Race'}
|
||||
{cancelMutation.isPending ? 'Cancelling...' : 'Cancel Race'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@@ -968,8 +955,7 @@ export default function RaceDetailPage() {
|
||||
raceName={race.track}
|
||||
onConfirm={async () => {
|
||||
try {
|
||||
await raceService.completeRace(race.id);
|
||||
await loadRaceData();
|
||||
await completeMutation.mutateAsync(race.id);
|
||||
setShowEndRaceModal(false);
|
||||
} catch (err) {
|
||||
alert(err instanceof Error ? err.message : 'Failed to complete race');
|
||||
|
||||
Reference in New Issue
Block a user