# Implementation Plan: Queue Collapsible Sections ## Overview Add collapsible, grouped sections to the IvantiTodoQueuePage. Items are organized into a hybrid layout: an "Inventory" section (CARD, GRANITE, DECOM workflow types) at the top, followed by vendor-grouped sections for FP and Archer items. Each section has a clickable header that toggles visibility. This is a frontend-only change to a single file with property-based tests for the grouping logic. ## Tasks - [x] 1. Add section header styles and icon imports - [x] 1.1 Add ChevronDown and ChevronRight to the lucide-react import statement - Add `ChevronDown, ChevronRight` to the existing import from `lucide-react` - _Requirements: 5.2_ - [x] 1.2 Add section header style entries to the STYLES constant - Add `sectionHeaderInventory`, `sectionHeaderVendor`, and `sectionCount` style objects to the existing `STYLES` constant - Use green accent (`#10B981`) for Inventory header, neutral (`#94A3B8`) for vendor headers - Include `cursor: 'pointer'`, `userSelect: 'none'`, monospace font, uppercase text - _Requirements: 3.3, 3.4, 3.5, 5.1, 5.3_ - [x] 2. Implement grouping computation and collapse state - [x] 2.1 Add the `groupedSections` useMemo hook - Add a `useMemo` that transforms `visibleItems` into an array of section objects `{ key, label, type, items }` - Items with workflow_type CARD, GRANITE, or DECOM go into the Inventory section - Remaining items are grouped by vendor field (null/empty vendor → "Unknown") - Inventory section appears first (if non-empty), vendor sections sorted alphabetically - Sections with zero items are omitted - _Requirements: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7_ - [x] 2.2 Add collapse state and toggle handler - Add `const [collapsedSections, setCollapsedSections] = useState({})` for collapse tracking - Add `toggleSection` callback that flips the boolean for a given section key - All sections default to expanded (empty object → falsy lookup) - _Requirements: 2.2, 2.7_ - [x] 3. Refactor render to use grouped sections with collapsible headers - [x] 3.1 Replace flat `visibleItems.map(...)` with grouped section rendering - Map over `groupedSections` instead of `visibleItems` directly - For each section, render a clickable Section Header with chevron icon, label, and item count - Conditionally render section body (item rows) only when section is not collapsed - Preserve existing queue item row rendering logic inside each section body - Add `role="button"`, `tabIndex={0}`, `aria-expanded`, `aria-label` to section headers for accessibility - _Requirements: 2.1, 2.3, 2.4, 2.5, 2.6, 3.1, 3.2_ - [x] 3.2 Verify cross-section selection still works correctly - Ensure Select All checkbox still toggles all `visibleItems` across all sections regardless of collapse state - Ensure selection count reflects total selected items across all sections - Ensure floating action bar operates on all selected items regardless of collapse state - Ensure collapsing a section does not clear or modify `selectedIds` - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6_ - [x] 3.3 Verify existing functionality is preserved - Ticket link badges continue to display on items with associated Jira tickets - Consolidation modal continues to function with selected items - Floating action bar appears when items are selected - Completed items count still displays at the bottom - Empty state renders without section headers when no visible items exist - _Requirements: 5.4, 5.5, 5.6, 5.7, 5.8_ - [x] 4. Checkpoint - Ensure frontend builds successfully - Ensure all tests pass, ask the user if questions arise. - [x] 5. Write property-based tests for grouping logic - [x]* 5.1 Write property test: Grouping Correctness - **Property 1: Grouping Correctness** - Every item with workflow_type CARD, GRANITE, or DECOM appears in the Inventory section; every FP/Archer item appears in the vendor section matching its vendor field (or "Unknown" if null/empty); no item appears in more than one section - Extract the grouping logic into a testable pure function or test it inline - **Validates: Requirements 1.1, 1.2, 1.5** - [x]* 5.2 Write property test: Section Ordering - **Property 2: Section Ordering** - Inventory section (if present) is always first; vendor sections are sorted alphabetically by label - **Validates: Requirements 1.3, 1.4** - [x]* 5.3 Write property test: Empty Section Omission - **Property 3: Empty Section Omission** - No section in the output has zero items; if no inventory-type items exist, no Inventory section appears - **Validates: Requirements 1.6, 1.7** - [x]* 5.4 Write property test: Section Header Count Accuracy - **Property 4: Section Header Count Accuracy** - For every section, the items array length equals the count that would be displayed in the header - **Validates: Requirements 3.1, 3.2** - [x]* 5.5 Write property test: Selection Independence from Collapse State - **Property 5: Selection Independence from Collapse State** - Toggling collapse state does not alter the set of selected item IDs; Select All always covers all visible items regardless of collapse - **Validates: Requirements 4.2, 4.4, 4.5** - [x] 6. Final checkpoint - Ensure all tests pass - Ensure all tests pass, ask the user if questions arise. ## Notes - Tasks marked with `*` are optional and can be skipped for faster MVP - This is a frontend-only change to a single file: `frontend/src/components/pages/IvantiTodoQueuePage.js` - Property tests should use `fast-check` (already a project dependency) and extract the grouping logic as a pure function for testability - The selection logic (`selectedIds`, `toggleSelectAll`, `allVisibleSelected`) operates on `visibleItems` which is independent of collapse state — no changes needed to selection logic - The collapse state is purely visual — it controls rendering, not data ## Task Dependency Graph ```json { "waves": [ { "id": 0, "tasks": ["1.1", "1.2"] }, { "id": 1, "tasks": ["2.1", "2.2"] }, { "id": 2, "tasks": ["3.1"] }, { "id": 3, "tasks": ["3.2", "3.3"] }, { "id": 4, "tasks": ["5.1", "5.2", "5.3", "5.4", "5.5"] } ] } ```