diff --git a/docs/DATA-MODEL.md b/docs/DATA-MODEL.md index e36000f..fda7d63 100644 --- a/docs/DATA-MODEL.md +++ b/docs/DATA-MODEL.md @@ -222,7 +222,11 @@ Namespaced, versioned, and small. Nothing here ever goes to the server. // timelineDayWidth, timelineGroup, showUpcoming, // timelineSplitUpcoming, detectDaily, showChores, // showCompleted, showIgnored, theme, regionConfirmed, - // onboarded } + // onboarded, routineGames?, routinesAsked? } + // routineGames is the games whose built-in weekly tasks + // the reader turned on; routinesAsked the games already + // asked about. Both absent means none — built-ins are + // opt-in for every install. PRD F17. // timelineDayWidth is px per day on the board, stored as the // measurement rather than a step number and read through // snapDayWidth — so a value from an older ladder still opens diff --git a/docs/superpowers/specs/2026-10-13-periodic-tasks-design.md b/docs/superpowers/specs/2026-10-13-periodic-tasks-design.md index 18acdc4..fae60b5 100644 --- a/docs/superpowers/specs/2026-10-13-periodic-tasks-design.md +++ b/docs/superpowers/specs/2026-10-13-periodic-tasks-design.md @@ -133,12 +133,14 @@ Monday; monthly to the 1st. number is visibly dated rather than presented as current. - **Asking.** When a game with built-ins becomes visible — first-run picker, or switched on in settings — and is not in `routinesAsked`, a one-line card at the top of the dailies - strip asks: `Track Zenless Zone Zero's weekly and monthly tasks? Yes · No thanks`. Either + strip asks: `Track Zenless Zone Zero's built-in weekly tasks? Yes · No thanks`. Either answer records the game in `routinesAsked`; Yes also adds it to `routineGames`. Never a modal, and never asked twice. -- **Toggle.** The games settings group shows a “Weekly tasks” switch on each game that has - built-ins, writing `routineGames`. Off hides the chips; their ticks and amounts stay. -- **Make it mine.** From a built-in chip's editor or the settings list: copies the template +- **Toggle.** *What you see* shows a “Built-in weekly tasks for ” switch, beside the daily + chores switch, for each game that has built-ins, writing `routineGames` (and answering the + strip's question). Off hides the chips; their ticks and amounts stay. Each built-in shows the + date its source gives (`asOf`), not the date we read it. +- **Make it mine.** From the settings list: copies the template into a `mytask:` record with `from` set, and copies the built-in's ticks and amounts to the new id (additive; the originals stay). A built-in whose id is some task's `from` is hidden; deleting that copy brings it back. diff --git a/src/client/App.tsx b/src/client/App.tsx index d865920..e86b361 100644 --- a/src/client/App.tsx +++ b/src/client/App.tsx @@ -35,7 +35,13 @@ import { clockFor, formatRemaining } from "../shared/time.ts"; import { dailySummary, isDaily, resolveDaily } from "../shared/daily.ts"; import { goalStatus, readGoal, type GoalStatus } from "../shared/goal.ts"; import { taskStatus, type TaskShape } from "../shared/task.ts"; -import { activeRoutines, mineFrom, routineToAsk, type Routine } from "../shared/routines.ts"; +import { + activeRoutines, + copyRoutineState, + mineFrom, + routineToAsk, + type Routine, +} from "../shared/routines.ts"; import { strandedOccurrences } from "../shared/recurrence.ts"; import { orderGames } from "./state/gameOrder.ts"; import { GameMetaProvider, type MetaResolver } from "./state/gameMeta.tsx"; @@ -212,10 +218,9 @@ export function App() { const makeItMine = (routine: Routine) => { if (tasks.tasks.some((t) => t.from === routine.id)) return; const id = tasks.addTask(mineFrom(routine)); - const log = daily.logs[routine.id]; - if (log !== undefined) daily.merge({ [id]: log }); - const numbers = amounts.amounts[routine.id]; - if (numbers !== undefined) amounts.merge({ [id]: numbers }); + const copy = copyRoutineState(daily.logs, amounts.amounts, routine.id, id); + daily.merge(copy.daily); + amounts.merge(copy.amounts); }; const taskStatusOf = (task: TaskShape): GoalStatus => diff --git a/src/client/components/Dailies.tsx b/src/client/components/Dailies.tsx index 6d359ea..c108a4a 100644 --- a/src/client/components/Dailies.tsx +++ b/src/client/components/Dailies.tsx @@ -384,6 +384,7 @@ export function Dailies({