# Phase 4: Database & Planning Fixes - Context

**Gathered:** 2026-03-15
**Status:** Ready for planning

<domain>
## Phase Boundary

Fix the missing threads/thread_candidates tables in the database, fix thread creation errors, and polish the planning tab UX including empty state, thread creation flow, and list layout. No new thread features (status tracking, comparison, etc.) — those are future phases.

</domain>

<decisions>
## Implementation Decisions

### Empty state design
- Guided + educational tone — explain what threads are for, not just "nothing here"
- Illustrated steps showing the flow: Create thread → Add candidates → Pick winner
- CTA button opens a modal dialog (not inline form)
- Should feel inviting and help new users understand the planning workflow

### Thread creation flow
- Always use a modal dialog for thread creation (both empty state and when threads exist)
- Modal collects: thread name (required) + category (required)
- Add `categoryId` column to threads table schema (foreign key to categories)
- Candidates created in a thread auto-inherit the thread's category by default (can be overridden per candidate)
- Remove the current inline text input + button form

### Planning tab layout
- Thread cards show category (icon + name) alongside existing info (candidate count, price range, date)
- Category filter — let users filter thread list by category
- Replace "Show archived threads" checkbox with Active / Resolved pill tab selector
- Threads sorted newest first by default

### Claude's Discretion
- "Create thread" button placement when threads exist (header area vs floating)
- Validation UX for thread creation modal (empty name handling, duplicate warnings)
- Loading skeleton design
- Exact spacing and typography
- Category filter UI pattern (dropdown, pills, sidebar)

</decisions>

<code_context>
## Existing Code Insights

### Reusable Assets
- `ThreadCard` component (`src/client/components/ThreadCard.tsx`): Existing card with name, candidate count, price range, date, status badge — needs category addition
- `CategoryHeader` component: Shows category emoji + name + totals — pattern for category display
- `useThreads` / `useCreateThread` hooks: Existing data fetching and mutation hooks
- `useUIStore` (Zustand): Panel/dialog state management — use for create thread modal
- Collection empty state (`src/client/routes/collection/index.tsx` lines 59-93): Pattern for empty states with emoji, heading, description, CTA button

### Established Patterns
- Drizzle ORM schema in `src/db/schema.ts` — add categoryId column to threads table here
- `@hono/zod-validator` for request validation on server routes
- Service layer with db as first param for testability
- TanStack Query for data fetching with query invalidation on mutations
- Tab navigation via URL search params (gear/planning tabs)

### Integration Points
- `src/db/schema.ts`: Add categoryId to threads table
- `src/server/routes/threads.ts`: Update create/update endpoints for categoryId
- `src/server/services/thread.service.ts`: Update service functions
- `src/shared/schemas.ts`: Update Zod schemas for thread creation
- `src/client/routes/collection/index.tsx` PlanningView: Replace inline form with modal trigger, add empty state, add pill tabs, add category filter
- `src/client/components/ThreadCard.tsx`: Add category display
- `tests/helpers/db.ts`: Update CREATE TABLE for threads to include category_id

</code_context>

<specifics>
## Specific Ideas

- The empty state illustrated steps should visually show the 3-step planning workflow (Create thread → Add candidates → Pick winner) — make it clear what threads are for
- Pill tabs for Active/Resolved should feel like a segment control, not full page tabs
- Category on thread cards should use the same icon + name pattern used elsewhere in the app

</specifics>

<deferred>
## Deferred Ideas

None — discussion stayed within phase scope

</deferred>

---

*Phase: 04-database-planning-fixes*
*Context gathered: 2026-03-15*
