From edf76f50db59e16072b933fbf713b85790c4d287 Mon Sep 17 00:00:00 2001 From: Erik Date: Wed, 15 Jul 2026 05:57:10 +0200 Subject: [PATCH] =?UTF-8?q?docs(spec):=20inventory=20search=20redesign=20?= =?UTF-8?q?=E2=80=94=20React=20full-page=20view=20+=20approved=20mockup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 --- .gitignore | 1 + ...-07-15-inventory-search-redesign-design.md | 115 +++++++ ...7-15-inventory-search-redesign-mockup.html | 294 ++++++++++++++++++ 3 files changed, 410 insertions(+) create mode 100644 docs/superpowers/specs/2026-07-15-inventory-search-redesign-design.md create mode 100644 docs/superpowers/specs/2026-07-15-inventory-search-redesign-mockup.html diff --git a/.gitignore b/.gitignore index b523c6d7..d9c8ee36 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ frontend/node_modules/ # permission-neutral so devs can `claude` interactively here without # inheriting production-agent restrictions. .claude/ +.superpowers/ diff --git a/docs/superpowers/specs/2026-07-15-inventory-search-redesign-design.md b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-design.md new file mode 100644 index 00000000..c5ef6caa --- /dev/null +++ b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-design.md @@ -0,0 +1,115 @@ +# Inventory Search redesign — React full-page view + +**Date:** 2026-07-15 +**Status:** Approved (layout + behaviors validated interactively in visual-companion mockup) +**Mockup:** `2026-07-15-inventory-search-redesign-mockup.html` (same directory — the approved clickable reference) + +## Problem + +The inventory search UI (`static/inventory.html` + `inventory.js`, ~2100 lines of +2010s-era dense gray vanilla HTML) is functionally complete (all filters work +against the Go `inventory-go` service, including the July 2026 spell filters) +but visually dated and inconsistent with the React dashboard. Full redesign +requested. + +## Decisions (user-validated) + +1. **Platform:** new full-page view in the existing React app (`frontend/`), + reached via `/?view=inventory` — same routing pattern as `?view=dashboard` + in `App.tsx`. +2. **Layout:** facet sidebar (direction A of three mocked options) + active- + filter chips row borrowed from direction B. +3. **Search trigger:** instant auto-search, debounced ~400 ms, no Search + button; in-flight requests aborted via `AbortController`. +4. **Item details:** right-side detail panel opened by row click; ↑/↓ moves + selection, Esc closes. +5. **Set analysis:** dropped entirely. The new page fully replaces + `inventory.html`/`inventory.js` — both deleted at cutover; the "Analyze + Sets" feature ceases to exist. +6. **Shareable URLs:** filter state serialized to the query string. + +## Layout (per approved mockup) + +- **Top bar:** title, name/material search box (`text` param), Reset (clears + all filters), column picker (⚙), result count + query time. +- **Chips row:** one removable chip per active filter; legendary-cantrip chips + styled gold (#fc6 on #2a2418). +- **Facet sidebar** (~210 px, collapsible groups with active-count badges): + - **Characters** — searchable checkbox list, All/None/Online links, green + online dots (from the `/live` data the app already polls). + - **Item type** — radios: All / Armor / Jewelry / Weapons (+subtype) / + Clothing (maps to `armor_only`/`jewelry_only`/`weapon_only`+`weapon_type`/ + `clothing_only`; shirts/pants reachable as clothing subtypes). + - **Slots** — jewelry slots (Ring/Bracelet/Neck/Trinket/Cloak) up front, + armor slots behind a "show armor slots" expander (`slot_names` CSV). + - **Cantrips** — find-as-you-type filter over the legendary cantrip list, + grouped (Attributes / Skills / Defense / Banes / Other); checked items pin + to a "Selected" section on top; gold styling; plus an "any-tier spell + search" text input (`spell_contains`). Checkbox values = the same display + names the old page sent (`legendary_cantrips` CSV, AND semantics). + - **Ratings** (collapsed) — min inputs for the 4 common ratings, "all 20 + ratings" expander for the rest (`min_*` params). + - **Equipment sets** (collapsed) — searchable set list (`item_set`/`item_sets`). + - **Item state** (collapsed) — equipped-only, bonded, attuned, rare + (`equipment_status`, `bonded`, `attuned`, `is_rare`). + - **Reqs & value** (collapsed) — wield level ≤, value ≥, workmanship ≥, + burden ≤ (`max_level`, `min_value`, `min_workmanship`, `max_burden`). +- **Results table:** server-side sort via `sort_by`/`sort_dir` (click headers); + sticky header; equipped marker (green ⚔); Spells column with legendary names + gold; pagination footer (200/page default, `page`/`limit`). Column set + togglable via the ⚙ picker, persisted to `localStorage`. +- **Detail panel** (~250 px): item name, slot, equipped state, character, + value/burden/wield/workmanship/mana, full ordered spell list (legendary + gold). Keyboard: ↑/↓/Esc. + +## Implementation shape + +- **No backend changes.** The existing `GET /api/inv/search/items` supports + every filter above (validated; the spell filters shipped 2026-07-14). +- New directory `frontend/src/components/inventory/`: + - `InventorySearchPage.tsx` — page layout, keyboard handling. + - `FilterSidebar.tsx` + one small component per filter group. + - `ActiveChips.tsx`, `ResultsTable.tsx`, `DetailPanel.tsx`. + - `useInventorySearch.ts` — single-reducer filter state, debounce, + AbortController fetch, URL (de)serialization. +- Filter state ↔ URL: serialize non-default filters into query params on + change (replaceState), parse on mount — bookmarkable searches. +- Styling: `frontend/src/styles/inventory.css`, `.inv-*` class prefix, + dashboard dark tokens (#111 bg, #1a1a1a panels, #333 borders, #88f accent, + #fc6 legendary gold, Segoe UI) — mirrors `map-layout.css` conventions. +- **No new npm dependencies.** +- Cantrip list + grouping: lift the value strings from the old + `inventory.html` checkbox grid (they are the strings the backend matches); + store as a typed constant module. +- Character list: reuse the app's existing live-players data source for names + + online status; fall back to `/api/inv/characters/list` for characters that + are offline/never online. + +## Cutover + +Same commit series: add the new view → repoint the dashboard tool-link that +currently opens `/inventory.html` to `/?view=inventory` → delete +`static/inventory.html` and `static/inventory.js`. `/inventory.html` then 404s +to the SPA fallback; acceptable (single-user tool, no external links). + +## Testing & verification + +The frontend has no test framework (build = `tsc -b && vite build`). +Verification per task: TypeScript build green + live checks in the Vite dev +server against the production API, then post-deploy spot checks of the same +scenarios used for the spell-filter validation (Invuln+Summon → 2 items; +Ring+Invuln → 56; filterless jewelry → ~4.8k). Adding a test harness is out +of scope. + +## Deploy + +`bash deploy-frontend.sh` (builds + copies into `static/`), commit `static/` ++ `frontend/` + deletions, push; server picks it up via bind mount, no +restart. + +## Out of scope + +- Set analysis (dropped per decision 5). +- Suitbuilder page (untouched). +- React-window (`InventoryWindow.tsx`) per-character inventory — unrelated. +- Mobile layout (desktop tool); no test framework introduction. diff --git a/docs/superpowers/specs/2026-07-15-inventory-search-redesign-mockup.html b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-mockup.html new file mode 100644 index 00000000..f019183c --- /dev/null +++ b/docs/superpowers/specs/2026-07-15-inventory-search-redesign-mockup.html @@ -0,0 +1,294 @@ + + + + +Inventory Search — mockup + + + + +
+ ⚔ Inventory Search + + + + 56 items · 24 ms +
+ +
+ ACTIVE + Jewelry × + Slot: Ring × + Legendary Invulnerability × + Legendary Summoning × +
+ +
+ + + +
+ + + + + +
ItemCharacterSlotValueWieldSpells / Cantrips
+
+ 123 + 200 / page +
+
+ +
+ +
+ + + +