website refactor

This commit is contained in:
2026-01-17 15:46:55 +01:00
parent 4d5ce9bfd6
commit 72a626ce71
346 changed files with 19308 additions and 8605 deletions

View File

@@ -16,13 +16,14 @@ import {
createRaceAction,
updateRaceAction,
deleteRaceAction
} from './actions';
} from '@/app/actions/leagueScheduleActions';
import { RaceScheduleCommandModel } from '@/lib/command-models/leagues/RaceScheduleCommandModel';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { ConfirmDialog } from '@/components/shared/ux/ConfirmDialog';
export function LeagueAdminSchedulePageClient() {
const params = useParams();
@@ -39,6 +40,8 @@ export function LeagueAdminSchedulePageClient() {
const [isPublishing, setIsPublishing] = useState(false);
const [isSaving, setIsSaving] = useState(false);
const [deletingRaceId, setDeletingRaceId] = useState<string | null>(null);
const [raceToDelete, setRaceToDelete] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
// Check admin status using domain hook
const { data: isAdmin, isLoading: isAdminLoading } = useLeagueAdminStatus(leagueId, currentDriverId);
@@ -48,7 +51,7 @@ export function LeagueAdminSchedulePageClient() {
// Auto-select season
const selectedSeasonId = seasonId || (seasonsData && seasonsData.length > 0
? (seasonsData.find((s) => s.status === 'active') ?? seasonsData[0])?.seasonId
? (seasonsData.find((s) => s.status === 'active') ?? seasonsData[0])?.seasonId || ''
: '');
// Load schedule using domain hook
@@ -65,6 +68,7 @@ export function LeagueAdminSchedulePageClient() {
if (!schedule || !selectedSeasonId) return;
setIsPublishing(true);
setError(null);
try {
const result = schedule.published
? await unpublishScheduleAction(leagueId, selectedSeasonId)
@@ -73,7 +77,7 @@ export function LeagueAdminSchedulePageClient() {
if (result.isOk()) {
router.refresh();
} else {
alert(result.getError());
setError(result.getError());
}
} finally {
setIsPublishing(false);
@@ -89,6 +93,7 @@ export function LeagueAdminSchedulePageClient() {
}
setIsSaving(true);
setError(null);
try {
const result = !editingRaceId
? await createRaceAction(leagueId, selectedSeasonId, form.toCommand())
@@ -100,7 +105,7 @@ export function LeagueAdminSchedulePageClient() {
setEditingRaceId(null);
router.refresh();
} else {
alert(result.getError());
setError(result.getError());
}
} finally {
setIsSaving(false);
@@ -120,18 +125,22 @@ export function LeagueAdminSchedulePageClient() {
}));
};
const handleDelete = async (raceId: string) => {
if (!selectedSeasonId) return;
const confirmed = window.confirm('Delete this race?');
if (!confirmed) return;
const handleDelete = (raceId: string) => {
setRaceToDelete(raceId);
};
const confirmDelete = async () => {
if (!selectedSeasonId || !raceToDelete) return;
setDeletingRaceId(raceId);
setDeletingRaceId(raceToDelete);
setError(null);
try {
const result = await deleteRaceAction(leagueId, selectedSeasonId, raceId);
const result = await deleteRaceAction(leagueId, selectedSeasonId, raceToDelete);
if (result.isOk()) {
router.refresh();
setRaceToDelete(null);
} else {
alert(result.getError());
setError(result.getError());
}
} finally {
setDeletingRaceId(null);
@@ -186,34 +195,47 @@ export function LeagueAdminSchedulePageClient() {
if (!data) return null;
return (
<LeagueAdminScheduleTemplate
viewData={data}
onSeasonChange={handleSeasonChange}
onPublishToggle={handlePublishToggle}
onAddOrSave={handleAddOrSave}
onEdit={handleEdit}
onDelete={handleDelete}
onCancelEdit={handleCancelEdit}
track={form.track}
car={form.car}
scheduledAtIso={form.scheduledAtIso}
editingRaceId={editingRaceId}
isPublishing={isPublishing}
isSaving={isSaving}
isDeleting={deletingRaceId}
setTrack={(val) => {
form.track = val;
setForm(new RaceScheduleCommandModel(form.toCommand()));
}}
setCar={(val) => {
form.car = val;
setForm(new RaceScheduleCommandModel(form.toCommand()));
}}
setScheduledAtIso={(val) => {
form.scheduledAtIso = val;
setForm(new RaceScheduleCommandModel(form.toCommand()));
}}
/>
<>
<LeagueAdminScheduleTemplate
viewData={data}
onSeasonChange={handleSeasonChange}
onPublishToggle={handlePublishToggle}
onAddOrSave={handleAddOrSave}
onEdit={handleEdit}
onDelete={handleDelete}
onCancelEdit={handleCancelEdit}
track={form.track}
car={form.car}
scheduledAtIso={form.scheduledAtIso}
editingRaceId={editingRaceId}
isPublishing={isPublishing}
isSaving={isSaving}
isDeleting={deletingRaceId}
error={error}
setTrack={(val) => {
form.track = val;
setForm(new RaceScheduleCommandModel(form.toCommand()));
}}
setCar={(val) => {
form.car = val;
setForm(new RaceScheduleCommandModel(form.toCommand()));
}}
setScheduledAtIso={(val) => {
form.scheduledAtIso = val;
setForm(new RaceScheduleCommandModel(form.toCommand()));
}}
/>
<ConfirmDialog
isOpen={!!raceToDelete}
onClose={() => setRaceToDelete(null)}
onConfirm={confirmDelete}
title="Delete Race"
description="Are you sure you want to delete this race? This will remove it from the schedule and cannot be undone."
confirmLabel="Delete Race"
variant="danger"
isLoading={!!deletingRaceId}
/>
</>
);
};

View File

@@ -1,70 +0,0 @@
'use server';
import { revalidatePath } from 'next/cache';
import { Result } from '@/lib/contracts/Result';
import { ScheduleAdminMutation } from '@/lib/mutations/leagues/ScheduleAdminMutation';
import { routes } from '@/lib/routing/RouteConfig';
export async function publishScheduleAction(leagueId: string, seasonId: string): Promise<Result<void, string>> {
const mutation = new ScheduleAdminMutation();
const result = await mutation.publishSchedule(leagueId, seasonId);
if (result.isOk()) {
revalidatePath(routes.league.schedule(leagueId));
}
return result;
}
export async function unpublishScheduleAction(leagueId: string, seasonId: string): Promise<Result<void, string>> {
const mutation = new ScheduleAdminMutation();
const result = await mutation.unpublishSchedule(leagueId, seasonId);
if (result.isOk()) {
revalidatePath(routes.league.schedule(leagueId));
}
return result;
}
export async function createRaceAction(
leagueId: string,
seasonId: string,
input: { track: string; car: string; scheduledAtIso: string }
): Promise<Result<void, string>> {
const mutation = new ScheduleAdminMutation();
const result = await mutation.createRace(leagueId, seasonId, input);
if (result.isOk()) {
revalidatePath(routes.league.schedule(leagueId));
}
return result;
}
export async function updateRaceAction(
leagueId: string,
seasonId: string,
raceId: string,
input: Partial<{ track: string; car: string; scheduledAtIso: string }>
): Promise<Result<void, string>> {
const mutation = new ScheduleAdminMutation();
const result = await mutation.updateRace(leagueId, seasonId, raceId, input);
if (result.isOk()) {
revalidatePath(routes.league.schedule(leagueId));
}
return result;
}
export async function deleteRaceAction(leagueId: string, seasonId: string, raceId: string): Promise<Result<void, string>> {
const mutation = new ScheduleAdminMutation();
const result = await mutation.deleteRace(leagueId, seasonId, raceId);
if (result.isOk()) {
revalidatePath(routes.league.schedule(leagueId));
}
return result;
}