160 lines
4.8 KiB
TypeScript
160 lines
4.8 KiB
TypeScript
'use client';
|
|
|
|
import { RaceFilterModal } from '@/components/races/RaceFilterModal';
|
|
import { RacePageHeader } from '@/components/races/RacePageHeader';
|
|
import { RaceScheduleTable } from '@/components/races/RaceScheduleTable';
|
|
import type { SessionStatus } from '@/components/races/SessionStatusBadge';
|
|
import type { RacesViewData } from '@/lib/view-data/RacesViewData';
|
|
import { Container } from '@/ui/Container';
|
|
import { Pagination } from '@/ui/Pagination';
|
|
import { Skeleton } from '@/ui/Skeleton';
|
|
import { Text } from '@/ui/Text';
|
|
import { Box } from '@/ui/primitives/Box';
|
|
import { Stack } from '@/ui/primitives/Stack';
|
|
|
|
export type StatusFilter = 'scheduled' | 'running' | 'completed' | 'cancelled' | 'all';
|
|
|
|
interface RacesAllTemplateProps {
|
|
viewData: RacesViewData;
|
|
races: RacesViewData['races'];
|
|
totalFilteredCount: number;
|
|
isLoading: boolean;
|
|
// Pagination
|
|
currentPage: number;
|
|
totalPages: number;
|
|
itemsPerPage: number;
|
|
onPageChange: (page: number) => void;
|
|
// Filters
|
|
statusFilter: StatusFilter;
|
|
setStatusFilter: (filter: StatusFilter) => void;
|
|
leagueFilter: string;
|
|
setLeagueFilter: (filter: string) => void;
|
|
searchQuery: string;
|
|
setSearchQuery: (query: string) => void;
|
|
// UI State
|
|
showFilters: boolean;
|
|
setShowFilters: (show: boolean) => void;
|
|
showFilterModal: boolean;
|
|
setShowFilterModal: (show: boolean) => void;
|
|
// Actions
|
|
onRaceClick: (raceId: string) => void;
|
|
onLeagueClick: (leagueId: string) => void;
|
|
}
|
|
|
|
export function RacesAllTemplate({
|
|
viewData,
|
|
races,
|
|
totalFilteredCount,
|
|
isLoading,
|
|
currentPage,
|
|
totalPages,
|
|
itemsPerPage,
|
|
onPageChange,
|
|
statusFilter,
|
|
setStatusFilter,
|
|
leagueFilter,
|
|
setLeagueFilter,
|
|
searchQuery,
|
|
setSearchQuery,
|
|
showFilterModal,
|
|
setShowFilterModal,
|
|
onRaceClick,
|
|
}: RacesAllTemplateProps) {
|
|
if (isLoading) {
|
|
return (
|
|
<Container size="lg" py={8}>
|
|
<Stack gap={6}>
|
|
<Skeleton width="100%" height="12rem" />
|
|
<Stack gap={4}>
|
|
{[1, 2, 3, 4, 5].map(i => (
|
|
<Skeleton key={i} width="100%" height="4rem" />
|
|
))}
|
|
</Stack>
|
|
</Stack>
|
|
</Container>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<Box as="main" minHeight="screen" bg="bg-base-black" py={8}>
|
|
<Container size="lg">
|
|
<Stack gap={8}>
|
|
<RacePageHeader
|
|
totalCount={viewData.totalCount}
|
|
scheduledCount={viewData.scheduledCount}
|
|
runningCount={viewData.runningCount}
|
|
completedCount={viewData.completedCount}
|
|
/>
|
|
|
|
<Box display="flex" justifyContent="between" alignItems="center">
|
|
<Text size="sm" color="text-gray-400">
|
|
Showing <Text as="span" color="text-white" weight="bold">{totalFilteredCount}</Text> races
|
|
</Text>
|
|
<Box
|
|
as="button"
|
|
onClick={() => setShowFilterModal(true)}
|
|
px={4}
|
|
py={2}
|
|
bg="bg-surface-charcoal"
|
|
border
|
|
borderColor="border-outline-steel"
|
|
fontSize="10px"
|
|
weight="bold"
|
|
uppercase
|
|
letterSpacing="wider"
|
|
hoverBorderColor="border-primary-accent"
|
|
transition
|
|
>
|
|
Filters
|
|
</Box>
|
|
</Box>
|
|
|
|
<Box as="section" bg="bg-surface-charcoal" border borderColor="border-outline-steel" overflow="hidden">
|
|
{races.length === 0 ? (
|
|
<Box p={12} textAlign="center">
|
|
<Text color="text-gray-500">No races found matching your criteria.</Text>
|
|
</Box>
|
|
) : (
|
|
<RaceScheduleTable
|
|
races={races.map(race => ({
|
|
id: race.id,
|
|
track: race.track,
|
|
car: race.car,
|
|
leagueName: race.leagueName,
|
|
time: race.timeLabel,
|
|
status: race.status as SessionStatus
|
|
}))}
|
|
onRaceClick={onRaceClick}
|
|
/>
|
|
)}
|
|
</Box>
|
|
|
|
<Pagination
|
|
currentPage={currentPage}
|
|
totalPages={totalPages}
|
|
totalItems={totalFilteredCount}
|
|
itemsPerPage={itemsPerPage}
|
|
onPageChange={onPageChange}
|
|
/>
|
|
|
|
<RaceFilterModal
|
|
isOpen={showFilterModal}
|
|
onClose={() => setShowFilterModal(false)}
|
|
statusFilter={statusFilter}
|
|
setStatusFilter={setStatusFilter}
|
|
leagueFilter={leagueFilter}
|
|
setLeagueFilter={setLeagueFilter}
|
|
timeFilter="all"
|
|
setTimeFilter={() => {}}
|
|
searchQuery={searchQuery}
|
|
setSearchQuery={setSearchQuery}
|
|
leagues={viewData.leagues}
|
|
showSearch={true}
|
|
showTimeFilter={false}
|
|
/>
|
|
</Stack>
|
|
</Container>
|
|
</Box>
|
|
);
|
|
}
|