updated rewards assignment and reward progress
This commit is contained in:
@@ -229,6 +229,15 @@ export const SCHEMA_PLAN: CollectionPlanEntry[] = [
|
||||
select("period", ["schedule", "daily", "weekly", "monthly"]),
|
||||
select("status", ["active", "completed"], true),
|
||||
bool("isPocketMoney"),
|
||||
// Standalone/one-off reward progress window. `period` stays empty for
|
||||
// these (they're measured once, not per-cycle). `completeBy` bounds how
|
||||
// far progress counts: `unlimited` (cumulative since startDate),
|
||||
// `week` (end of current week), or `custom` (a specific completeByDate).
|
||||
// `startDate` is when tracking begins — without it "unlimited" would
|
||||
// count points earned before the reward existed.
|
||||
select("completeBy", ["unlimited", "week", "custom"]),
|
||||
text("startDate"),
|
||||
text("completeByDate"),
|
||||
], {
|
||||
createRule: RULE_PARENT_WRITE,
|
||||
updateRule: RULE_PARENT_SCOPED,
|
||||
|
||||
@@ -104,6 +104,43 @@ export function periodEnd(period: string, start: string): string {
|
||||
return start;
|
||||
}
|
||||
|
||||
// Compute the completion-counting window for a bonus. Recurring period-based
|
||||
// bonuses keep their per-cycle window (periodStart..periodEnd). Standalone /
|
||||
// one-off rewards (no `period`) are scoped by `completeBy` + `startDate`:
|
||||
// - `completeBy === "week"` → current week [weekStart, weekEnd]
|
||||
// - `completeBy === "custom"` → [startDate, completeByDate]
|
||||
// - otherwise (`unlimited`/empty) → [startDate, ∞] (cumulative)
|
||||
// `from`/`to` of "" mean unbounded on that side (legacy configs with no dates
|
||||
// count everything since records began, i.e. the admin-dashboard behaviour).
|
||||
export function bonusWindow(
|
||||
cfg: { period?: string; completeBy?: string; startDate?: string; completeByDate?: string },
|
||||
payday: number,
|
||||
tz: string,
|
||||
): { from: string; to: string } {
|
||||
if (cfg.period) {
|
||||
const start = periodStart(cfg.period, payday, tz);
|
||||
return { from: start, to: periodEnd(cfg.period, start) };
|
||||
}
|
||||
const from = cfg.startDate || "";
|
||||
let to = "";
|
||||
if (cfg.completeBy === "week") to = periodEnd("weekly", weekStart(payday, tz));
|
||||
else if (cfg.completeBy === "custom") to = cfg.completeByDate || "";
|
||||
return { from, to };
|
||||
}
|
||||
|
||||
// True if a completion record's date falls within the window (dates may be
|
||||
// YYYY-MM-DD or ISO with a time portion).
|
||||
export function completionInWindow(
|
||||
c: { date?: string },
|
||||
win: { from: string; to: string },
|
||||
): boolean {
|
||||
const day = (c.date || "").slice(0, 10);
|
||||
if (!day) return false;
|
||||
if (win.from && day < win.from) return false;
|
||||
if (win.to && day > win.to) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The completion window a chore of a given frequency is "done for" in the
|
||||
// current period. Weekly chores are done once per week ([weekStart, +7)),
|
||||
// daily chores once per day ([today, +1)). Half-open [from, to).
|
||||
|
||||
Reference in New Issue
Block a user