clean pass update with rewards and completions
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
import { Chart, registerables } from 'chart.js';
|
||||
import { ViewHeader, CardGrid, Card } from '$lib/components';
|
||||
import { formatDDMMYY } from '$lib/format';
|
||||
import { famStore } from '$lib/stores/fam.svelte';
|
||||
import { handleOf } from '@shared/slugify';
|
||||
import { addDaysStr, resolveTz, todayInTz } from '@shared/timezone';
|
||||
|
||||
@@ -54,6 +55,28 @@
|
||||
let allTimeCash = $derived(Number(stats.allTimeCash) || 0);
|
||||
let allTimeChores = $derived(Number(stats.allTimeChores) || 0);
|
||||
|
||||
// ─── Goals completed (rewards from bonus configs, pocket money excluded) ───
|
||||
// Derived from famStore so realtime updates (a goal met / revoked) flow in.
|
||||
let rewards = $derived(famStore.initialized ? famStore.rewards : data.rewards || []);
|
||||
let bonusConfigs = $derived(
|
||||
famStore.initialized ? famStore.bonusConfigs : data.bonusConfigs || []
|
||||
);
|
||||
let goalsByMember = $derived.by(() => {
|
||||
const ws = (summary?.weekStart as string) || todayInTz(famTz);
|
||||
const pmIds = new Set(bonusConfigs.filter((c: any) => c.isPocketMoney).map((c: any) => c.id));
|
||||
const map = new Map<string, { count: number; names: string[] }>();
|
||||
for (const r of rewards as any[]) {
|
||||
if (!r.bonusConfigId || pmIds.has(r.bonusConfigId)) continue;
|
||||
if ((r.date || '').slice(0, 10) < ws) continue;
|
||||
const cfg = bonusConfigs.find((c: any) => c.id === r.bonusConfigId);
|
||||
const entry = map.get(r.memberId) || { count: 0, names: [] };
|
||||
entry.count++;
|
||||
if (cfg?.name && !entry.names.includes(cfg.name)) entry.names.push(cfg.name);
|
||||
map.set(r.memberId, entry);
|
||||
}
|
||||
return map;
|
||||
});
|
||||
|
||||
// ─── Trend chart window: show current month, expand a month at a time up to 3. ───
|
||||
let trend = $derived.by(() => {
|
||||
const series = Array.isArray(stats.series) ? stats.series : [];
|
||||
@@ -340,6 +363,7 @@
|
||||
{@const scPot = dailyPointsPotential(s.memberId)}
|
||||
{@const scVal = avgDailyPointsFor(s)}
|
||||
{@const scPct = scPot > 0 ? Math.min(100, Math.round((scVal / scPot) * 100)) : 0}
|
||||
{@const goals = goalsByMember.get(s.memberId)}
|
||||
<div class="column col-member">
|
||||
<div class="member-head">
|
||||
<span class="dot" style="background:{s.memberColor}"></span>
|
||||
@@ -378,6 +402,12 @@
|
||||
<span class="stat-lbl">Done</span>
|
||||
<span class="stat-val">{wkDone}/{wkTotal}</span>
|
||||
</div>
|
||||
<div class="stat-row">
|
||||
<span class="stat-lbl">Goals 🎉</span>
|
||||
<span class="stat-val goals" title={goals?.names.join(' · ')}
|
||||
>{goals?.count ?? 0}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/each}
|
||||
@@ -656,6 +686,9 @@
|
||||
.stat-val.cash {
|
||||
color: #059669;
|
||||
}
|
||||
.stat-val.goals {
|
||||
color: #059669;
|
||||
}
|
||||
|
||||
/* ── Chart ── */
|
||||
.chart-wrap {
|
||||
|
||||
Reference in New Issue
Block a user