homelabby/.planning/phases/03-dashboard-intake-ui/03-03-SUMMARY.md

7.3 KiB

phase plan subsystem tags requires provides affects tech-stack key-files key-decisions duration completed
03-dashboard-intake-ui 03 ui
react
typescript
tanstack-query
tanstack-router
zustand
tailwind
clickhouse-design
inventory
web/src/store/ui.ts (useUIStore — viewMode, setViewMode)
web/src/components/ui/badge.tsx (Badge with status variants)
web/src/components/ui/button.tsx (Button with forest/ghost/outline variants)
web/src/components/ui/card.tsx (Card, CardHeader, CardTitle, CardContent, CardFooter)
internal/api/handlers.InventoryItemResponse (JSON shape from GET /api/inventory)
web/src/lib/api.ts (InventoryItem type, fetchInventory, fetchInventoryItem)
web/src/hooks/useInventory.ts (useInventory, useInventoryItem TanStack Query hooks)
web/src/components/layout/AppShell.tsx (TopBar + main content wrapper)
web/src/components/layout/TopBar.tsx (sticky nav with HWLab branding)
web/src/components/inventory/StatusBadge.tsx (catalog_status color-coded badge)
web/src/components/inventory/ItemCard.tsx (grid card component)
web/src/components/inventory/ItemRow.tsx (list-mode row component)
web/src/components/inventory/FilterBar.tsx (search + status filter + view toggle)
web/src/pages/DashboardPage.tsx (/ route — inventory grid/list)
web/src/pages/ItemDetailPage.tsx (/item/$id route — full detail view)
web/src/router.tsx (indexRoute + itemRoute updated to lazy-load real pages)
03-04, 03-05 (intake + scan pages reuse AppShell and TopBar)
added patterns
TanStack Query useQuery with typed fetchJSON wrapper (no axios)
Zustand viewMode persists grid/list toggle across navigation within session
lazy() + Suspense for route-level code splitting (DashboardPage + ItemDetailPage split into separate chunks)
client-side filter via useMemo — no server-side filtering for <200 items
label-upper CSS class applied to uppercase tracked labels
created modified
web/src/lib/api.ts
web/src/hooks/useInventory.ts
web/src/components/inventory/StatusBadge.tsx
web/src/components/inventory/ItemCard.tsx
web/src/components/inventory/ItemRow.tsx
web/src/components/layout/TopBar.tsx
web/src/components/layout/AppShell.tsx
web/src/components/inventory/FilterBar.tsx
web/src/pages/DashboardPage.tsx
web/src/pages/ItemDetailPage.tsx
web/src/router.tsx
id summary
DASH-01 lazy() + Suspense for DashboardPage and ItemDetailPage — creates separate JS chunks (9.17KB + 4.10KB) keeping initial bundle lean
id summary
DASH-02 Client-side filtering via useMemo on items array — acceptable for <=200 item limit from API; no server-side filter params needed
id summary
DASH-03 fetchJSON generic wraps raw fetch with typed error handling — no axios dependency, consistent with project WHAT NOT TO USE list
12min 2026-04-10

Phase 3 Plan 03: Dashboard + Item Detail Pages Summary

Inventory dashboard and item detail views wired to GET /api/inventory with ClickHouse design (volt/canvas/charcoal), grid/list toggle via Zustand, client-side search+filter, and mobile-responsive two-column detail layout

Performance

  • Duration: ~12 min
  • Completed: 2026-04-10
  • Tasks: 2
  • Files created: 10
  • Files modified: 1

Accomplishments

  • web/src/lib/api.ts — typed fetchInventory / fetchInventoryItem using native fetch with error unwrapping; exports InventoryItem interface matching backend JSON shape
  • web/src/hooks/useInventory.tsuseInventory() and useInventoryItem(id) TanStack Query hooks with proper query keys for cache invalidation
  • AppShell + TopBar — sticky dark header with volt "HWLab" brand, forest-green "Add Item" button, outline "Scan" button; main content area with 7xl max-width
  • StatusBadge — maps catalog_status string to 6 color-coded Badge variants (indexed=green, draft=gray, needs_research=yellow, researched=blue, complete=forest, destructive=red)
  • ItemCard — grid card with aspect-video photo (or Package placeholder icon), volt HW ID, item name, StatusBadge, ai_notes preview (2-line clamp), hover volt border, View in NetBox link
  • ItemRow — list-mode row with 4px status color indicator bar, HW ID, name, badge, ai_notes (hidden on mobile), hover reveal NetBox link
  • FilterBar — search input with icon, catalog_status dropdown, item count label, grid/list toggle (Zustand viewMode)
  • DashboardPage — full inventory view with loading/error/empty states, responsive grid (1→2→3→4→5 cols by breakpoint), list view in border container
  • ItemDetailPage — back nav, header with HW ID + name + status + NetBox action, two-column lg (photos left, fields right) single-column mobile, ai_notes card, test_data pretty-printed JSON code block
  • router.tsx updated — DashboardPage and ItemDetailPage lazy-loaded via lazy() + Suspense with Spinner fallback; intake/scan stubs preserved

Task Commits

  1. Task 1: API client, hooks, layout, components1867846
  2. Task 2: Pages, FilterBar, router wiring19c2bb7

Files Created/Modified

File Purpose
web/src/lib/api.ts Typed fetch wrappers + InventoryItem interface
web/src/hooks/useInventory.ts TanStack Query hooks
web/src/components/inventory/StatusBadge.tsx Status → Badge color mapping
web/src/components/inventory/ItemCard.tsx Grid card (photo, HW ID, name, status, action)
web/src/components/inventory/ItemRow.tsx List-mode row with status color bar
web/src/components/layout/TopBar.tsx Sticky app header with navigation
web/src/components/layout/AppShell.tsx TopBar + main content wrapper
web/src/components/inventory/FilterBar.tsx Search + status filter + view toggle
web/src/pages/DashboardPage.tsx / route — inventory grid/list with filters
web/src/pages/ItemDetailPage.tsx /item/$id route — detail view, mobile responsive
web/src/router.tsx Lazy-loaded real pages replacing stubs

Deviations from Plan

None — plan executed exactly as written.

Known Stubs

None — all data flows from useInventory / useInventoryItem hooks which call the real backend API. No hardcoded or mock data in any component. Empty state and loading state are functional UI states, not stubs.

Threat Surface Coverage

No new network endpoints, auth paths, or trust boundary changes introduced — this plan is purely frontend components consuming the existing GET /api/inventory endpoints established in Plan 03-02.

Self-Check

Files created:

  • web/src/lib/api.ts: FOUND
  • web/src/hooks/useInventory.ts: FOUND
  • web/src/components/inventory/StatusBadge.tsx: FOUND
  • web/src/components/inventory/ItemCard.tsx: FOUND
  • web/src/components/inventory/ItemRow.tsx: FOUND
  • web/src/components/layout/TopBar.tsx: FOUND
  • web/src/components/layout/AppShell.tsx: FOUND
  • web/src/components/inventory/FilterBar.tsx: FOUND
  • web/src/pages/DashboardPage.tsx: FOUND
  • web/src/pages/ItemDetailPage.tsx: FOUND

Commits:

  • 1867846: feat(03-03): API client, TanStack Query hooks, layout shell, inventory item components
  • 19c2bb7: feat(03-03): DashboardPage, ItemDetailPage, FilterBar, and router wiring

npm run build: PASS (1717 modules, 0 TypeScript errors, dist/assets/ written)

Self-Check: PASSED