brackt/app/components/draft/QueueSection.tsx

202 lines
5.2 KiB
TypeScript
Raw Normal View History

import { Button } from "~/components/ui/button";
import { Badge } from "~/components/ui/badge";
import { AutodraftSettings } from "~/components/AutodraftSettings";
import {
DndContext,
closestCenter,
KeyboardSensor,
PointerSensor,
useSensor,
useSensors,
} from "@dnd-kit/core";
import type { DragEndEvent } from "@dnd-kit/core";
import {
arrayMove,
SortableContext,
sortableKeyboardCoordinates,
useSortable,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
interface QueueSectionProps {
queue: Array<{
id: string;
participantId: string;
}>;
availableParticipants: Array<{
id: string;
name: string;
}>;
eligibility: {
flexPicksUsed: number;
flexPicksAvailable: number;
picksBySport: Record<string, number>;
sportAvailability: Record<
string,
{ sportName: string; sportId: string }
>;
ineligibleReasons: Record<string, string>;
} | null;
seasonId: string;
teamId: string;
isMyTurn: boolean;
userAutodraft: {
isEnabled: boolean;
mode: "next_pick" | "while_on";
};
onRemoveFromQueue: (queueId: string) => void;
onAutodraftUpdate: (isEnabled: boolean, mode: "next_pick" | "while_on") => void;
onReorder: (participantIds: string[]) => void;
}
// Sortable queue item component
function SortableQueueItem({
item,
index,
participantName,
onRemove,
}: {
item: { id: string; participantId: string };
index: number;
participantName: string;
onRemove: () => void;
}) {
const {
attributes,
listeners,
setNodeRef,
transform,
transition,
isDragging,
} = useSortable({ id: item.id });
const style = {
transform: CSS.Transform.toString(transform),
transition,
opacity: isDragging ? 0.5 : 1,
};
return (
<div
ref={setNodeRef}
style={style}
className="flex items-center justify-between p-2 bg-muted rounded-lg touch-none"
>
<div className="flex items-center gap-2 flex-1" {...attributes} {...listeners}>
<div className="cursor-grab active:cursor-grabbing">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="text-muted-foreground"
>
<line x1="5" y1="9" x2="19" y2="9"></line>
<line x1="5" y1="15" x2="19" y2="15"></line>
</svg>
</div>
<Badge variant="default" className="text-xs">{index + 1}</Badge>
<div>
<p className="font-semibold text-sm">{participantName}</p>
</div>
</div>
<Button
variant="ghost"
size="icon"
className="h-7 w-7 text-destructive hover:text-destructive hover:bg-destructive/10"
onClick={onRemove}
title="Remove from queue"
>
<span className="text-lg">×</span>
</Button>
</div>
);
}
export function QueueSection({
queue,
availableParticipants,
eligibility,
seasonId,
teamId,
isMyTurn,
userAutodraft,
onRemoveFromQueue,
onAutodraftUpdate,
onReorder,
}: QueueSectionProps) {
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
);
const handleDragEnd = (event: DragEndEvent) => {
const { active, over } = event;
if (over && active.id !== over.id) {
const oldIndex = queue.findIndex((item) => item.id === active.id);
const newIndex = queue.findIndex((item) => item.id === over.id);
const reorderedQueue = arrayMove(queue, oldIndex, newIndex);
const participantIds = reorderedQueue.map((item) => item.participantId);
onReorder(participantIds);
}
};
return (
<div className="p-4">
{/* Queue List */}
{queue.length === 0 ? (
<p className="text-muted-foreground text-sm text-center py-8">
Click participants to add to your queue
</p>
) : (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
>
<SortableContext
items={queue.map((item) => item.id)}
strategy={verticalListSortingStrategy}
>
<div className="space-y-1.5 mb-4">
{queue.map((item, index) => (
<SortableQueueItem
key={item.id}
item={item}
index={index}
participantName={
availableParticipants.find(
(p) => p.id === item.participantId
)?.name || "Unknown"
}
onRemove={() => onRemoveFromQueue(item.id)}
/>
))}
</div>
</SortableContext>
</DndContext>
)}
{/* Autodraft Settings */}
<AutodraftSettings
seasonId={seasonId}
teamId={teamId}
isEnabled={userAutodraft.isEnabled}
mode={userAutodraft.mode}
isMyTurn={isMyTurn}
onUpdate={onAutodraftUpdate}
/>
</div>
);
}