fix(tasks): a cycle chip counts its days left whether ticked or not
It printed the unticked days left, so ticking a cycle off dropped its figure by one, and on the last day read 0d. Tasks now carry daysLeft, the period's days from today, and the chip prints that. Found in the whole-branch review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f19ef32e4a
commit
4427f6c2e5
3 files changed
+17
-2
No files matched your search
+3
-1
@@ -86,6 +86,8 @@ export interface GoalStatus {
|
||||
open: number | null;
|
||||
/** Fewer days left than check-ins needed. The target is never lowered. */
|
||||
shortfall: boolean;
|
||||
/** A task's days left in its period from today, ticked or not — what a cycle's chip shows. */
|
||||
daysLeft?: number | undefined;
|
||||
}
|
||||
|
||||
/** Bounds a walk over keys when the end is unknown; matches daily.ts. */
|
||||
@@ -207,7 +209,7 @@ export function goalSummary(goal: Goal | undefined): string {
|
||||
/** The Dailies chip's short count. */
|
||||
export function goalCount(s: GoalStatus): string {
|
||||
// "cy" means nothing; the days left in a cycle say where it is.
|
||||
if (s.scope === "cycle") return `${num(s.count)}/${num(s.required)} · ${s.open ?? 0}d`;
|
||||
if (s.scope === "cycle") return `${num(s.count)}/${num(s.required)} · ${s.daysLeft ?? s.open ?? 0}d`;
|
||||
const unit = s.scope === "week" ? " wk" : s.scope === "month" ? " mo" : "";
|
||||
return `${num(s.count)}/${num(s.required)}${unit}`;
|
||||
}
|
||||
|
||||
+2
-1
@@ -87,7 +87,7 @@ export function taskStatus(input: {
|
||||
return {
|
||||
scope, measure: "amount", periodStart: start, required, count,
|
||||
met: count >= required, needed: Math.max(0, required - count),
|
||||
open: left.length, shortfall: false,
|
||||
open: left.length, shortfall: false, daysLeft: left.length,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ export function taskStatus(input: {
|
||||
return {
|
||||
scope, measure: "days", periodStart: start, required, count,
|
||||
met: count >= required, needed, open, shortfall: needed > open,
|
||||
daysLeft: left.length,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, test } from "bun:test";
|
||||
import { RESERVED_ID_SEGMENTS } from "../src/shared/custom.ts";
|
||||
import { nextResetMs } from "../src/shared/daily.ts";
|
||||
import { goalCount } from "../src/shared/goal.ts";
|
||||
import { mintTaskId, TaskSchema, taskCaption, taskStatus, type Task } from "../src/shared/task.ts";
|
||||
|
||||
/**
|
||||
@@ -171,3 +172,14 @@ describe("a task on another server's clock", () => {
|
||||
expect(after.periodStart).toBe("2026-10-08");
|
||||
});
|
||||
});
|
||||
|
||||
describe("a cycle chip's days left", () => {
|
||||
test("is the days left in the cycle, ticked or not", () => {
|
||||
const t = task({ period: { unit: "cycle", days: 14, from: "2026-10-16" }, measure: { kind: "days", required: 1 } });
|
||||
const at = (logged: string[], day: string) =>
|
||||
goalCount(taskStatus({ task: t, region: "europe", now: noon(day), logged }));
|
||||
expect(at([], "2026-10-20")).toBe("0/1 · 10d");
|
||||
expect(at(["2026-10-20"], "2026-10-20")).toBe("1/1 · 10d");
|
||||
expect(at(["2026-10-29"], "2026-10-29")).toBe("1/1 · 1d");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user