#109 — Checkbox-Semantik in der Einkaufsliste umkehren (leer = zu kaufen, angehakt = erledigt) #112
Labels
No labels
priority/could
priority/must
priority/should
priority/wont
status/blocked
status/claimed
status/done-migrated
type/bug
type/feature
type/infra
type/tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
robert/todo#112
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Story: Checkbox-Semantik in der Einkaufsliste umkehren (leer = zu kaufen, angehakt = erledigt)
As a Nutzer der Einkaufsliste,
I want to dass ein neu hinzugefügtes Produkt mit einem leeren Kästchen erscheint, das ich abhake, wenn
ich es gekauft habe,
so that sich das Verhalten intuitiv anfühlt (leer = noch zu erledigen, angehakt = erledigt) statt
umgekehrt.
Wichtig — das ist eine Umkehr der bestehenden, bewusst getroffenen
#90-Design-Entscheidung, kein reinerDefault-Wert-Fix:
ShoppingProductItem.tsxs eigener Kommentar dokumentiert die aktuelle Absicht explizit:"every product rendered here is already active ... so it always starts checked and unchecking is how an
item gets taken off the list". Das Kästchen bedeutet heute "ist aktiv auf der Liste" (angehakt) vs. "wurde
abgehakt und verschwindet von der Liste" (leer). Nur den Startwert auf "leer" umzustellen, ohne die
Bedeutung von an/abgehakt zu vertauschen, würde ein neues Produkt als "bereits erledigt" erscheinen lassen —
das Gegenteil vom gewünschten Verhalten. Diese Story kehrt die gesamte Bedeutung um, nicht nur den
Anfangswert.
Acceptance criteria:
aktiven Liste (bisher: Entfernen passierte beim Ab-haken eines bereits angehakten Kästchens —
jetzt passiert dasselbe beim An-haken eines leeren Kästchens).
onUncheck-Prop-Name/-Semantik inShoppingProductItem.tsx, ggf. das "Recently checked off"-Restore-Verhalten aus#81, das nach eigenerBeschreibung "checked off" = "von der Liste entfernt" meint) werden konsistent auf die neue Bedeutung
umgestellt, nicht nur die Checkbox-Optik.
#81) funktioniert unverändert als Wiederherstellungs-Funktion für geradeentfernte Produkte — nur der Auslöser (jetzt: ankreuzen statt abkreuzen) ändert sich.
(
ShoppingCartCheckPanel,IsInCart) ist ein unabhängiges Konzept ("schon online bestellt") und vondieser Story nicht betroffen.
Out of scope for this story:
An-/Abhaken) und ist von dieser Story nicht betroffen.
unverändert.
design (
109_shopping_checkbox_semantics_inversion_design.md)Design note —
#109Checkbox semantics inversion (Shopping List)Scope: Frontend only. No backend/API change — the underlying command that removes a product from
the active list is already
DeactivateShoppingProductCommand(from#81/#90); this story only invertswhich checkbox gesture and starting state trigger it.
Change:
ShoppingProductItem.tsx: checkbox now renderschecked={false}(was alwayschecked). TheonUncheckprop is renamed toonCheck— same callback signature and same underlying effect(deactivate + push to "recently checked off" history), just fired by the opposite gesture (checking
an empty box, not unchecking a filled one).
ShoppingListPage.tsx:handleUncheckrenamed tohandleCheck, body unchanged (still callsdeactivateShoppingProductandpushShoppingCheckedOff).RecentlyCheckedOffPanel.tsx/store.ts'sshoppingCheckedOffHistory: no change needed — both arealready gesture-agnostic ("history of recently-removed products"), not tied to the old
checked/unchecked meaning.
ShoppingCartCheckPanel/IsInCart(independent "alreadyordered online" concept) and Pantry (different domain, no plain check/uncheck concept).
Why no new component/prop needed beyond the rename: the story is a pure inversion of an existing
gesture, not a new capability — same command, same history mechanism, only the checkbox's default
visual state and which click direction fires the callback change.
Tests:
ShoppingProductItem.test.tsxandShoppingListPage.test.tsxupdated to assertnot.toBeChecked()by default and to referenceonCheck; the click-to-deactivate assertion itselfwas already gesture-agnostic (
fireEvent.clickon the checkbox) and needed no behavioral change.