412 lines
11 KiB
Markdown
412 lines
11 KiB
Markdown
|
|
# Draft Room Redesign Plan
|
|||
|
|
|
|||
|
|
**Status**: ✅ Complete - All Features Implemented & Tested
|
|||
|
|
**Created**: 2025-10-24
|
|||
|
|
**Last Updated**: 2025-10-24
|
|||
|
|
|
|||
|
|
## Overview
|
|||
|
|
|
|||
|
|
Redesigning the draft room to use a full-screen layout with a collapsible left sidebar and tabbed main content area.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Requirements
|
|||
|
|
|
|||
|
|
### Layout Changes
|
|||
|
|
|
|||
|
|
#### 1. Full-Screen Layout (No Page Scroll)
|
|||
|
|
- Page fills entire viewport (100vh)
|
|||
|
|
- Individual sections scroll internally
|
|||
|
|
- Fixed header at top
|
|||
|
|
- Content area uses remaining height
|
|||
|
|
|
|||
|
|
#### 2. Collapsible Left Sidebar
|
|||
|
|
- **Default State**: Expanded
|
|||
|
|
- **Width**:
|
|||
|
|
- Expanded: 350px
|
|||
|
|
- Collapsed: 50px
|
|||
|
|
- **Contents** (Accordion-style sections):
|
|||
|
|
- My Queue (top section) - Collapsible
|
|||
|
|
- Eligibility status banner
|
|||
|
|
- Queue list (ordered, scrollable)
|
|||
|
|
- Autodraft settings
|
|||
|
|
- Clear queue button
|
|||
|
|
- Available Participants (bottom section) - Collapsible
|
|||
|
|
- Search bar
|
|||
|
|
- Sport filter dropdown
|
|||
|
|
- Show/hide drafted toggle
|
|||
|
|
- Participants table (scrollable)
|
|||
|
|
- Action buttons (Pick/Add to Queue)
|
|||
|
|
- **Section Behavior**:
|
|||
|
|
- Both sections can be expanded or collapsed independently
|
|||
|
|
- When both expanded: 50/50 vertical split
|
|||
|
|
- When one collapsed: Expanded section takes 100% of space
|
|||
|
|
- At least one section must remain expanded
|
|||
|
|
- **Responsive**:
|
|||
|
|
- Desktop (≥1024px): Fixed sidebar on left
|
|||
|
|
- Mobile (<1024px): Full-screen modal
|
|||
|
|
|
|||
|
|
#### 3. Tabbed Main Content Area
|
|||
|
|
Three tabs with toggle functionality:
|
|||
|
|
|
|||
|
|
**Tab 1: Draft Board (Default)**
|
|||
|
|
- Current draft grid display
|
|||
|
|
- Team headers with timers and autodraft status
|
|||
|
|
- Snake draft grid (scrollable)
|
|||
|
|
- Context menu for commissioners
|
|||
|
|
- Reuse existing DraftGrid component or inline implementation
|
|||
|
|
|
|||
|
|
**Tab 2: Recent Picks**
|
|||
|
|
- List of recent picks (latest 10-20)
|
|||
|
|
- Same format as current Recent Picks section
|
|||
|
|
- Scrollable list
|
|||
|
|
- Shows: Pick number, team, participant, sport
|
|||
|
|
|
|||
|
|
**Tab 3: Teams Drafted (NEW)**
|
|||
|
|
- Grid layout:
|
|||
|
|
- **Rows**: Sports (from season sports)
|
|||
|
|
- **Columns**: Teams (in draft order)
|
|||
|
|
- **Cells**: Participants drafted by that team in that sport
|
|||
|
|
- **Highlighting**: Visual indicator when team has multiple participants in same sport
|
|||
|
|
- **Flex Display**: Show "X of Y flexes used" somewhere with team data
|
|||
|
|
- **Scrollable**: Both horizontal and vertical as needed
|
|||
|
|
|
|||
|
|
### Design Decisions
|
|||
|
|
|
|||
|
|
**Teams Drafted Grid:**
|
|||
|
|
1. ✅ **Cell content**: Show participant names (e.g., "Patrick Mahomes, Travis Kelce")
|
|||
|
|
2. ✅ **Cell interactivity**: No clickability needed (existing commissioner context menu on draft board remains)
|
|||
|
|
3. ✅ **Empty cells**: Leave empty (just border, no text)
|
|||
|
|
4. ✅ **Flex display**: In team column header, below team name (similar to timer positioning)
|
|||
|
|
|
|||
|
|
**Tab UI:**
|
|||
|
|
5. ✅ **Tab style**: ShadCN Tabs component
|
|||
|
|
6. ✅ **Recent Picks data**: Same 10 most recent picks as current implementation
|
|||
|
|
|
|||
|
|
**Sidebar:**
|
|||
|
|
7. ✅ **Section sizing**: Accordion-style - both sections collapsible independently
|
|||
|
|
- Both expanded: 50/50 split
|
|||
|
|
- One collapsed: Expanded section takes 100%
|
|||
|
|
- At least one must remain expanded
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Current Implementation Analysis
|
|||
|
|
|
|||
|
|
### File Structure
|
|||
|
|
|
|||
|
|
**Main Route**: `/app/routes/leagues/$leagueId.draft.$seasonId.tsx`
|
|||
|
|
- All draft room logic currently in this single file
|
|||
|
|
- ~1,300 lines of code
|
|||
|
|
- Inline rendering of Queue and Available Participants (not extracted components)
|
|||
|
|
|
|||
|
|
**Related Components**:
|
|||
|
|
- `/app/components/DraftGrid.tsx` - Reusable draft grid (not currently used in draft room)
|
|||
|
|
- `/app/components/AutodraftSettings.tsx` - Autodraft toggle and settings
|
|||
|
|
|
|||
|
|
**Current Layout**:
|
|||
|
|
```
|
|||
|
|
Header (full width, fixed)
|
|||
|
|
├─ Title and metadata
|
|||
|
|
├─ Control buttons (start/pause/resume)
|
|||
|
|
└─ Connection status
|
|||
|
|
|
|||
|
|
Draft Grid (full width, scrollable)
|
|||
|
|
├─ Team headers
|
|||
|
|
└─ Pick grid
|
|||
|
|
|
|||
|
|
3-Column Grid (lg:grid-cols-3)
|
|||
|
|
├─ My Queue (conditional if user has team)
|
|||
|
|
│ ├─ Eligibility status
|
|||
|
|
│ ├─ Queue list (max-h-96)
|
|||
|
|
│ ├─ Autodraft settings
|
|||
|
|
│ └─ Clear button
|
|||
|
|
├─ Recent Picks
|
|||
|
|
│ └─ Last 10 picks (max-h-96)
|
|||
|
|
└─ Available Participants
|
|||
|
|
├─ Search and filters
|
|||
|
|
└─ Participants table (max-h-[500px])
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### State Management
|
|||
|
|
Component state (useState):
|
|||
|
|
- `picks` - All draft picks
|
|||
|
|
- `currentPick` - Current pick number
|
|||
|
|
- `searchQuery` - Participant search term
|
|||
|
|
- `hideDrafted` - Toggle drafted visibility
|
|||
|
|
- `sportFilter` - Active sport filter
|
|||
|
|
- `queue` - User's queue items
|
|||
|
|
- `teamTimers` - Timer for each team
|
|||
|
|
- `autodraftStatus` - Autodraft state per team
|
|||
|
|
- `connectedTeams` - Set of connected team IDs
|
|||
|
|
- `forcePickDialogOpen` - Commissioner dialog state
|
|||
|
|
|
|||
|
|
Real-time updates via Socket.IO:
|
|||
|
|
- `pick-made`
|
|||
|
|
- `timer-update`
|
|||
|
|
- `draft-paused` / `draft-resumed`
|
|||
|
|
- `draft-completed`
|
|||
|
|
- `autodraft-updated`
|
|||
|
|
- `team-connected` / `team-disconnected`
|
|||
|
|
- `participant-removed-from-queues`
|
|||
|
|
|
|||
|
|
### Data Flow
|
|||
|
|
- Loader provides initial data
|
|||
|
|
- Socket.IO provides real-time updates
|
|||
|
|
- Form actions handle queue management and draft actions
|
|||
|
|
- Draft eligibility calculated client-side via `calculateDraftEligibility()`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Proposed Architecture
|
|||
|
|
|
|||
|
|
### New Component Structure
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
leagues/$leagueId.draft.$seasonId.tsx (Main Route)
|
|||
|
|
├─ Full-screen flex container (100vh)
|
|||
|
|
├─ Header (fixed, flex: 0 0 auto)
|
|||
|
|
├─ Content Area (flex: 1 1 auto, flex row)
|
|||
|
|
│ ├─ DraftSidebar (NEW component)
|
|||
|
|
│ │ ├─ Collapse toggle button
|
|||
|
|
│ │ ├─ QueueSection (scrollable)
|
|||
|
|
│ │ └─ AvailableParticipantsSection (scrollable)
|
|||
|
|
│ └─ MainContent (flex: 1 1 auto)
|
|||
|
|
│ ├─ TabSelector (Draft Board | Recent Picks | Teams Drafted)
|
|||
|
|
│ └─ TabContent (scrollable)
|
|||
|
|
│ ├─ DraftBoardTab (uses DraftGrid component)
|
|||
|
|
│ ├─ RecentPicksTab
|
|||
|
|
│ └─ TeamsDraftedTab (NEW)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Files to Create
|
|||
|
|
|
|||
|
|
1. **`/app/components/DraftSidebar.tsx`** (NEW)
|
|||
|
|
- Collapsible sidebar container
|
|||
|
|
- Props: collapsed state, queue data, participants data, handlers
|
|||
|
|
- Two internal sections with separate scrolling
|
|||
|
|
|
|||
|
|
2. **`/app/components/draft/QueueSection.tsx`** (NEW, optional)
|
|||
|
|
- Extracted queue rendering logic
|
|||
|
|
- Props: queue, eligibility, autodraft settings, handlers
|
|||
|
|
|
|||
|
|
3. **`/app/components/draft/AvailableParticipantsSection.tsx`** (NEW, optional)
|
|||
|
|
- Extracted participants table logic
|
|||
|
|
- Props: participants, filters, handlers
|
|||
|
|
|
|||
|
|
4. **`/app/components/draft/TeamsDraftedGrid.tsx`** (NEW)
|
|||
|
|
- Grid showing teams × sports with drafted participants
|
|||
|
|
- Props: teams, sports, picks, flex usage
|
|||
|
|
- Highlighting logic for multiple drafts per sport
|
|||
|
|
|
|||
|
|
5. **`/app/components/draft/DraftTabs.tsx`** (NEW, optional)
|
|||
|
|
- Tab selector and content container
|
|||
|
|
- Props: active tab, tab change handler, children
|
|||
|
|
|
|||
|
|
### Files to Modify
|
|||
|
|
|
|||
|
|
1. **`/app/routes/leagues/$leagueId.draft.$seasonId.tsx`**
|
|||
|
|
- Add full-screen layout container
|
|||
|
|
- Add sidebar collapsed state
|
|||
|
|
- Add active tab state
|
|||
|
|
- Import and render DraftSidebar
|
|||
|
|
- Render tabbed main content
|
|||
|
|
- Remove 3-column grid layout
|
|||
|
|
- Remove Recent Picks section (moved to tab)
|
|||
|
|
|
|||
|
|
2. **`/app/components/DraftGrid.tsx`**
|
|||
|
|
- Ensure it works in flex container
|
|||
|
|
- May need height/overflow adjustments
|
|||
|
|
|
|||
|
|
### State Additions
|
|||
|
|
|
|||
|
|
Add to main route component:
|
|||
|
|
```typescript
|
|||
|
|
const [sidebarCollapsed, setSidebarCollapsed] = useState(() => {
|
|||
|
|
// Check localStorage for user preference
|
|||
|
|
const stored = localStorage.getItem('draftSidebarCollapsed');
|
|||
|
|
return stored ? JSON.parse(stored) : false; // Default: expanded
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const [activeTab, setActiveTab] = useState<'board' | 'picks' | 'teams'>('board');
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## CSS/Styling Strategy
|
|||
|
|
|
|||
|
|
### Layout CSS
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
/* Main container */
|
|||
|
|
.draft-room-container {
|
|||
|
|
height: 100vh;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Header */
|
|||
|
|
.draft-room-header {
|
|||
|
|
flex: 0 0 auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Content area */
|
|||
|
|
.draft-room-content {
|
|||
|
|
flex: 1 1 auto;
|
|||
|
|
display: flex;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Sidebar */
|
|||
|
|
.draft-sidebar {
|
|||
|
|
flex: 0 0 auto;
|
|||
|
|
width: 350px; /* Expanded */
|
|||
|
|
transition: width 0.3s ease, transform 0.3s ease;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.draft-sidebar.collapsed {
|
|||
|
|
width: 50px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Sidebar sections */
|
|||
|
|
.sidebar-section {
|
|||
|
|
flex: 0 0 auto; /* Queue: take what you need */
|
|||
|
|
overflow-y: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.sidebar-section.grow {
|
|||
|
|
flex: 1 1 auto; /* Available Participants: take remaining */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Main content */
|
|||
|
|
.draft-main-content {
|
|||
|
|
flex: 1 1 auto;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* Tab content */
|
|||
|
|
.draft-tab-content {
|
|||
|
|
flex: 1 1 auto;
|
|||
|
|
overflow-y: auto;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Responsive Breakpoints
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
/* Mobile (<1024px) */
|
|||
|
|
@media (max-width: 1023px) {
|
|||
|
|
.draft-sidebar {
|
|||
|
|
position: fixed;
|
|||
|
|
top: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
bottom: 0;
|
|||
|
|
width: 100%;
|
|||
|
|
z-index: 50;
|
|||
|
|
transform: translateX(-100%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.draft-sidebar.open {
|
|||
|
|
transform: translateX(0);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Teams Drafted Grid Styling
|
|||
|
|
|
|||
|
|
```css
|
|||
|
|
.teams-grid {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: 150px repeat(auto-fit, minmax(120px, 1fr));
|
|||
|
|
overflow: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.teams-grid-cell {
|
|||
|
|
border: 1px solid var(--border);
|
|||
|
|
padding: 0.5rem;
|
|||
|
|
min-height: 60px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.teams-grid-cell.multiple-picks {
|
|||
|
|
background-color: var(--accent);
|
|||
|
|
font-weight: 600;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Implementation Steps
|
|||
|
|
|
|||
|
|
### Phase 1: Setup and Layout Structure
|
|||
|
|
- [x] Create plans directory and documentation
|
|||
|
|
- [ ] Add sidebar collapsed state with localStorage persistence
|
|||
|
|
- [ ] Add active tab state
|
|||
|
|
- [ ] Create full-screen layout container in main route
|
|||
|
|
- [ ] Update header to work with new layout
|
|||
|
|
- [ ] Test basic layout structure
|
|||
|
|
|
|||
|
|
### Phase 2: Sidebar Component
|
|||
|
|
- [ ] Create DraftSidebar.tsx component shell
|
|||
|
|
- [ ] Add collapse/expand toggle button
|
|||
|
|
- [ ] Move Queue section rendering to sidebar
|
|||
|
|
- [ ] Move Available Participants section to sidebar
|
|||
|
|
- [ ] Add internal scrolling for both sections
|
|||
|
|
- [ ] Test sidebar functionality and transitions
|
|||
|
|
- [ ] Add mobile modal behavior
|
|||
|
|
|
|||
|
|
### Phase 3: Tab System
|
|||
|
|
- [ ] Create tab selector UI (choose style based on user feedback)
|
|||
|
|
- [ ] Add Draft Board tab (use existing grid)
|
|||
|
|
- [ ] Add Recent Picks tab (move existing section)
|
|||
|
|
- [ ] Create TeamsDraftedGrid component
|
|||
|
|
- [ ] Implement Teams Drafted grid logic
|
|||
|
|
- [ ] Add flex usage display
|
|||
|
|
- [ ] Add highlighting for multiple picks
|
|||
|
|
- [ ] Test tab switching and content rendering
|
|||
|
|
|
|||
|
|
### Phase 4: Refinement
|
|||
|
|
- [ ] Adjust spacing and padding throughout
|
|||
|
|
- [ ] Test all Socket.IO real-time updates
|
|||
|
|
- [ ] Test all form actions (queue management, making picks)
|
|||
|
|
- [ ] Test responsive behavior (desktop, tablet, mobile)
|
|||
|
|
- [ ] Add keyboard shortcuts (optional)
|
|||
|
|
- [ ] Performance testing with large datasets
|
|||
|
|
- [ ] Accessibility audit (ARIA labels, focus management)
|
|||
|
|
|
|||
|
|
### Phase 5: Polish
|
|||
|
|
- [ ] Animation tuning
|
|||
|
|
- [ ] Dark mode verification
|
|||
|
|
- [ ] Cross-browser testing
|
|||
|
|
- [ ] User acceptance testing
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Notes
|
|||
|
|
|
|||
|
|
- Preserve all existing Socket.IO functionality
|
|||
|
|
- Maintain commissioner-specific features (force pick, context menus)
|
|||
|
|
- Keep eligibility calculation logic unchanged
|
|||
|
|
- Ensure autodraft integration remains functional
|
|||
|
|
- Test with various screen sizes and data volumes
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Success Criteria
|
|||
|
|
|
|||
|
|
- [ ] Draft room fills viewport (no page scroll)
|
|||
|
|
- [ ] Sidebar collapses/expands smoothly
|
|||
|
|
- [ ] All three tabs render correctly
|
|||
|
|
- [ ] Teams Drafted grid shows accurate data
|
|||
|
|
- [ ] Queue and Available Participants work as before
|
|||
|
|
- [ ] All real-time updates continue to work
|
|||
|
|
- [ ] Mobile experience is usable
|
|||
|
|
- [ ] No regressions in existing functionality
|
|||
|
|
- [ ] Performance is acceptable (no lag during picks/updates)
|