website refactor

This commit is contained in:
2026-01-17 15:46:55 +01:00
parent 4d5ce9bfd6
commit 72a626ce71
346 changed files with 19308 additions and 8605 deletions

View File

@@ -2,43 +2,30 @@
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 '@/components/achievements/AchievementGrid';
import { ProfileHero } from '@/components/drivers/ProfileHero';
import { ProfileHeader } from '@/components/profile/ProfileHeader';
import { ProfileNavTabs, type ProfileTab } from '@/components/profile/ProfileNavTabs';
import { ProfileDetailsPanel } from '@/components/profile/ProfileDetailsPanel';
import { SessionHistoryTable } from '@/components/profile/SessionHistoryTable';
import { ProfileStatGrid } from '@/ui/ProfileStatGrid';
import { ProfileTabs, type ProfileTab as ProfileTabsType } from '@/ui/ProfileTabs';
import { TeamMembershipGrid } from '@/ui/TeamMembershipGrid';
import { AchievementGrid } from '@/components/achievements/AchievementGrid';
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';
import { User } from 'lucide-react';
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({
@@ -46,26 +33,21 @@ export function ProfileTemplate({
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>
<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>
<Box maxWidth="42rem" mx="auto">
<Box maxWidth="42rem" mx="auto" width="100%">
<Card>
<Stack gap={6}>
<Box>
@@ -78,123 +60,89 @@ export function ProfileTemplate({
</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>
</Stack>
);
}
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>
<Stack gap={8}>
<ProfileHeader
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}
onAddFriend={onFriendRequestSend}
friendRequestSent={friendRequestSent}
isOwnProfile={true}
/>
{/* Breadcrumb */}
<Breadcrumbs
items={[
{ label: 'Home', href: '/' },
{ label: 'Drivers', href: '/drivers' },
{ label: viewData.driver.name },
]}
/>
<ProfileNavTabs activeTab={activeTab} onTabChange={onTabChange} />
<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
}))}
{activeTab === 'overview' && (
<Stack gap={8}>
<ProfileDetailsPanel
driver={{
name: viewData.driver.name,
country: viewData.driver.countryCode,
bio: viewData.driver.bio
}}
/>
)}
<ProfileTabs activeTab={activeTab as unknown as ProfileTabsType} onTabChange={onTabChange as unknown as (tab: ProfileTabsType) => void} />
{viewData.teamMemberships.length > 0 && (
<Box as="section" aria-labelledby="teams-heading">
<Stack gap={4}>
<Heading level={3} id="teams-heading" fontSize="1.125rem">Teams</Heading>
<TeamMembershipGrid
memberships={viewData.teamMemberships.map(m => ({
team: { id: m.teamId, name: m.teamName },
role: m.roleLabel,
joinedAt: new Date() // Placeholder
}))}
/>
</Stack>
</Box>
)}
{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>
)}
{viewData.extendedProfile && (
<Box as="section" aria-labelledby="achievements-heading">
<Stack gap={4}>
<Stack direction="row" justify="between" align="center">
<Heading level={3} id="achievements-heading" fontSize="1.125rem">Achievements</Heading>
<Text size="sm" color="#6b7280">{viewData.extendedProfile.achievements.length} earned</Text>
</Stack>
<AchievementGrid
achievements={viewData.extendedProfile.achievements.map(a => ({
...a,
rarity: a.rarityLabel,
earnedAt: new Date() // Placeholder
}))}
/>
</Stack>
</Box>
)}
</Stack>
)}
{activeTab === 'stats' && viewData.stats && (
<Card>
<Stack gap={6}>
<Heading level={2} icon={<Icon icon={Activity} size={5} color="#00f2ff" />}>
Performance Overview
</Heading>
{activeTab === 'history' && (
<Box as="section" aria-labelledby="history-heading">
<Stack gap={4}>
<Heading level={3} id="history-heading" fontSize="1.125rem">Race History</Heading>
<Card>
<SessionHistoryTable results={[]} />
</Card>
</Stack>
</Box>
)}
{activeTab === 'stats' && viewData.stats && (
<Box as="section" aria-labelledby="stats-heading">
<Stack gap={4}>
<Heading level={3} id="stats-heading" fontSize="1.125rem">Performance Overview</Heading>
<Card>
<ProfileStatGrid
stats={[
{ label: 'Races', value: viewData.stats.totalRacesLabel },
@@ -203,30 +151,10 @@ export function ProfileTemplate({
{ 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>
</Card>
</Stack>
</Box>
)}
</Stack>
);
}