feat(tasks): set up a task that repeats every N days
Add a task gains "Every N days": a length of 2 to 366 days and the date a cycle began. Editing one keeps its length and start, and "days needed" is capped at the cycle's length. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a80f581d8b
commit
be3c1408d2
3 files changed
+138
-19
No files matched your search
@@ -1296,6 +1296,7 @@ describe("the reader's weekly and monthly tasks in settings", () => {
|
||||
const fields = {
|
||||
game: "zzz", title: "Activity points", unit: "week" as const, weekday: 1, monthDay: 1,
|
||||
kind: "amount" as const, required: "1", target: "2,100", amountUnit: "points",
|
||||
cycleDays: "14", cycleFrom: "",
|
||||
};
|
||||
expect(taskDraftFrom(fields)).toEqual({
|
||||
game: "zzz", title: "Activity points",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { stillNeededLine } from "../src/client/components/formParts.tsx";
|
||||
import {
|
||||
TaskForm,
|
||||
taskDraftFrom,
|
||||
taskFieldsFrom,
|
||||
taskStillNeeded,
|
||||
withTaskTemplate,
|
||||
type TaskFields,
|
||||
@@ -29,6 +30,8 @@ const typed: TaskFields = {
|
||||
required: "2",
|
||||
target: "1300",
|
||||
amountUnit: "points",
|
||||
cycleDays: "14",
|
||||
cycleFrom: "",
|
||||
};
|
||||
|
||||
describe("the still-needed line", () => {
|
||||
@@ -311,6 +314,10 @@ describe("review fixes: Save never sits disabled without a reason", () => {
|
||||
{ ...typed, kind: "days", required: "8" },
|
||||
{ ...typed, unit: "month", kind: "days", required: "31" },
|
||||
{ ...typed, unit: "month", monthDay: "" },
|
||||
{ ...typed, unit: "cycle", cycleFrom: "2026-10-16" },
|
||||
{ ...typed, unit: "cycle", cycleFrom: "" },
|
||||
{ ...typed, unit: "cycle", cycleDays: "1", cycleFrom: "2026-10-16" },
|
||||
{ ...typed, unit: "cycle", kind: "days", required: "4", cycleDays: "3", cycleFrom: "2026-10-16" },
|
||||
];
|
||||
for (const f of cases) {
|
||||
expect({ target: f.target, required: f.required, empty: taskStillNeeded(f).length === 0 })
|
||||
@@ -357,3 +364,46 @@ describe("follow-up: a wait with the end set to unknown", () => {
|
||||
expect(eventFormState({ ...v, endKnown: true }, null).needs).toEqual(["an end date"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("a task every N days", () => {
|
||||
const shiyu: TaskFields = {
|
||||
...typed, title: "Shiyu Defense", unit: "cycle", kind: "days", required: "1",
|
||||
cycleDays: "14", cycleFrom: "2026-10-16",
|
||||
};
|
||||
|
||||
test("becomes a cycle period", () => {
|
||||
expect(taskDraftFrom(shiyu)?.period).toEqual({ unit: "cycle", days: 14, from: "2026-10-16" });
|
||||
});
|
||||
|
||||
test("needs a length of 2 to 366 days and a start date", () => {
|
||||
expect(taskStillNeeded({ ...shiyu, cycleDays: "1" })).toEqual(["a length of 2 to 366 days"]);
|
||||
expect(taskStillNeeded({ ...shiyu, cycleDays: "367" })).toEqual(["a length of 2 to 366 days"]);
|
||||
expect(taskStillNeeded({ ...shiyu, cycleDays: "" })).toEqual(["a length of 2 to 366 days"]);
|
||||
expect(taskStillNeeded({ ...shiyu, cycleFrom: "" })).toEqual(["a start date"]);
|
||||
});
|
||||
|
||||
test("days needed is bounded by the cycle's length and by 31", () => {
|
||||
expect(taskStillNeeded({ ...shiyu, cycleDays: "3", required: "3" })).toEqual([]);
|
||||
expect(taskStillNeeded({ ...shiyu, cycleDays: "3", required: "4" })).toEqual(["how many days"]);
|
||||
expect(taskStillNeeded({ ...shiyu, cycleDays: "42", required: "32" })).toEqual(["how many days"]);
|
||||
});
|
||||
|
||||
test("editing one keeps its length and start", () => {
|
||||
const initial = {
|
||||
game: "zzz", title: "Shiyu Defense",
|
||||
period: { unit: "cycle" as const, days: 14, from: "2026-10-16" },
|
||||
measure: { kind: "days" as const, required: 1 },
|
||||
};
|
||||
expect(taskDraftFrom(taskFieldsFrom(initial, ["zzz"]))).toEqual(initial);
|
||||
const html = renderToStaticMarkup(
|
||||
<TaskForm lanes={["zzz"]} initial={initial} onSave={noop} onCancel={noop} />,
|
||||
);
|
||||
expect(html).toMatch(/aria-pressed="true"[^>]*>Every N days</);
|
||||
expect(html).toContain('value="14"');
|
||||
expect(html).toContain('value="2026-10-16"');
|
||||
});
|
||||
|
||||
test("a week or month task still starts with a two-week cycle on offer", () => {
|
||||
expect(taskFieldsFrom(undefined, ["zzz"])).toMatchObject({ unit: "week", cycleDays: "14", cycleFrom: "" });
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user