brackt/app/routes/admin.sports.tsx
2026-05-19 23:02:58 -07:00

143 lines
4.9 KiB
TypeScript

import { Link } from "react-router";
import type { Route } from "./+types/admin.sports";
import { findAllSportsWithActiveSeasons } from "~/models/sport";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "~/components/ui/card";
import { Button } from "~/components/ui/button";
import { Plus, Trophy } from "lucide-react";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "~/components/ui/table";
import { Badge } from "~/components/ui/badge";
import { SportIcon } from "~/components/SportIcon";
export function meta(): Route.MetaDescriptors {
return [{ title: "Sports - Brackt Admin" }];
}
export async function loader() {
const sports = await findAllSportsWithActiveSeasons();
return { sports };
}
export default function AdminSports({ loaderData }: Route.ComponentProps) {
const { sports } = loaderData;
return (
<div className="p-8">
<div className="flex items-center justify-between mb-6">
<div>
<h1 className="text-3xl font-bold">Sports</h1>
<p className="text-muted-foreground mt-1">
Manage all sports in the system
</p>
</div>
<Button asChild>
<Link to="/admin/sports/new">
<Plus className="mr-2 h-4 w-4" />
Add Sport
</Link>
</Button>
</div>
<Card>
<CardHeader>
<CardTitle>All Sports</CardTitle>
<CardDescription>
{sports.length} {sports.length === 1 ? "sport" : "sports"} total
</CardDescription>
</CardHeader>
<CardContent>
{sports.length === 0 ? (
<div className="text-center py-12">
<Trophy className="mx-auto h-12 w-12 text-muted-foreground" />
<h3 className="mt-4 text-lg font-semibold">No sports yet</h3>
<p className="text-muted-foreground mt-2">
Get started by creating your first sport
</p>
<Button className="mt-4" asChild>
<Link to="/admin/sports/new">
<Plus className="mr-2 h-4 w-4" />
Add Sport
</Link>
</Button>
</div>
) : (
<Table>
<TableHeader>
<TableRow>
<TableHead>Name</TableHead>
<TableHead>Type</TableHead>
<TableHead>Slug</TableHead>
<TableHead>Public Page</TableHead>
<TableHead>Current Seasons</TableHead>
<TableHead className="text-right">Actions</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{sports.map((sport) => (
<TableRow key={sport.id}>
<TableCell className="font-medium">
<div className="flex items-center gap-3">
<SportIcon sportName={sport.name} iconUrl={sport.iconUrl} size="sm" />
<span>{sport.name}</span>
</div>
</TableCell>
<TableCell>
<Badge variant={sport.type === "team" ? "default" : "secondary"}>
{sport.type}
</Badge>
</TableCell>
<TableCell className="text-muted-foreground">
{sport.slug}
</TableCell>
<TableCell>
<Badge variant={sport.excludeFromHomepage ? "secondary" : "default"}>
{sport.excludeFromHomepage ? "Hidden" : "Shown"}
</Badge>
</TableCell>
<TableCell>
{sport.activeSeasons.length > 0 ? (
<div className="flex flex-col gap-1">
{sport.activeSeasons.map((season) => (
<Link
key={season.id}
to={`/admin/sports-seasons/${season.id}`}
className="text-sm text-primary hover:underline"
>
{season.name} ({season.year})
</Link>
))}
</div>
) : (
<span className="text-sm text-muted-foreground">
No current seasons
</span>
)}
</TableCell>
<TableCell className="text-right">
<Button variant="ghost" size="sm" asChild>
<Link to={`/admin/sports/${sport.id}`}>Edit</Link>
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)}
</CardContent>
</Card>
</div>
);
}