2026-04-16 22:00:00 -07:00
|
|
|
import type { CSSProperties, ReactNode } from "react";
|
2026-04-16 20:46:00 -07:00
|
|
|
import { cn } from "~/lib/utils";
|
|
|
|
|
|
2026-04-16 22:00:00 -07:00
|
|
|
export type CoronaState =
|
|
|
|
|
| { type: "eliminated"; points: 0 }
|
|
|
|
|
| { type: "pending" }
|
|
|
|
|
| { type: "scored"; brightness: number; points: number };
|
|
|
|
|
|
2026-04-16 20:46:00 -07:00
|
|
|
type CoronaVariant =
|
|
|
|
|
| "gradient"
|
|
|
|
|
| "electric"
|
|
|
|
|
| "emerald"
|
|
|
|
|
| "amber"
|
|
|
|
|
| "coral";
|
|
|
|
|
|
|
|
|
|
interface DraftPickCellProps {
|
|
|
|
|
pickNumber: number;
|
|
|
|
|
round: number;
|
|
|
|
|
pickInRound: number;
|
|
|
|
|
state: "picked" | "current" | "upcoming";
|
|
|
|
|
pick?: {
|
|
|
|
|
participant: { name: string };
|
|
|
|
|
sport: { name: string };
|
|
|
|
|
};
|
|
|
|
|
corona?: CoronaVariant;
|
2026-04-16 22:00:00 -07:00
|
|
|
coronaState?: CoronaState;
|
2026-04-16 20:46:00 -07:00
|
|
|
className?: string;
|
|
|
|
|
children?: ReactNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const coronaClasses: Record<CoronaVariant, string> = {
|
|
|
|
|
gradient: "[background:linear-gradient(to_bottom,#adf661,#2ce1c1)]",
|
|
|
|
|
electric: "bg-electric",
|
|
|
|
|
emerald: "bg-emerald-500",
|
|
|
|
|
amber: "bg-amber-accent",
|
|
|
|
|
coral: "bg-coral-accent",
|
|
|
|
|
};
|
|
|
|
|
|
2026-04-16 22:00:00 -07:00
|
|
|
function getCoronaStyle(cs: CoronaState): CSSProperties {
|
|
|
|
|
switch (cs.type) {
|
|
|
|
|
case "eliminated":
|
|
|
|
|
return { background: "oklch(0.45 0.20 25)" };
|
|
|
|
|
case "pending":
|
|
|
|
|
return { background: "rgba(255, 255, 255, 0.08)" };
|
|
|
|
|
case "scored":
|
|
|
|
|
return {
|
|
|
|
|
background: "linear-gradient(to bottom, #adf661, #2ce1c1)",
|
|
|
|
|
opacity: cs.brightness,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-16 20:46:00 -07:00
|
|
|
export function DraftPickCell({
|
|
|
|
|
pickNumber,
|
|
|
|
|
round,
|
|
|
|
|
pickInRound,
|
|
|
|
|
state,
|
|
|
|
|
pick,
|
|
|
|
|
corona = "gradient",
|
2026-04-16 22:00:00 -07:00
|
|
|
coronaState,
|
2026-04-16 20:46:00 -07:00
|
|
|
className,
|
|
|
|
|
children,
|
|
|
|
|
}: DraftPickCellProps) {
|
2026-04-17 09:36:13 -07:00
|
|
|
const showCorona = state === "picked" || (state === "upcoming" && !!coronaState);
|
|
|
|
|
const isCurrent = state === "current";
|
2026-04-16 20:46:00 -07:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={cn(
|
|
|
|
|
"relative flex-1 min-w-32 overflow-hidden",
|
|
|
|
|
className,
|
|
|
|
|
)}
|
|
|
|
|
>
|
2026-04-17 09:36:13 -07:00
|
|
|
{isCurrent ? (
|
|
|
|
|
<div className="absolute inset-0 rounded-lg [background:linear-gradient(to_bottom,#adf661,#2ce1c1)] animate-pulse-gradient" />
|
|
|
|
|
) : showCorona && coronaState ? (
|
2026-04-16 22:00:00 -07:00
|
|
|
<div
|
|
|
|
|
className="absolute top-0.5 bottom-0.5 left-0 right-0 rounded-lg"
|
|
|
|
|
style={getCoronaStyle(coronaState)}
|
|
|
|
|
/>
|
|
|
|
|
) : showCorona ? (
|
2026-04-16 20:46:00 -07:00
|
|
|
<div
|
|
|
|
|
className={cn(
|
|
|
|
|
"absolute top-0.5 bottom-0.5 left-0 right-0 rounded-lg",
|
|
|
|
|
coronaClasses[corona],
|
|
|
|
|
)}
|
|
|
|
|
/>
|
2026-04-16 22:00:00 -07:00
|
|
|
) : null}
|
2026-04-16 20:46:00 -07:00
|
|
|
<div
|
|
|
|
|
className={cn(
|
2026-04-16 22:00:00 -07:00
|
|
|
"relative z-10 h-14 border-2 rounded-lg p-2 transition-all",
|
2026-04-17 09:36:13 -07:00
|
|
|
(showCorona || isCurrent) && "mr-1",
|
|
|
|
|
isCurrent
|
|
|
|
|
? "bg-muted/80 border-transparent"
|
|
|
|
|
: state === "picked" || (state === "upcoming" && showCorona)
|
2026-04-16 20:46:00 -07:00
|
|
|
? "bg-muted border-transparent"
|
|
|
|
|
: "border-border bg-card",
|
|
|
|
|
)}
|
|
|
|
|
title={`Overall Pick #${pickNumber}`}
|
|
|
|
|
>
|
2026-04-17 09:36:13 -07:00
|
|
|
<div className={cn("flex", isCurrent ? "items-center justify-center h-full" : "gap-1 items-start")}>
|
2026-04-16 22:00:00 -07:00
|
|
|
{state === "picked" && pick ? (
|
|
|
|
|
<div className="text-sm min-w-0 flex-1">
|
|
|
|
|
<div className="font-semibold truncate text-sm">{pick.participant.name}</div>
|
|
|
|
|
<div className="text-muted-foreground truncate text-xs">
|
|
|
|
|
{pick.sport.name}
|
|
|
|
|
</div>
|
2026-04-16 20:46:00 -07:00
|
|
|
</div>
|
2026-04-17 09:36:13 -07:00
|
|
|
) : isCurrent ? (
|
|
|
|
|
<div className="text-sm font-bold text-white">On The Clock</div>
|
2026-04-16 22:00:00 -07:00
|
|
|
) : null}
|
2026-04-17 09:36:13 -07:00
|
|
|
{!isCurrent && (
|
|
|
|
|
<div className="flex flex-col items-end shrink-0">
|
|
|
|
|
<div className="text-xs font-mono text-muted-foreground leading-5">
|
|
|
|
|
{round}.{String(pickInRound).padStart(2, "0")}
|
|
|
|
|
</div>
|
|
|
|
|
{coronaState && coronaState.type !== "pending" && (
|
|
|
|
|
<span className={`text-xs font-mono font-bold mt-0.5 ${coronaState.type === "eliminated" ? "text-coral-accent" : "text-emerald-400"}`}>
|
|
|
|
|
{coronaState.type === "scored" && "▲"}{coronaState.points}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
2026-04-16 22:00:00 -07:00
|
|
|
</div>
|
2026-04-17 09:36:13 -07:00
|
|
|
)}
|
2026-04-16 22:00:00 -07:00
|
|
|
</div>
|
2026-04-16 20:46:00 -07:00
|
|
|
{children && <div className="absolute inset-0 pointer-events-none [&_*]:pointer-events-auto">{children}</div>}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|