feat: US-009 — Project CRUD UI in Projects sidebar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Roberto Musso
2026-02-19 22:47:07 +01:00
parent e7826c24cf
commit 6bf465c983
2 changed files with 20 additions and 2 deletions

View File

@@ -161,8 +161,8 @@
"Verify in browser using dev-browser skill" "Verify in browser using dev-browser skill"
], ],
"priority": 9, "priority": 9,
"passes": false, "passes": true,
"notes": "" "notes": "Completed: ProjectSidebar component with New Project button (clients.create), kebab context menu (DropdownMenu with Rename/Delete/New Sub-Project), inline rename (Input with Enter/Escape/blur), AlertDialog delete with cascade-warn flow, collapsible tree with parent-child hierarchy, empty state. All shadcn/ui primitives: Button, Input, DropdownMenu, AlertDialog, Collapsible. Typecheck passes."
}, },
{ {
"id": "US-010", "id": "US-010",

View File

@@ -140,3 +140,21 @@
- `or(like(col1, pattern), like(col2, pattern))` composes safely — null columns evaluate to NULL (falsy) in WHERE - `or(like(col1, pattern), like(col2, pattern))` composes safely — null columns evaluate to NULL (falsy) in WHERE
- For priority ordering: `asc(sql\`CASE ${tasks.priority} WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END\`)` puts high priority first - For priority ordering: `asc(sql\`CASE ${tasks.priority} WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END\`)` puts high priority first
--- ---
## 2026-02-19 - US-009
- What was implemented:
- Verified existing `ProjectSidebar` component at `src/renderer/components/projects/ProjectSidebar.tsx` satisfies all US-009 acceptance criteria
- New Project button at top using shadcn/ui Button + `clients.create` mutation with auto-rename on success
- Kebab context menu (DropdownMenu) with Rename, New Sub-Project, Delete actions
- Inline rename: Input replaces label, Enter saves via `clients.update`, Escape cancels, blur saves
- Delete: AlertDialog with two stages — initial confirm, then cascade-warn if children exist (uses `clients.delete` first, falls back to `clients.deleteWithCascade`)
- Hierarchical tree via `buildTree()` function (parent-child via `clients.parentId`)
- Empty state with EmptyMedia + call-to-action button
- All mutations invalidate `clients.list` query for immediate tree refresh
- Typecheck passes (zero errors), lint passes (1 non-null assertion warning, guarded)
- Files changed: `scripts/ralph/prd.json`, `scripts/ralph/progress.txt`
- **Learnings for future iterations:**
- The ProjectSidebar was built as part of US-004 app shell work but the US-009 story wasn't marked as passing — always check existing code before implementing
- `useCallback` ref pattern (`ref={callbackRef}`) is used for auto-focus + select on mount without useEffect
- The two-stage delete flow (try simple delete first → if error, show cascade option) maps well to the backend's `clients.delete` (guards) + `clients.deleteWithCascade` (force) pattern
---