brackt/app/components/league/settings/SportsSection.tsx
Claude 9f2eb57e7a
Show season name instead of year/bracket format; add local timezone hint to draft time
Replace the raw year number and scoringType string in the league creation
sport picker, review step, and league settings sports section with the
human-readable season name (e.g. "2025 NBA Season"), matching how the
league homepage sports list already displays seasons.

Add a client-side local timezone label below the draft date & time fields
on both the league creation wizard and the league settings page, so users
know that draft times are in their local timezone.

https://claude.ai/code/session_01GtJowGruAc1A4jURkSDVjX
2026-05-15 22:00:30 +00:00

91 lines
3.2 KiB
TypeScript

import { ClipboardList } from "lucide-react";
import { Label } from "~/components/ui/label";
import { Button } from "~/components/ui/button";
import { cn } from "~/lib/utils";
import { SportIcon } from "~/components/league/SportIcon";
import { SettingsSection, SettingsStatusPill } from "./SettingsSection";
type SportsSeason = {
id: string;
name: string;
year: number;
scoringType: string;
sport: { id: string; name: string; slug: string; type: string; iconUrl: string | null };
};
const BRACKT_SLUG = "brackt";
export function SportsSection({
active,
canEditSports,
selectedSports,
displaySportsSeasons,
onSportToggle,
onClearAll,
}: {
active: boolean;
canEditSports: boolean;
selectedSports: Set<string>;
displaySportsSeasons: SportsSeason[];
onSportToggle: (id: string) => void;
onClearAll: () => void;
}) {
return (
<SettingsSection
id="sports"
icon={ClipboardList}
title="Sports"
description="Manage draftable sports seasons for this league. Sports lock when the draft starts."
status={<SettingsStatusPill tone={canEditSports ? "success" : "locked"}>{canEditSports ? "Editable" : "Locked"}</SettingsStatusPill>}
className={active ? undefined : "hidden"}
>
<div className="space-y-4">
<div className="flex items-center justify-between gap-3">
<Label>{selectedSports.size} selected</Label>
{canEditSports && selectedSports.size > 0 && (
<Button type="button" variant="ghost" size="sm" onClick={onClearAll}>
Clear all
</Button>
)}
</div>
<div className="space-y-2">
{displaySportsSeasons.length > 0 ? (
displaySportsSeasons.map((ss) => {
const selected = selectedSports.has(ss.id);
return (
<label
key={ss.id}
htmlFor={`sport-${ss.id}`}
className={cn(
"mb-2 flex cursor-pointer items-center gap-3 rounded-md border p-3 text-sm transition-colors last:mb-0",
selected ? "border-primary bg-primary/10 text-primary" : "border-border bg-background hover:border-primary/50",
!canEditSports && "cursor-not-allowed opacity-65"
)}
>
<input
id={`sport-${ss.id}`}
type="checkbox"
name="sportsSeasons"
value={ss.id}
checked={selected}
onChange={() => onSportToggle(ss.id)}
disabled={!canEditSports}
className="sr-only"
/>
<SportIcon sport={ss.sport} />
<span className="min-w-0 flex-1 overflow-hidden">
<span className="block truncate font-medium">
{ss.sport.slug === BRACKT_SLUG ? "Brackt" : ss.name}
</span>
</span>
</label>
);
})
) : (
<p className="p-3 text-sm text-muted-foreground">No sports seasons available.</p>
)}
</div>
</div>
</SettingsSection>
);
}