From 32980428f2da164c875c839a0c47a7998e58fb0c Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Sat, 25 Oct 2025 10:04:21 -0700 Subject: [PATCH] feat: Integrate accordion component for sidebar and update autodraft settings to sync with props --- app/components/AutodraftSettings.tsx | 11 +- app/components/DraftSidebar.tsx | 152 ++++++------------ .../draft/AvailableParticipantsSection.tsx | 14 +- app/components/draft/QueueSection.tsx | 4 +- app/components/ui/accordion.tsx | 64 ++++++++ app/routes.ts | 1 + package-lock.json | 32 ++++ package.json | 1 + 8 files changed, 162 insertions(+), 117 deletions(-) create mode 100644 app/components/ui/accordion.tsx diff --git a/app/components/AutodraftSettings.tsx b/app/components/AutodraftSettings.tsx index 17e9ad4..8449f32 100644 --- a/app/components/AutodraftSettings.tsx +++ b/app/components/AutodraftSettings.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import { Switch } from "~/components/ui/switch"; import { RadioGroup, RadioGroupItem } from "~/components/ui/radio-group"; import { Label } from "~/components/ui/label"; @@ -24,6 +24,15 @@ export function AutodraftSettings({ const [localMode, setLocalMode] = useState<"next_pick" | "while_on">(mode); const [isUpdating, setIsUpdating] = useState(false); + // Sync local state with props when they change (from socket events) + useEffect(() => { + setLocalEnabled(isEnabled); + }, [isEnabled]); + + useEffect(() => { + setLocalMode(mode); + }, [mode]); + const handleToggle = async (checked: boolean) => { setLocalEnabled(checked); setIsUpdating(true); diff --git a/app/components/DraftSidebar.tsx b/app/components/DraftSidebar.tsx index 040186a..278bf4b 100644 --- a/app/components/DraftSidebar.tsx +++ b/app/components/DraftSidebar.tsx @@ -1,7 +1,12 @@ -import { useState, useEffect } from "react"; import type { ReactNode } from "react"; -import { ChevronLeft, ChevronRight, ChevronDown, ChevronUp } from "lucide-react"; +import { ChevronLeft, ChevronRight } from "lucide-react"; import { Button } from "~/components/ui/button"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "~/components/ui/accordion"; import { cn } from "~/lib/utils"; interface DraftSidebarProps { @@ -19,59 +24,6 @@ export function DraftSidebar({ participantsSection, className, }: DraftSidebarProps) { - // Track which sections are expanded - // At least one must be expanded at all times - const [queueExpanded, setQueueExpanded] = useState(() => { - if (typeof window === "undefined") return true; - const stored = localStorage.getItem("draftSidebarQueueExpanded"); - return stored !== null ? JSON.parse(stored) : true; - }); - - const [participantsExpanded, setParticipantsExpanded] = useState(() => { - if (typeof window === "undefined") return true; - const stored = localStorage.getItem("draftSidebarParticipantsExpanded"); - return stored !== null ? JSON.parse(stored) : true; - }); - - // Persist section states to localStorage - useEffect(() => { - if (typeof window !== "undefined") { - localStorage.setItem( - "draftSidebarQueueExpanded", - JSON.stringify(queueExpanded) - ); - } - }, [queueExpanded]); - - useEffect(() => { - if (typeof window !== "undefined") { - localStorage.setItem( - "draftSidebarParticipantsExpanded", - JSON.stringify(participantsExpanded) - ); - } - }, [participantsExpanded]); - - const toggleQueueSection = () => { - // Prevent collapsing if it's the only expanded section - if (queueExpanded && !participantsExpanded) { - return; - } - setQueueExpanded(!queueExpanded); - }; - - const toggleParticipantsSection = () => { - // Prevent collapsing if it's the only expanded section - if (participantsExpanded && !queueExpanded) { - return; - } - setParticipantsExpanded(!participantsExpanded); - }; - - // Calculate flex sizes for sections - const queueFlexSize = queueExpanded && participantsExpanded ? "1" : queueExpanded ? "1" : "0"; - const participantsFlexSize = queueExpanded && participantsExpanded ? "1" : participantsExpanded ? "1" : "0"; - if (collapsed) { return (
- {/* Collapse button */} -
- -
+ {/* Queue Section */} + + +

My Queue

+
+ + {queueSection} + +
- {/* Queue Section */} -
- - {queueExpanded && ( -
{queueSection}
- )} -
+ {/* Available Participants Section */} + + +

Available Participants

+
+ +
+ {participantsSection} +
+
+
+ - {/* Available Participants Section */} -
- - {participantsExpanded && ( -
{participantsSection}
- )} + {/* Collapse button at bottom */} +
+ +
-
); } diff --git a/app/components/draft/AvailableParticipantsSection.tsx b/app/components/draft/AvailableParticipantsSection.tsx index a8cdfff..05b0e80 100644 --- a/app/components/draft/AvailableParticipantsSection.tsx +++ b/app/components/draft/AvailableParticipantsSection.tsx @@ -50,10 +50,8 @@ export function AvailableParticipantsSection({ onRemoveFromQueue, }: AvailableParticipantsSectionProps) { return ( -
-
-

Available Participants

- +
+
{/* Search Input */}
- {/* Table */} -
-
+ {/* Table - This will scroll independently */} +
+
+
@@ -270,6 +269,7 @@ export function AvailableParticipantsSection({ )}
+
diff --git a/app/components/draft/QueueSection.tsx b/app/components/draft/QueueSection.tsx index 4c01a70..b1512b4 100644 --- a/app/components/draft/QueueSection.tsx +++ b/app/components/draft/QueueSection.tsx @@ -46,7 +46,7 @@ export function QueueSection({ onAutodraftUpdate, }: QueueSectionProps) { return ( - <> +

Queue ({queue.length})

{queue.length > 0 && ( @@ -159,6 +159,6 @@ export function QueueSection({ isMyTurn={isMyTurn} onUpdate={onAutodraftUpdate} /> - +
); } diff --git a/app/components/ui/accordion.tsx b/app/components/ui/accordion.tsx new file mode 100644 index 0000000..6d1a5d8 --- /dev/null +++ b/app/components/ui/accordion.tsx @@ -0,0 +1,64 @@ +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDownIcon } from "lucide-react" + +import { cn } from "app/lib/utils" + +function Accordion({ + ...props +}: React.ComponentProps) { + return +} + +function AccordionItem({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function AccordionTrigger({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + + ) +} + +function AccordionContent({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + +
{children}
+
+ ) +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/app/routes.ts b/app/routes.ts index cce232c..4a20640 100644 --- a/app/routes.ts +++ b/app/routes.ts @@ -26,6 +26,7 @@ export default [ route("api/draft/resume", "routes/api/draft.resume.ts"), route("api/draft/force-autopick", "routes/api/draft.force-autopick.ts"), route("api/draft/force-manual-pick", "routes/api/draft.force-manual-pick.ts"), + route("api/autodraft/update", "routes/api/autodraft.update.ts"), route("user-profile", "routes/user-profile.tsx"), route("how-to-play", "routes/how-to-play.tsx"), route("test-socket", "routes/test-socket.tsx"), diff --git a/package-lock.json b/package-lock.json index 7248137..7b94a07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "name": "brackt.com", "dependencies": { "@clerk/react-router": "^2.1.0", + "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-collapsible": "^1.1.12", @@ -2600,6 +2601,37 @@ "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", "license": "MIT" }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz", + "integrity": "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collapsible": "1.1.12", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-alert-dialog": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.1.15.tgz", diff --git a/package.json b/package.json index 337defd..f9a3c50 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ }, "dependencies": { "@clerk/react-router": "^2.1.0", + "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-checkbox": "^1.3.3", "@radix-ui/react-collapsible": "^1.1.12",