Skip to content

feat(tasks): ask who did a task worth points, and give the points to them - #418

Merged
svenger87 merged 1 commit into
mainfrom
feat/task-done-by
Oct 25, 2026
Merged

svenger87 merged 1 commit into
mainfrom
feat/task-done-by

Conversation

@svenger87

Copy link
Copy Markdown
Owner

Summary

A task's points always went to its assignee, or to whoever's turn it was. When Jonas takes Mira's turn at the dishes, Mira gets the points and her creature cheers. Ticking a task worth points on the tasks page or the Tasks widget now asks "Who did it?", and the person picked gets the points. The idea comes from Yuvomi's wall-display picker.

Database (migration_zzzzzzzzzzzzz_todo_done_by.sql). Every client ticks through PostgREST, so this lives in the triggers, like points and turns do.

  • todos.done_by is an argument sent with the tick. A new BEFORE UPDATE trigger, todos_zz_done_by, reads it and then clears it, so it is NULL again after every update. That means a later tick from Home Assistant or an assistant never inherits the previous answer.
  • The trigger is named so it runs after todos_schedule_update, so it only records ticks that actually took. A second tick on a day that is already done changes nothing.
  • It records the answer in three places:
    • todos.last_completed_by, which only the trigger sets; an edit can't change it.
    • todo_occurrences.completed_by, next to person_id (whose turn it was).
    • detail.done_by on the task-log entry.
  • Un-ticking clears all three.
  • record_todo_points is replaced. It now pays the person who did it, or the assignee or turn person as before. Only children get points, as before, so a parent doing the chore earns nobody points.
  • The person must be in this family and not in the recycle bin; anyone else is ignored. An insert can't carry done_by.

UI

  • The new DoneByPicker (lib/done-by.ts) only appears for a tick worth points, in a family with more than one person. Order: whoever the task is for, then the other children, then adults. One tap ticks the task; closing the dialog leaves it unticked. Un-ticking never asks.
  • The cheering creature is the doer's (detectTaskTick).
  • A repeating task shows "Last: 3. Oct, Jonas".

Not in this PR: a done_by field on the Integration API and MCP tools, so assistants can say "Jonas did the dishes"; and showing who did each day in the history strip. Both would build on these columns.

Type of change

  • Bug fix
  • New feature
  • Refactor (no user-facing change)
  • Documentation
  • Translation
  • Plugin / integration

Test plan

  • e2e/todo-done-by.spec.ts: when the picker asks, the order, un-ticking never asks, which creature cheers, and the migration's invariants
  • e2e/todo-done-by-db.spec.ts (live database, added to e2e.yml):
    • one-off task paid to the doer, and the un-tick takes it back
    • a tick that doesn't name anyone goes back to the assignee
    • turns: the day records turn and doer; a second tick changes nothing; un-tick, then a tick without an answer pays the turn person
    • a parent earns nobody points; a person from another family is ignored
    • an edit can't set the doer; an insert can't carry an answer
    • The spec re-applies its migration before each test, because todo-turns-db.spec.ts re-applies the older function it replaces.
  • Locally, against Postgres 16 with every migration applied from scratch:
    • todo-done-by-db: 4/4
    • todo-turns-db: 13/13 still green
    • point-adjustments-db and family-delete-db: green
    • The migration applies twice cleanly.
    • This ran through a stand-in docker exec that forwards to the local database, since there was no Docker daemon.
  • Full stack-free suite as CI runs it: 10,428 passed. npm run lint, npx tsc --noEmit and the changelog check pass.
  • Not exercised in a browser: tick a pointed task on the wall, pick a sibling, and check the sibling's balance and creature

Screenshots

None. The dialog reuses the existing Dialog and PersonAvatar components: a grid of large name buttons, 96px tall.

Checklist

  • npm run lint passes
  • New strings added to both messages/en.json and messages/de.json (and fr)
  • Schema changes ship as a new webapp/docker/migration*.sql file (idempotent: IF NOT EXISTS, CREATE OR REPLACE)
  • No secrets, real API keys, or personal hostnames in the diff
  • I agree to the licensing of contributions
  • CHANGELOG.md updated under [Unreleased] (Added)
  • Commit follows Conventional Commits

Generated by Claude Code

…them

A task's points went to its assignee or to whoever's turn it was, so a
child who took a sibling's turn earned the sibling the points. Ticking a
task worth points on the tasks page or the Tasks widget now asks who did
it.

- migration_zzzzzzzzzzzzz_todo_done_by.sql: todos.done_by is an argument
  sent with a tick. A trigger that runs after todos_schedule_update reads
  it, records it in todos.last_completed_by, todo_occurrences.completed_by
  and the task log, and clears it, so a later tick from Home Assistant or
  an assistant never inherits it. record_todo_points pays whoever did it,
  else the assignee or turn as before; children only, as before.
- DoneByPicker (lib/done-by.ts): asked only for a tick worth points in a
  family of more than one; whoever the task is for comes first. Un-ticking
  never asks.
- The cheering creature is the doer's. A repeating task shows who last
  did it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STyQ3UYK3VBFvcZ3Je5jCr
@svenger87
svenger87 marked this pull request as ready for review October 25, 2026 13:42
@svenger87
svenger87 merged commit 12b436b into main Oct 25, 2026
14 checks passed
@svenger87
svenger87 deleted the feat/task-done-by branch October 25, 2026 13:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants