Skip to content

feat(chores): allow transferring a chore back to the bonus pool from the Transfer dialog - #372

Merged
mrramam merged 2 commits into
jherforth:mainfrom
adamecker:pr/bonus-chore-transfer-back
Nov 2, 2026
Merged

mrramam merged 2 commits into
jherforth:mainfrom
adamecker:pr/bonus-chore-transfer-back

Conversation

@adamecker

Copy link
Copy Markdown
Contributor

Description

A chore that was assigned to a person could never go back to the bonus pool
from the wall display: the Transfer dialog only ever listed real users. The
schedule editor already allowed it (its "Unassigned (Bonus chore)" choice),
and the API already accepted it (PATCH /api/chore-schedules/:id with
user_id: 0 stores NULL, which is how the bonus pool is read) — only the
widget's Transfer dialog blocked it.

This change closes that UI gap, nothing else:

  • The Transfer dialog now lists the bonus pool ("Unassigned (Bonus chore)",
    🧺) as a target whenever the chore is currently assigned to someone. A
    chore that is already in the bonus pool gets no bonus row.
  • The dialog's selection handling no longer treats user id 0 as "nothing
    selected": the confirm button enables for the bonus target, and the
    already-finished revoke/keep choice stays hidden for bonus (the pool has
    no day to complete, so no transfer bonus is ever attached on the way
    back).
  • The Transfer menu item also appears when the chore is assigned even if
    there is no other real user to hand it to (previously it required another
    person in the list, so a single-person household could not transfer
    back at all).

Unchanged on purpose: assigning to real users, claiming a bonus chore,
streaks, schedules, and completion behavior. A transfer bonus attached by
an earlier person-to-person move still rides on the schedule and pays
whoever completes it next, exactly as before — moving back to bonus does
not clear it. The daily-bonus re-check on reassignment already handles a
null new owner (it skips the award for bonus and re-checks the previous
owner, who may have become all-done by losing the chore).

Changes

  • client/src/components/ChoreWidget.jsx — bonus target in the Transfer
    dialog, 0-safe selection/confirm handling, Transfer menu gating.
  • client/src/utils/choreHelpers.js — new pure getTransferTargets
    helper (real users except the assignee, plus the bonus row when
    assigned).
  • client/src/utils/choreHelpers.test.js — unit tests for the helper.
  • server/tests/choreTransferBack.test.js — real-server test: assigned
    → PATCH user_id: 0 → reads back NULL (bonus pool) → claimable again
    by a person. No server change was needed; the test pins the API half.

Verification

  • Client suite: 82 files, 910 tests, all passing (includes 5 new
    getTransferTargets tests).
  • Server suite: 708 tests, all passing.
  • Build and translation check pass.
  • Transfer-back flow verified end to end: seeded a
    chore assigned to one person, opened its Transfer dialog (bonus row
    listed alongside the other people, assignee correctly excluded),
    transferred to the bonus pool, and confirmed via the API that the
    schedule's assignee reads back as null and that the chore appears in
    the Bonus Chores pool with claim buttons for every person.

Screenshots

Transfer dialog showing the bonus target:

Transfer dialog

The chore back in the Bonus Chores pool after transfer (2-clam card with
claim buttons for every person):

Bonus pool

Generated with Muse AI 🤖

@mrramam

mrramam commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Read c614681, not run. The change does what it says and stays in the widget: the bonus row appears only for an assigned chore, the dialog no longer reads id 0 as nothing selected, the revoke/keep box stays hidden for the pool, and the menu item shows for a single-person household. getTransferTargets and its tests read clearly.

One thing before merge. A pending transfer bonus rides back into the pool. If a parent moved a chore to Henry with "keep reward" (the schedule now carries transfer_bonus_clams), and then sends it back to bonus before Henry does it, the PATCH leaves that value on the schedule. Whoever picks the chore up from the pool is paid Henry's bonus at completion (the payout in the completion route clears it only then). The API already accepts the field, so confirmTransfer can send transfer_bonus_clams: 0 when the target is the pool, which keeps the change client-side. A test for that in choreTransferBack.test.js would close it.

Optional: the menu condition now repeats the dialog's rule in a second form. getTransferTargets(users, choreMenu.schedule?.user_id, '').length > 0 says the same thing once.

…he pool

A chore moved to a user with "keep reward" carries transfer_bonus_clams.
Sending it back to bonus left that value on the schedule, so whoever
claimed it from the pool would be paid the previous holder's bonus.
confirmTransfer now sends transfer_bonus_clams: 0 for a pool target,
which the API already accepts. Also collapses the Transfer menu-item
condition onto getTransferTargets, which states the same rule once.

Addresses review feedback on jherforth#372.
@adamecker

Copy link
Copy Markdown
Contributor Author

Fixed, thanks for catching it:

  • confirmTransfer now sends transfer_bonus_clams: 0 when the target is the bonus pool, so a bonus carried in from a "keep reward" transfer no longer rides back into the pool for the next claimant. Client-side only, as suggested — the API already accepts the field.
  • Added a test in choreTransferBack.test.js covering exactly that round trip: keep-reward transfer sets the bonus, the pool transfer (with the PATCH shape the dialog now sends) clears it.
  • Also took the optional cleanup: the Transfer menu-item condition now reads getTransferTargets(users, choreMenu.schedule?.user_id, '').length > 0, which states the same rule once (verified equivalent for assigned, pool, and single-person-household cases).

Commit a6342fb on this branch; choreTransferBack.test.js passes (2/2).

@mrramam
mrramam merged commit 1d815bc into jherforth:main Nov 2, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in HomeGlow Kanban Nov 2, 2026
@jherforth jherforth added the enhancement New feature or request label Nov 3, 2026
@jherforth jherforth added this to the 2.0 milestone Nov 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants