Files
gridpilot.gg/apps/website/templates/DriverProfileTemplate.tsx
2026-01-26 17:56:11 +01:00

218 lines
7.4 KiB
TypeScript

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&apos;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>
);
}