docs: split CLAUDE.md into docs/{development,deployment,history/fase-*}

CLAUDE.md shrinks to rules + status + index (175 lines, down from 476).
Dev setup, prod deploy, and per-phase build records move to docs/.
Gotchas regrouped by domain (auth, frontend, PWA, testing, backend, deploy,
platform) and unnumbered so they don't drift as new ones land.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-18 22:21:20 +02:00
parent 3d85d0a50e
commit 768b3cda58
11 changed files with 441 additions and 403 deletions

55
docs/history/fase-5.md Normal file
View File

@@ -0,0 +1,55 @@
# Fase 5 — what has been built (complete in scope)
## 5.8 big-button create (match /notes)
- `/lists` sticky bottom create bar removed; masthead gains a primary "New list" button next to the Trash ghost icon
- `handleCreate` creates with empty name + `goto(/lists/[id])`; detail view shows a prominent editable title input (2632px) with 500 ms autosave (`renameList`)
- Matches `/notes` pattern end-to-end
## 5.10 row redesign (button-row + gesture toggle + overlay + drag handles)
- Shopping items have **no checkbox** in normal mode. Row is `drag-handle | name-button | qty stepper`. Checked items render strikethrough + muted.
- **Swipe right on unchecked → mark checked** (green reveal), **swipe left on checked → uncheck** (neutral reveal). Opposite direction is a no-op snap-back. `SWIPE_COMMIT_THRESHOLD=120`, `SWIPE_REVEAL_WIDTH=96`. No undo toast — the gesture is symmetric and the inverse swipe reverses.
- **Double-tap opens an overlay** (Dialog / bottom sheet) with: name input + Delete (red) + Confirm + X close. 300 ms tap-window. Delete still routes through `scheduleUndoable``UndoToast`.
- **Drag handle** on the left, always visible on mobile, `md:opacity-0 md:group-hover:opacity-100` on desktop. Handle's `onpointerdown` flips a `dragEnabled` flag so dnd only kicks in from the handle, leaving row swipes untouched.
- `unit` column **dropped** (migration `011_drop_shopping_items_unit.sql`). The double-tap overlay only edits name, so an unreachable `unit` would be stranded data. Users encode units inside the name (e.g. "Milk 1L"); seed updated accordingly.
## 5.11 selection mode + bulk actions
- **Entry**: long-press 500 ms on mobile or `data-testid="selection-toggle"` button in the desktop header. Preselects the row you pressed (mobile).
- Inside selection mode: single-tap toggles selection, swipe + double-tap disabled, stepper + drag handle hidden. Row gains a checkbox on the left.
- **Chrome**: header turns into `data-testid="selection-bar"` (dark slate-900 with "N selected" + Cancel + desktop-inline actions). Mobile bottom action bar (`data-testid="selection-action-bar"`) above BottomTabBar with Delete / Move / Mark-checked.
- **Bulk actions** (one Supabase call each): `bulkDeleteItems` + single UndoToast with batch snapshot, `bulkMoveItems` via a list picker sheet (`data-testid="move-picker"`) listing the collective's other active lists + a "Create new list" row, `bulkCheckItems` filters `is_checked=false` so it only marks, never toggles.
## 5.12 detail-view chrome (hide MobileTopBar, sticky contextual bars)
- On `/lists/[id]`, `/tasks/[id]`, `/notes/[id]`, `/lists/[id]/session` the global `MobileTopBar` is hidden via an `isDetailRoute` regex check in `(app)/+layout.svelte`. The route's own contextual header (back + title + actions) becomes the only top chrome and is now `sticky top-0 z-30 bg-surface/80 backdrop-blur-xl`.
- `BottomTabBar` stays visible so users can hop between sections.
## 5.15 detail-view title chrome cleanup
- `/lists/[id]` and `/tasks/[id]` dropped the uppercase eyebrow label ("ACTIVE LIST" / "TASK MANAGER") that used to sit above the editable title. Title moved up into that space.
- `/lists/[id]` status signal replaces the hardcoded "ACTIVE LIST": `completed` → title with `text-text-secondary line-through`; `archived` → muted pill next to title (`data-testid="list-status-pill"`); `active` → plain title.
- `/tasks/[id]` has no status on `task_lists`; just the label drop.
## 5.14 inline add-form (last element of the list)
- `/lists/[id]` + `/tasks/[id]` no longer have a bottom-sticky add form. The form renders **inline as the last child of the unchecked / pending section** (just above Checked / Completed). Empty-state branch shows message + form beneath it.
- On `/lists/[id]` the frequency chips (`ItemSuggestions`) moved below the input (input row on top, chips on second line). Mobile: horizontal scroll; desktop: wrap.
- Hides entirely while `selectionMode` is active.
- Svelte 5 snippets `addItemForm` / `addTaskForm` so the form is rendered in both the empty-state branch and the between-sections slot without duplication.
- `data-testid="add-item-form"` / `"add-task-form"` hooks added for future placement assertions.
## Earlier sub-phases (still relevant)
- `apps/web/src/lib/components/layout/DesktopSidebar.svelte` — desktop sidebar extracted from `(app)/+layout.svelte`, `data-testid="desktop-sidebar"`, `hidden md:flex`
- `apps/web/src/lib/components/layout/MobileTopBar.svelte` — hamburger + collective name + avatar link; `md:hidden sticky top-0 z-30 backdrop-blur-xl`
- `apps/web/src/lib/components/layout/BottomTabBar.svelte` — 4 nav items icon-only, glassmorphism, `pb-[env(safe-area-inset-bottom)]`, `aria-current="page"` on the active route, `data-testid="bottom-tab-bar"`
- `apps/web/src/lib/components/layout/MobileDrawer.svelte` — backdrop + collective switcher + manage/settings/logout, `data-testid="mobile-drawer"`
- `apps/web/src/lib/components/ScreenMasthead.svelte` — uppercase label (`data-testid="masthead-label"`) + big title (`data-testid="masthead-title"`) + optional `meta` / `actions` snippets. Applied on `/lists`, `/tasks`, `/notes`, `/search`.
- `apps/web/src/lib/sync/undoQueue.ts``scheduleUndoable({ label, restore, commit, ttlMs? })` with 4-s TTL; auto-commits on timeout, `undo(id)` cancels + restores
- `apps/web/src/lib/components/UndoToast.svelte` — rendered globally in `(app)/+layout.svelte`, shows latest undoable, offset above bottom tab bar on mobile
- `/lists/[id]` swipe-delete: `SWIPE_MAX=96`, `SWIPE_THRESHOLD=48` (latch-open), `SWIPE_COMMIT_THRESHOLD=200` (full-swipe commit via `scheduleUndoable`)
- `apps/web/src/lib/components/ItemSuggestions.svelte` — mobile: horizontal scroll with `[scrollbar-width:none]`; desktop: wraps
- `(app)/+layout.svelte`**critical fix**: outer container now `flex flex-col md:flex-row` (was `flex` only). Without this MobileTopBar and main rendered as horizontal siblings on mobile and the masthead was pushed off-screen.
- Mobile tests: `mobile-shell.test.ts` (M-01..M-04), `mobile-masthead.test.ts` (M-05 × 4 routes), `mobile-swipe-delete.test.ts` (M-06/M-07 `.skip` — Chromium touch emulation too flaky), `undoQueue.test.ts` (5 unit tests)