website refactor

This commit is contained in:
2026-01-16 01:40:01 +01:00
parent b533de8486
commit d86aa4583b
7 changed files with 214 additions and 64 deletions

View File

@@ -17,6 +17,7 @@ import {
updateRaceAction,
deleteRaceAction
} from './actions';
import { RaceScheduleCommandModel } from '@/lib/command-models/leagues/RaceScheduleCommandModel';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
@@ -31,10 +32,9 @@ export function LeagueAdminSchedulePageClient() {
// Form state
const [seasonId, setSeasonId] = useState<string>('');
const [track, setTrack] = useState('');
const [car, setCar] = useState('');
const [scheduledAtIso, setScheduledAtIso] = useState('');
const [form, setForm] = useState(() => new RaceScheduleCommandModel());
const [editingRaceId, setEditingRaceId] = useState<string | null>(null);
const [errors, setErrors] = useState<Record<string, string>>({});
// Action state
const [isPublishing, setIsPublishing] = useState(false);
@@ -59,9 +59,8 @@ export function LeagueAdminSchedulePageClient() {
const handleSeasonChange = (newSeasonId: string) => {
setSeasonId(newSeasonId);
setEditingRaceId(null);
setTrack('');
setCar('');
setScheduledAtIso('');
setForm(new RaceScheduleCommandModel());
setErrors({});
};
const handlePublishToggle = async () => {
@@ -84,23 +83,24 @@ export function LeagueAdminSchedulePageClient() {
};
const handleAddOrSave = async () => {
if (!selectedSeasonId || !scheduledAtIso) return;
if (!selectedSeasonId) return;
const validationErrors = form.validate();
if (Object.keys(validationErrors).length > 0) {
setErrors(validationErrors as Record<string, string>);
return;
}
setIsSaving(true);
try {
const result = !editingRaceId
? await createRaceAction(leagueId, selectedSeasonId, { track, car, scheduledAtIso })
: await updateRaceAction(leagueId, selectedSeasonId, editingRaceId, {
...(track ? { track } : {}),
...(car ? { car } : {}),
...(scheduledAtIso ? { scheduledAtIso } : {}),
});
? await createRaceAction(leagueId, selectedSeasonId, form.toCommand())
: await updateRaceAction(leagueId, selectedSeasonId, editingRaceId, form.toCommand());
if (result.isOk()) {
// Reset form
setTrack('');
setCar('');
setScheduledAtIso('');
setForm(new RaceScheduleCommandModel());
setErrors({});
setEditingRaceId(null);
router.refresh();
} else {
@@ -117,9 +117,12 @@ export function LeagueAdminSchedulePageClient() {
if (!race) return;
setEditingRaceId(raceId);
setTrack(race.track || '');
setCar(race.car || '');
setScheduledAtIso(race.scheduledAt.toISOString());
setForm(new RaceScheduleCommandModel({
track: race.track || '',
car: race.car || '',
scheduledAtIso: race.scheduledAt.toISOString(),
}));
setErrors({});
};
const handleDelete = async (raceId: string) => {
@@ -142,9 +145,8 @@ export function LeagueAdminSchedulePageClient() {
const handleCancelEdit = () => {
setEditingRaceId(null);
setTrack('');
setCar('');
setScheduledAtIso('');
setForm(new RaceScheduleCommandModel());
setErrors({});
};
// Derived states
@@ -198,16 +200,25 @@ export function LeagueAdminSchedulePageClient() {
onEdit={handleEdit}
onDelete={handleDelete}
onCancelEdit={handleCancelEdit}
track={track}
car={car}
scheduledAtIso={scheduledAtIso}
track={form.track}
car={form.car}
scheduledAtIso={form.scheduledAtIso}
editingRaceId={editingRaceId}
isPublishing={isPublishing}
isSaving={isSaving}
isDeleting={deletingRaceId}
setTrack={setTrack}
setCar={setCar}
setScheduledAtIso={setScheduledAtIso}
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()));
}}
/>
);
};

View File

@@ -607,7 +607,7 @@ export function CreateLeagueWizard({ stepName, onStepChange }: CreateLeagueWizar
Create a new league
</Heading>
<Text size="sm" color="text-gray-500" block>
We&apos;ll also set up your first season in {steps.length} easy steps.
We'll also set up your first season in {steps.length} easy steps.
</Text>
<Text size="xs" color="text-gray-500" block mt={1}>
A league is your long-term brand. Each season is a block of races you can run again and again.