Skip to content

Sticker chart card and logging a job done on an earlier dayUpstream pr/sticker - #1063

Closed
cad861 wants to merge 17 commits into
tempus2016:mainfrom
cad861:upstream-pr/sticker
Closed

cad861 wants to merge 17 commits into
tempus2016:mainfrom
cad861:upstream-pr/sticker

Conversation

@cad861

@cad861 cad861 commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds the Sticker Chart card (today's jobs as stickers to tap, stars filling towards a reward or this week's jobs) and lets a parent log a job done on an earlier day that nobody ticked: complete_chore takes completed_date (parent-only, last 7 days), and the admin panel has a "Log a past job" dialog per child that shows the chart for the chosen day.

Changes since #913, following your review:

  • Rebased onto current main.
  • Backdated completions go through the same recording and follow-up code as a parent ticking a job (_async_record_completion + _async_after_completions): badges, quests, challenges, last_completed and one-shot disabling all behave as for any approval. last_completed is only moved forward, never back behind a later completion, and undoing a backdated job leaves the streak alone.
  • Weekly-target chores can be logged on any day while that week's quota is open; open-ended, teamwork, rotation and auction-won chores are refused with a clear message. The weekly target bonus is settled for the week the job belongs to, and every-N-days chores only on their days. week_progress counts a weekly-target chore's quota once and gives open-ended chores no "available" total.
  • Panel dialog: waits for the card module before mounting it, and falls back to a plain job list (instead of throwing) if the card can't be built or the overview sensor is missing.
  • No sound or confetti for a past day; the day picker uses HA's time zone, not the browser clock.
  • Test files ruff-formatted.

Depends on the photo PR (#1062) — this branch is stacked on it, so it shows those two commits until that one lands.

Related issue

N/A — follows #913.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behaviour)
  • Documentation only
  • CI / tooling / chore

How has this been tested?

  • Ran ruff check . locally (matches the Ruff CI check)
  • Ran pytest locally (matches the Run tests CI check)
  • Exercised the change on a live Home Assistant instance
  • For card changes: hard-refreshed the browser and checked the console for errors

ruff format --check and ruff check clean; pytest 3215 passed; npm test 653 passed; translation and data-file checks pass. New tests: tests/test_complete_chore_on_date.py (hooks, weekly-target/open-ended/teamwork/auction rules, weekly bonus, every-N-days, undo), tests/test_week_progress.py, tests/test_sticker_chart_card.py, and tests/frontend/taskmate-sticker-chart-backdate.test.cjs (panel guards, no sound or celebration on a past day, day picker in several time zones).

Live: on my HA (2026.9) the card is in daily use for two children. I used "Log a past job" from the panel for an earlier day: the dialog opened with that day's chart, ticking a job logged and paid it for that day, and undoing it took it back. That instance runs this change on top of 6.1.0; the branch here is rebased on current main, so the 6.2 weekly target bonus interaction is covered by tests only.

Checklist

  • My code follows the existing patterns in the codebase
  • I bumped manifest.json version if this is a release-bound change
  • Any new user-facing strings are translated into all locales
    (da, de, fr, nb, nn, pl, pt, pt-BR) in this same PR — not English-only
  • I updated the README / docs where relevant
  • I did not add Claude / AI co-author attribution to commits or files

Version left for you to set at release.

Adds an optional per-child picture entity (normally the child's person.*).
Its picture is read on every update and exposed as avatar_image, and a
shared __taskmate_child_visual helper makes every card prefer the photo
and fall back to the MDI avatar. The panel's child dialog gets a
"Photo from" picker.
A child's photo is read from their picture entity, but the sensors' shared
context was cached per coordinator update, so a photo changed on the person
entity stayed stale until the next TaskMate refresh. Track each child's
picture entity and refresh the sensors when its picture really changes, and
make the shared cache aware of external entity changes.
Adds the taskmate-sticker-chart-card Lovelace card and an admin-panel
dialog for logging jobs done on an earlier day. Builds on the child photo
change for the children's faces.

Backdated completions run the same post-approval hooks as a normal
approval (badges, quests, challenges, last_completed, one-shot disabling),
account for weekly-target and open-ended chores, and are marked so undoing
one does not lower the streak.
…chores

A job logged for an earlier day settles that week's weekly target bonus
(tempus2016#1044), and an every-N-days chore (tempus2016#1038) can only be logged on one of
its days.
Copilot AI balanced review requested due to automatic review settings October 14, 2026 01:40
@cad861
cad861 requested a review from tempus2016 as a code owner October 14, 2026 01:40
@github-actions github-actions Bot added documentation Improvements or additions to documentation backend Python integration code cards Lovelace cards / frontend (www/*.js) translations i18n / locale strings tests Test suite labels Oct 14, 2026
The photo change already adds panel.child_picture_entity_label and _hint;
this branch added them a second time, which check-json rejects as
duplicate keys.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Historical scheduling, weekly quotas, one-shot progress, and recurrence undo bookkeeping contain unresolved correctness issues.

8 open findings
What changed in this PR

Adds a sticker-chart card, historical chore completion, weekly progress, and child photos across TaskMate.

Changes:

  • Adds the sticker-chart card and localized configuration.
  • Adds parent-only backdated chore completion and panel UI.
  • Adds child photos and weekly progress across sensors/cards.
File Description
README.md Updates card count and listing.
custom_components/​taskmate/​__init__.py Routes backdated completion requests.
custom_components/​taskmate/​coord_assignments.py Tracks picture-entity changes.
custom_components/​taskmate/​coord_avatars.py Resolves child photos.
custom_components/​taskmate/​coord_chores.py Implements backdating and undo behavior.
custom_components/​taskmate/​coord_points.py Calculates weekly progress.
custom_components/​taskmate/​coordinator.py Stores child picture selection.
custom_components/​taskmate/​frontend.py Registers the sticker-chart card.
custom_components/​taskmate/​models.py Adds photo and backdated fields.
custom_components/​taskmate/​sensor.py Exposes photos and weekly progress.
custom_components/​taskmate/​services.yaml Documents completed_date.
custom_components/​taskmate/​websocket.py Adds photo fields and day-completion API.
custom_components/​taskmate/​www/​taskmate-approvals-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-calendar-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-child-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-design.js Adds shared child-face rendering.
custom_components/​taskmate/​www/​taskmate-incentive-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-leaderboard-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-overview-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-panel.js Adds photo selection and backdating dialog.
custom_components/​taskmate/​www/​taskmate-parent-dashboard-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-points-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-points-display-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-reorder-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-reward-progress-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-rewards-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-sticker-chart-card.js Implements the sticker chart.
custom_components/​taskmate/​www/​taskmate-streak-card.js Displays child photos.
custom_components/​taskmate/​www/​taskmate-weekly-card.js Displays child photos.
custom_components/​taskmate/​www/​locales/​da.json Adds Danish strings.
custom_components/​taskmate/​www/​locales/​de.json Adds German strings.
custom_components/​taskmate/​www/​locales/​en-GB.json Adds British English strings.
custom_components/​taskmate/​www/​locales/​en.json Adds English strings.
custom_components/​taskmate/​www/​locales/​fr.json Adds French strings.
custom_components/​taskmate/​www/​locales/​nb.json Adds Norwegian Bokmål strings.
custom_components/​taskmate/​www/​locales/​nn.json Adds Norwegian Nynorsk strings.
custom_components/​taskmate/​www/​locales/​pl.json Adds Polish strings.
custom_components/​taskmate/​www/​locales/​pt-BR.json Adds Brazilian Portuguese strings.
custom_components/​taskmate/​www/​locales/​pt.json Adds Portuguese strings.
tests/​frontend/​harness.cjs Extends frontend card testing.
tests/​frontend/​taskmate-sticker-chart-backdate.test.cjs Tests backdated chart behavior.
tests/​test_child_picture_entity.py Tests picture resolution and refreshes.
tests/​test_complete_chore_on_date.py Tests historical completion behavior.
tests/​test_sensor_attributes.py Tests external-state cache invalidation.
tests/​test_sticker_chart_card.py Adds structural card checks.
tests/​test_week_progress.py Tests weekly progress calculations.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread custom_components/taskmate/coord_chores.py Outdated
Comment thread custom_components/taskmate/coord_points.py
Comment thread custom_components/taskmate/www/taskmate-panel.js
Comment thread custom_components/taskmate/www/taskmate-panel.js
Comment thread custom_components/taskmate/www/taskmate-sticker-chart-card.js
Comment thread custom_components/taskmate/www/taskmate-sticker-chart-card.js Outdated
Comment thread custom_components/taskmate/www/taskmate-sticker-chart-card.js Outdated
Comment thread custom_components/taskmate/www/taskmate-sticker-chart-card.js Outdated
The past-day sticker chart skipped the weekly-target cap, so after a
backdated tick filled the selected week's quota the tile still offered
another tap that TaskMate then refused, and a week other than the current
one could offer a tap on an already-full quota. The day lookup now also
returns that week's progress per child, and the card caps a past day with
it exactly as it caps today with weekly_chore_progress.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Past-day scheduling, completed one-shot visibility, vacation handling, and weekly target calculations contain unresolved correctness issues.

8 open findings
Previously missed (2)

In code that hasn't changed since last review

Medium severity Backdated completions are allowed during vacation periods

custom_components/​taskmate/​coord_chores.py:1176

The date-schedule check does not account for configured vacation periods, although chores are hidden on those dates elsewhere and week_progress explicitly removes those days from the available total. A direct complete_chore call can therefore backdate and award a chore on a planned vacation day. Reject is_vacation_day(day) before the weekly-target/schedule checks.

Medium severity Weekly denominator ignores teamwork point sharing and bonuses

custom_components/​taskmate/​coord_points.py:75

Teamwork completions award team_share_points (including split mode and team_bonus), but the weekly denominator uses the full base points. A 10-point, two-person split chore contributes 10 available points while each child can earn only 5; conversely a team bonus can make earned exceed available. Use the same per-participant point calculation as completion and sensor rendering.

🧠 Review effort: Balanced

…a day

Addresses the Copilot review on tempus2016#1063:

- A switched-off chore is refused even when it has a weekly target (that
  path skipped the due-day check, which was where it used to be caught),
  and a day inside a holiday is refused.
- The rules live in _backdate_refusal. The day lookup now also returns the
  chores each child could have logged that day (loggable), so the plain
  list and the past-day sticker chart follow every schedule TaskMate knows
  (recurrences, every-N-days, calendar moves, holidays), not just weekdays.
  The plain list also leaves out weekly-target chores whose quota that
  week is full.
- A finished one-off job keeps its tile on the day it was ticked, so it can
  still be undone.
- Reduced motion also stops the celebration bouncing and the confetti.
- Week progress counts a teamwork chore at each member's share plus any
  team bonus, as it is paid.
Addresses the Copilot review on tempus2016#1062:

- The chore board, kiosk and recap cards now draw a child through the
  shared face helper, so a child's photo shows there too and a child
  without one keeps their avatar. (The badges card has no per-child avatar
  to draw: its sensor sends none, so it always shows the generic icon.)
- The set of tracked picture entities trims each id the same way the photo
  lookup reads it, so a stray space can't leave a photo untracked.
Addresses the second Copilot review on tempus2016#1062: the bounty board and auction
cards drew every child as an initial, and the child card's teamwork row
read the avatar directly. All three now use the shared face helper, so a
child's photo shows there; the bounty and auction cards keep the initial
for a child without one.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Backdated undo, one-shot visibility, birthday exclusions, and weekly goal calculations have unresolved correctness issues.

1 open finding
8 resolved since last review
Previously missed (2)

In code that hasn't changed since last review

Medium severity Backdating ignores birthday day-off exclusions

custom_components/​taskmate/​coord_chores.py:1220

Backdating bypasses the existing birthday day-off rule: _is_chore_scheduled_for_date only evaluates the chore's calendar schedule, so a non-mandatory chore can be offered and logged on a child's birthday even when birthday_chores_off is enabled. Apply the same child-specific birthday exclusion used by the normal due/availability paths; mandatory chores should remain eligible.

Medium severity Photo picker excludes non-person entities with pictures

custom_components/​taskmate/​www/​taskmate-panel.js:10097

The stacked photo change is described as supporting a person or any entity with a picture, and the backend resolver accepts any entity ID, but this picker restricts users to person.*. Since the custom picker filters out every other domain, the panel cannot configure the advertised non-person case. Remove the domain restriction or filter candidates by entity_picture instead.

🧠 Review effort: Balanced

Comment thread custom_components/taskmate/coord_chores.py
…ty with a picture

Addresses the third Copilot review on tempus2016#1062:

- The badges sensor now says whose badges they are (child_name,
  child_avatar, avatar_image), and the card draws that face through the
  shared helper. Before, the sensor sent neither, so the card always
  showed a generic icon.
- "Photo from" lists any entity that has a picture (person, image,
  camera...) instead of person entities only, matching what the backend
  accepts.
Addresses the latest Copilot review on tempus2016#1063:

- Undoing a completion refunded its weekly target bonus only inside the
  streak block, which skips backdated jobs, so a backdated job's bonus
  outlived the job. The refund now runs for every completion.
- A child's birthday with "chores off" is refused for every chore but the
  mandatory ones, the same rule today's chore list follows.
@cad861
cad861 requested a balanced review from Copilot October 14, 2026 09:49

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Weekly targets miscalculate completed one-shot and birthday chores, and undo lacks keyboard accessibility.

0 open findings

1 resolved since last review
Previously missed (2)

In code that hasn't changed since last review

Medium severity Apply birthday rules consistently to weekly goal denominator

custom_components/​taskmate/​coord_points.py:88

The denominator does not apply the existing birthday rules. With birthday_chores_off, non-mandatory jobs on the child's birthday are counted even though they cannot be completed; when chores remain enabled, earned includes the birthday multiplier but available does not. This can make the weekly target either unreachable or fill early, so exclude birthday days off and apply the same multiplier as _award_points.

Medium severity Provide keyboard-accessible undo for completed chores

custom_components/​taskmate/​www/​taskmate-sticker-chart-card.js:895

Undo is exposed only through a pointer press-and-hold. Keyboard activation always calls _complete, which is a no-op for an already completed tile, so keyboard and switch-device users cannot perform the advertised undo action. Add a keyboard-accessible undo control or key binding and expose it in the accessible label/instructions.

🧠 Review effort: Balanced

The weekly goal's denominator now drops a child's non-mandatory chores on
their birthday day off and applies the birthday multiplier to that day,
matching what the chores would actually pay.

Delete/Backspace on a ticked tile undoes it, the keyboard twin of
press-and-hold, and the tile advertises it with aria-keyshortcuts.
TaskMate's child sensors show the photo chosen for the child, so picking
one as the source made the face refer to itself and go stale. The picker
no longer lists them and the backend ignores one if it was already saved.

The hint now says any entity with a picture can be used, the child's
person being the usual choice.
@tempus2016

Copy link
Copy Markdown
Owner

Thanks, this round covers everything I had. The weekly bonus now comes back off when a past-day job is undone, the birthday day off is respected (including in the weekly goal), and the sticker chart has keyboard undo. Nice to see tests for each of them.

This one waits on #1062, so it inherits the hint translation follow-up I left there. When that lands I'll test this on my dev instance and review it properly. It's a large change to points and streaks, so it may take me a little while.

tempus2016 added a commit that referenced this pull request Oct 14, 2026
…day (#1063) (#1064)

Contributed by @cad861 in #1063.

Co-authored-by: cad861 <50969049+cad861@users.noreply.github.com>
@tempus2016

Copy link
Copy Markdown
Owner

Merged, thank you! Squash-merging #1062 left this branch with a small conflict in sensor.py (two neighbouring additions), and I can't push to your fork, so it went in through #1064. That's your branch with main merged in, giving a tree identical to this PR's head, and you're credited as co-author on the commit (e249237). I've also picked up the picker hint translations myself, so there's nothing left for you to do there. Closing this one as landed.

@cad861

cad861 commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

Merged, thank you! Squash-merging #1062 left this branch with a small conflict in sensor.py (two neighbouring additions), and I can't push to your fork, so it went in through #1064. That's your branch with main merged in, giving a tree identical to this PR's head, and you're credited as co-author on the commit (e249237). I've also picked up the picker hint translations myself, so there's nothing left for you to do there. Closing this one as landed

Great thank you and for the credit. Keep up the great work!

@cad861
cad861 deleted the upstream-pr/sticker branch October 14, 2026 22:07
@tempus2016 tempus2016 added this to the v6.4.0 milestone Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Python integration code cards Lovelace cards / frontend (www/*.js) documentation Improvements or additions to documentation tests Test suite translations i18n / locale strings

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants