website refactor

This commit is contained in:
2026-01-14 23:46:04 +01:00
parent c1a86348d7
commit 4a2d7d15a5
294 changed files with 5637 additions and 3418 deletions

View File

@@ -0,0 +1,85 @@
'use client';
import React, { useState, useEffect } from 'react';
import { RaceDetailTemplate, type RaceDetailViewData } from '@/templates/RaceDetailTemplate';
interface RaceDetailPageClientProps {
viewData: RaceDetailViewData;
onBack: () => void;
onRegister: () => void;
onWithdraw: () => void;
onCancel: () => void;
onReopen: () => void;
onEndRace: () => void;
onFileProtest: () => void;
onResultsClick: () => void;
onStewardingClick: () => void;
onLeagueClick: (id: string) => void;
onDriverClick: (id: string) => void;
isOwnerOrAdmin: boolean;
}
export function RaceDetailPageClient({
viewData,
onBack,
onRegister,
onWithdraw,
onCancel,
onReopen,
onEndRace,
onFileProtest,
onResultsClick,
onStewardingClick,
onLeagueClick,
onDriverClick,
isOwnerOrAdmin
}: RaceDetailPageClientProps) {
const [showProtestModal, setShowProtestModal] = useState(false);
const [showEndRaceModal, setShowEndRaceModal] = useState(false);
const [animatedRatingChange, setAnimatedRatingChange] = useState(0);
const ratingChange = viewData.userResult?.ratingChange ?? null;
useEffect(() => {
if (ratingChange !== null) {
let start = 0;
const end = ratingChange;
const duration = 1000;
const startTime = performance.now();
const animate = (currentTime: number) => {
const elapsed = currentTime - startTime;
const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 3);
const current = Math.round(start + (end - start) * eased);
setAnimatedRatingChange(current);
if (progress < 1) {
requestAnimationFrame(animate);
}
};
requestAnimationFrame(animate);
}
}, [ratingChange]);
return (
<RaceDetailTemplate
viewData={viewData}
isLoading={false}
onBack={onBack}
onRegister={onRegister}
onWithdraw={onWithdraw}
onCancel={onCancel}
onReopen={onReopen}
onEndRace={onEndRace}
onFileProtest={onFileProtest}
onResultsClick={onResultsClick}
onStewardingClick={onStewardingClick}
onLeagueClick={onLeagueClick}
onDriverClick={onDriverClick}
isOwnerOrAdmin={isOwnerOrAdmin}
animatedRatingChange={animatedRatingChange}
/>
);
}

View File

@@ -34,7 +34,7 @@ export default async function RaceDetailPage({ params }: RaceDetailPageProps) {
data={null}
Template={({ data: _data }) => (
<RaceDetailTemplate
viewModel={undefined}
viewData={undefined}
isLoading={false}
error={new Error('Failed to load race details')}
onBack={() => {}}
@@ -48,12 +48,8 @@ export default async function RaceDetailPage({ params }: RaceDetailPageProps) {
onStewardingClick={() => {}}
onLeagueClick={() => {}}
onDriverClick={() => {}}
currentDriverId={''}
isOwnerOrAdmin={false}
showProtestModal={false}
setShowProtestModal={() => {}}
showEndRaceModal={false}
setShowEndRaceModal={() => {}}
animatedRatingChange={0}
mutationLoading={{
register: false,
withdraw: false,
@@ -78,23 +74,12 @@ export default async function RaceDetailPage({ params }: RaceDetailPageProps) {
const viewData = result.unwrap();
// Convert ViewData to ViewModel for the template
// The template expects a ViewModel, so we need to adapt
const viewModel = {
race: viewData.race,
league: viewData.league,
entryList: viewData.entryList,
registration: viewData.registration,
userResult: viewData.userResult,
canReopenRace: viewData.canReopenRace,
};
return (
<PageWrapper
data={viewData}
Template={({ data: _data }) => (
<RaceDetailTemplate
viewModel={viewModel}
viewData={viewData}
isLoading={false}
error={null}
onBack={() => {}}
@@ -108,12 +93,8 @@ export default async function RaceDetailPage({ params }: RaceDetailPageProps) {
onStewardingClick={() => {}}
onLeagueClick={() => {}}
onDriverClick={() => {}}
currentDriverId={''}
isOwnerOrAdmin={false}
showProtestModal={false}
setShowProtestModal={() => {}}
showEndRaceModal={false}
setShowEndRaceModal={() => {}}
animatedRatingChange={0}
mutationLoading={{
register: false,
withdraw: false,