brackt/app/components/league/settings/LeagueBasicsSection.tsx

124 lines
4.3 KiB
TypeScript
Raw Normal View History

import { Trophy } from "lucide-react";
import { Input } from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { Button } from "~/components/ui/button";
import { StepperInput } from "~/components/league/StepperInput";
import { SettingsSection, SettingsStatusPill } from "./SettingsSection";
export function LeagueBasicsSection({
active,
season,
leagueName,
onLeagueNameChange,
isPublicDraftBoard,
onIsPublicDraftBoardChange,
teamCountValue,
onTeamCountValueChange,
teamsWithOwners,
canEditTeamCount,
minTeamCount,
inviteUrl,
copied,
onCopyInviteLink,
}: {
active: boolean;
season: { inviteCode: string | null } | null;
leagueName: string;
onLeagueNameChange: (v: string) => void;
isPublicDraftBoard: boolean;
onIsPublicDraftBoardChange: (v: boolean) => void;
teamCountValue: number;
onTeamCountValueChange: (v: number) => void;
teamsWithOwners: number;
canEditTeamCount: boolean;
minTeamCount: number;
inviteUrl: string;
copied: boolean;
onCopyInviteLink: () => void;
}) {
return (
<SettingsSection
id="league-basics"
icon={Trophy}
title="League Basics"
description="High-level league identity and public visibility controls."
status={<SettingsStatusPill tone="success">Always editable</SettingsStatusPill>}
className={active ? undefined : "hidden"}
>
<input type="hidden" name="teamCount" value={teamCountValue} />
<div className="space-y-5">
<div className="space-y-2">
<Label htmlFor="name">League Name</Label>
<Input
id="name"
name="name"
type="text"
value={leagueName}
onChange={(e) => onLeagueNameChange(e.target.value)}
placeholder="Enter league name"
required
minLength={3}
maxLength={50}
/>
</div>
<label
htmlFor="isPublicDraftBoard"
className="flex cursor-pointer items-start gap-3 rounded-lg border p-4"
>
<input
type="checkbox"
id="isPublicDraftBoard"
name="isPublicDraftBoard"
checked={isPublicDraftBoard}
onChange={(e) => onIsPublicDraftBoardChange(e.target.checked)}
className="mt-1 h-4 w-4 rounded border-border"
/>
<span>
<span className="block font-medium">Public draft board</span>
<span className="text-sm text-muted-foreground">Allow anyone with the link to view the board without logging in.</span>
</span>
</label>
<div className="rounded-lg border p-4">
<div className="mb-3">
<Label>Number of Teams</Label>
<p className="text-sm text-muted-foreground">Minimum {minTeamCount} based on teams with owners.</p>
</div>
<StepperInput
value={teamCountValue}
min={canEditTeamCount ? minTeamCount : teamCountValue}
max={canEditTeamCount ? 16 : teamCountValue}
onChange={onTeamCountValueChange}
decrementLabel="Decrease team count"
incrementLabel="Increase team count"
/>
{!canEditTeamCount && (
<p className="mt-3 text-sm text-muted-foreground">Locked after the draft starts.</p>
)}
</div>
{season?.inviteCode && (
<div className="rounded-lg border p-4">
<div className="mb-3">
<h3 className="font-medium">Invite Link</h3>
<p className="text-sm text-muted-foreground">
{/* eslint-disable-next-line no-nested-ternary */}
{(() => {
const open = teamCountValue - teamsWithOwners;
return open > 0
? `${open} open spot${open === 1 ? "" : "s"} available.`
: "No open team spots right now.";
})()}
</p>
</div>
<div className="flex flex-col gap-2 sm:flex-row">
<Input readOnly value={inviteUrl} onClick={(e) => e.currentTarget.select()} className="text-sm" />
<Button type="button" variant={copied ? "default" : "outline"} onClick={onCopyInviteLink}>
{copied ? "Copied" : "Copy"}
</Button>
</div>
</div>
)}
</div>
</SettingsSection>
);
}