--- phase: 35-bug-fixes plan: 01 type: execute wave: 1 depends_on: [] files_modified: - src/client/routes/threads/$threadId/index.tsx - src/client/hooks/useItems.ts - src/client/routes/login.tsx autonomous: true requirements: - FIX-01 - FIX-02 - FIX-04 must_haves: truths: - "Clicking Add Candidate on the thread page opens CatalogSearchOverlay in thread mode" - "The AddCandidateModal component and addCandidateOpen state are deleted from the thread route file" - "ItemWithCategory includes imageUrl, dominantColor, cropZoom, cropX, cropY, priceCurrency fields" - "Navigating to /login immediately redirects to the server /login route with no intermediate UI" artifacts: - path: "src/client/routes/threads/$threadId/index.tsx" provides: "Thread detail page — Add Candidate button calls openCatalogSearch('thread')" contains: "openCatalogSearch" - path: "src/client/hooks/useItems.ts" provides: "ItemWithCategory interface with image fields" contains: "imageUrl: string | null" - path: "src/client/routes/login.tsx" provides: "Auto-redirect login page" contains: "window.location.href = \"/login\"" key_links: - from: "thread detail toolbar button" to: "useUIStore.openCatalogSearch('thread')" via: "onClick handler" pattern: "openCatalogSearch\\(\"thread\"\\)" - from: "LoginPage useEffect" to: "window.location.href = \"/login\"" via: "useEffect with empty deps" pattern: "useEffect.*window\\.location\\.href" --- Three self-contained type/wiring fixes that resolve wrong-modal, missing-image, and login-redirect bugs from the v2.3 backlog. Purpose: Clear the modal confusion on thread pages (FIX-01), surface item images that the server already returns but the TypeScript type hides (FIX-02), and skip the redundant intermediate login UI (FIX-04). Output: Updated thread route, useItems hook, and login route. @$HOME/.claude/get-shit-done/workflows/execute-plan.md @$HOME/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/35-bug-fixes/35-CONTEXT.md @.planning/phases/35-bug-fixes/35-UI-SPEC.md From src/client/stores/uiStore.ts: ```typescript // Catalog search actions openCatalogSearch: (mode: "collection" | "thread") => void; closeCatalogSearch: () => void; catalogSearchOpen: boolean; catalogSearchMode: "collection" | "thread" | null; // Session thread tracking (used by CatalogSearchOverlay to scope to a thread) catalogSessionThreadId: number | null; setCatalogSessionThreadId: (id: number | null) => void; ``` From src/client/routes/threads/$threadId/index.tsx (current state): - Line 44: `const [addCandidateOpen, setAddCandidateOpen] = useState(false);` - Line 144: `onClick={() => setAddCandidateOpen(true)}` — this is the broken Add Candidate button - Lines 307-313: `{addCandidateOpen && }` — the modal to remove - Lines 317-639: Full `AddCandidateModal` component and its interfaces/constants — all to delete From src/client/hooks/useItems.ts (current state): - `ItemWithCategory` interface (lines 27-43) is missing these fields the server already returns: - `imageUrl: string | null` - `dominantColor: string | null` - `cropZoom: number | null` - `cropX: number | null` - `cropY: number | null` - `priceCurrency: string | null` From src/client/routes/login.tsx (current state): - Renders full card UI with a sign-in button that calls `window.location.href = "/login"` - Has `useAuth` hook check and a `useNavigate` for already-authenticated users - Both the auth check and full UI need to be removed — replace with immediate useEffect redirect Task 1: Wire Add Candidate button and delete AddCandidateModal (FIX-01) src/client/routes/threads/$threadId/index.tsx - src/client/routes/threads/$threadId/index.tsx (read the full file — understand current modal state, imports, and FAB wiring pattern) - src/client/stores/uiStore.ts (confirm openCatalogSearch and setCatalogSessionThreadId signatures) Make two changes to src/client/routes/threads/$threadId/index.tsx: **1. Wire the toolbar button (per D-01, D-03):** Replace the `openCatalogSearch` and `setCatalogSessionThreadId` Zustand selectors in the component — add these two lines to the existing `useUIStore` selectors at the top of `ThreadDetailPage`: ```typescript const openCatalogSearch = useUIStore((s) => s.openCatalogSearch); const setCatalogSessionThreadId = useUIStore((s) => s.setCatalogSessionThreadId); ``` Delete the `addCandidateOpen` state (line 44): ```typescript // DELETE THIS LINE: const [addCandidateOpen, setAddCandidateOpen] = useState(false); ``` Change the toolbar button's onClick from `() => setAddCandidateOpen(true)` to: ```typescript onClick={() => { setCatalogSessionThreadId(threadId); openCatalogSearch("thread"); }} ``` Remove the cursor-default: the button already has class string — ensure `cursor-pointer` is present (the button has no explicit cursor class currently, so browsers default to pointer for `