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
115 lines
3.3 KiB
TypeScript
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>
|
|
);
|
|
}
|