'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 ( ); }