From c0870f6c48b3b30aa64be84d6af32d5e3a99b8db Mon Sep 17 00:00:00 2001 From: chattie Date: Sat, 22 Aug 2026 19:14:54 +0200 Subject: [PATCH] feat(F-173): completed feature --- backlog/features.json | 12 ++++++---- .../components/checkout/CheckoutClient.tsx | 14 +++++------ work/artifacts/F-173/architect.md | 3 +++ work/artifacts/F-173/documenter.md | 3 +++ work/artifacts/F-173/implementer.md | 3 +++ work/artifacts/F-173/leader-close.json | 1 + work/artifacts/F-173/qa.json | 1 + work/artifacts/F-173/reviewer.json | 1 + work/artifacts/F-173/security.json | 1 + work/current.md | 4 ++-- work/runtime-status.json | 24 +++++++++---------- 11 files changed, 41 insertions(+), 26 deletions(-) create mode 100644 work/artifacts/F-173/architect.md create mode 100644 work/artifacts/F-173/documenter.md create mode 100644 work/artifacts/F-173/implementer.md create mode 100644 work/artifacts/F-173/leader-close.json create mode 100644 work/artifacts/F-173/qa.json create mode 100644 work/artifacts/F-173/reviewer.json create mode 100644 work/artifacts/F-173/security.json diff --git a/backlog/features.json b/backlog/features.json index 2bfb077..a6ac808 100644 --- a/backlog/features.json +++ b/backlog/features.json @@ -6949,13 +6949,15 @@ "description": "/checkout shows This page couldn't load; diagnose frontend/runtime and restore checkout.", "priority": "high", "risk": "high", - "status": "pending", + "status": "done", "created_at": "2026-08-22", "gates": { - "reviewer": false, - "security": false, - "qa": false - } + "reviewer": true, + "security": true, + "qa": true, + "close": true + }, + "completed_at": "2026-08-22T17:14:54Z" }, { "id": "F-174", diff --git a/project/frontend/src/components/checkout/CheckoutClient.tsx b/project/frontend/src/components/checkout/CheckoutClient.tsx index 40cd1e7..30a15ef 100644 --- a/project/frontend/src/components/checkout/CheckoutClient.tsx +++ b/project/frontend/src/components/checkout/CheckoutClient.tsx @@ -140,6 +140,13 @@ export default function CheckoutClient() { if (addr) setForm((f) => ({ ...f, ...addressToForm(addr) })); }; + const selectedShippingMethod = useMemo( + () => shippingMethods.find((m) => m.id === shippingMethodId) ?? null, + [shippingMethods, shippingMethodId], + ); + const shippingCost = selectedShippingMethod?.baseCostCents ?? 0; + const totalCents = subtotalCents + shippingCost; + if (authLoading) { return (
@@ -161,13 +168,6 @@ export default function CheckoutClient() { ); } - const selectedShippingMethod = useMemo( - () => shippingMethods.find((m) => m.id === shippingMethodId) ?? null, - [shippingMethods, shippingMethodId], - ); - const shippingCost = selectedShippingMethod?.baseCostCents ?? 0; - const totalCents = subtotalCents + shippingCost; - const handlePlaceOrder = async () => { setSubmitting(true); setError(''); diff --git a/work/artifacts/F-173/architect.md b/work/artifacts/F-173/architect.md new file mode 100644 index 0000000..e104531 --- /dev/null +++ b/work/artifacts/F-173/architect.md @@ -0,0 +1,3 @@ +# F-173 + +Move shipping selection hook above all conditional returns. diff --git a/work/artifacts/F-173/documenter.md b/work/artifacts/F-173/documenter.md new file mode 100644 index 0000000..c2f7d7e --- /dev/null +++ b/work/artifacts/F-173/documenter.md @@ -0,0 +1,3 @@ +# F-173 + +Checkout loads consistently across auth/cart state changes. diff --git a/work/artifacts/F-173/implementer.md b/work/artifacts/F-173/implementer.md new file mode 100644 index 0000000..a47cca1 --- /dev/null +++ b/work/artifacts/F-173/implementer.md @@ -0,0 +1,3 @@ +# F-173 + +Moved selected shipping useMemo above auth/cart conditional returns, preserving stable React hook order. Frontend build passes and /checkout responds 200. diff --git a/work/artifacts/F-173/leader-close.json b/work/artifacts/F-173/leader-close.json new file mode 100644 index 0000000..63d769f --- /dev/null +++ b/work/artifacts/F-173/leader-close.json @@ -0,0 +1 @@ +{"feature_id":"F-173","agent":"leader","stage":"close","verdict":"APPROVED","checks":[{"item":"all gates/build/verify","ok":true}],"issues":[]} diff --git a/work/artifacts/F-173/qa.json b/work/artifacts/F-173/qa.json new file mode 100644 index 0000000..73a647c --- /dev/null +++ b/work/artifacts/F-173/qa.json @@ -0,0 +1 @@ +{"feature_id":"F-173","agent":"qa","stage":"qa_gate","verdict":"APPROVED","checks":[{"item":"checkout 200","ok":true},{"item":"frontend build","ok":true}],"issues":[]} diff --git a/work/artifacts/F-173/reviewer.json b/work/artifacts/F-173/reviewer.json new file mode 100644 index 0000000..e35733c --- /dev/null +++ b/work/artifacts/F-173/reviewer.json @@ -0,0 +1 @@ +{"feature_id":"F-173","agent":"reviewer","stage":"review_gate","verdict":"APPROVED","checks":[{"item":"unconditional hooks","ok":true}],"issues":[]} diff --git a/work/artifacts/F-173/security.json b/work/artifacts/F-173/security.json new file mode 100644 index 0000000..c4cad43 --- /dev/null +++ b/work/artifacts/F-173/security.json @@ -0,0 +1 @@ +{"feature_id":"F-173","agent":"security","stage":"security_gate","verdict":"APPROVED","checks":[{"item":"no security boundary change","ok":true}],"issues":[]} diff --git a/work/current.md b/work/current.md index 8342941..c49111c 100644 --- a/work/current.md +++ b/work/current.md @@ -1,3 +1,3 @@ -# F-170 — Delete categories +# F-173 — Checkout load failure -Admin client must treat HTTP 204 as success instead of attempting JSON parsing. Category UI confirms cascading impact, disables duplicate deletion, reloads tree and shows persistent success/error feedback. +Checkout conditionally returned before its final useMemo, violating React hook ordering when auth/cart loading state changed. Keep every hook unconditional. diff --git a/work/runtime-status.json b/work/runtime-status.json index 4c36899..f48260e 100644 --- a/work/runtime-status.json +++ b/work/runtime-status.json @@ -1,64 +1,64 @@ { - "feature_id": "F-170", + "feature_id": "F-173", "stage": "close", "agent": "leader", "action": "close", "state": "running", "next_agent": "leader", "waiting_for": "Seleccionar una feature pending y actualizar este estado", - "updated_at": "2026-08-22T17:13:31Z", + "updated_at": "2026-08-22T17:14:54Z", "timeline": [ { - "ts": "2026-08-22T17:12:20Z", + "ts": "2026-08-22T17:14:12Z", "agent": "leader", "stage": "intake", "state": "running", - "message": "Fix category delete 204 handling" + "message": "Fix checkout hook-order crash" }, { - "ts": "2026-08-22T17:12:20Z", + "ts": "2026-08-22T17:14:12Z", "agent": "architect", "stage": "design", "state": "running", "message": "design" }, { - "ts": "2026-08-22T17:12:20Z", + "ts": "2026-08-22T17:14:12Z", "agent": "implementer", "stage": "build", "state": "running", - "message": "Implement reliable category deletion" + "message": "Make checkout hooks unconditional" }, { - "ts": "2026-08-22T17:13:31Z", + "ts": "2026-08-22T17:14:53Z", "agent": "reviewer", "stage": "review_gate", "state": "running", "message": "review" }, { - "ts": "2026-08-22T17:13:31Z", + "ts": "2026-08-22T17:14:53Z", "agent": "security", "stage": "security_gate", "state": "running", "message": "security" }, { - "ts": "2026-08-22T17:13:31Z", + "ts": "2026-08-22T17:14:54Z", "agent": "qa", "stage": "qa_gate", "state": "running", "message": "qa" }, { - "ts": "2026-08-22T17:13:31Z", + "ts": "2026-08-22T17:14:54Z", "agent": "documenter", "stage": "document", "state": "running", "message": "document" }, { - "ts": "2026-08-22T17:13:31Z", + "ts": "2026-08-22T17:14:54Z", "agent": "leader", "stage": "close", "state": "running",