- Full-width 4:3 aspect ratio hero image area with rounded corners
- Placeholder state: gray background with ImagePlus icon and helper text
- Preview state: object-cover image with circular X remove button
- Upload state: semi-transparent spinner overlay
- Entire area clickable to upload/replace image
- Moved ImageUpload to first element in both ItemForm and CandidateForm
- Removed redundant "Image" label wrappers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Root cause: Zod schemas for createItem and createCandidate did not
include imageFilename field, so @hono/zod-validator silently stripped
it from validated payloads before reaching the service layer
- Images uploaded successfully but filename was never persisted to DB
- Added imageFilename as optional string to both createItemSchema and
createCandidateSchema
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add createThreadModalOpen state to uiStore with open/close actions
- Create CreateThreadModal with name input and category dropdown
- Modal submits via useCreateThread with name + categoryId
- Fix pre-existing formatting in uiStore.ts (spaces to tabs)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add categoryId column with FK to categories on threads table
- Update createThreadSchema to require categoryId
- Update updateThreadSchema to allow optional categoryId
- Update test helper CREATE TABLE to include category_id
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create SetupCard component with name, item count, weight, cost display
- Build setups list page with inline create form and grid layout
- Build setup detail page with category-grouped items and sticky totals bar
- Create ItemPicker component in SlideOutPanel with category-grouped checkboxes
- Add onRemove prop to ItemCard for non-destructive setup item removal
- Setup detail has delete confirmation dialog with collection safety note
- Empty states for both setup list and setup detail pages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move collection view from / to /collection with gear/planning tabs
- Rewrite / as dashboard with three summary cards (Collection, Planning, Setups)
- Refactor TotalsBar to accept optional stats/linkTo/title props
- Create DashboardCard component for dashboard summary cards
- Create useSetups hooks (CRUD + sync/remove item mutations)
- Update __root.tsx with route-aware TotalsBar, FAB visibility, resolve navigation
- Add item picker and setup delete UI state to uiStore
- Invalidate setups queries on item update/delete for stale data prevention
- Update routeTree.gen.ts with new collection/setups routes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Setup service with CRUD, syncSetupItems, removeSetupItem
- SQL aggregation for itemCount, totalWeight, totalCost via COALESCE
- Hono routes for all 7 endpoints with zValidator
- Mount setupRoutes at /api/setups
- All 87 tests pass (24 new setup tests)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add setups and setupItems tables to DB schema
- Add Zod schemas for setup create/update/sync
- Add Setup/SetupItem types to shared types
- Add setup tables to test helper
- Write service and route tests (RED - no implementation yet)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create CandidateCard with edit, delete, and pick winner actions
- Create CandidateForm with same fields as ItemForm for candidate add/edit
- Build thread detail page with candidate grid and resolution banner
- Update root layout with candidate panel, delete dialog, and resolve dialog
- Hide FAB on thread detail pages, keep it for gear tab
- Resolution navigates back to planning tab after success
- Thread CRUD: GET /, POST /, GET /:id, PUT /:id, DELETE /:id
- Candidate CRUD: POST /:id/candidates, PUT/DELETE nested candidates
- Resolution: POST /:id/resolve with validation and error handling
- Image cleanup on thread/candidate deletion
- Routes mounted at /api/threads in server index
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Thread CRUD: create, update, delete with cascade candidate cleanup
- Candidate CRUD: create, update, delete with all item-compatible fields
- getAllThreads with subquery aggregates for candidateCount and price range
- getThreadWithCandidates with candidate+category join
- resolveThread: atomic transaction creating collection item from candidate data
- Category fallback to Uncategorized on resolution if category deleted
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add threads and threadCandidates tables to Drizzle schema
- Add Zod schemas for thread/candidate/resolve validation
- Add Thread/ThreadCandidate types to shared types
- Update test helper with threads and thread_candidates tables
- Write comprehensive failing tests for thread service
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Settings API: GET/PUT /api/settings/:key with SQLite persistence
- useSettings hook with TanStack Query for settings CRUD
- OnboardingWizard: 3-step modal overlay (welcome, create category, add item)
- Root layout checks onboarding completion flag before rendering wizard
- Skip option available at every step, all paths persist completion to DB
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CategoryPicker combobox with search, select, and inline create
- SlideOutPanel with backdrop, escape key, and slide animation
- ItemForm with all fields, validation, dollar-to-cents conversion
- Root layout with TotalsBar, panel, confirm dialog, and floating add button
- Collection page with card grid grouped by category, empty state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- API fetch wrapper with error handling and multipart upload
- Weight/price formatters for display
- TanStack Query hooks for items, categories, and totals with cache invalidation
- Zustand UI store for panel and confirm dialog state
- TotalsBar, CategoryHeader, ItemCard, ConfirmDialog, ImageUpload components
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Item routes: GET, POST, PUT, DELETE with Zod validation and image cleanup
- Category routes: GET, POST, PUT, DELETE with Uncategorized protection
- Totals route: per-category and global aggregates
- Image upload: multipart file handling with type/size validation
- Routes use DI via Hono context variables for testability
- Integration tests: 10 tests covering all endpoints and edge cases
- All 30 tests passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Item CRUD: getAllItems with category join, getById, create, update, delete
- Category CRUD: getAll ordered by name, create, update, delete with reassignment
- Totals: per-category aggregates and global totals via SQL SUM/COUNT
- All 20 service tests passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Create Drizzle schema with items, categories, and settings tables
- Set up database connection singleton with WAL mode and foreign keys
- Add seed script for default Uncategorized category
- Create shared Zod validation schemas for items and categories
- Export TypeScript types inferred from Zod and Drizzle schemas
- Add in-memory SQLite test helper for isolated test databases
- Wire seed into Hono server startup
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Initialize bun project with all frontend/backend dependencies
- Configure Vite with TanStack Router plugin, React, and Tailwind v4
- Create Hono server with health check and static file serving
- Set up TanStack Router file-based routes with root layout
- Add Drizzle config, Biome linter, and proper .gitignore
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>