218 lines
7.4 KiB
TypeScript
218 lines
7.4 KiB
TypeScript
'use client';
|
|
|
|
import { AchievementGrid } from '@/components/achievements/AchievementGrid';
|
|
import { RatingBreakdown } from '@/components/drivers/RatingBreakdown';
|
|
import { FriendsPreview } from '@/components/social/FriendsPreview';
|
|
import { TeamMembershipGrid } from '@/components/teams/TeamMembershipGrid';
|
|
import { Box } from '@/ui/Box';
|
|
import { Breadcrumbs } from '@/ui/Breadcrumbs';
|
|
import { Button } from '@/ui/Button';
|
|
import { Container } from '@/ui/Container';
|
|
import { LoadingSpinner } from '@/ui/LoadingSpinner';
|
|
import { Stack } from '@/ui/Stack';
|
|
import { Text } from '@/ui/Text';
|
|
import { ArrowLeft } from 'lucide-react';
|
|
import React from 'react';
|
|
|
|
import { CareerStats } from '@/components/drivers/CareerStats';
|
|
import { DriverPerformanceOverview } from '@/components/drivers/DriverPerformanceOverview';
|
|
import { DriverProfileHeader } from '@/components/drivers/DriverProfileHeader';
|
|
import { DriverProfileTabs, type ProfileTab } from '@/components/drivers/DriverProfileTabs';
|
|
import { DriverRacingProfile } from '@/components/drivers/DriverRacingProfile';
|
|
import { DriverStatsPanel } from '@/components/drivers/DriverStatsPanel';
|
|
|
|
import type { DriverProfileViewData } from '@/lib/view-data/DriverProfileViewData';
|
|
|
|
interface DriverProfileTemplateProps {
|
|
viewData: DriverProfileViewData;
|
|
isLoading?: boolean;
|
|
error?: string | null;
|
|
onBackClick: () => void;
|
|
onAddFriend: () => void;
|
|
friendRequestSent: boolean;
|
|
activeTab: ProfileTab;
|
|
onTabChange: (tab: ProfileTab) => void;
|
|
isSponsorMode?: boolean;
|
|
sponsorInsights?: React.ReactNode;
|
|
}
|
|
|
|
export function DriverProfileTemplate({
|
|
viewData,
|
|
isLoading = false,
|
|
error = null,
|
|
onBackClick,
|
|
onAddFriend,
|
|
friendRequestSent,
|
|
activeTab,
|
|
onTabChange,
|
|
isSponsorMode = false,
|
|
sponsorInsights = null,
|
|
}: DriverProfileTemplateProps) {
|
|
if (isLoading) {
|
|
return (
|
|
<Container size="lg" spacing="lg">
|
|
<Stack align="center" justify="center" gap={4}>
|
|
<LoadingSpinner size={10} />
|
|
<Text color="text-gray-400">Loading driver profile...</Text>
|
|
</Stack>
|
|
</Container>
|
|
);
|
|
}
|
|
|
|
if (error || !viewData?.currentDriver) {
|
|
return (
|
|
<Container size="md" spacing="lg">
|
|
<Stack align="center" gap={6}>
|
|
<Text color="text-warning-amber">{error || 'Driver not found'}</Text>
|
|
<Button variant="secondary" onClick={onBackClick}>
|
|
Back to Drivers
|
|
</Button>
|
|
</Stack>
|
|
</Container>
|
|
);
|
|
}
|
|
|
|
const { currentDriver, stats, teamMemberships, socialSummary, extendedProfile } = viewData;
|
|
|
|
const careerStats = stats ? [
|
|
{ label: 'Rating', value: stats.ratingLabel, color: 'text-primary-blue' },
|
|
{ label: 'Wins', value: stats.winsLabel, color: 'text-performance-green' },
|
|
{ label: 'Podiums', value: stats.podiumsLabel, color: 'text-warning-amber' },
|
|
{ label: 'Total Races', value: stats.totalRacesLabel },
|
|
{ label: 'Avg Finish', value: stats.avgFinishLabel, subValue: 'POS' },
|
|
{ label: 'Consistency', value: stats.consistencyLabel, color: 'text-primary-blue' },
|
|
] : [];
|
|
|
|
return (
|
|
<Container size="lg" spacing="md">
|
|
<Stack gap={6}>
|
|
{/* Back Navigation & Breadcrumbs */}
|
|
<Stack gap={4}>
|
|
<Box display="flex" alignItems="center" justifyContent="between">
|
|
<Button
|
|
variant="secondary"
|
|
onClick={onBackClick}
|
|
icon={<ArrowLeft size={16} />}
|
|
>
|
|
Back to Drivers
|
|
</Button>
|
|
</Box>
|
|
<Breadcrumbs
|
|
items={[
|
|
{ label: 'Home', href: '/' },
|
|
{ label: 'Drivers', href: '/drivers' },
|
|
{ label: currentDriver.name },
|
|
]}
|
|
/>
|
|
</Stack>
|
|
|
|
{/* Sponsor Insights Card */}
|
|
{isSponsorMode && sponsorInsights}
|
|
|
|
{/* Hero Header Section */}
|
|
<DriverProfileHeader
|
|
name={currentDriver.name}
|
|
avatarUrl={currentDriver.avatarUrl}
|
|
nationality={currentDriver.country}
|
|
rating={stats?.rating || 0}
|
|
ratingLabel={currentDriver.ratingLabel}
|
|
safetyRatingLabel="SR 92"
|
|
globalRankLabel={currentDriver.globalRankLabel}
|
|
bio={currentDriver.bio}
|
|
friendRequestSent={friendRequestSent}
|
|
onAddFriend={onAddFriend}
|
|
/>
|
|
|
|
{/* Stats Grid */}
|
|
{careerStats.length > 0 && (
|
|
<DriverStatsPanel stats={careerStats} />
|
|
)}
|
|
|
|
{/* Team Memberships */}
|
|
{teamMemberships.length > 0 && (
|
|
<TeamMembershipGrid
|
|
memberships={teamMemberships.map((m) => ({
|
|
team: { id: m.teamId, name: m.teamName },
|
|
role: m.role,
|
|
joinedAtLabel: m.joinedAtLabel
|
|
}))}
|
|
/>
|
|
)}
|
|
|
|
{/* Tab Navigation */}
|
|
<DriverProfileTabs activeTab={activeTab} onTabChange={onTabChange} />
|
|
|
|
{/* Tab Content */}
|
|
{activeTab === 'overview' && (
|
|
<Stack gap={6}>
|
|
{stats && (
|
|
<DriverPerformanceOverview
|
|
stats={{
|
|
wins: stats.wins,
|
|
podiums: stats.podiums,
|
|
totalRaces: stats.totalRaces,
|
|
consistency: stats.consistency || 0,
|
|
dnfs: stats.dnfs,
|
|
bestFinish: stats.bestFinish || 0,
|
|
avgFinish: stats.avgFinish || 0
|
|
}}
|
|
/>
|
|
)}
|
|
|
|
{extendedProfile && (
|
|
<DriverRacingProfile
|
|
racingStyle={extendedProfile.racingStyle}
|
|
favoriteTrack={extendedProfile.favoriteTrack}
|
|
favoriteCar={extendedProfile.favoriteCar}
|
|
availableHours={extendedProfile.availableHours}
|
|
lookingForTeam={extendedProfile.lookingForTeam}
|
|
openToRequests={extendedProfile.openToRequests}
|
|
/>
|
|
)}
|
|
|
|
{extendedProfile && extendedProfile.achievements.length > 0 && (
|
|
<AchievementGrid
|
|
achievements={extendedProfile.achievements.map((a) => ({
|
|
...a,
|
|
rarity: a.rarityLabel,
|
|
earnedAtLabel: a.earnedAtLabel
|
|
}))}
|
|
/>
|
|
)}
|
|
|
|
{socialSummary.friends.length > 0 && (
|
|
<FriendsPreview friends={socialSummary.friends} />
|
|
)}
|
|
</Stack>
|
|
)}
|
|
|
|
{activeTab === 'stats' && (
|
|
<Stack gap={6}>
|
|
{stats ? (
|
|
<CareerStats stats={{
|
|
totalRaces: stats.totalRaces,
|
|
wins: stats.wins,
|
|
podiums: stats.podiums,
|
|
consistency: stats.consistency
|
|
}} />
|
|
) : (
|
|
<Box display="flex" flexDirection="col" alignItems="center" justifyContent="center" py={12} gap={4} rounded="2xl" border borderColor="border-charcoal-outline" bg="bg-deep-charcoal/30">
|
|
<Text color="text-gray-400">No statistics available yet</Text>
|
|
<Text size="sm" color="text-gray-500">This driver hasn't completed any races yet</Text>
|
|
</Box>
|
|
)}
|
|
</Stack>
|
|
)}
|
|
|
|
{activeTab === 'ratings' && (
|
|
<RatingBreakdown
|
|
skillRating={stats?.rating || 1450}
|
|
safetyRating={92} // Placeholder as not in viewData yet
|
|
sportsmanshipRating={4.8} // Placeholder as not in viewData yet
|
|
/>
|
|
)}
|
|
</Stack>
|
|
</Container>
|
|
);
|
|
}
|