Files
famapp/docs/tasks/11-lists-module.md
ginnoir 09d6adbf18 Calendars as entities, uniform widget contract, multi-dashboard tasks
Architecture refinements before module work begins:

- Calendars become first-class entities (mirror of lists). Each
  calendar has its own visibility (private | household) and is
  independently shareable. Updated CLAUDE.md data model and task 10.

- Drop the singleton/parameterized split for dashboard widgets. Every
  widget declares a configSchema + defaultConfig + resolveConfigOptions
  and every placement is an independent instance — same widgetId can
  appear multiple times on one dashboard pointed at different things.
  Updated task 04 contract; tasks 11/12 widget sections aligned.

- Add tasks 25 (multiple dashboards per user) and 26 (customizable
  layout + widget configuration). Replaces the previously-considered
  three-task plan with a cleaner two-task split that the uniform
  contract enables. Phase 3 index updated; STATUS records the rationale.

- Task 20 reframed as a single-dashboard MVP that exercises the new
  contract end-to-end before the customization layer lands.
2026-05-06 01:14:49 -05:00

50 lines
2.3 KiB
Markdown

# 11 — Lists module (shopping + task)
## Goal
Implement the `lists` module supporting two list types out of the box (`shopping`, `task`), with the schema designed so additional types can be added later without migration.
## Depends on
- 04, 07
## Scope
### Schema
- `lists`: `id`, `household_id`, `type` (text — not an enum, to allow extension), `name`, `archived`, `created_at`.
- `list_items`: `id`, `list_id`, `text`, `done` boolean, `qty` text nullable, `notes` text nullable, `due_at` timestamptz nullable, `assignee_id` fk users nullable, `position` int (for ordering), `created_at`, `updated_at`.
Seed: one default list of each type per household on first access (idempotent).
### Server
- `listLists({ type? })`, `getList(id)`, `createList`, `renameList`, `archiveList`.
- `addItem`, `toggleItem`, `updateItem`, `deleteItem`, `reorderItems`.
### UI
- `/lists` index showing all lists grouped by type.
- `/lists/[id]` — fast keyboard-driven entry: focus stays in input, Enter adds, checkbox toggles, swipe-left (mobile) deletes.
- Realtime: SSE subscription on the list id; updates from the other user appear without refresh. (Implementation detail: Postgres `LISTEN/NOTIFY` channel `list:<id>`; thin SSE route handler bridges it. Document the pattern in `docs/decisions/`.)
### Manifest
- Entity types: `lists.list` (shareable read+write via share token), `lists.item` (inherits via list, not directly shareable).
- Quick-adds: "Add to shopping" / "Add to tasks" (single item to the household's default list of that type), "New list".
- Widget (uniform contract per task 04):
- **`lists.list`** — `config: { listIds: "all" | string[]; showCompleted: boolean; limit?: number }`. Default `{ listIds: "all", showCompleted: false }`. `resolveConfigOptions` returns the user's accessible lists with type/name. Multiple instances per dashboard supported (one per list, or merged across several).
## Out of scope
- Reordering across lists.
- Per-item images.
- Recurring tasks (use reminders module later if needed).
## Acceptance criteria
- [ ] Both default lists are auto-seeded.
- [ ] Adding an item on one device appears on the other within ~1s via SSE.
- [ ] `type` is `text` not `enum` — adding a third type works without a migration.
- [ ] Playwright: add item → check it off → archive list.