website cleanup

This commit is contained in:
2025-12-24 13:04:18 +01:00
parent 5e491d9724
commit a7aee42409
69 changed files with 1624 additions and 938 deletions

View File

@@ -1,7 +1,7 @@
import Card from '@/components/ui/Card';
import RankBadge from '@/components/drivers/RankBadge';
import DriverIdentity from '@/components/drivers/DriverIdentity';
import type { DriverDTO } from '@core/racing/application/dto/DriverDTO';
import { DriverViewModel } from '@/lib/view-models/DriverViewModel';
export interface DriverCardProps {
id: string;
@@ -29,13 +29,11 @@ export default function DriverCard(props: DriverCardProps) {
onClick,
} = props;
const driver: DriverDTO = {
// Create a proper DriverViewModel instance
const driverViewModel = new DriverViewModel({
id,
iracingId: '',
name,
country: nationality,
joinedAt: '',
};
});
return (
<Card
@@ -47,7 +45,7 @@ export default function DriverCard(props: DriverCardProps) {
<RankBadge rank={rank} size="lg" />
<DriverIdentity
driver={driver}
driver={driverViewModel}
href={`/drivers/${id}`}
meta={`${nationality}${racesCompleted} races`}
size="md"

View File

@@ -1,9 +1,9 @@
import Link from 'next/link';
import Image from 'next/image';
import type { DriverDTO } from '@/lib/types/generated/DriverDTO';
import type { DriverViewModel } from '@/lib/view-models/DriverViewModel';
export interface DriverIdentityProps {
driver: DriverDTO;
driver: DriverViewModel;
href?: string;
contextLabel?: React.ReactNode;
meta?: React.ReactNode;
@@ -21,6 +21,9 @@ export default function DriverIdentity(props: DriverIdentityProps) {
const metaTextClasses = 'text-xs md:text-sm text-gray-400';
// Use provided avatar URL or fallback to default avatar path
const avatarUrl = driver.avatarUrl || `/api/media/avatar/${driver.id}`;
const content = (
<div className="flex items-center gap-3 md:gap-4 flex-1 min-w-0">
<div
@@ -28,7 +31,7 @@ export default function DriverIdentity(props: DriverIdentityProps) {
style={{ width: avatarSize, height: avatarSize }}
>
<Image
src={getImageService().getDriverAvatar(driver.id)}
src={avatarUrl}
alt={driver.name}
width={avatarSize}
height={avatarSize}

View File

@@ -1,6 +1,6 @@
'use client';
import type { DriverDTO } from '@core/racing/application/dto/DriverDTO';
import type { DriverDTO } from '@/lib/types/generated/DriverDTO';
import Card from '../ui/Card';
import ProfileHeader from '../profile/ProfileHeader';
import ProfileStats from './ProfileStats';
@@ -8,17 +8,14 @@ import CareerHighlights from './CareerHighlights';
import DriverRankings from './DriverRankings';
import PerformanceMetrics from './PerformanceMetrics';
import { useEffect, useState } from 'react';
import { DriverTeamPresenter } from '@/lib/presenters/DriverTeamPresenter';
import { getPrimaryLeagueIdForDriver } from '@/lib/leagueMembership';
import type { ProfileOverviewOutputPort } from '@core/racing/application/ports/output/ProfileOverviewOutputPort';
import type { DriverTeamViewModel } from '@core/racing/application/presenters/IDriverTeamPresenter';
import { useServices } from '@/lib/services/ServiceProvider';
interface DriverProfileProps {
driver: DriverDTO;
isOwnProfile?: boolean;
onEditClick?: () => void;
}
interface DriverProfileStatsViewModel {
rating: number;
wins: number;
@@ -33,36 +30,49 @@ interface DriverProfileStatsViewModel {
overallRank?: number;
}
type DriverProfileOverviewViewModel = ProfileOverviewOutputPort | null;
interface DriverTeamViewModel {
team: {
name: string;
tag: string;
};
}
export default function DriverProfile({ driver, isOwnProfile = false, onEditClick }: DriverProfileProps) {
const [profileData, setProfileData] = useState<DriverProfileOverviewViewModel>(null);
const { driverService } = useServices();
const [profileData, setProfileData] = useState<DriverProfileStatsViewModel | null>(null);
const [teamData, setTeamData] = useState<DriverTeamViewModel | null>(null);
useEffect(() => {
const load = async () => {
// Load profile data using GetProfileOverviewUseCase
const profileUseCase = getGetProfileOverviewUseCase();
const profileViewModel = await profileUseCase.execute({ driverId: driver.id });
setProfileData(profileViewModel);
// Load team data using caller-owned presenter
const teamUseCase = getGetDriverTeamUseCase();
const driverTeamPresenter = new DriverTeamPresenter();
await teamUseCase.execute({ driverId: driver.id }, driverTeamPresenter);
const teamResult = driverTeamPresenter.getViewModel();
setTeamData(teamResult ?? null);
try {
// Load driver profile
const profile = await driverService.getDriverProfile(driver.id);
// Extract stats from profile
if (profile.stats) {
setProfileData(profile.stats);
}
// Load team data if available
if (profile.teamMemberships && profile.teamMemberships.length > 0) {
const currentTeam = profile.teamMemberships.find(m => m.isCurrent) || profile.teamMemberships[0];
setTeamData({
team: {
name: currentTeam.teamName,
tag: currentTeam.teamTag ?? ''
}
});
}
} catch (error) {
console.error('Failed to load driver profile data:', error);
}
};
void load();
}, [driver.id]);
}, [driver.id, driverService]);
const driverStats = profileData?.stats || null;
const primaryLeagueId = getPrimaryLeagueIdForDriver(driver.id);
const leagueRank = primaryLeagueId
? getLeagueRankings(driver.id, primaryLeagueId)
: { rank: 0, totalDrivers: 0, percentile: 0 };
const globalRank = profileData?.driver?.globalRank ?? null;
const totalDrivers = profileData?.driver?.totalDrivers ?? 0;
const driverStats = profileData;
const globalRank = profileData?.overallRank ?? null;
const totalDrivers = 1000; // Placeholder
const performanceStats = driverStats ? {
winRate: driverStats.totalRaces > 0 ? (driverStats.wins / driverStats.totalRaces) * 100 : 0,
@@ -83,14 +93,6 @@ export default function DriverProfile({ driver, isOwnProfile = false, onEditClic
percentile: driverStats.percentile ?? 0,
rating: driverStats.rating ?? 0,
},
{
type: 'league' as const,
name: 'Primary League',
rank: leagueRank.rank,
totalDrivers: leagueRank.totalDrivers,
percentile: leagueRank.percentile,
rating: driverStats.rating ?? 0,
},
] : [];
return (

View File

@@ -1,6 +1,6 @@
import { Users, Trophy, ChevronRight } from 'lucide-react';
import Heading from '@/components/ui/Heading';
import Button from '@/components/ui/Button';
import { Trophy, Users } from 'lucide-react';
import Button from '../ui/Button';
interface HeroSectionProps {
icon?: React.ElementType;

View File

@@ -4,9 +4,7 @@ import { useState, useEffect } from 'react';
import Card from '../ui/Card';
import Button from '../ui/Button';
import RaceResultCard from '../races/RaceResultCard';
import { Race } from '@core/racing/domain/entities/Race';
import { Result } from '@core/racing/domain/entities/Result';
import { League } from '@core/racing/domain/entities/League';
import { useServices } from '@/lib/services/ServiceProvider';
interface RaceHistoryProps {
driverId: string;

View File

@@ -1,7 +1,7 @@
'use client';
import { useState } from 'react';
import type { DriverDTO } from '@core/racing/application/dto/DriverDTO';
import type { DriverDTO } from '@/lib/types/generated/DriverDTO';
import Card from '../ui/Card';
import Button from '../ui/Button';
import Input from '../ui/Input';

View File

@@ -4,7 +4,6 @@ import Card from '../ui/Card';
import RankBadge from './RankBadge';
import { useState, useEffect } from 'react';
import { getPrimaryLeagueIdForDriver } from '@/lib/leagueMembership';
import type { ProfileOverviewOutputPort } from '@core/racing/application/ports/output/ProfileOverviewOutputPort';
interface ProfileStatsProps {
driverId?: string;