This commit is contained in:
JCEEE
2026-09-14 21:29:10 +01:00
parent 49658bd791
commit f9fa99f5ff
5 changed files with 31 additions and 24 deletions
+1 -1
View File
@@ -208,7 +208,7 @@
<span class="msg-author" style="color:{colorOf(msg)}">{msg.authorName}</span>
{/if}
<div class="bubble" style="background:{colorOf(msg) + '33'}; color:{colorOf(msg)}">
{#each renderContent(msg.content) as seg (msg.id + ':' + seg.text)}
{#each renderContent(msg.content) as seg, i (msg.id + ':' + i)}
{#if seg.mention}
<button class="mention" onclick={() => insertMention(seg.text.slice(1))}
>{seg.text}</button
@@ -1,16 +1,19 @@
<script lang="ts">
import type { Snippet } from 'svelte';
let {
announcement = '',
role = '',
seasons = [],
connected = true,
children,
left
}: {
announcement?: string
role?: string
seasons?: { id: string; name: string; color: string; active: boolean }[]
connected?: boolean
children?: any
left?: Snippet
} = $props();
</script>
@@ -19,6 +22,7 @@
{#if role}
<span class="role-pill {role}">{role}</span>
{/if}
{@render left?.()}
<span
class="conn-dot"
class:up={connected}
+10 -10
View File
@@ -55,14 +55,13 @@ export async function toggle(pb: any, famId: string, memberId: string, body: { a
const chore = choreList?.[0];
const isTodo = chore?.isTodo;
const isShared = chore?.shared === true || !chore?.memberId;
// Only one-off shared todos are claimed (winner takes it). Recurring
// shared chores stay unassigned so every member completes independently
// each period — claiming them permanently hides the chore from siblings.
const isClaimable = isShared && !!isTodo;
let filter: string;
if (isShared && !isTodo) {
// Shared non-todo: any completion in the period = already claimed
const { payday, tz } = await famMetaSU(famId);
const { from, to } = periodWindow(chore?.frequency, payday, tz);
filter = `assignedChoreId = '${assignedChoreId}' && date >= '${from}' && date < '${to}'`;
} else if (isTodo) {
if (isTodo) {
filter = `assignedChoreId = '${assignedChoreId}' && memberId = '${memberId}'`;
} else {
const { payday, tz } = await famMetaSU(famId);
@@ -78,8 +77,8 @@ export async function toggle(pb: any, famId: string, memberId: string, body: { a
if (isTodo && existing[0].rewardId) {
await pb.collection('rewards').delete(existing[0].rewardId).catch(() => {});
}
// If this was a shared chore claimed by this member, un-share it
if (isShared && existing[0].memberId === memberId) {
// If this was a claimed one-off todo, release it back to shared.
if (isClaimable && existing[0].memberId === memberId) {
await claimChore(assignedChoreId, famId, '');
}
evaluateFam(pb, famId).catch(() => {});
@@ -107,8 +106,9 @@ export async function toggle(pb: any, famId: string, memberId: string, body: { a
completedAt: new Date().toISOString(),
...(rewardId ? { rewardId } : {})
});
// Claim the shared chore by setting memberId
if (isShared) {
// Claim a shared one-off todo by setting memberId (recurring shared
// chores stay unassigned — see isClaimable above).
if (isClaimable) {
await claimChore(assignedChoreId, famId, memberId);
}
evaluateFam(pb, famId).catch(() => {});
+12 -10
View File
@@ -306,6 +306,18 @@
announcement={disabled && !activating ? accessMessage(accessReason, isParent) : ''}
connected={!famStore.connectionDown}
>
{#snippet left()}
<button
class="shared-toggle"
class:on={sharedOn}
onclick={toggleShared}
aria-label="Toggle shared computer mode"
aria-pressed={sharedOn}
title={sharedOn ? 'Shared computer mode is ON' : 'Mark this as a shared computer'}
>
{@html monitorIcon}
</button>
{/snippet}
<button class="chat-toggle" onclick={() => chatStore.toggle()} aria-label="Open chat">
{@html chatIcon}
{#if chatStore.unread > 0}
@@ -323,16 +335,6 @@
></span>
</button>
{/if}
<button
class="shared-toggle"
class:on={sharedOn}
onclick={toggleShared}
aria-label="Toggle shared computer mode"
aria-pressed={sharedOn}
title={sharedOn ? 'Shared computer mode is ON' : 'Mark this as a shared computer'}
>
{@html monitorIcon}
</button>
</TopNav>
<main class="app-main" class:join-page={page.url.pathname.split('/')[2] === 'join'}>
<div class="page-wrap">
@@ -550,9 +550,10 @@
const name = bonusConfigs.find((b: BonusConfig) => b.id === r.bonusConfigId)?.name || r.label;
map.set(name, (map.get(name) || 0) + 1);
}
// Only badge recurring/multiple bonuses — a single occurrence (×1) is
// already obvious from the wallet, so it just adds noise here.
return [...map.entries()].map(([name, count]) => ({ name, count })).filter((t) => t.count > 1);
// Badge every bonus earned this week — including a single occurrence
// (×1): the hero is the child's only at-a-glance signal, so nothing
// earned should stay invisible here.
return [...map.entries()].map(([name, count]) => ({ name, count }));
});
let anyWeekBonuses = $derived(weekRewards.length > 0);