wip
This commit is contained in:
@@ -19,27 +19,17 @@ import {
|
||||
import Button from '@/components/ui/Button';
|
||||
import Input from '@/components/ui/Input';
|
||||
import Heading from '@/components/ui/Heading';
|
||||
import { getDriverRepository, getDriverStats, getAllDriverRankings, getImageService } from '@/lib/di-container';
|
||||
import { getGetDriversLeaderboardUseCase } from '@/lib/di-container';
|
||||
import type { DriverLeaderboardItemViewModel, SkillLevel } from '@gridpilot/racing/application/presenters/IDriversLeaderboardPresenter';
|
||||
import Image from 'next/image';
|
||||
|
||||
// ============================================================================
|
||||
// TYPES
|
||||
// ============================================================================
|
||||
|
||||
type SkillLevel = 'beginner' | 'intermediate' | 'advanced' | 'pro';
|
||||
type SortBy = 'rank' | 'rating' | 'wins' | 'podiums' | 'winRate';
|
||||
|
||||
interface DriverListItem {
|
||||
id: string;
|
||||
name: string;
|
||||
rating: number;
|
||||
skillLevel: SkillLevel;
|
||||
nationality: string;
|
||||
racesCompleted: number;
|
||||
wins: number;
|
||||
podiums: number;
|
||||
rank: number;
|
||||
}
|
||||
type DriverListItem = DriverLeaderboardItemViewModel;
|
||||
|
||||
// ============================================================================
|
||||
// SKILL LEVEL CONFIG
|
||||
@@ -81,7 +71,6 @@ interface TopThreePodiumProps {
|
||||
}
|
||||
|
||||
function TopThreePodium({ drivers, onDriverClick }: TopThreePodiumProps) {
|
||||
const imageService = getImageService();
|
||||
const top3 = drivers.slice(0, 3);
|
||||
|
||||
if (top3.length < 3) return null;
|
||||
@@ -122,7 +111,7 @@ function TopThreePodium({ drivers, onDriverClick }: TopThreePodiumProps) {
|
||||
{/* Avatar */}
|
||||
<div className={`relative ${position === 1 ? 'w-24 h-24 lg:w-28 lg:h-28' : 'w-20 h-20 lg:w-24 lg:h-24'} rounded-full overflow-hidden border-4 ${position === 1 ? 'border-yellow-400 shadow-[0_0_30px_rgba(250,204,21,0.3)]' : position === 2 ? 'border-gray-300' : 'border-amber-600'} group-hover:scale-105 transition-transform`}>
|
||||
<Image
|
||||
src={imageService.getDriverAvatar(driver.id)}
|
||||
src={driver.avatarUrl}
|
||||
alt={driver.name}
|
||||
fill
|
||||
className="object-cover"
|
||||
@@ -178,7 +167,6 @@ function TopThreePodium({ drivers, onDriverClick }: TopThreePodiumProps) {
|
||||
|
||||
export default function DriverLeaderboardPage() {
|
||||
const router = useRouter();
|
||||
const imageService = getImageService();
|
||||
const [drivers, setDrivers] = useState<DriverListItem[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
@@ -188,44 +176,10 @@ export default function DriverLeaderboardPage() {
|
||||
|
||||
useEffect(() => {
|
||||
const load = async () => {
|
||||
const driverRepo = getDriverRepository();
|
||||
const allDrivers = await driverRepo.findAll();
|
||||
const rankings = getAllDriverRankings();
|
||||
|
||||
const items: DriverListItem[] = allDrivers.map((driver) => {
|
||||
const stats = getDriverStats(driver.id);
|
||||
const rating = stats?.rating ?? 0;
|
||||
const wins = stats?.wins ?? 0;
|
||||
const podiums = stats?.podiums ?? 0;
|
||||
const totalRaces = stats?.totalRaces ?? 0;
|
||||
|
||||
let effectiveRank = Number.POSITIVE_INFINITY;
|
||||
if (typeof stats?.overallRank === 'number' && stats.overallRank > 0) {
|
||||
effectiveRank = stats.overallRank;
|
||||
} else {
|
||||
const indexInGlobal = rankings.findIndex((entry) => entry.driverId === driver.id);
|
||||
if (indexInGlobal !== -1) {
|
||||
effectiveRank = indexInGlobal + 1;
|
||||
}
|
||||
}
|
||||
|
||||
const skillLevel: SkillLevel =
|
||||
rating >= 3000 ? 'pro' : rating >= 2500 ? 'advanced' : rating >= 1800 ? 'intermediate' : 'beginner';
|
||||
|
||||
return {
|
||||
id: driver.id,
|
||||
name: driver.name,
|
||||
rating,
|
||||
skillLevel,
|
||||
nationality: driver.country,
|
||||
racesCompleted: totalRaces,
|
||||
wins,
|
||||
podiums,
|
||||
rank: effectiveRank,
|
||||
};
|
||||
});
|
||||
|
||||
setDrivers(items);
|
||||
const useCase = getGetDriversLeaderboardUseCase();
|
||||
await useCase.execute();
|
||||
const viewModel = useCase.presenter.getViewModel();
|
||||
setDrivers(viewModel.drivers);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
@@ -443,7 +397,7 @@ export default function DriverLeaderboardPage() {
|
||||
{/* Driver Info */}
|
||||
<div className="col-span-5 lg:col-span-4 flex items-center gap-3">
|
||||
<div className="relative w-10 h-10 rounded-full overflow-hidden border-2 border-charcoal-outline">
|
||||
<Image src={imageService.getDriverAvatar(driver.id)} alt={driver.name} fill className="object-cover" />
|
||||
<Image src={driver.avatarUrl} alt={driver.name} fill className="object-cover" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className="text-white font-semibold truncate group-hover:text-primary-blue transition-colors">
|
||||
|
||||
Reference in New Issue
Block a user