website refactor
This commit is contained in:
@@ -11,24 +11,21 @@ import { Icon } from '@/ui/Icon';
|
||||
import { Group } from '@/ui/Group';
|
||||
import { Calendar, Plus } from 'lucide-react';
|
||||
import { DateDisplay } from '@/lib/display-objects/DateDisplay';
|
||||
import {
|
||||
registerForRaceAction,
|
||||
withdrawFromRaceAction,
|
||||
navigateToEditRaceAction,
|
||||
navigateToRescheduleRaceAction,
|
||||
navigateToRaceResultsAction
|
||||
} from '@/app/actions/leagueScheduleActions';
|
||||
|
||||
interface LeagueScheduleTemplateProps {
|
||||
viewData: LeagueScheduleViewData;
|
||||
onRegister: (raceId: string) => Promise<void>;
|
||||
onWithdraw: (raceId: string) => Promise<void>;
|
||||
onEdit: (raceId: string) => void;
|
||||
onReschedule: (raceId: string) => void;
|
||||
onResultsClick: (raceId: string) => void;
|
||||
onCreateRace?: () => void;
|
||||
}
|
||||
|
||||
export function LeagueScheduleTemplate({
|
||||
viewData,
|
||||
onRegister,
|
||||
onWithdraw,
|
||||
onEdit,
|
||||
onReschedule,
|
||||
onResultsClick,
|
||||
onCreateRace
|
||||
}: LeagueScheduleTemplateProps) {
|
||||
const [selectedRace, setSelectedRace] = useState<{
|
||||
@@ -85,15 +82,27 @@ export function LeagueScheduleTemplate({
|
||||
};
|
||||
|
||||
const handleRegister = async (raceId: string) => {
|
||||
await onRegister(raceId);
|
||||
await registerForRaceAction(raceId, viewData.leagueId, viewData.currentDriverId || '');
|
||||
setModalOpen(false);
|
||||
};
|
||||
|
||||
const handleWithdraw = async (raceId: string) => {
|
||||
await onWithdraw(raceId);
|
||||
await withdrawFromRaceAction(raceId, viewData.currentDriverId || '', viewData.leagueId);
|
||||
setModalOpen(false);
|
||||
};
|
||||
|
||||
const handleEdit = (raceId: string) => {
|
||||
navigateToEditRaceAction(raceId, viewData.leagueId);
|
||||
};
|
||||
|
||||
const handleReschedule = (raceId: string) => {
|
||||
navigateToRescheduleRaceAction(raceId, viewData.leagueId);
|
||||
};
|
||||
|
||||
const handleResultsClick = (raceId: string) => {
|
||||
navigateToRaceResultsAction(raceId, viewData.leagueId);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box display="flex" flexDirection="col" gap={8}>
|
||||
<Box as="header" display="flex" flexDirection="col" gap={2}>
|
||||
@@ -122,10 +131,10 @@ export function LeagueScheduleTemplate({
|
||||
isAdmin={viewData.isAdmin}
|
||||
onRegister={handleRegister}
|
||||
onWithdraw={handleWithdraw}
|
||||
onEdit={onEdit}
|
||||
onReschedule={onReschedule}
|
||||
onEdit={handleEdit}
|
||||
onReschedule={handleReschedule}
|
||||
onRaceDetail={handleRaceDetail}
|
||||
onResultsClick={onResultsClick}
|
||||
onResultsClick={handleResultsClick}
|
||||
/>
|
||||
|
||||
{selectedRace && (
|
||||
@@ -135,7 +144,7 @@ export function LeagueScheduleTemplate({
|
||||
onClose={handleCloseModal}
|
||||
onRegister={() => handleRegister(selectedRace.id)}
|
||||
onWithdraw={() => handleWithdraw(selectedRace.id)}
|
||||
onResultsClick={() => onResultsClick(selectedRace.id)}
|
||||
onResultsClick={() => handleResultsClick(selectedRace.id)}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
import { LeagueCard } from '@/components/leagues/LeagueCardWrapper';
|
||||
import type { LeaguesViewData } from '@/lib/view-data/LeaguesViewData';
|
||||
import { LeagueSummaryViewModel } from '@/lib/view-models/LeagueSummaryViewModel';
|
||||
import { LEAGUE_CATEGORIES, CategoryId, LeagueCategory } from '@/lib/config/leagueCategories';
|
||||
import { PageHeader } from '@/ui/PageHeader';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Input } from '@/ui/Input';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Group } from '@/ui/Group';
|
||||
@@ -22,39 +24,19 @@ import {
|
||||
Search,
|
||||
Trophy,
|
||||
Filter,
|
||||
Sparkles,
|
||||
type LucideIcon,
|
||||
} from 'lucide-react';
|
||||
import React from 'react';
|
||||
import { TemplateProps } from '@/lib/contracts/components/ComponentContracts';
|
||||
|
||||
export type CategoryId =
|
||||
| 'all'
|
||||
| 'driver'
|
||||
| 'team'
|
||||
| 'nations'
|
||||
| 'trophy'
|
||||
| 'new'
|
||||
| 'popular'
|
||||
| 'openSlots'
|
||||
| 'endurance'
|
||||
| 'sprint';
|
||||
|
||||
export interface Category {
|
||||
id: CategoryId;
|
||||
label: string;
|
||||
icon: LucideIcon;
|
||||
description: string;
|
||||
filter: (league: LeaguesViewData['leagues'][number]) => boolean;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
interface LeaguesTemplateProps extends TemplateProps<LeaguesViewData> {
|
||||
searchQuery: string;
|
||||
onSearchChange: (query: string) => void;
|
||||
activeCategory: CategoryId;
|
||||
onCategoryChange: (id: CategoryId) => void;
|
||||
filteredLeagues: LeaguesViewData['leagues'];
|
||||
categories: Category[];
|
||||
categories: LeagueCategory[];
|
||||
onCreateLeague: () => void;
|
||||
onLeagueClick: (id: string) => void;
|
||||
onClearFilters: () => void;
|
||||
@@ -114,6 +96,30 @@ export function LeaguesTemplate({
|
||||
/>
|
||||
</FeatureGrid>
|
||||
|
||||
{/* Featured Leagues Section */}
|
||||
{viewData.leagues.filter(l => (l.usedDriverSlots ?? 0) > 20).length > 0 && (
|
||||
<Stack gap={4}>
|
||||
<Group align="center" gap={2}>
|
||||
<Icon icon={Sparkles} size={5} intent="warning" />
|
||||
<Heading level={3} weight="bold" uppercase letterSpacing="wider">Featured Leagues</Heading>
|
||||
</Group>
|
||||
<Surface variant="dark" padding={6} rounded="2xl" border borderColor="var(--ui-color-intent-warning-muted)">
|
||||
<FeatureGrid columns={{ base: 1, md: 2 }} gap={6}>
|
||||
{viewData.leagues
|
||||
.filter(l => (l.usedDriverSlots ?? 0) > 20)
|
||||
.slice(0, 2)
|
||||
.map((league) => (
|
||||
<LeagueCard
|
||||
key={`featured-${league.id}`}
|
||||
league={league as unknown as LeagueSummaryViewModel}
|
||||
onClick={() => onLeagueClick(league.id)}
|
||||
/>
|
||||
))}
|
||||
</FeatureGrid>
|
||||
</Surface>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{/* Control Bar */}
|
||||
<ControlBar
|
||||
leftContent={
|
||||
|
||||
Reference in New Issue
Block a user