Files
gridpilot.gg/apps/website/templates/RacesIndexTemplate.tsx
Marc Mintel 09632d004d
Some checks failed
CI / lint-typecheck (pull_request) Failing after 12s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
code quality
2026-01-26 22:16:33 +01:00

115 lines
3.3 KiB
TypeScript

import { NextUpRacePanel } from '@/components/races/NextUpRacePanel';
import { RacesCommandBar } from '@/components/races/RacesCommandBar';
import { RacesDayGroup } from '@/components/races/RacesDayGroup';
import { RacesEmptyState } from '@/components/races/RacesEmptyState';
import { RacesLiveRail } from '@/components/races/RacesLiveRail';
import { RaceFilterModal } from '@/components/races/RaceFilterModal';
import type { RacesViewData, RaceViewData } from '@/lib/view-data/RacesViewData';
import { PageHeader } from '@/ui/PageHeader';
import { Section } from '@/ui/Section';
import { Stack } from '@/ui/Stack';
import { Flag } from 'lucide-react';
export interface RacesIndexTemplateProps {
viewData: RacesViewData & {
nextUpRace?: RaceViewData;
};
// Filters
statusFilter: string;
setStatusFilter: (filter: string) => void;
leagueFilter: string;
setLeagueFilter: (filter: string) => void;
timeFilter: string;
setTimeFilter: (filter: string) => void;
// Actions
onRaceClick: (raceId: string) => void;
// UI State
showFilterModal: boolean;
setShowFilterModal: (show: boolean) => void;
}
export function RacesIndexTemplate({
viewData,
statusFilter,
setStatusFilter,
leagueFilter,
setLeagueFilter,
timeFilter,
setTimeFilter,
onRaceClick,
showFilterModal,
setShowFilterModal,
}: RacesIndexTemplateProps) {
const hasRaces = viewData.racesByDate.length > 0;
return (
<Section variant="default" padding="md">
<PageHeader
title="Races"
description="Live Sessions & Upcoming Events"
icon={Flag}
/>
<Stack gap={12}>
{/* 1. Status Rail: Live sessions first */}
<RacesLiveRail
liveRaces={viewData.liveRaces}
onRaceClick={onRaceClick}
/>
{/* 2. Command Bar: Fast filters */}
<RacesCommandBar
timeFilter={timeFilter}
setTimeFilter={setTimeFilter}
leagueFilter={leagueFilter}
setLeagueFilter={setLeagueFilter}
leagues={viewData.leagues}
onShowMoreFilters={() => setShowFilterModal(true)}
/>
{/* 3. Next Up: High signal panel */}
{timeFilter === 'upcoming' && viewData.nextUpRace && (
<NextUpRacePanel
race={viewData.nextUpRace}
onRaceClick={onRaceClick}
/>
)}
{/* 4. Browse by Day: Grouped schedule */}
{hasRaces ? (
<Stack gap={8}>
{viewData.racesByDate.map((group) => (
<RacesDayGroup
key={group.dateKey}
dateLabel={group.dateLabel}
races={group.races}
onRaceClick={onRaceClick}
/>
))}
</Stack>
) : (
<RacesEmptyState />
)}
</Stack>
<RaceFilterModal
isOpen={showFilterModal}
onClose={() => setShowFilterModal(false)}
statusFilter={statusFilter as any}
setStatusFilter={setStatusFilter}
leagueFilter={leagueFilter}
setLeagueFilter={setLeagueFilter}
timeFilter={timeFilter as any}
setTimeFilter={setTimeFilter}
searchQuery=""
setSearchQuery={() => {}}
leagues={viewData.leagues}
showSearch={true}
showTimeFilter={false}
/>
</Section>
);
}