New design (#309)
* Redesign home page with new layout and component system
- Two-column layout (My Leagues 2/3, Upcoming Events 1/3) with mobile stack
- LeagueRow: square avatar, gradient draft highlight, rank/points display, progress bar
- MyLeaguesCard, CreateLeagueCard with shared SectionCardHeader
- UpcomingEventsCard: vertical timeline with grouped multi-league events
- Shared gradient system: BracktGradients SVG defs, GradientIcon wrapper, brand.ts constants
- Button default variant updated to green→cyan gradient
- Navbar: plain nav links with gradient hover, support/admin icon buttons
- Accessibility fixes: semantic h2 headings, aria-label on LeagueAvatar and nav elements
- Storybook stories for all new components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Responsive league row layout and mobile polish
- League rows stack avatar+name on top, stats full-width below on mobile
- Stats spread to right side on sm+ screens with border separator on mobile
- Tighter padding on mobile (px-3/py-3), full padding on sm+
- Card headers and content use px-3 sm:px-6 to reduce mobile gutters
- Two-column home layout deferred to lg breakpoint (tablet gets stacked)
- Active leagues sorted by completion percentage descending
- Default rank 1 / 0 points for active leagues with no scoring events yet
- Fix ordinal bug for 11th/12th/13th; add aria-labels to rank change indicators
- Remove dead StatDivider className prop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Improve claude file.
* Add StandingsPreview card component with podium row styling
- New StandingsPreview component with gold/silver/bronze row tints for
top 3, team avatar, and LeagueRow-style stat columns (Ranking + Points)
with rank and 7-day point change indicators
- Fix GradientIcon in Storybook by adding BracktGradients decorator to
preview.tsx (renamed from .ts to support JSX)
- Fix degenerate SVG gradient on horizontal strokes by switching
BracktGradients to gradientUnits="userSpaceOnUse" with Lucide-space
coordinates (0→24)
- Revert erroneous fill: url(#gradient) from GradientIcon; stroke-only
fix was sufficient once gradientUnits was corrected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update components on league homepage.
* Finish up league page styling.
* Work on standings page.
* Add story for RecentScoresCard
* Update Point Progression Chart.
* Sort point progression legend by ranking and add team links to standings rows
* Fix standings discrepancy on change.
* Create draft cell component.
* Update draft board page
* Draft room improvements.
* Update some draft room styling.
* Fix context menu missing.
* Move tab navigation and autodraft to header row, narrow sidebar
* Virtualize available participants list, memoize draft room props
Adds @tanstack/react-virtual to replace separate mobile/desktop lists
with a single unified virtual scroll loop. Also memoizes miniDraftGrid
and availableParticipantsSectionProps, and switches pick lookup from
Array.find to a Map for O(1) access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update draft room UI.
* More draft room fixes.
* Draft room tweaks.
* Fix Rosters page.
* Queue Section fixes.
* Mobile Draft fixes.
* Fix draft board page.
* Create bracket look.
* Bracket work.
* Finish bracket page.
* Homepage initial styling
* homepage copy
* Add privacy policy. Fixes #88.
* how to play copy
* rules copy
* Fix brackets on homepage.
* Add footer to website.
* Glow on dots.
* Landing page copy.
* Fix sidebar.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:14:55 -07:00
|
|
|
|
import { formatDistanceToNow } from "date-fns";
|
|
|
|
|
|
import { Link } from "react-router";
|
|
|
|
|
|
import { Button } from "~/components/ui/button";
|
|
|
|
|
|
import { LeagueAvatar } from "./LeagueAvatar";
|
2026-04-24 11:11:20 -07:00
|
|
|
|
import { StatColumn, StatDivider, RankingDisplay } from "./StatHelpers";
|
New design (#309)
* Redesign home page with new layout and component system
- Two-column layout (My Leagues 2/3, Upcoming Events 1/3) with mobile stack
- LeagueRow: square avatar, gradient draft highlight, rank/points display, progress bar
- MyLeaguesCard, CreateLeagueCard with shared SectionCardHeader
- UpcomingEventsCard: vertical timeline with grouped multi-league events
- Shared gradient system: BracktGradients SVG defs, GradientIcon wrapper, brand.ts constants
- Button default variant updated to green→cyan gradient
- Navbar: plain nav links with gradient hover, support/admin icon buttons
- Accessibility fixes: semantic h2 headings, aria-label on LeagueAvatar and nav elements
- Storybook stories for all new components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Responsive league row layout and mobile polish
- League rows stack avatar+name on top, stats full-width below on mobile
- Stats spread to right side on sm+ screens with border separator on mobile
- Tighter padding on mobile (px-3/py-3), full padding on sm+
- Card headers and content use px-3 sm:px-6 to reduce mobile gutters
- Two-column home layout deferred to lg breakpoint (tablet gets stacked)
- Active leagues sorted by completion percentage descending
- Default rank 1 / 0 points for active leagues with no scoring events yet
- Fix ordinal bug for 11th/12th/13th; add aria-labels to rank change indicators
- Remove dead StatDivider className prop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Improve claude file.
* Add StandingsPreview card component with podium row styling
- New StandingsPreview component with gold/silver/bronze row tints for
top 3, team avatar, and LeagueRow-style stat columns (Ranking + Points)
with rank and 7-day point change indicators
- Fix GradientIcon in Storybook by adding BracktGradients decorator to
preview.tsx (renamed from .ts to support JSX)
- Fix degenerate SVG gradient on horizontal strokes by switching
BracktGradients to gradientUnits="userSpaceOnUse" with Lucide-space
coordinates (0→24)
- Revert erroneous fill: url(#gradient) from GradientIcon; stroke-only
fix was sufficient once gradientUnits was corrected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update components on league homepage.
* Finish up league page styling.
* Work on standings page.
* Add story for RecentScoresCard
* Update Point Progression Chart.
* Sort point progression legend by ranking and add team links to standings rows
* Fix standings discrepancy on change.
* Create draft cell component.
* Update draft board page
* Draft room improvements.
* Update some draft room styling.
* Fix context menu missing.
* Move tab navigation and autodraft to header row, narrow sidebar
* Virtualize available participants list, memoize draft room props
Adds @tanstack/react-virtual to replace separate mobile/desktop lists
with a single unified virtual scroll loop. Also memoizes miniDraftGrid
and availableParticipantsSectionProps, and switches pick lookup from
Array.find to a Map for O(1) access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update draft room UI.
* More draft room fixes.
* Draft room tweaks.
* Fix Rosters page.
* Queue Section fixes.
* Mobile Draft fixes.
* Fix draft board page.
* Create bracket look.
* Bracket work.
* Finish bracket page.
* Homepage initial styling
* homepage copy
* Add privacy policy. Fixes #88.
* how to play copy
* rules copy
* Fix brackets on homepage.
* Add footer to website.
* Glow on dots.
* Landing page copy.
* Fix sidebar.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:14:55 -07:00
|
|
|
|
|
|
|
|
|
|
export interface LeagueRowProps {
|
|
|
|
|
|
leagueId: string;
|
|
|
|
|
|
leagueName: string;
|
|
|
|
|
|
numSports: number;
|
|
|
|
|
|
status: "draft" | "active" | "pre_draft" | "completed";
|
|
|
|
|
|
seasonId?: string;
|
2026-04-24 11:11:20 -07:00
|
|
|
|
displayRank?: string | number;
|
New design (#309)
* Redesign home page with new layout and component system
- Two-column layout (My Leagues 2/3, Upcoming Events 1/3) with mobile stack
- LeagueRow: square avatar, gradient draft highlight, rank/points display, progress bar
- MyLeaguesCard, CreateLeagueCard with shared SectionCardHeader
- UpcomingEventsCard: vertical timeline with grouped multi-league events
- Shared gradient system: BracktGradients SVG defs, GradientIcon wrapper, brand.ts constants
- Button default variant updated to green→cyan gradient
- Navbar: plain nav links with gradient hover, support/admin icon buttons
- Accessibility fixes: semantic h2 headings, aria-label on LeagueAvatar and nav elements
- Storybook stories for all new components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Responsive league row layout and mobile polish
- League rows stack avatar+name on top, stats full-width below on mobile
- Stats spread to right side on sm+ screens with border separator on mobile
- Tighter padding on mobile (px-3/py-3), full padding on sm+
- Card headers and content use px-3 sm:px-6 to reduce mobile gutters
- Two-column home layout deferred to lg breakpoint (tablet gets stacked)
- Active leagues sorted by completion percentage descending
- Default rank 1 / 0 points for active leagues with no scoring events yet
- Fix ordinal bug for 11th/12th/13th; add aria-labels to rank change indicators
- Remove dead StatDivider className prop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Improve claude file.
* Add StandingsPreview card component with podium row styling
- New StandingsPreview component with gold/silver/bronze row tints for
top 3, team avatar, and LeagueRow-style stat columns (Ranking + Points)
with rank and 7-day point change indicators
- Fix GradientIcon in Storybook by adding BracktGradients decorator to
preview.tsx (renamed from .ts to support JSX)
- Fix degenerate SVG gradient on horizontal strokes by switching
BracktGradients to gradientUnits="userSpaceOnUse" with Lucide-space
coordinates (0→24)
- Revert erroneous fill: url(#gradient) from GradientIcon; stroke-only
fix was sufficient once gradientUnits was corrected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update components on league homepage.
* Finish up league page styling.
* Work on standings page.
* Add story for RecentScoresCard
* Update Point Progression Chart.
* Sort point progression legend by ranking and add team links to standings rows
* Fix standings discrepancy on change.
* Create draft cell component.
* Update draft board page
* Draft room improvements.
* Update some draft room styling.
* Fix context menu missing.
* Move tab navigation and autodraft to header row, narrow sidebar
* Virtualize available participants list, memoize draft room props
Adds @tanstack/react-virtual to replace separate mobile/desktop lists
with a single unified virtual scroll loop. Also memoizes miniDraftGrid
and availableParticipantsSectionProps, and switches pick lookup from
Array.find to a Map for O(1) access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update draft room UI.
* More draft room fixes.
* Draft room tweaks.
* Fix Rosters page.
* Queue Section fixes.
* Mobile Draft fixes.
* Fix draft board page.
* Create bracket look.
* Bracket work.
* Finish bracket page.
* Homepage initial styling
* homepage copy
* Add privacy policy. Fixes #88.
* how to play copy
* rules copy
* Fix brackets on homepage.
* Add footer to website.
* Glow on dots.
* Landing page copy.
* Fix sidebar.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:14:55 -07:00
|
|
|
|
currentRank?: number;
|
|
|
|
|
|
totalPoints?: number;
|
|
|
|
|
|
previousRank?: number;
|
|
|
|
|
|
completionPercentage?: number;
|
|
|
|
|
|
draftDateTime?: string | null;
|
|
|
|
|
|
picksUntilMyTurn?: number;
|
|
|
|
|
|
draftPosition?: number;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
function ordinal(n: number): string {
|
|
|
|
|
|
const v = n % 100;
|
|
|
|
|
|
// 11–13 are always "th" (e.g. 11th, 12th, 13th)
|
|
|
|
|
|
if (v >= 11 && v <= 13) return `${n}th`;
|
|
|
|
|
|
const s = ["th", "st", "nd", "rd"];
|
|
|
|
|
|
return `${n}${s[n % 10] ?? "th"}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ─── Season progress bar ──────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
function SeasonProgress({ pct, status }: { pct: number; status: "active" | "completed" }) {
|
|
|
|
|
|
const label = status === "completed" ? "100% Complete" : `${pct}% Complete`;
|
|
|
|
|
|
const fill = status === "completed" ? 100 : pct;
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="flex items-center gap-1.5 mt-1.5 w-40">
|
|
|
|
|
|
<div className="flex-1 h-1 rounded-full bg-white/10 overflow-hidden">
|
|
|
|
|
|
<div
|
|
|
|
|
|
className="h-full rounded-full bg-electric transition-all"
|
|
|
|
|
|
style={{ width: `${fill}%` }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span className="text-xs text-muted-foreground shrink-0">{label}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ─── Row variants ─────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
function DraftRow({ leagueId, leagueName, seasonId, picksUntilMyTurn }: LeagueRowProps) {
|
|
|
|
|
|
const draftUrl = `/leagues/${leagueId}/draft/${seasonId}`;
|
|
|
|
|
|
const picksLabel =
|
|
|
|
|
|
picksUntilMyTurn === 0
|
|
|
|
|
|
? "You're on the clock!"
|
|
|
|
|
|
: picksUntilMyTurn !== undefined
|
|
|
|
|
|
? `Up in ${picksUntilMyTurn} pick${picksUntilMyTurn === 1 ? "" : "s"}`
|
|
|
|
|
|
: null;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<div className="flex items-start gap-3 rounded-lg border border-primary/40 bg-primary/10 px-3 py-3 sm:px-5 sm:py-4">
|
|
|
|
|
|
<LeagueAvatar leagueId={leagueId} leagueName={leagueName} />
|
|
|
|
|
|
<div className="flex-1 min-w-0">
|
|
|
|
|
|
<p className="font-semibold leading-tight truncate">{leagueName}</p>
|
|
|
|
|
|
<div className="flex items-center gap-2 mt-0.5 flex-wrap">
|
|
|
|
|
|
<div className="flex items-center gap-1.5">
|
|
|
|
|
|
<span className="h-1.5 w-1.5 animate-pulse rounded-full bg-electric" />
|
|
|
|
|
|
<span className="text-xs font-semibold tracking-wide text-electric uppercase">
|
|
|
|
|
|
Draft in Progress
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{picksLabel && (
|
|
|
|
|
|
<span className="text-xs text-muted-foreground">{picksLabel}</span>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{seasonId && (
|
|
|
|
|
|
<Button asChild size="sm" className="mt-3 sm:hidden">
|
|
|
|
|
|
<Link to={draftUrl}>Enter Draft</Link>
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{seasonId && (
|
|
|
|
|
|
<Button asChild size="sm" className="shrink-0 hidden sm:inline-flex">
|
|
|
|
|
|
<Link to={draftUrl}>Enter Draft</Link>
|
|
|
|
|
|
</Button>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function ActiveRow({
|
|
|
|
|
|
leagueId,
|
|
|
|
|
|
leagueName,
|
2026-04-24 11:11:20 -07:00
|
|
|
|
displayRank,
|
New design (#309)
* Redesign home page with new layout and component system
- Two-column layout (My Leagues 2/3, Upcoming Events 1/3) with mobile stack
- LeagueRow: square avatar, gradient draft highlight, rank/points display, progress bar
- MyLeaguesCard, CreateLeagueCard with shared SectionCardHeader
- UpcomingEventsCard: vertical timeline with grouped multi-league events
- Shared gradient system: BracktGradients SVG defs, GradientIcon wrapper, brand.ts constants
- Button default variant updated to green→cyan gradient
- Navbar: plain nav links with gradient hover, support/admin icon buttons
- Accessibility fixes: semantic h2 headings, aria-label on LeagueAvatar and nav elements
- Storybook stories for all new components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Responsive league row layout and mobile polish
- League rows stack avatar+name on top, stats full-width below on mobile
- Stats spread to right side on sm+ screens with border separator on mobile
- Tighter padding on mobile (px-3/py-3), full padding on sm+
- Card headers and content use px-3 sm:px-6 to reduce mobile gutters
- Two-column home layout deferred to lg breakpoint (tablet gets stacked)
- Active leagues sorted by completion percentage descending
- Default rank 1 / 0 points for active leagues with no scoring events yet
- Fix ordinal bug for 11th/12th/13th; add aria-labels to rank change indicators
- Remove dead StatDivider className prop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Improve claude file.
* Add StandingsPreview card component with podium row styling
- New StandingsPreview component with gold/silver/bronze row tints for
top 3, team avatar, and LeagueRow-style stat columns (Ranking + Points)
with rank and 7-day point change indicators
- Fix GradientIcon in Storybook by adding BracktGradients decorator to
preview.tsx (renamed from .ts to support JSX)
- Fix degenerate SVG gradient on horizontal strokes by switching
BracktGradients to gradientUnits="userSpaceOnUse" with Lucide-space
coordinates (0→24)
- Revert erroneous fill: url(#gradient) from GradientIcon; stroke-only
fix was sufficient once gradientUnits was corrected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update components on league homepage.
* Finish up league page styling.
* Work on standings page.
* Add story for RecentScoresCard
* Update Point Progression Chart.
* Sort point progression legend by ranking and add team links to standings rows
* Fix standings discrepancy on change.
* Create draft cell component.
* Update draft board page
* Draft room improvements.
* Update some draft room styling.
* Fix context menu missing.
* Move tab navigation and autodraft to header row, narrow sidebar
* Virtualize available participants list, memoize draft room props
Adds @tanstack/react-virtual to replace separate mobile/desktop lists
with a single unified virtual scroll loop. Also memoizes miniDraftGrid
and availableParticipantsSectionProps, and switches pick lookup from
Array.find to a Map for O(1) access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update draft room UI.
* More draft room fixes.
* Draft room tweaks.
* Fix Rosters page.
* Queue Section fixes.
* Mobile Draft fixes.
* Fix draft board page.
* Create bracket look.
* Bracket work.
* Finish bracket page.
* Homepage initial styling
* homepage copy
* Add privacy policy. Fixes #88.
* how to play copy
* rules copy
* Fix brackets on homepage.
* Add footer to website.
* Glow on dots.
* Landing page copy.
* Fix sidebar.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:14:55 -07:00
|
|
|
|
currentRank,
|
|
|
|
|
|
totalPoints,
|
|
|
|
|
|
previousRank,
|
|
|
|
|
|
completionPercentage = 0,
|
|
|
|
|
|
}: LeagueRowProps) {
|
|
|
|
|
|
const showStats = currentRank !== undefined || totalPoints !== undefined;
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Link
|
|
|
|
|
|
to={`/leagues/${leagueId}`}
|
|
|
|
|
|
className="flex flex-col sm:flex-row sm:items-center gap-3 rounded-lg bg-card px-3 py-3 sm:px-5 sm:py-4 hover:bg-white/[0.06] transition-colors"
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* Avatar + name */}
|
|
|
|
|
|
<div className="flex items-center gap-3 min-w-0 flex-1">
|
|
|
|
|
|
<LeagueAvatar leagueId={leagueId} leagueName={leagueName} />
|
|
|
|
|
|
<div className="min-w-0">
|
|
|
|
|
|
<p className="font-semibold leading-tight truncate">{leagueName}</p>
|
|
|
|
|
|
<SeasonProgress pct={completionPercentage} status="active" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{/* Stats — second row on mobile, right side on desktop */}
|
|
|
|
|
|
{showStats && (
|
|
|
|
|
|
<div className="flex items-center gap-4 border-t border-border/50 pt-2 sm:border-0 sm:pt-0 sm:shrink-0">
|
2026-04-24 11:11:20 -07:00
|
|
|
|
{displayRank !== undefined && (
|
|
|
|
|
|
<RankingDisplay
|
|
|
|
|
|
displayRank={displayRank}
|
|
|
|
|
|
rankChange={previousRank !== undefined && currentRank !== undefined && previousRank !== currentRank ? previousRank - currentRank : undefined}
|
|
|
|
|
|
/>
|
New design (#309)
* Redesign home page with new layout and component system
- Two-column layout (My Leagues 2/3, Upcoming Events 1/3) with mobile stack
- LeagueRow: square avatar, gradient draft highlight, rank/points display, progress bar
- MyLeaguesCard, CreateLeagueCard with shared SectionCardHeader
- UpcomingEventsCard: vertical timeline with grouped multi-league events
- Shared gradient system: BracktGradients SVG defs, GradientIcon wrapper, brand.ts constants
- Button default variant updated to green→cyan gradient
- Navbar: plain nav links with gradient hover, support/admin icon buttons
- Accessibility fixes: semantic h2 headings, aria-label on LeagueAvatar and nav elements
- Storybook stories for all new components
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Responsive league row layout and mobile polish
- League rows stack avatar+name on top, stats full-width below on mobile
- Stats spread to right side on sm+ screens with border separator on mobile
- Tighter padding on mobile (px-3/py-3), full padding on sm+
- Card headers and content use px-3 sm:px-6 to reduce mobile gutters
- Two-column home layout deferred to lg breakpoint (tablet gets stacked)
- Active leagues sorted by completion percentage descending
- Default rank 1 / 0 points for active leagues with no scoring events yet
- Fix ordinal bug for 11th/12th/13th; add aria-labels to rank change indicators
- Remove dead StatDivider className prop
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Improve claude file.
* Add StandingsPreview card component with podium row styling
- New StandingsPreview component with gold/silver/bronze row tints for
top 3, team avatar, and LeagueRow-style stat columns (Ranking + Points)
with rank and 7-day point change indicators
- Fix GradientIcon in Storybook by adding BracktGradients decorator to
preview.tsx (renamed from .ts to support JSX)
- Fix degenerate SVG gradient on horizontal strokes by switching
BracktGradients to gradientUnits="userSpaceOnUse" with Lucide-space
coordinates (0→24)
- Revert erroneous fill: url(#gradient) from GradientIcon; stroke-only
fix was sufficient once gradientUnits was corrected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update components on league homepage.
* Finish up league page styling.
* Work on standings page.
* Add story for RecentScoresCard
* Update Point Progression Chart.
* Sort point progression legend by ranking and add team links to standings rows
* Fix standings discrepancy on change.
* Create draft cell component.
* Update draft board page
* Draft room improvements.
* Update some draft room styling.
* Fix context menu missing.
* Move tab navigation and autodraft to header row, narrow sidebar
* Virtualize available participants list, memoize draft room props
Adds @tanstack/react-virtual to replace separate mobile/desktop lists
with a single unified virtual scroll loop. Also memoizes miniDraftGrid
and availableParticipantsSectionProps, and switches pick lookup from
Array.find to a Map for O(1) access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update draft room UI.
* More draft room fixes.
* Draft room tweaks.
* Fix Rosters page.
* Queue Section fixes.
* Mobile Draft fixes.
* Fix draft board page.
* Create bracket look.
* Bracket work.
* Finish bracket page.
* Homepage initial styling
* homepage copy
* Add privacy policy. Fixes #88.
* how to play copy
* rules copy
* Fix brackets on homepage.
* Add footer to website.
* Glow on dots.
* Landing page copy.
* Fix sidebar.
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 13:14:55 -07:00
|
|
|
|
)}
|
|
|
|
|
|
{currentRank !== undefined && totalPoints !== undefined && <StatDivider />}
|
|
|
|
|
|
{totalPoints !== undefined && (
|
|
|
|
|
|
<StatColumn label="Points">
|
|
|
|
|
|
<span className="text-2xl font-bold leading-none text-electric">
|
|
|
|
|
|
{Math.round(totalPoints).toLocaleString("en-US")}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</StatColumn>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</Link>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function PreDraftRow({
|
|
|
|
|
|
leagueId,
|
|
|
|
|
|
leagueName,
|
|
|
|
|
|
draftDateTime,
|
|
|
|
|
|
draftPosition,
|
|
|
|
|
|
}: LeagueRowProps) {
|
|
|
|
|
|
let draftTimeValue = "Not scheduled";
|
|
|
|
|
|
if (draftDateTime) {
|
|
|
|
|
|
const draftDate = new Date(draftDateTime);
|
|
|
|
|
|
draftTimeValue =
|
|
|
|
|
|
draftDate > new Date()
|
|
|
|
|
|
? formatDistanceToNow(draftDate, { addSuffix: true })
|
|
|
|
|
|
: "Starting soon";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Link
|
|
|
|
|
|
to={`/leagues/${leagueId}`}
|
|
|
|
|
|
className="flex flex-col sm:flex-row sm:items-center gap-3 rounded-lg bg-card px-3 py-3 sm:px-5 sm:py-4 hover:bg-white/[0.06] transition-colors"
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* Avatar + name */}
|
|
|
|
|
|
<div className="flex items-center gap-3 min-w-0 flex-1">
|
|
|
|
|
|
<LeagueAvatar leagueId={leagueId} leagueName={leagueName} />
|
|
|
|
|
|
<div className="min-w-0">
|
|
|
|
|
|
<p className="font-semibold leading-tight truncate">{leagueName}</p>
|
|
|
|
|
|
<p className="text-xs text-muted-foreground mt-0.5">Pre-Draft</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{/* Stats — second row on mobile, right side on desktop */}
|
|
|
|
|
|
<div className="flex items-center gap-4 border-t border-border/50 pt-2 sm:border-0 sm:pt-0 sm:shrink-0">
|
|
|
|
|
|
<StatColumn label="Draft">
|
|
|
|
|
|
<span className="text-2xl font-bold leading-none">{draftTimeValue}</span>
|
|
|
|
|
|
</StatColumn>
|
|
|
|
|
|
{draftPosition !== undefined && (
|
|
|
|
|
|
<>
|
|
|
|
|
|
<StatDivider />
|
|
|
|
|
|
<StatColumn label="Position">
|
|
|
|
|
|
<span className="text-2xl font-bold leading-none">
|
|
|
|
|
|
{ordinal(draftPosition)}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</StatColumn>
|
|
|
|
|
|
</>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Link>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function CompletedRow({
|
|
|
|
|
|
leagueId,
|
|
|
|
|
|
leagueName,
|
|
|
|
|
|
completionPercentage = 0,
|
|
|
|
|
|
}: LeagueRowProps) {
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Link
|
|
|
|
|
|
to={`/leagues/${leagueId}`}
|
|
|
|
|
|
className="flex items-center gap-3 rounded-lg bg-card px-3 py-3 sm:px-5 sm:py-4 hover:bg-white/[0.06] transition-colors"
|
|
|
|
|
|
>
|
|
|
|
|
|
<LeagueAvatar leagueId={leagueId} leagueName={leagueName} />
|
|
|
|
|
|
<div className="flex-1 min-w-0">
|
|
|
|
|
|
<p className="font-semibold leading-tight truncate">{leagueName}</p>
|
|
|
|
|
|
<SeasonProgress pct={completionPercentage} status="completed" />
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</Link>
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ─── Public export ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
export function LeagueRow(props: LeagueRowProps) {
|
|
|
|
|
|
if (props.status === "draft") return <DraftRow {...props} />;
|
|
|
|
|
|
if (props.status === "active") return <ActiveRow {...props} />;
|
|
|
|
|
|
if (props.status === "pre_draft") return <PreDraftRow {...props} />;
|
|
|
|
|
|
return <CompletedRow {...props} />;
|
|
|
|
|
|
}
|