--- phase: 09-weight-classification-and-visualization plan: 01 subsystem: database, api, ui tags: [drizzle, sqlite, hono, react, tailwind, classification, setup-items] # Dependency graph requires: - phase: 08-search-filter-and-candidate-status provides: StatusBadge pattern for click-interactive badges, muted gray styling convention provides: - classification column on setupItems join table (base/worn/consumable) - updateItemClassification service function - classification-preserving syncSetupItems - PATCH /api/setups/:id/items/:itemId/classification endpoint - ClassificationBadge click-to-cycle component - apiPatch client helper - useUpdateItemClassification mutation hook affects: [09-02-weight-breakdown-visualization] # Tech tracking tech-stack: added: [] patterns: [click-to-cycle badge, classification preservation on sync, per-join-table metadata] key-files: created: - src/client/components/ClassificationBadge.tsx - drizzle/0003_misty_mongu.sql modified: - src/db/schema.ts - src/shared/schemas.ts - src/shared/types.ts - src/server/services/setup.service.ts - src/server/routes/setups.ts - src/client/lib/api.ts - src/client/hooks/useSetups.ts - src/client/routes/setups/$setupId.tsx - tests/helpers/db.ts - tests/services/setup.service.test.ts - tests/routes/setups.test.ts key-decisions: - "ClassificationBadge uses simple click-to-cycle (not popup) since only 3 values" - "Classification stored on setupItems join table so same item can differ across setups" - "syncSetupItems reads classifications into Map before delete, restores after re-insert" patterns-established: - "Click-to-cycle badge: for small enums (3 values), direct click cycling is simpler than popup" - "Join table metadata preservation: save metadata before atomic sync, restore after re-insert" - "apiPatch helper: PATCH method available in client API library for partial updates" requirements-completed: [CLAS-01, CLAS-03, CLAS-04] # Metrics duration: 5min completed: 2026-03-16 --- # Phase 9 Plan 1: Classification Schema and Badge Summary **Per-setup item classification (base/worn/consumable) with click-to-cycle badge, classification-preserving sync, and full test coverage** ## Performance - **Duration:** 5 min - **Started:** 2026-03-16T14:08:56Z - **Completed:** 2026-03-16T14:13:32Z - **Tasks:** 2 - **Files modified:** 12 ## Accomplishments - Added classification column to setupItems table with Drizzle migration (defaults to "base") - Implemented classification-preserving syncSetupItems that saves/restores classifications across atomic re-sync - Built PATCH endpoint with Zod validation for updating item classification within a setup - Created ClassificationBadge component with click-to-cycle interaction (base weight -> worn -> consumable) - Wired badge into setup detail page below each ItemCard in the category-grouped grid - Added apiPatch client helper and useUpdateItemClassification mutation hook - 7 new tests (5 service, 2 route) covering classification CRUD, preservation, cross-setup independence, and validation ## Task Commits Each task was committed atomically: 1. **Task 1: Schema migration, service layer, and tests for classification** - `4491e4c` (feat - TDD red/green) 2. **Task 2: API route, client hook, ClassificationBadge, and wiring** - `fb738d7` (feat) ## Files Created/Modified - `src/db/schema.ts` - Added classification column to setupItems table - `drizzle/0003_misty_mongu.sql` - SQLite migration for classification column - `src/shared/schemas.ts` - Added classificationSchema and updateClassificationSchema - `src/shared/types.ts` - Added UpdateClassification type - `src/server/services/setup.service.ts` - Added updateItemClassification, modified getSetupWithItems and syncSetupItems - `src/server/routes/setups.ts` - Added PATCH /:id/items/:itemId/classification endpoint - `src/client/lib/api.ts` - Added apiPatch helper - `src/client/hooks/useSetups.ts` - Added classification field and useUpdateItemClassification hook - `src/client/components/ClassificationBadge.tsx` - New click-to-cycle badge component - `src/client/routes/setups/$setupId.tsx` - Wired ClassificationBadge into item grid - `tests/helpers/db.ts` - Added classification column to test schema - `tests/services/setup.service.test.ts` - Added 5 classification tests - `tests/routes/setups.test.ts` - Added 2 classification integration tests ## Decisions Made - ClassificationBadge uses simple click-to-cycle rather than popup (only 3 values, simpler UX) - Classification stored on setupItems join table (not items table) so same item can have different roles in different setups - syncSetupItems preserves classifications by reading into Map before delete and restoring after re-insert ## Deviations from Plan None - plan executed exactly as written. ## Issues Encountered None ## User Setup Required None - no external service configuration required. ## Next Phase Readiness - Classification data is available for weight breakdown visualization (Plan 09-02) - getSetupWithItems returns classification field for every item, ready for grouping by classification - All 121 tests pass across the full suite ## Self-Check: PASSED All 14 files verified present. Both task commits (4491e4c, fb738d7) confirmed in git history. --- *Phase: 09-weight-classification-and-visualization* *Completed: 2026-03-16*