140 lines
4.6 KiB
TypeScript
140 lines
4.6 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
import {
|
|
Search,
|
|
Crown,
|
|
} from 'lucide-react';
|
|
import { Heading } from '@/ui/Heading';
|
|
import { Box } from '@/ui/Box';
|
|
import { Stack } from '@/ui/Stack';
|
|
import { Text } from '@/ui/Text';
|
|
import { Container } from '@/ui/Container';
|
|
import { Grid } from '@/ui/Grid';
|
|
import { GridItem } from '@/ui/GridItem';
|
|
import { Surface } from '@/ui/Surface';
|
|
import { Icon } from '@/ui/Icon';
|
|
import { FeaturedDriverCard } from '@/ui/FeaturedDriverCard';
|
|
import { SkillDistribution } from '@/ui/SkillDistribution';
|
|
import { CategoryDistribution } from '@/ui/CategoryDistribution';
|
|
import { LeaderboardPreview } from '@/ui/LeaderboardPreview';
|
|
import { RecentActivity } from '@/ui/RecentActivity';
|
|
import { PageHero } from '@/ui/PageHero';
|
|
import { Users, Trophy } from 'lucide-react';
|
|
import { DriversSearch } from '@/ui/DriversSearch';
|
|
import { EmptyState } from '@/ui/EmptyState';
|
|
import type { DriversViewData } from '@/lib/types/view-data/DriversViewData';
|
|
|
|
interface DriversTemplateProps {
|
|
viewData: DriversViewData | null;
|
|
searchQuery: string;
|
|
onSearchChange: (query: string) => void;
|
|
filteredDrivers: DriversViewData['drivers'];
|
|
onDriverClick: (id: string) => void;
|
|
onViewLeaderboard: () => void;
|
|
}
|
|
|
|
export function DriversTemplate({
|
|
viewData,
|
|
searchQuery,
|
|
onSearchChange,
|
|
filteredDrivers,
|
|
onDriverClick,
|
|
onViewLeaderboard
|
|
}: DriversTemplateProps) {
|
|
const drivers = viewData?.drivers || [];
|
|
const totalRaces = viewData?.totalRaces || 0;
|
|
const totalWins = viewData?.totalWins || 0;
|
|
const activeCount = viewData?.activeCount || 0;
|
|
|
|
// Featured drivers (top 4)
|
|
const featuredDrivers = filteredDrivers.slice(0, 4);
|
|
|
|
return (
|
|
<Container size="lg" py={8}>
|
|
<Stack gap={10}>
|
|
{/* Hero Section */}
|
|
<PageHero
|
|
title="Drivers"
|
|
description="Meet the racers who make every lap count. From rookies to champions, track their journey and see who's dominating the grid."
|
|
icon={Users}
|
|
stats={[
|
|
{ label: 'drivers', value: drivers.length, color: 'text-primary-blue' },
|
|
{ label: 'active', value: activeCount, color: 'text-performance-green', animate: true },
|
|
{ label: 'total wins', value: totalWins.toLocaleString(), color: 'text-warning-amber' },
|
|
{ label: 'races', value: totalRaces.toLocaleString(), color: 'text-neon-aqua' },
|
|
]}
|
|
actions={[
|
|
{
|
|
label: 'View Leaderboard',
|
|
onClick: onViewLeaderboard,
|
|
icon: Trophy,
|
|
description: 'See full driver rankings'
|
|
}
|
|
]}
|
|
/>
|
|
|
|
{/* Search */}
|
|
<DriversSearch query={searchQuery} onChange={onSearchChange} />
|
|
|
|
{/* Featured Drivers */}
|
|
{!searchQuery && (
|
|
<Box>
|
|
<Stack direction="row" align="center" gap={3} mb={4}>
|
|
<Surface variant="muted" rounded="xl" padding={2}>
|
|
<Icon icon={Crown} size={6} color="#f59e0b" />
|
|
</Surface>
|
|
<Box>
|
|
<Heading level={2}>Featured Drivers</Heading>
|
|
<Text size="xs" color="text-gray-500">Top performers on the grid</Text>
|
|
</Box>
|
|
</Stack>
|
|
|
|
<Grid cols={4} gap={4}>
|
|
{featuredDrivers.map((driver, index) => (
|
|
<GridItem key={driver.id} colSpan={12} mdSpan={6} lgSpan={3}>
|
|
<FeaturedDriverCard
|
|
driver={driver}
|
|
position={index + 1}
|
|
onClick={() => onDriverClick(driver.id)}
|
|
/>
|
|
</GridItem>
|
|
))}
|
|
</Grid>
|
|
</Box>
|
|
)}
|
|
|
|
{/* Active Drivers */}
|
|
{!searchQuery && <RecentActivity drivers={drivers} onDriverClick={onDriverClick} />}
|
|
|
|
{/* Skill Distribution */}
|
|
{!searchQuery && <SkillDistribution drivers={drivers} />}
|
|
|
|
{/* Category Distribution */}
|
|
{!searchQuery && <CategoryDistribution drivers={drivers} />}
|
|
|
|
{/* Leaderboard Preview */}
|
|
<LeaderboardPreview
|
|
drivers={filteredDrivers}
|
|
onDriverClick={onDriverClick}
|
|
onNavigate={() => onViewLeaderboard()}
|
|
/>
|
|
|
|
{/* Empty State */}
|
|
{filteredDrivers.length === 0 && (
|
|
<EmptyState
|
|
icon={Search}
|
|
title="No drivers found"
|
|
description={`No drivers found matching "${searchQuery}"`}
|
|
action={{
|
|
label: 'Clear search',
|
|
onClick: () => onSearchChange(''),
|
|
variant: 'secondary'
|
|
}}
|
|
/>
|
|
)}
|
|
</Stack>
|
|
</Container>
|
|
);
|
|
}
|