Fix guest cart never reaching the server on login
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.
This commit is contained in:
+28
-7
@@ -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<void> {
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user