brackt/app/routes/admin.sports-seasons.$id.events.tsx

212 lines
8 KiB
TypeScript
Raw Normal View History

import { Form, Link } from "react-router";
import type { Route } from "./+types/admin.sports-seasons.$id.events";
import { loader, action } from "./admin.sports-seasons.$id.events.server";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "~/components/ui/select";
import { Badge } from "~/components/ui/badge";
import { Calendar, Trophy, ArrowLeft, Trash2 } from "lucide-react";
import { format } from "date-fns";
export { loader, action };
export default function SportsSeasonEvents({
loaderData,
actionData,
}: Route.ComponentProps) {
const { sportsSeason, events } = loaderData;
const getEventTypeLabel = (type: string) => {
switch (type) {
case "playoff_game":
return "Playoff Game";
case "major_tournament":
return "Major Tournament";
case "race":
return "Race";
case "final_standings":
return "Final Standings";
default:
return type;
}
};
const getStatusBadge = (isComplete: boolean) => {
return isComplete ? (
<Badge variant="default" className="bg-green-500">
Completed
</Badge>
) : (
<Badge variant="secondary">In Progress</Badge>
);
};
return (
<div className="p-8">
<div className="max-w-4xl">
<div className="mb-6">
<Button variant="ghost" size="sm" asChild className="mb-2">
<Link to={`/admin/sports-seasons/${sportsSeason.id}`}>
<ArrowLeft className="mr-2 h-4 w-4" />
Back to Sports Season
</Link>
</Button>
<h1 className="text-3xl font-bold">Scoring Events</h1>
<p className="text-muted-foreground mt-1">
{sportsSeason.sport.name} - {sportsSeason.name}
</p>
</div>
<div className="space-y-6">
{/* Create New Event Card */}
<Card>
<CardHeader>
<CardTitle>Create New Event</CardTitle>
<CardDescription>
Add a new scoring event (game, tournament, race, etc.)
</CardDescription>
</CardHeader>
<CardContent>
<Form method="post" className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Event Name</Label>
<Input
id="name"
name="name"
type="text"
placeholder="e.g., Super Bowl, Round 1, Game 3"
required
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="eventType">Event Type</Label>
<Select name="eventType" defaultValue="playoff_game" required>
<SelectTrigger id="eventType">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="playoff_game">Playoff Game</SelectItem>
<SelectItem value="major_tournament">Major Tournament</SelectItem>
<SelectItem value="race">Race</SelectItem>
<SelectItem value="final_standings">Final Standings</SelectItem>
</SelectContent>
</Select>
</div>
<div className="space-y-2">
<Label htmlFor="playoffRound">Playoff Round (Optional)</Label>
<Input
id="playoffRound"
name="playoffRound"
type="text"
placeholder="e.g., Quarterfinals, Round 1"
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="eventDate">Event Date (Optional)</Label>
<Input id="eventDate" name="eventDate" type="date" />
</div>
{actionData?.error && (
<div className="bg-destructive/15 text-destructive px-4 py-3 rounded-md text-sm">
{actionData.error}
</div>
)}
<Button type="submit" className="w-full">
<Trophy className="mr-2 h-4 w-4" />
Create Event
</Button>
</Form>
</CardContent>
</Card>
{/* Events List */}
<Card>
<CardHeader>
<CardTitle>Events</CardTitle>
<CardDescription>
{events.length} {events.length === 1 ? "event" : "events"}
</CardDescription>
</CardHeader>
<CardContent>
{events.length === 0 ? (
<p className="text-sm text-muted-foreground">
No events created yet. Create your first event above.
</p>
) : (
<div className="space-y-3">
{events.map((event: { id: string; name: string; eventType: string; playoffRound?: string | null; eventDate?: string | null; isComplete: boolean }) => (
<Card key={event.id} className="hover:border-primary/50 transition-colors">
<CardContent className="pt-6">
<div className="flex items-start justify-between gap-4">
<Link
to={`/admin/sports-seasons/${sportsSeason.id}/events/${event.id}`}
className="flex-1 cursor-pointer"
>
<div className="flex items-center gap-2 mb-1">
<h3 className="font-semibold">{event.name}</h3>
{getStatusBadge(event.isComplete)}
</div>
<div className="flex items-center gap-4 text-sm text-muted-foreground">
<span>
{getEventTypeLabel(event.eventType)}
</span>
{event.playoffRound && <span>{event.playoffRound}</span>}
{event.eventDate && (
<span className="flex items-center gap-1">
<Calendar className="h-3 w-3" />
{format(new Date(event.eventDate), "MMM d, yyyy")}
</span>
)}
</div>
</Link>
<Form method="post" className="flex-shrink-0">
<input type="hidden" name="intent" value="delete-event" />
<input type="hidden" name="eventId" value={event.id} />
<Button
type="submit"
size="sm"
variant="ghost"
className="text-destructive hover:text-destructive"
onClick={(e) => {
if (!confirm(`Delete event "${event.name}"? This will also delete all results.`)) {
e.preventDefault();
}
}}
>
<Trash2 className="h-4 w-4" />
</Button>
</Form>
</div>
</CardContent>
</Card>
))}
</div>
)}
</CardContent>
</Card>
</div>
</div>
</div>
);
}