This commit is contained in:
Home Assistant Version Control
2026-09-25 04:10:30 +00:00
parent 56c80f896e
commit ad634c1b84
60 changed files with 2895 additions and 794 deletions
@@ -345,6 +345,8 @@ class TaskMatePanel extends HTMLElement {
['Pool refund (reward sold out):', 'activity.reason_pool_refund_sold_out'],
['Pool refund (reward cost reduced):', 'activity.reason_pool_refund_cost_reduced'],
['Pool refund (reward deleted):', 'activity.reason_pool_refund_deleted'],
['Pool refund (reward funding changed):', 'activity.reason_pool_refund_funding_changed'],
['Pool refund (reward assignment changed):', 'activity.reason_pool_refund_assignment_changed'],
['Penalty:', 'activity.reason_penalty'],
['Bonus:', 'activity.reason_bonus'],
];
@@ -1417,6 +1419,7 @@ class TaskMatePanel extends HTMLElement {
timed_rate_points: 10, timed_rate_minutes: 5, timed_max_daily_minutes: 0,
assigned_to: [], requires_approval: true,
time_category: "anytime", completion_sound: "coin", daily_limit: 1,
weekly_target: 0,
difficulty: "medium",
claim_allowance_minutes: 0,
schedule_mode: "specific_days",
@@ -1657,6 +1660,7 @@ class TaskMatePanel extends HTMLElement {
completion_sound: d.completion_sound || "coin",
difficulty: d.difficulty || "medium",
daily_limit: Number(d.daily_limit) || 1,
weekly_target: Math.max(0, Number(d.weekly_target) || 0),
schedule_mode: d.schedule_mode || "specific_days",
due_days: d.due_days || [],
recurrence: d.recurrence || "weekly",
@@ -3235,7 +3239,7 @@ class TaskMatePanel extends HTMLElement {
ts: c.approved_at || c.claimed_at, kind: "claim",
child: (childById[c.child_id] || {}).name || "?",
label: `${this._t("panel.activity_claimed_reward", {name: (rewardById[c.reward_id] || {}).name || this._t("panel.activity_deleted_reward")})}`,
points: -((rewardById[c.reward_id] || {}).cost || 0),
points: -(c.approved_cost ?? (rewardById[c.reward_id] || {}).cost ?? 0),
}));
transactions.forEach(t => events.push({
ts: t.created_at, kind: "manual",
@@ -3283,6 +3287,10 @@ class TaskMatePanel extends HTMLElement {
chorePoints = Math.floor(c.timed_duration_seconds / rateSeconds) * (chore.timed_rate_points || 0);
}
}
// What the child was promised when they submitted beats anything
// recalculated here: a chore edited while the work sat in the
// queue, or a speed/roulette bonus that no longer applies.
chorePoints = c.submitted_points ?? chorePoints;
const photoCap = [choreName, (child && child.name) || "", c.completed_at ? new Date(c.completed_at).toLocaleString([], { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) : ""].filter(Boolean).join(" · ");
return `
<div class="tm-approval-item">
@@ -3464,6 +3472,11 @@ class TaskMatePanel extends HTMLElement {
? this._t("panel.common_one_shot")
: ((c.due_days || []).length === 0 ? this._t("panel.common_daily") : (c.due_days || []).map(d => this._labelOf(DAYS, d)).join(" · "));
const schedClass = c.schedule_mode === "recurring" ? "tm-pill-accent" : c.schedule_mode === "one_shot" ? "tm-pill-warn" : "tm-pill-success";
// A weekly quota doesn't replace the day list — the chore is still only
// offered on those days, it just stops once the week's count is filled.
const weeklyPill = Number(c.weekly_target) > 0
? ` <span class="tm-pill tm-pill-accent">${this._t("panel.chore_weekly_target_pill", { count: Number(c.weekly_target) })}</span>`
: "";
const modeBadge = c.assignment_mode && c.assignment_mode !== "everyone"
? `<span class="tm-pill tm-pill-${this._esc(c.assignment_mode)}">${this._t(`panel.assign_${c.assignment_mode}_short`)}</span>` : "";
const nameCell = renaming
@@ -3485,7 +3498,7 @@ class TaskMatePanel extends HTMLElement {
<td><span class="tm-pill">${this._esc(this._timeCategoryLabel(c.time_category))}</span></td>
<td>${assignedNames} ${modeBadge}</td>
<td>${currentName}</td>
<td><span class="tm-pill ${schedClass} tm-pill-dot">${this._esc(schedLabel)}</span></td>
<td><span class="tm-pill ${schedClass} tm-pill-dot">${this._esc(schedLabel)}</span>${weeklyPill}</td>
<td>${c.requires_approval ? `<span class='tm-yes'>${this._t("panel.common_yes")}</span>` : `<span class='tm-no'>${this._t("panel.common_no")}</span>`}</td>
</tr>
`;
@@ -4539,7 +4552,7 @@ class TaskMatePanel extends HTMLElement {
<div class="tm-setting-row">
<div class="tm-setting-label">${this._t("panel.settings_card_design_label")}<small>${this._t("panel.settings_card_design_hint")}</small></div>
<select class="tm-select" data-setting="card_design">
${["classic","playroom","console","cleanpro"].map(v => `<option value="${v}" ${v === (s.card_design || "classic") ? "selected" : ""}>${this._esc(this._t("common.design." + v))}</option>`).join("")}
${["classic","playroom","console","cleanpro","accessible","graphite"].map(v => `<option value="${v}" ${v === (s.card_design || "classic") ? "selected" : ""}>${this._esc(this._t("common.design." + v))}</option>`).join("")}
</select>
</div>
<div class="tm-setting-row">
@@ -5433,6 +5446,8 @@ class TaskMatePanel extends HTMLElement {
`).join("")}
</div>
</div>
${this._field(this._t("panel.chore_weekly_target_label"), "weekly_target", d.weekly_target || 0, "number",
this._t("panel.chore_weekly_target_hint"))}
` : "",
showRecurring ? `
<div class="tm-field-row">