From 2a7a117705a179eadf7a2040c8ffb469cd631007 Mon Sep 17 00:00:00 2001
From: Lucas Winther
Date: Sun, 16 Aug 2026 20:41:30 +0200
Subject: [PATCH] fix(sheet): make "Mark done" mark it done
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The button advanced one step round the untouched → doing → done cycle,
so pressing "Mark done" on a fresh event produced "doing it" and needed
a second press. Worse, the press after "done" cleared the status
outright rather than undoing anything.
Three states need three targets — that is the control directly above it.
This one is the commit, so it sets done and back. cycleStatus had no
other caller and is gone.
Co-Authored-By: Claude Opus 5 (1M context)
---
docs/PRD.md | 4 ++++
src/client/App.tsx | 2 --
src/client/components/EventDetail.tsx | 13 ++++++++++---
src/client/state/useProgress.ts | 28 +++++----------------------
4 files changed, 19 insertions(+), 28 deletions(-)
diff --git a/docs/PRD.md b/docs/PRD.md
index 836282c..60cc421 100644
--- a/docs/PRD.md
+++ b/docs/PRD.md
@@ -87,6 +87,10 @@ completion the user already has.
Three states, not two: untouched, doing it, done. Plus an optional effort estimate — quick, short,
long, grind — and a free-text note.
+Three states need three targets. A single control cycling untouched → doing → done makes a button
+labelled "Mark done" produce "doing it", which is the control lying about itself; the detail sheet
+has an explicit control per state, and its primary action goes straight to done and back.
+
Effort is not decoration. Combined with the time remaining it answers the question the calendar
can't: *can I still finish this?* The same two days is comfortable for a quick event and hopeless
for a grind, so an event carrying an effort estimate gets a "tight" or "running out of time" flag
diff --git a/src/client/App.tsx b/src/client/App.tsx
index 5d01106..ee1c10f 100644
--- a/src/client/App.tsx
+++ b/src/client/App.tsx
@@ -118,7 +118,6 @@ export function App() {
ignored.toggle(id);
setLastIgnored(wasIgnored ? null : { id, title });
};
- const toggle = prog.cycleStatus;
useEffect(() => {
const ac = new AbortController();
@@ -424,7 +423,6 @@ export function App() {
onEffort={prog.setEffort}
onNote={prog.setNote}
onIgnore={(id) => toggleIgnored(id, openRow.event.title)}
- onToggle={toggle}
onClose={() => setOpenId(null)}
/>
)}
diff --git a/src/client/components/EventDetail.tsx b/src/client/components/EventDetail.tsx
index 2dfe3cc..8e2dd18 100644
--- a/src/client/components/EventDetail.tsx
+++ b/src/client/components/EventDetail.tsx
@@ -24,7 +24,6 @@ export function EventDetail({
dailyDays,
onDaily,
onToggleDay,
- onToggle,
onIgnore,
onStatus,
onEffort,
@@ -47,7 +46,6 @@ export function EventDetail({
dailyDays: string[];
onDaily: (id: string, daily: boolean | undefined) => void;
onToggleDay: (id: string, day: string) => void;
- onToggle: (id: string) => void;
onIgnore: (id: string) => void;
onStatus: (id: string, s: Status | undefined) => void;
onEffort: (id: string, e: Effort | undefined) => void;
@@ -198,10 +196,19 @@ export function EventDetail({
)}
+ {/* Says what it does and does what it says.
+
+ It used to advance one step round the untouched → doing → done
+ cycle, so a reader pressing a button labelled "Mark done" on a fresh
+ event got "doing it" and had to press it again — and the second
+ press from "done" silently wiped the status rather than undoing
+ anything. Three states need three targets, which is what the control
+ above is; this one is the commit, so it goes straight to done and
+ back. */}