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. } }