docs(11-02): complete drag-to-reorder ranking UI plan
- Add 11-02-SUMMARY.md with implementation details and deviation docs - Update STATE.md: progress 100%, decisions, session record - Update ROADMAP.md: phase 11 complete (2/2 plans with summaries) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
85
.planning/phases/11-candidate-ranking/11-02-SUMMARY.md
Normal file
85
.planning/phases/11-candidate-ranking/11-02-SUMMARY.md
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
phase: 11-candidate-ranking
|
||||
plan: "02"
|
||||
subsystem: client-ui
|
||||
tags: [drag-reorder, framer-motion, rank-badges, view-toggle, list-view]
|
||||
dependency_graph:
|
||||
requires: [11-01]
|
||||
provides: [drag-to-reorder-ui, rank-badges, list-grid-toggle]
|
||||
affects: [threads/$threadId.tsx, CandidateCard, CandidateListItem, uiStore, useCandidates]
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns:
|
||||
- framer-motion Reorder.Group + Reorder.Item with useDragControls for drag handle
|
||||
- tempItems pattern to prevent React Query flicker during optimistic drag
|
||||
- RankBadge exported from CandidateListItem for reuse across views
|
||||
- candidateViewMode in uiStore for list/grid toggle state
|
||||
key_files:
|
||||
created:
|
||||
- src/client/components/CandidateListItem.tsx
|
||||
modified:
|
||||
- src/client/hooks/useCandidates.ts
|
||||
- src/client/stores/uiStore.ts
|
||||
- src/client/components/CandidateCard.tsx
|
||||
- src/client/routes/threads/$threadId.tsx
|
||||
- src/client/lib/iconData.tsx
|
||||
- src/client/hooks/useThreads.ts
|
||||
decisions:
|
||||
- Resolved thread list view uses plain div (not Reorder.Group) — no drag, rank badges visible
|
||||
- handleDragEnd fires on Reorder.Group onPointerUp to debounce reorder API call
|
||||
- biome-ignore applied to useExhaustiveDependencies for thread?.candidates dep — intentional trigger
|
||||
metrics:
|
||||
duration: 4min
|
||||
completed: 2026-03-16T21:29:07Z
|
||||
tasks_completed: 3
|
||||
files_changed: 7
|
||||
---
|
||||
|
||||
# Phase 11 Plan 02: Drag-to-Reorder UI Summary
|
||||
|
||||
Drag-to-reorder candidate ranking with list/grid view toggle, gold/silver/bronze rank badges, and framer-motion Reorder.Group with tempItems flicker prevention.
|
||||
|
||||
## What Was Built
|
||||
|
||||
### Task 1: useReorderCandidates hook + uiStore view mode + CandidateListItem component
|
||||
- Added `useReorderCandidates` mutation hook to `useCandidates.ts` using `apiPatch` to hit `PATCH /api/threads/:id/candidates/reorder`
|
||||
- Added `candidateViewMode: "list" | "grid"` and `setCandidateViewMode` to `uiStore.ts`
|
||||
- Created `CandidateListItem.tsx` — horizontal card for list view with drag handle (GripVertical), RankBadge (medal icon), 48x48 image thumbnail, badge row (weight/price/category/status/pros-cons), and hover-reveal action buttons
|
||||
- Exported `RankBadge` component (gold `#D4AF37`, silver `#C0C0C0`, bronze `#CD7F32`) for reuse
|
||||
- Added `style` prop support to `LucideIcon` for colored medal icons
|
||||
- Added `pros` and `cons` fields to `CandidateWithCategory` in `useThreads.ts` (Rule 2 auto-fix — missing after Phase 10)
|
||||
|
||||
### Task 2: Thread detail page with view toggle, Reorder.Group, rank badges in grid view
|
||||
- Updated `CandidateCard.tsx`: added `rank?: number` prop and renders `<RankBadge rank={rank} />` in badge row
|
||||
- Updated `threads/$threadId.tsx`:
|
||||
- List/grid view toggle (LayoutList / LayoutGrid icons) using `candidateViewMode` from uiStore
|
||||
- Active list view: `<Reorder.Group>` wrapping `<CandidateListItem>` instances for drag-to-reorder
|
||||
- Resolved list view: plain `<div>` with `<CandidateListItem isActive={false}>` — rank badges visible, drag handles hidden
|
||||
- Grid view: existing `<CandidateCard>` grid with `rank={index + 1}` passed to each card
|
||||
- `tempItems` state: holds in-progress drag order, falls back to `thread.candidates` when null
|
||||
- `handleDragEnd`: fires `reorderMutation.mutate({ orderedIds })` and clears tempItems on settled
|
||||
- `useEffect` clears tempItems when `thread?.candidates` reference changes (fresh server data)
|
||||
|
||||
### Task 3: Human verification (auto-approved — auto_chain_active)
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 2 - Missing] Added pros/cons fields to CandidateWithCategory in useThreads.ts**
|
||||
- **Found during:** Task 1 (needed by CandidateListItem)
|
||||
- **Issue:** `CandidateWithCategory` interface in `useThreads.ts` was missing `pros` and `cons` fields added in Phase 10. CandidateListItem needed these to render the "+/- Notes" badge.
|
||||
- **Fix:** Added `pros: string | null` and `cons: string | null` to the interface
|
||||
- **Files modified:** `src/client/hooks/useThreads.ts`
|
||||
- **Commit:** acfa995
|
||||
|
||||
**2. [Rule 2 - Missing] Added style prop to LucideIcon component**
|
||||
- **Found during:** Task 1 (needed by RankBadge for medal colors)
|
||||
- **Issue:** LucideIcon only accepted `className` for styling; RankBadge needed inline `style={{ color }}` for gold/silver/bronze hex colors not achievable via Tailwind
|
||||
- **Fix:** Added optional `style?: React.CSSProperties` prop to LucideIcon and passed through to icon component
|
||||
- **Files modified:** `src/client/lib/iconData.tsx`
|
||||
- **Commit:** acfa995
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
All created/modified files exist. Both task commits (acfa995, 94c07e7) confirmed in git log.
|
||||
Reference in New Issue
Block a user