Files
sanihome/src/lib/guest-cart.ts
T

120 lines
3.6 KiB
TypeScript

import type { CartItem } from "@/lib/cart-types";
/** Must match customer dashboard `GUEST_CART_STORAGE_KEY`. */
export const MESHKEE_GUEST_CART_KEY = "meshkee-guest-cart";
export const LEGACY_GUEST_CART_KEY = "sanihome-guest-cart";
export const GUEST_CART_URL_PARAM = "guestCart";
export type MeshkeeGuestCartItem = {
id: string;
name: string;
slug?: string;
price: number;
originalPrice?: number;
image: string | null;
quantity: number;
};
function cookieDomain(): string | undefined {
if (typeof window === "undefined") return undefined;
const host = window.location.hostname.toLowerCase();
if (host === "localhost" || host === "127.0.0.1") return undefined;
const parts = host.split(".").filter(Boolean);
if (parts.length < 2) return undefined;
return `.${parts.slice(-2).join(".")}`;
}
function parseItems(raw: string | null): CartItem[] {
if (!raw) return [];
try {
const parsed = JSON.parse(raw) as CartItem[];
return Array.isArray(parsed) ? parsed : [];
} catch {
return [];
}
}
/** Map storefront cart lines to the shared guest-cart shape (id = variant id). */
export function toMeshkeeGuestItems(items: CartItem[]): MeshkeeGuestCartItem[] {
const result: MeshkeeGuestCartItem[] = [];
for (const item of items) {
const variantId = (item.storeItemVariantId || item.id || "").trim();
if (!variantId) continue;
result.push({
id: variantId,
name: item.name || "محصول",
...(item.slug ? { slug: item.slug } : {}),
price: item.price,
image: item.image ?? null,
quantity: Math.max(1, Math.floor(item.quantity) || 1),
});
}
return result;
}
export function encodeGuestCartForUrl(items: CartItem[]): string {
const payload = toMeshkeeGuestItems(items);
const json = JSON.stringify(payload);
return btoa(unescape(encodeURIComponent(json)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
}
function writeSharedCookie(items: MeshkeeGuestCartItem[]) {
if (typeof document === "undefined") return;
const domain = cookieDomain();
const maxAge = 60 * 60 * 24 * 30;
const encoded = encodeURIComponent(
JSON.stringify(
items.map(({ id, name, slug, price, originalPrice, quantity }) => ({
id,
name,
slug,
price,
originalPrice,
quantity,
image: null as string | null,
})),
),
);
if (encoded.length > 3500) return;
let cookie = `${MESHKEE_GUEST_CART_KEY}=${encoded}; path=/; max-age=${maxAge}; SameSite=Lax`;
if (domain) cookie += `; domain=${domain}`;
document.cookie = cookie;
}
export function readGuestCart(): CartItem[] {
if (typeof window === "undefined") return [];
const primary = parseItems(localStorage.getItem(MESHKEE_GUEST_CART_KEY));
if (primary.length > 0) return primary;
const legacy = parseItems(localStorage.getItem(LEGACY_GUEST_CART_KEY));
if (legacy.length > 0) {
writeGuestCart(legacy);
return legacy;
}
return [];
}
export function writeGuestCart(items: CartItem[]) {
if (typeof window === "undefined") return;
const raw = JSON.stringify(items);
localStorage.setItem(MESHKEE_GUEST_CART_KEY, raw);
localStorage.removeItem(LEGACY_GUEST_CART_KEY);
try {
writeSharedCookie(toMeshkeeGuestItems(items));
} catch {
// ignore cookie failures
}
}
export function clearGuestCart() {
if (typeof window === "undefined") return;
localStorage.removeItem(MESHKEE_GUEST_CART_KEY);
localStorage.removeItem(LEGACY_GUEST_CART_KEY);
const domain = cookieDomain();
let cookie = `${MESHKEE_GUEST_CART_KEY}=; path=/; max-age=0; SameSite=Lax`;
if (domain) cookie += `; domain=${domain}`;
document.cookie = cookie;
}