website refactor

This commit is contained in:
2026-01-19 18:01:30 +01:00
parent 6154d54435
commit 61b5cf3b64
120 changed files with 2226 additions and 2021 deletions

View File

@@ -1,25 +1,18 @@
'use client';
import { DashboardControlBar } from '@/components/dashboard/DashboardControlBar';
import { DashboardKpiRow } from '@/components/dashboard/DashboardKpiRow';
import { DashboardRail } from '@/components/dashboard/DashboardRail';
import { DashboardShell } from '@/components/dashboard/DashboardShell';
import { RecentActivityTable, type ActivityItem } from '@/components/dashboard/RecentActivityTable';
import { TelemetryPanel } from '@/components/dashboard/TelemetryPanel';
import { routes } from '@/lib/routing/RouteConfig';
import type { DashboardViewData } from '@/lib/view-data/DashboardViewData';
import { Avatar } from '@/ui/Avatar';
import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button';
import { IconButton } from '@/ui/IconButton';
import { Grid } from '@/ui/Grid';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Bell, Calendar, LayoutDashboard, Search, Settings, Trophy, Users } from 'lucide-react';
import { useRouter } from 'next/navigation';
interface DashboardTemplateProps {
viewData: DashboardViewData;
onNavigateToRaces: () => void;
}
/**
@@ -29,8 +22,10 @@ interface DashboardTemplateProps {
* Composes semantic dashboard components into a high-density data environment.
* Complies with architectural constraints by using UI primitives.
*/
export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
const router = useRouter();
export function DashboardTemplate({
viewData,
onNavigateToRaces,
}: DashboardTemplateProps) {
const {
currentDriver,
nextRace,
@@ -43,11 +38,11 @@ export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
} = viewData;
const kpiItems = [
{ label: 'Rating', value: currentDriver.rating, color: 'var(--color-telemetry)' },
{ label: 'Rank', value: `#${currentDriver.rank}`, color: 'var(--color-warning)' },
{ label: 'Rating', value: currentDriver.rating, intent: 'primary' as const },
{ label: 'Rank', value: `#${currentDriver.rank}`, intent: 'warning' as const },
{ label: 'Starts', value: currentDriver.totalRaces },
{ label: 'Wins', value: currentDriver.wins, color: 'var(--color-success)' },
{ label: 'Podiums', value: currentDriver.podiums, color: 'var(--color-warning)' },
{ label: 'Wins', value: currentDriver.wins, intent: 'success' as const },
{ label: 'Podiums', value: currentDriver.podiums, intent: 'warning' as const },
{ label: 'Leagues', value: activeLeaguesCount },
];
@@ -59,68 +54,8 @@ export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
status: item.type === 'race_result' ? 'success' : 'info'
}));
const railContent = (
<DashboardRail>
<Stack direction="col" align="center" gap={6} fullWidth>
<Box h="8" w="8" rounded="sm" bg="primary-accent" display="flex" alignItems="center" justifyContent="center">
<Text size="xs" weight="bold">GP</Text>
</Box>
<IconButton
icon={LayoutDashboard}
onClick={() => router.push(routes.protected.dashboard)}
variant="ghost"
color="primary-accent"
/>
<IconButton
icon={Trophy}
onClick={() => router.push(routes.public.leagues)}
variant="ghost"
color="var(--color-text-low)"
/>
<IconButton
icon={Calendar}
onClick={() => router.push(routes.public.races)}
variant="ghost"
color="var(--color-text-low)"
/>
<IconButton
icon={Users}
onClick={() => router.push(routes.public.teams)}
variant="ghost"
color="var(--color-text-low)"
/>
</Stack>
<Box mt="auto" display="flex" flexDirection="col" alignItems="center" gap={6} pb={4}>
<IconButton
icon={Settings}
onClick={() => router.push(routes.protected.profile)}
variant="ghost"
color="var(--color-text-low)"
/>
</Box>
</DashboardRail>
);
const controlBarActions = (
<Stack direction="row" align="center" gap={4}>
<IconButton icon={Search} variant="ghost" color="var(--color-text-low)" />
<Box position="relative">
<IconButton icon={Bell} variant="ghost" color="var(--color-text-low)" />
<Box position="absolute" top="0" right="0" h="1.5" w="1.5" rounded="full" bg="critical-red" />
</Box>
<Avatar
src={currentDriver.avatarUrl}
alt={currentDriver.name}
size={32}
/>
</Stack>
);
return (
<DashboardShell
rail={railContent}
controlBar={<DashboardControlBar title="Telemetry Workspace" actions={controlBarActions} />}
>
<Stack gap={6}>
{/* KPI Overview */}
<DashboardKpiRow items={kpiItems} />
@@ -132,14 +67,14 @@ export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
<TelemetryPanel title="Active Session">
<Box display="flex" alignItems="center" justifyContent="between">
<Box>
<Text size="xs" color="var(--color-text-low)" mb={1} block>Next Event</Text>
<Text size="xs" color="text-gray-500" mb={1} block>Next Event</Text>
<Text size="lg" weight="bold" block>{nextRace.track}</Text>
<Text size="xs" color="var(--color-telemetry)" font="mono" block>{nextRace.car}</Text>
<Text size="xs" color="primary-accent" font="mono" block>{nextRace.car}</Text>
</Box>
<Box textAlign="right">
<Text size="xs" color="var(--color-text-low)" mb={1} block>Starts In</Text>
<Text size="xl" font="mono" weight="bold" color="var(--color-warning)" block>{nextRace.timeUntil}</Text>
<Text size="xs" color="var(--color-text-low)" block>{nextRace.formattedDate} @ {nextRace.formattedTime}</Text>
<Text size="xs" color="text-gray-500" mb={1} block>Starts In</Text>
<Text size="xl" font="mono" weight="bold" color="warning-amber" block>{nextRace.timeUntil}</Text>
<Text size="xs" color="text-gray-500" block>{nextRace.formattedDate} @ {nextRace.formattedTime}</Text>
</Box>
</Box>
</TelemetryPanel>
@@ -150,7 +85,7 @@ export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
<RecentActivityTable items={activityItems} />
) : (
<Box py={8} textAlign="center">
<Text italic color="var(--color-text-low)">No recent activity recorded.</Text>
<Text italic color="text-gray-500">No recent activity recorded.</Text>
</Box>
)}
</TelemetryPanel>
@@ -164,18 +99,18 @@ export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
{hasLeagueStandings ? (
<Stack direction="col" gap={3}>
{leagueStandings.map((standing) => (
<Box key={standing.leagueId} display="flex" alignItems="center" justifyContent="between" borderBottom borderColor="rgba(35, 39, 43, 0.3)" pb={2}>
<Box key={standing.leagueId} display="flex" alignItems="center" justifyContent="between" borderBottom borderColor="rgba(255, 255, 255, 0.1)" pb={2}>
<Box>
<Text size="xs" weight="bold" truncate block maxWidth="180px">{standing.leagueName}</Text>
<Text size="xs" color="var(--color-text-low)" block>Pos: {standing.position} / {standing.totalDrivers}</Text>
<Text size="xs" color="text-gray-500" block>Pos: {standing.position} / {standing.totalDrivers}</Text>
</Box>
<Text size="sm" font="mono" weight="bold" color="var(--color-telemetry)">{standing.points} PTS</Text>
<Text size="sm" font="mono" weight="bold" color="primary-accent">{standing.points} PTS</Text>
</Box>
))}
</Stack>
) : (
<Box py={4} textAlign="center">
<Text italic color="var(--color-text-low)">No active championships.</Text>
<Text italic color="text-gray-500">No active championships.</Text>
</Box>
)}
</TelemetryPanel>
@@ -183,21 +118,21 @@ export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
<TelemetryPanel title="Upcoming Schedule">
<Stack direction="col" gap={4}>
{upcomingRaces.slice(0, 3).map((race) => (
<Box key={race.id} group cursor="pointer">
<Box key={race.id} cursor="pointer">
<Box display="flex" justifyContent="between" alignItems="start" mb={1}>
<Text size="xs" weight="bold" groupHoverTextColor="var(--color-primary)" transition>{race.track}</Text>
<Text size="xs" font="mono" color="var(--color-text-low)">{race.timeUntil}</Text>
<Text size="xs" weight="bold">{race.track}</Text>
<Text size="xs" font="mono" color="text-gray-500">{race.timeUntil}</Text>
</Box>
<Box display="flex" justifyContent="between">
<Text size="xs" color="var(--color-text-low)">{race.car}</Text>
<Text size="xs" color="var(--color-text-low)">{race.formattedDate}</Text>
<Text size="xs" color="text-gray-500">{race.car}</Text>
<Text size="xs" color="text-gray-500">{race.formattedDate}</Text>
</Box>
</Box>
))}
<Button
variant="secondary"
fullWidth
onClick={() => router.push(routes.public.races)}
onClick={onNavigateToRaces}
>
<Text size="xs" weight="bold" uppercase letterSpacing="widest">View Full Schedule</Text>
</Button>
@@ -206,6 +141,6 @@ export function DashboardTemplate({ viewData }: DashboardTemplateProps) {
</Stack>
</Box>
</Grid>
</DashboardShell>
</Stack>
);
}