"use client"; import { useEffect, useRef } from "react"; import { useCart, pullServerCart } from "../lib/cart"; // Mirrors the local cart to the server whenever it changes, so a logged-in // customer's cart follows them across devices (see Customers.ts's `cart` // field). Renders nothing — mounted once in the root layout. Debounced // (not fired on every keystroke-equivalent quantity bump) and silently a // no-op when logged out — POST /api/account/cart 401s in that case, which // this component doesn't need to distinguish from success; there's simply // nothing to keep in sync yet. // // Push (local→server) and pull (server→local) are both handled here, but // deliberately asymmetric: push reacts to every local cart change (that's // this device's news to share), pull only runs on mount and on window // focus (see pullServerCart()'s own comment on why it's safe to call // repeatedly) — no polling interval, since "another device changed my // cart while this tab has been open and unfocused the whole time" is a // rare enough case not to justify a persistent timer. export function CartSync() { const cart = useCart(); const isFirstRender = useRef(true); useEffect(() => { // Skip the mount-time fire — this would otherwise POST on every page // load even when nothing actually changed. if (isFirstRender.current) { isFirstRender.current = false; return; } const timeout = setTimeout(() => { fetch("/api/account/cart", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ cart }), }).catch(() => { // Best-effort — a failed sync just means the next cart change (or // the next login-time merge) tries again. }); }, 800); return () => clearTimeout(timeout); }, [cart]); useEffect(() => { pullServerCart(); window.addEventListener("focus", pullServerCart); return () => window.removeEventListener("focus", pullServerCart); }, []); return null; }