fix bugs
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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(() => {});
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user