Adds Gear/Planning/Setups pill tabs to the collection page so users
can switch tabs without going back to the dashboard. Also skips
React Query retries on 404 responses for immediate error display.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds export (GET /api/items/export) and import (POST /api/items/import) routes
backed by a pure csv.service with no external deps, plus useExportItems/useImportItems
hooks and an Import/Export section in the Settings page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds SetupImpactSelector dropdown and ImpactDeltaBadge inline badge, wired into the thread detail page. Delta badges appear on CandidateListItem, CandidateCard, and ComparisonTable (Weight Impact / Price Impact rows) whenever a setup is selected for comparison.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- totals.service: multiply weight/cost sums by quantity in category and global totals
- setup.service: multiply by quantity in getAllSetups SQL subqueries; expose quantity in getSetupWithItems item list
- thread.service: explicitly pass quantity: 1 when inserting resolved item
- ItemForm: add Quantity number input (min=1, default=1) after price field
- ItemCard: show ×N badge next to item name when quantity > 1
- CollectionView: pass quantity prop to ItemCard in both filtered and grouped views
- $setupId.tsx: pass quantity to ItemCard; multiply by quantity in client-side per-setup totals
- WeightSummaryCard: multiply by quantity in all chart and legend weight calculations
- useItems / useSetups: add quantity to ItemWithCategory / SetupItemWithCategory interfaces
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Created useFormatters() combining useWeightUnit + useCurrency + formatWeight/formatPrice
into a single hook returning weight(grams) and price(cents) bound functions plus
raw unit and currency values. Updated all 14 consumer files to use the new hook,
removing the repeated 4-import + 2-hook-call pattern from each.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves CollectionView, PlanningView, and SetupsView out of the 634-line collection/index.tsx into dedicated component files. Pure extraction — zero logic changes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a TanStack Router error boundary to the root route so rendering errors or uncaught React Query failures show a friendly error page instead of white-screening the app. The error boundary displays a professional error message with a "Try again" button that resets state and invalidates router data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Exclude drizzle/ and .planning/ from Biome (generated files with
incompatible formatting). Auto-fix import ordering and formatting
in existing source files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The wizard creates categories via POST which requires auth.
Gate the wizard on isAuthenticated so users create their
account first via Sign In, then the wizard appears.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extend uiStore candidateViewMode union to include "compare" value
- Add columns-3 compare toggle button, shown only when thread has 2+ candidates
- Hide "Add Candidate" button when in compare view (read-only intent)
- Import and render ComparisonTable when candidateViewMode === "compare"
- Pass displayItems so compare view reflects any pending reorder state
- Existing list/grid views unchanged; all 135 tests pass
onPointerUp was incorrectly placed on the resolved-thread div instead
of the active-thread Reorder.Group, causing drag reorder to not persist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redesign WeightSummaryCard stats from a disconnected 4-column grid to a
compact legend-style list with color dots, percentages, and a divider
before the total row. Switch chart and legend colors to a neutral gray
palette.
Add a currency selector to settings (USD, EUR, GBP, JPY, CAD, AUD) that
changes the displayed symbol across the app. This is visual only — no
value conversion is performed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- StatusBadge: clickable pill badge with popup menu (researching/ordered/arrived)
- Muted gray styling, LucideIcon per status, click-outside dismiss, Escape key support
- CandidateCard: status + onStatusChange props, StatusBadge in pill row after category
- Thread detail page: passes candidate.status and useUpdateCandidate for onStatusChange
- Fix Biome formatting for candidateStatusSchema enum
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Sticky search/filter toolbar with text input and CategoryFilterDropdown
- useMemo-based filtering by name (search) and categoryId (dropdown)
- "Showing X of Y items" count when filters active
- Flat grid (no category headers) when any filter is active
- "No items match your search" empty state for filtered results
- Replace PlanningView native select with CategoryFilterDropdown
- Add segmented g/oz/lb/kg toggle to TotalsBar with settings persistence
- Pass unit parameter to all 8 formatWeight call sites across components and routes
- Import useWeightUnit hook in ItemCard, CandidateCard, CategoryHeader, SetupCard, ItemPicker, Dashboard, SetupDetail
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Setups now lives alongside My Gear and Planning under /collection?tab=setups
instead of its own /setups route. Dashboard card updated to link to the new
tab. Setup detail pages (/setups/:id) remain unchanged.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch all interactive UI elements (buttons, focus rings, active tabs,
FAB, links, spinners) from blue to gray to match icon colors for a
more cohesive look. Mute card badge text colors to pastels (blue-400,
green-500, purple-500) to keep the focus on card content.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Run biome check --write --unsafe to fix tabs, import ordering, and
non-null assertions across entire codebase. Disable a11y rules not
applicable to this single-user app. Exclude auto-generated routeTree.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Show an external link icon on ItemCard and CandidateCard that opens a
confirmation dialog before navigating to product URLs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace all raw emoji characters in dashboard cards, empty states,
and onboarding wizard with LucideIcon components for visual consistency.
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>
- 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
- 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>
- 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>