From 03d1cd2bb6523e78911a0989ae025d54c657bba8 Mon Sep 17 00:00:00 2001 From: jtricerolph Date: Wed, 22 Jul 2026 09:53:17 +0000 Subject: [PATCH] Restore collapsible filter accordions alongside new sort chip Status and Filters dropdowns are back as expanding chips. Sort chip sits inline to the right of the two accordion headers as a peer element in a flex filter-row. Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/index.css | 27 ++++++++- frontend/src/pages/Summary.tsx | 106 ++++++++++++++++++++++----------- 2 files changed, 95 insertions(+), 38 deletions(-) diff --git a/frontend/src/index.css b/frontend/src/index.css index 0f30c1f..91248a8 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -261,8 +261,31 @@ html, body, #root { height: 100%; margin: 0; font-size: 14px; } .badge-unusable { background: var(--danger); } /* ── Filter chips ──────────────────────────────────────────── */ -.chip-bar { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; } -.chip-divider { width: 1px; height: 20px; background: var(--card-border); flex-shrink: 0; margin: 0 2px; } +.filter-row { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 4px; } +.filter-row .filter-section { flex: 1; min-width: 0; margin-bottom: 0; } +.filter-row .sort-chip { flex-shrink: 0; align-self: center; white-space: nowrap; } +.filter-section { margin-bottom: 10px; } +.filter-section-header { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 8px; + background: var(--card-bg); + border: 1px solid var(--card-border); + cursor: pointer; + user-select: none; + font-size: 12px; + color: var(--text-mid); + transition: border-color .12s; +} +.filter-section-header:hover { border-color: var(--gold); } +.filter-section-label { font-weight: 600; color: var(--text-dark); white-space: nowrap; } +.filter-section-summary { flex: 1; color: var(--gold); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.filter-section-summary.muted { color: var(--text-mid); font-weight: 400; } +.filter-section-chevron { flex-shrink: 0; transition: transform .18s; } +.filter-section-chevron.open { transform: rotate(180deg); } +.chip-bar { display: flex; gap: 6px; flex-wrap: wrap; margin: 8px 0 4px; align-items: center; } .chip { display: inline-flex; align-items: center; diff --git a/frontend/src/pages/Summary.tsx b/frontend/src/pages/Summary.tsx index 466510e..e1d8dec 100644 --- a/frontend/src/pages/Summary.tsx +++ b/frontend/src/pages/Summary.tsx @@ -1,5 +1,5 @@ import { useCallback, useEffect, useMemo, useState } from 'react' -import { Plus, RefreshCw, Camera, BedDouble, Layers, ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react' +import { Plus, RefreshCw, Camera, BedDouble, Layers, ChevronDown, ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react' import type { Task, Category, Location, AppConfig, TaskStatus, Priority } from '../types' import { STATUS_LABELS, can } from '../types' import { fetchTasks, fetchLocations, fetchConfig, fetchOccupancy } from '../api' @@ -27,6 +27,9 @@ export default function Summary() { const [roomsView, setRoomsView] = useState(false) const [groupByLocation, setGroupByLocation] = useState(false) + const [statusOpen, setStatusOpen] = useState(false) + const [filtersOpen, setFiltersOpen] = useState(false) + type SortMode = 'default' | 'priority_desc' | 'priority_asc' | 'age_asc' | 'age_desc' const [sortMode, setSortMode] = useState('default') @@ -146,41 +149,72 @@ export default function Summary() { {error &&
{error}
} -
- - {OPEN_STATUSES.map(s => ( - - ))} - - {!roomsView && categories.map(c => ( - - ))} - - {roomsCategoryExists && ( - - )} - - - + {OPEN_STATUSES.map(s => ( + + ))} +
+ )} + + +
+
setFiltersOpen(v => !v)}> + Filters + + {[ + !roomsView && categoryFilter ? categories.find(c => c.id === categoryFilter)?.name : null, + roomsView ? 'Rooms view' : null, + mineOnly ? 'Mine only' : null, + groupByLocation ? 'Grouped' : null, + ].filter(Boolean).join(' · ') || 'All categories'} + + +
+ {filtersOpen && ( +
+ {!roomsView && categories.map(c => ( + + ))} + + {roomsCategoryExists && ( + + )} + +
+ )} +
+ +