Files
famapp/docs/tasks/11-lists-module.md
T
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

2.3 KiB

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.listconfig: { 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.