Files
gridpilot.gg/apps/website/templates/ProfileTemplate.tsx
2026-01-15 18:52:03 +01:00

233 lines
7.7 KiB
TypeScript

'use client';
import React from 'react';
import { CreateDriverForm } from '@/components/drivers/CreateDriverForm';
import { ProfileRaceHistory } from '@/components/drivers/ProfileRaceHistory';
import { ProfileSettings } from '@/components/drivers/ProfileSettings';
import { AchievementGrid } from '@/ui/AchievementGrid';
import { ProfileHero } from '@/ui/ProfileHero';
import { ProfileStatGrid } from '@/ui/ProfileStatGrid';
import { ProfileTabs, type ProfileTab as ProfileTabsType } from '@/ui/ProfileTabs';
import { TeamMembershipGrid } from '@/ui/TeamMembershipGrid';
import type { ProfileViewData } from '@/lib/view-data/ProfileViewData';
import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button';
import { Card } from '@/ui/Card';
import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text';
import {
Activity,
Award,
History,
User,
} from 'lucide-react';
import { Breadcrumbs } from '@/ui/Breadcrumbs';
export type ProfileTab = 'overview' | 'history' | 'stats';
interface ProfileTemplateProps {
viewData: ProfileViewData;
mode: 'profile-exists' | 'needs-profile';
activeTab: ProfileTab;
onTabChange: (tab: ProfileTab) => void;
editMode: boolean;
onEditModeChange: (edit: boolean) => void;
friendRequestSent: boolean;
onFriendRequestSend: () => void;
onSaveSettings: (updates: { bio?: string; country?: string }) => Promise<void>;
}
export function ProfileTemplate({
viewData,
mode,
activeTab,
onTabChange,
editMode,
onEditModeChange,
friendRequestSent,
onFriendRequestSend,
onSaveSettings,
}: ProfileTemplateProps) {
if (mode === 'needs-profile') {
return (
<Container size="md">
<Stack align="center" gap={4} mb={8}>
<Surface variant="muted" rounded="xl" border padding={4}>
<Icon icon={User} size={8} color="#3b82f6" />
</Surface>
<Box>
<Heading level={1}>Create Your Driver Profile</Heading>
<Text color="text-gray-400">Join the GridPilot community and start your racing journey</Text>
</Box>
</Stack>
<Box maxWidth="42rem" mx="auto">
<Card>
<Stack gap={6}>
<Box>
<Heading level={2}>Get Started</Heading>
<Text size="sm" color="text-gray-400">
Create your driver profile to join leagues, compete in races, and connect with other drivers.
</Text>
</Box>
<CreateDriverForm onSuccess={() => {}} isPending={false} />
</Stack>
</Card>
</Box>
</Container>
);
}
if (editMode) {
return (
<Container size="md">
<Stack gap={6}>
<Stack direction="row" align="center" justify="between">
<Heading level={1}>Edit Profile</Heading>
<Button variant="secondary" onClick={() => onEditModeChange(false)}>
Cancel
</Button>
</Stack>
<ProfileSettings
driver={{
id: viewData.driver.id,
name: viewData.driver.name,
country: viewData.driver.countryCode,
avatarUrl: viewData.driver.avatarUrl,
iracingId: viewData.driver.iracingId || '',
joinedAt: new Date().toISOString(),
rating: null,
globalRank: null,
consistency: null,
bio: viewData.driver.bio,
totalDrivers: null,
}}
onSave={async (updates) => {
await onSaveSettings(updates);
onEditModeChange(false);
}}
/>
</Stack>
</Container>
);
}
return (
<Container size="lg">
<Stack gap={6}>
{/* Back Navigation */}
<Box>
<Button
variant="secondary"
onClick={() => {}}
icon={<Icon icon={History} size={4} />}
>
Back to Drivers
</Button>
</Box>
{/* Breadcrumb */}
<Breadcrumbs
items={[
{ label: 'Home', href: '/' },
{ label: 'Drivers', href: '/drivers' },
{ label: viewData.driver.name },
]}
/>
<ProfileHero
driver={{
...viewData.driver,
country: viewData.driver.countryCode,
iracingId: Number(viewData.driver.iracingId) || 0,
joinedAt: new Date().toISOString(), // Placeholder
}}
stats={viewData.stats ? { rating: Number(viewData.stats.ratingLabel) || 0 } : null}
globalRank={Number(viewData.stats?.globalRankLabel) || 0}
timezone={viewData.extendedProfile?.timezone || 'UTC'}
socialHandles={viewData.extendedProfile?.socialHandles.map(s => ({ ...s, platform: s.platformLabel })) || []}
onAddFriend={onFriendRequestSend}
friendRequestSent={friendRequestSent}
/>
{viewData.driver.bio && (
<Card>
<Stack gap={3}>
<Heading level={2} icon={<Icon icon={User} size={5} color="#3b82f6" />}>
About
</Heading>
<Text color="text-gray-300" block>{viewData.driver.bio}</Text>
</Stack>
</Card>
)}
{viewData.teamMemberships.length > 0 && (
<TeamMembershipGrid
memberships={viewData.teamMemberships.map(m => ({
team: { id: m.teamId, name: m.teamName },
role: m.roleLabel,
joinedAt: new Date() // Placeholder
}))}
/>
)}
<ProfileTabs activeTab={activeTab as unknown as ProfileTabsType} onTabChange={onTabChange as unknown as (tab: ProfileTabsType) => void} />
{activeTab === 'history' && (
<Card>
<Stack gap={4}>
<Heading level={2} icon={<Icon icon={History} size={5} color="#f87171" />}>
Race History
</Heading>
<ProfileRaceHistory driverId={viewData.driver.id} />
</Stack>
</Card>
)}
{activeTab === 'stats' && viewData.stats && (
<Card>
<Stack gap={6}>
<Heading level={2} icon={<Icon icon={Activity} size={5} color="#00f2ff" />}>
Performance Overview
</Heading>
<ProfileStatGrid
stats={[
{ label: 'Races', value: viewData.stats.totalRacesLabel },
{ label: 'Wins', value: viewData.stats.winsLabel, color: '#10b981' },
{ label: 'Podiums', value: viewData.stats.podiumsLabel, color: '#f59e0b' },
{ label: 'Consistency', value: viewData.stats.consistencyLabel, color: '#3b82f6' },
]}
/>
</Stack>
</Card>
)}
{activeTab === 'overview' && viewData.extendedProfile && (
<Card>
<Stack gap={4}>
<Stack direction="row" align="center" justify="between">
<Heading level={2} icon={<Icon icon={Award} size={5} color="#facc15" />}>
Achievements
</Heading>
<Text size="sm" color="text-gray-400" weight="normal">{viewData.extendedProfile.achievements.length} earned</Text>
</Stack>
<AchievementGrid
achievements={viewData.extendedProfile.achievements.map(a => ({
...a,
rarity: a.rarityLabel,
earnedAt: new Date() // Placeholder
}))}
/>
</Stack>
</Card>
)}
</Stack>
</Container>
);
}