import { useMemo } from "react"; import { Button } from "~/components/ui/button"; import { Badge } from "~/components/ui/badge"; import { Checkbox } from "~/components/ui/checkbox"; import { Popover, PopoverTrigger, PopoverContent, } from "~/components/ui/popover"; import { Sheet, SheetTrigger, SheetContent, SheetTitle, SheetFooter, SheetClose, } from "~/components/ui/sheet"; import { ListPlus, ListX, ChevronDown } from "lucide-react"; function getParticipantState( participant: { id: string; sport: { id: string } }, draftedParticipantIds: Set, queueMap: Map, eligibility: { eligibleSportIds: Set; ineligibleReasons: Record; } | null ) { const isDrafted = draftedParticipantIds.has(participant.id); const isInQueue = queueMap.has(participant.id); const isEligible = eligibility ? eligibility.eligibleSportIds.has(participant.sport.id) : true; const ineligibleReason = eligibility?.ineligibleReasons[participant.sport.id]; return { isDrafted, isInQueue, isEligible, ineligibleReason }; } interface AvailableParticipantsSectionProps { participants: Array<{ id: string; name: string; sport: { id: string; name: string; }; }>; searchQuery: string; sportFilters: string[]; hideDrafted: boolean; hideIneligible: boolean; hideCompletedSports: boolean; uniqueSports: string[]; draftedParticipantIds: Set; queue: Array<{ id: string; participantId: string }>; eligibility: { eligibleSportIds: Set; ineligibleReasons: Record; } | null; canPick: boolean; hasTeam: boolean; onSearchChange: (query: string) => void; onSportFiltersChange: (sports: string[]) => void; onHideDraftedChange: (hide: boolean) => void; onHideIneligibleChange: (hide: boolean) => void; onHideCompletedSportsChange: (hide: boolean) => void; onMakePick: (participantId: string) => void; onAddToQueue: (participantId: string) => void; onRemoveFromQueue: (queueId: string) => void; } export function AvailableParticipantsSection({ participants, searchQuery, sportFilters, hideDrafted, hideIneligible, hideCompletedSports, uniqueSports, draftedParticipantIds, queue, eligibility, canPick, hasTeam, onSearchChange, onSportFiltersChange, onHideDraftedChange, onHideIneligibleChange, onHideCompletedSportsChange, onMakePick, onAddToQueue, onRemoveFromQueue, }: AvailableParticipantsSectionProps) { const queueMap = useMemo( () => new Map(queue.map((item) => [item.participantId, item.id])), [queue] ); const sportFilterSet = useMemo(() => new Set(sportFilters), [sportFilters]); const triggerText = sportFilters.length === 0 ? "All Sports" : sportFilters.length === 1 ? sportFilters[0] : `${sportFilters.length} sports`; const triggerAriaLabel = sportFilters.length === 0 ? "Filter by sport: All Sports" : sportFilters.length === 1 ? `Filter by sport: ${sportFilters[0]}` : `Filter by sport: ${sportFilters.length} sports selected`; function handleToggleSport(sport: string, checked: boolean | "indeterminate") { if (checked === true) { onSportFiltersChange([...sportFilters, sport]); } else { onSportFiltersChange(sportFilters.filter((s) => s !== sport)); } } const emptyMessage = useMemo(() => { if (participants.length > 0) return null; const active: string[] = []; if (hideDrafted) active.push("drafted players"); if (hideIneligible && eligibility) active.push("ineligible players"); if (hideCompletedSports) active.push("drafted sports"); if (sportFilters.length > 0) active.push("other sports"); if (active.length === 0) return "No participants found."; return `No participants found. Try showing ${active.join(", ")}.`; }, [participants.length, hideDrafted, hideIneligible, hideCompletedSports, eligibility, sportFilters]); return (
{/* Search Input */} onSearchChange(e.target.value)} className="w-full px-3 py-2 border rounded-md text-base md:text-sm bg-background text-foreground" />
{/* Sport Filter Multi-Select */}
{/* Mobile: bottom sheet */}
Filter by sport
{uniqueSports.map((sport) => { const checkboxId = `sheet-sport-filter-${sport.replace(/\s+/g, "-").toLowerCase()}`; return ( ); })}
{sportFilters.length > 0 && ( )}
{/* Desktop: popover */}
{sportFilters.length > 0 && (
)}
{uniqueSports.map((sport) => { const checkboxId = `popover-sport-filter-${sport.replace(/\s+/g, "-").toLowerCase()}`; return ( ); })}
{/* Show/Hide Drafted Toggle */} {/* Show/Hide Ineligible Toggle - only show if user has a team */} {hasTeam && eligibility && ( )} {/* Show drafted sports - only show if user has a team */} {hasTeam && ( )}
{/* Mobile Card List - visible on mobile only */}
{participants.length === 0 ? (
{emptyMessage}
) : ( participants.map((participant) => { const { isDrafted, isInQueue, isEligible, ineligibleReason } = getParticipantState(participant, draftedParticipantIds, queueMap, eligibility); return (
{participant.name}
{participant.sport.name} {isDrafted && ( Drafted )} {!isDrafted && !isEligible && ( Ineligible )} {isInQueue && !isDrafted && isEligible && ( Queued )}
{hasTeam && !isDrafted && (
{!isInQueue ? ( ) : ( )}
)}
); }) )}
{/* Desktop Table - hidden on mobile */}
{hasTeam && ( )} {participants.length === 0 ? ( ) : ( participants.map((participant) => { const { isDrafted, isInQueue, isEligible, ineligibleReason } = getParticipantState(participant, draftedParticipantIds, queueMap, eligibility); return ( {hasTeam && ( )} ); }) )}
Participant SportQueue
{emptyMessage}
{participant.name} {isDrafted && ( Drafted )} {!isDrafted && !isEligible && ( Ineligible )} {isInQueue && !isDrafted && isEligible && ( Queued )}
{participant.sport.name}
{!isDrafted && ( <> {/* Queue icon button */} {!isInQueue ? ( ) : ( )} {/* Draft button - always visible, disabled when not your turn */} )}
); }