From 1ec442cc05613187a513f98d901f308d85e27a50 Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 1 Aug 2026 10:46:57 +0000 Subject: [PATCH] Fix guest cart never reaching the server on login MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mergeServerCartIntoLocal() relied on CartSync's own change-triggered push to upload the merged cart — but if the server cart was empty (first login on this account) and the local guest cart wasn't, the merge loop never actually ran (nothing in the server response to add), so no write/change-event ever fired and CartSync's effect never pushed anything. The guest cart looked fine on the device that just logged in, but never reached any other device. Now pushes explicitly at the end regardless of whether anything changed. --- app/lib/cart.ts | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/app/lib/cart.ts b/app/lib/cart.ts index 28f5f3c..cef2330 100644 --- a/app/lib/cart.ts +++ b/app/lib/cart.ts @@ -132,18 +132,39 @@ export function useCart(): CartItem[] { // logout — the local cart is always either empty (no guest additions since // the last logout) or holds only genuinely new guest-session items, never a // stale copy of what's already in the server cart, so this add never -// double-counts. CartSync then picks up the resulting change and pushes the -// merged cart back to the server on its own, closing the loop without a -// separate save call here. +// double-counts. +// +// Always pushes the resulting cart to the server itself at the end, +// explicitly — does NOT rely on CartSync's own change-triggered push. +// That was the bug (confirmed live 2026-08-01): logging in with an empty +// server cart but a non-empty guest cart means the merge loop below never +// actually runs (nothing in `data.cart` to add), so `writeCart` is never +// called, no change event fires, and CartSync's effect — which only +// re-fires when the cart *reference* actually changes — never pushes the +// guest cart to the server at all. The cart looked fine on the device +// that was already logged in, but never reached any other device. An +// explicit push here doesn't depend on anything having changed. export async function mergeServerCartIntoLocal(): Promise { try { const res = await fetch("/api/account/cart"); - if (!res.ok) return; - const data: { cart?: CartItem[] } = await res.json(); - for (const item of data.cart ?? []) addToCart(item.id, item.qty, item.variant); + if (res.ok) { + const data: { cart?: CartItem[] } = await res.json(); + for (const item of data.cart ?? []) addToCart(item.id, item.qty, item.variant); + } } catch { // Best-effort — a failed merge just means the server-side cart stays - // as it was; nothing local is lost either way. + // as it was; nothing local is lost either way. Still fall through to + // push below — the local (guest) cart is genuine either way. + } + try { + await fetch("/api/account/cart", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ cart: readCart() }), + }); + } catch { + // Best-effort — CartSync's own push will retry on the next cart + // change, or the next login-time merge tries again. } }