import { Form, Link } from "react-router";
import { useState } from "react";
import type { Route } from "./+types/admin.sports-seasons.$id.events";
import { loader, action } from "./admin.sports-seasons.$id.events.server";
import { localDateTimeToUtcIso } from "~/lib/date-utils";
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 { Textarea } from "~/components/ui/textarea";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "~/components/ui/alert-dialog";
import { Calendar, Trophy, ArrowLeft, Trash2, ListPlus } from "lucide-react";
import { format, parseISO } from "date-fns";
import { QualifyingPointsStandings } from "~/components/scoring/QualifyingPointsStandings";
import { getEventTypeLabel } from "~/models/scoring-event";
export function meta({ data }: Route.MetaArgs): Route.MetaDescriptors {
return [{ title: `Events — ${data?.sportsSeason?.name ?? "Sports Season"} - Brackt Admin` }];
}
export { loader, action };
function getStatusBadge(isComplete: boolean, eventType: string, eventDate?: string | null, eventStartsAt?: Date | string | null) {
if (isComplete) {
return (
Completed
);
}
if (eventType === "schedule_event") {
const isPast = eventStartsAt
? new Date(eventStartsAt) < new Date()
: eventDate !== null && eventDate !== undefined && eventDate < new Date().toISOString().split("T")[0];
return isPast ? (
Results Pending
) : (
Upcoming
);
}
return In Progress;
}
export default function SportsSeasonEvents({
loaderData,
actionData,
}: Route.ComponentProps) {
const { sportsSeason, events, qpStandings, scoringRules } = loaderData;
const [createEventStartsAt, setCreateEventStartsAt] = useState("");
const defaultEventType =
sportsSeason.scoringPattern === "qualifying_points"
? "major_tournament"
: sportsSeason.scoringPattern === "season_standings"
? "schedule_event"
: "playoff_game";
return (
Scoring Events
{sportsSeason.sport.name} - {sportsSeason.name}
{sportsSeason.scoringPattern === "qualifying_points" && (
Qualifying Points Mode
)}
{/* Success/Error Messages */}
{actionData?.error && (
{actionData.error}
)}
{actionData?.success && (
{actionData.success}
)}
{/* QP Standings for qualifying points sports */}
{sportsSeason.scoringPattern === "qualifying_points" && qpStandings && (
= sportsSeason.totalMajors &&
!sportsSeason.qualifyingPointsFinalized
}
/>
)}
{/* Create New Event Card */}
Create New Event
Add a new scoring event (bracket, tournament, standings, etc.)
{/* Bulk Create Card */}
Bulk Import Events
Paste a schedule — one event per line. Format:{" "}
Event Name, YYYY-MM-DD[, HH:MM]
{" "}
(date and time are optional; time is UTC).
{/* Events List */}
Events
{events.length} {events.length === 1 ? "event" : "events"}
{events.length === 0 ? (
No events created yet. Create your first event above.
) : (
{events.map((event: { id: string; name: string; eventType: string; eventDate?: string | null; eventStartsAt?: Date | string | null; isComplete: boolean }) => (
{event.name}
{getStatusBadge(event.isComplete, event.eventType, event.eventDate, event.eventStartsAt)}
{getEventTypeLabel(event.eventType)}
{(event.eventDate || event.eventStartsAt) && (
{format(
event.eventStartsAt
? new Date(event.eventStartsAt)
: parseISO(event.eventDate ?? ""),
"MMM d, yyyy"
)}
{event.eventStartsAt && (
· {format(new Date(event.eventStartsAt), "h:mm a")}
)}
)}
Delete "{event.name}"?
This will also delete all results for this event. This action cannot be undone.
Cancel
))}
)}
);
}