add yesterday catchup

This commit is contained in:
JCEEE
2026-09-23 09:43:25 +01:00
parent 31da825e93
commit a710e22f35
4 changed files with 170 additions and 15 deletions
@@ -45,9 +45,19 @@ export async function myChores(pb: any, famId: string, memberId: string) {
};
}
export async function toggle(pb: any, famId: string, memberId: string, body: { assignedChoreId: string; date: string }) {
export async function toggle(pb: any, famId: string, memberId: string, body: { assignedChoreId: string; date: string; completedAt?: string }) {
const { assignedChoreId, date } = body;
if (!assignedChoreId || !date) throw new Error('assignedChoreId and date required');
// Backdated catch-up (yesterday mode) stamps the completion for the viewed
// day, never "now" — the logical `date` always comes from the client, and
// an explicit `completedAt` is honoured when it parses (validated ISO,
// defaulting to now). Server-side period windows are always computed from
// the real current day, so a yesterday stamp can't shift window logic.
let completedAt = new Date().toISOString();
if (typeof body.completedAt === 'string') {
const t = new Date(body.completedAt).getTime();
if (Number.isFinite(t)) completedAt = new Date(t).toISOString();
}
// Chore existence is checked as superuser so a stale client ID (parent
// re-saved the chores grid → old assigned rows deleted, new ids issued)
@@ -113,7 +123,7 @@ export async function toggle(pb: any, famId: string, memberId: string, body: { a
memberId,
assignedChoreId,
date,
completedAt: new Date().toISOString(),
completedAt,
...(rewardId ? { rewardId } : {})
});
// Claim a shared one-off todo by setting memberId (recurring shared
+1 -1
View File
@@ -56,7 +56,7 @@ export function createServices(
cleanupExpiredTodos: (famId: string) => choresSvc.cleanupExpiredTodos(pb, famId)
},
completions: {
toggle: (famId: string, body: { assignedChoreId: string; date: string }) =>
toggle: (famId: string, body: { assignedChoreId: string; date: string; completedAt?: string }) =>
completionsSvc.toggle(pb, famId, uid, body),
revoke: (famId: string, completionId: string) =>
completionsSvc.revoke(pb, famId, completionId)