187 files
This commit is contained in:
1 parent
28fa34d78a
commit
1e1b12d52b
187 files changed
+40899
-32654
No files matched your search
@@ -61,6 +61,7 @@ class TaskMateChildCard extends LitElement {
|
||||
super();
|
||||
this._loading = {};
|
||||
this._celebrating = null;
|
||||
this._celebrationWeeklyBonus = 0;
|
||||
this._confetti = [];
|
||||
// Optimistic completions: track chores that were just completed
|
||||
// These are used to immediately hide the DONE button before the server confirms
|
||||
@@ -1462,6 +1463,13 @@ class TaskMateChildCard extends LitElement {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.celebration-weekly-bonus {
|
||||
margin-top: 8px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
color: var(--fun-purple);
|
||||
}
|
||||
|
||||
.celebration-points ha-icon {
|
||||
--mdc-icon-size: 28px;
|
||||
color: var(--fun-yellow);
|
||||
@@ -2996,7 +3004,7 @@ class TaskMateChildCard extends LitElement {
|
||||
<span class="ch-emoji">${r.glyph}</span>
|
||||
<div class="ch-mid">
|
||||
<div class="ch-name">${r.chore.name}</div>
|
||||
${r.done ? "" : html`<div class="chip soft" style="margin-top:3px">+${r.points} ⭐</div>`}
|
||||
${r.done ? "" : html`<div class="chip soft" style="margin-top:3px">+${r.points} <ha-icon style="--mdc-icon-size:1.1em;vertical-align:-0.15em" icon="${this._pointsIcon()}"></ha-icon></div>`}
|
||||
${this._designChoreMeta(r)}
|
||||
</div>
|
||||
${r.done
|
||||
@@ -4141,9 +4149,10 @@ class TaskMateChildCard extends LitElement {
|
||||
const timeStr = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
|
||||
|
||||
// Rate display
|
||||
const pointsName = attrs.points_name || this._t('common.stars');
|
||||
const rateLabel = chore.timed_rate_minutes === 1
|
||||
? `${ratePoints} ${this._t('child.pts_per_min')}`
|
||||
: `${ratePoints} ${this._t('child.pts_per_n_min', {count: chore.timed_rate_minutes})}`;
|
||||
? `${ratePoints} ${this._t('child.pts_per_min', {pointsName})}`
|
||||
: `${ratePoints} ${this._t('child.pts_per_n_min', {count: chore.timed_rate_minutes, pointsName})}`;
|
||||
|
||||
// Daily cap info
|
||||
const maxMin = chore.timed_max_daily_minutes || 0;
|
||||
@@ -4373,7 +4382,7 @@ class TaskMateChildCard extends LitElement {
|
||||
// for non-parents with one friendly message instead of a doomed service call.
|
||||
// The one exception is a child's own tick still inside the undo window
|
||||
// (#918), which goes through the restricted undo_chore service.
|
||||
if (!window.__taskmate_is_parent(this.hass)) {
|
||||
if (!this._isParent()) {
|
||||
const own = (todaysCompletions || []).find(
|
||||
c => c.chore_id === chore.id && c.child_id === child.id && c.bonus_subtask_id === subtask.id
|
||||
);
|
||||
@@ -4454,6 +4463,9 @@ class TaskMateChildCard extends LitElement {
|
||||
<ha-icon icon="${pointsIcon}"></ha-icon>
|
||||
+${points}
|
||||
</div>
|
||||
${this._celebrationWeeklyBonus ? html`
|
||||
<div class="celebration-weekly-bonus">${this._t('child.weekly_target_bonus_reached', { points: this._celebrationWeeklyBonus })}</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -4559,6 +4571,17 @@ class TaskMateChildCard extends LitElement {
|
||||
},
|
||||
};
|
||||
|
||||
// Weekly target bonus (#1044): this tap fills the week's quota, and the
|
||||
// chore pays without approval, so the bonus lands right now — say so in
|
||||
// the celebration. Read before the call, while progress is still pre-tap.
|
||||
const weeklyTarget = Number(chore.weekly_target) || 0;
|
||||
const weeklyBonus = Number(chore.weekly_target_bonus) || 0;
|
||||
const weeklyProgress = Number((child.weekly_chore_progress || {})[chore.id] || 0);
|
||||
this._celebrationWeeklyBonus = weeklyTarget > 0 && weeklyBonus > 0
|
||||
&& chore.requires_approval === false && !chore.require_photo && !chore.open_ended
|
||||
&& weeklyProgress + 1 === weeklyTarget
|
||||
? weeklyBonus : 0;
|
||||
|
||||
this._loading = { ...this._loading, [chore.id]: true };
|
||||
this.requestUpdate();
|
||||
|
||||
@@ -4925,6 +4948,16 @@ class TaskMateChildCard extends LitElement {
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Parent-only controls are shown to admins and TaskMate parents unless the
|
||||
* card sets show_parent_actions: false (#1032) — for a shared kids' dashboard
|
||||
* where a parent account stays signed in. The card then behaves exactly as it
|
||||
* does for a child. Display only; the services keep their own permission checks.
|
||||
*/
|
||||
_isParent() {
|
||||
return this.config?.show_parent_actions !== false && window.__taskmate_is_parent(this.hass);
|
||||
}
|
||||
|
||||
/** True if an error from reject_chore is an authorization/admin rejection. */
|
||||
_isUnauthorized(error) {
|
||||
const text = `${error?.message || ""} ${error?.code || ""}`.toLowerCase();
|
||||
@@ -5049,7 +5082,7 @@ class TaskMateChildCard extends LitElement {
|
||||
// with one clear, friendly message and never fire the doomed call.
|
||||
// The one exception is a child's own completion still inside the undo
|
||||
// window (#918), which goes through the restricted undo_chore service.
|
||||
if (!window.__taskmate_is_parent(this.hass)) {
|
||||
if (!this._isParent()) {
|
||||
const latest = this._latestCompletion(childCompletionsToday);
|
||||
if (this._childCanUndo(latest)) {
|
||||
await this._childUndo(latest, chore, child);
|
||||
@@ -5181,12 +5214,18 @@ class TaskMateChildCard extends LitElement {
|
||||
return i.status === "open" ? "tm-insp-row-open" : i.status === "passed" ? "tm-insp-row-passed" : "";
|
||||
}
|
||||
|
||||
_pointsIcon() {
|
||||
const attrs = (window.__taskmate_attrs && window.__taskmate_attrs(this.hass, this.config?.entity))
|
||||
|| this.hass?.states?.[this.config?.entity]?.attributes || {};
|
||||
return attrs.points_icon || "mdi:star";
|
||||
}
|
||||
|
||||
_renderInspectionTag(chore, child) {
|
||||
const i = this._inspectionFor(chore, child);
|
||||
if (!i) return "";
|
||||
const tags = {
|
||||
open: ["mdi:magnify-scan", this._t("inspection.tag_open")],
|
||||
passed: ["mdi:star", this._t("inspection.tag_passed", { bonus: i.bonus })],
|
||||
passed: [this._pointsIcon(), this._t("inspection.tag_passed", { bonus: i.bonus })],
|
||||
redo: ["mdi:restore", this._t("inspection.tag_redo")],
|
||||
failed: ["mdi:magnify-scan", this._t("inspection.tag_failed")],
|
||||
};
|
||||
@@ -5289,6 +5328,7 @@ class TaskMateChildCard extends LitElement {
|
||||
|
||||
_closeCelebration() {
|
||||
this._celebrating = null;
|
||||
this._celebrationWeeklyBonus = 0;
|
||||
this.requestUpdate();
|
||||
}
|
||||
}
|
||||
@@ -5527,6 +5567,7 @@ class TaskMateChildCardEditor extends LitElement {
|
||||
{ name: 'pre_reader', selector: { boolean: {} } },
|
||||
{ name: 'pre_reader_labels', selector: { boolean: {} } },
|
||||
{ name: 'pre_reader_points', selector: { boolean: {} } },
|
||||
{ name: 'show_parent_actions', selector: { boolean: {} } },
|
||||
{ name: 'debug', selector: { boolean: {} } },
|
||||
];
|
||||
}
|
||||
@@ -5548,6 +5589,7 @@ class TaskMateChildCardEditor extends LitElement {
|
||||
pre_reader: this._t('child.editor.pre_reader'),
|
||||
pre_reader_labels: this._t('child.editor.pre_reader_labels'),
|
||||
pre_reader_points: this._t('child.editor.pre_reader_points'),
|
||||
show_parent_actions: this._t('common.editor.show_parent_actions'),
|
||||
debug: this._t('child.editor.show_debug'),
|
||||
};
|
||||
return labels[entry.name] ?? entry.name;
|
||||
@@ -5564,6 +5606,7 @@ class TaskMateChildCardEditor extends LitElement {
|
||||
dependency_mode: this._t('child.editor.dependency_helper'),
|
||||
elapsed_time_mode: this._t('child.editor.elapsed_helper'),
|
||||
include_anytime_chores: this._t('child.editor.include_anytime_chores_helper'),
|
||||
show_parent_actions: this._t('common.editor.show_parent_actions_helper'),
|
||||
};
|
||||
return helpers[entry.name] ?? '';
|
||||
};
|
||||
@@ -5587,6 +5630,7 @@ class TaskMateChildCardEditor extends LitElement {
|
||||
pre_reader: this.config.pre_reader === true,
|
||||
pre_reader_labels: this.config.pre_reader_labels === true,
|
||||
pre_reader_points: this.config.pre_reader_points === true,
|
||||
show_parent_actions: this.config.show_parent_actions !== false,
|
||||
debug: this.config.debug === true,
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user