Add guest cart drawer, Continue handoff, and shared customer login.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-25 17:33:39 +03:30
co-authored by Cursor
parent ad05241a77
commit 16340c3b48
18 changed files with 1082 additions and 97 deletions
+49 -28
View File
@@ -2,10 +2,14 @@
import Image from "next/image";
import Link from "next/link";
import { useEffect, useState } from "react";
import { cartCount } from "@/lib/cart";
import { useState } from "react";
import { customerLoginUrl } from "@/lib/customer";
import { parentCategories } from "@/lib/data";
import { SITE } from "@/lib/site";
import { useCart } from "@/lib/cart";
import { useSession } from "@/lib/session";
import { AccountMenu } from "./AccountMenu";
import { CartPopup } from "./CartPopup";
import { IconCart, IconChevron, IconClose, IconMenu, IconUser } from "./Icons";
import { SearchBox } from "./SearchBox";
@@ -19,18 +23,11 @@ const nav = [
export function Header() {
const [open, setOpen] = useState(false);
const [mega, setMega] = useState(false);
const [count, setCount] = useState(0);
useEffect(() => {
const sync = () => setCount(cartCount());
sync();
window.addEventListener("cart-updated", sync);
window.addEventListener("storage", sync);
return () => {
window.removeEventListener("cart-updated", sync);
window.removeEventListener("storage", sync);
};
}, []);
const [cartOpen, setCartOpen] = useState(false);
const { itemCount } = useCart();
const { isAuthenticated, user, logout, isWebsiteAdmin } = useSession();
const displayName = user?.firstName?.trim() || "حساب من";
const loginHref = customerLoginUrl("/");
return (
<header className="sticky top-0 z-50 bg-white border-b border-black/5">
@@ -95,19 +92,29 @@ export function Header() {
<SearchBox className="hidden md:block ms-4 max-w-sm flex-1 rounded-full bg-zinc-100 px-3" />
<div className="flex items-center gap-2 ms-auto">
<a
href={SITE.customerUrl}
className="flex items-center gap-2 rounded-full px-3 py-2 text-sm hover:bg-zinc-100"
{isAuthenticated ? (
<div className="hidden sm:block">
<AccountMenu displayName={displayName} isWebsiteAdmin={isWebsiteAdmin} onLogout={logout} />
</div>
) : (
<a href={loginHref} className="flex items-center gap-2 rounded-full px-3 py-2 text-sm hover:bg-zinc-100">
<IconUser />
<span className="hidden sm:inline">ورود / ثبت نام</span>
</a>
)}
<button
type="button"
onClick={() => setCartOpen(true)}
aria-label={itemCount > 0 ? `سبد خرید، ${itemCount.toLocaleString("fa-IR")} کالا` : "سبد خرید"}
className="relative grid place-items-center w-10 h-10 rounded-full hover:bg-zinc-100"
>
<IconUser />
<span className="hidden sm:inline">ورود / ثبت نام</span>
</a>
<Link href="/cart" className="relative grid place-items-center w-10 h-10 rounded-full hover:bg-zinc-100">
<IconCart className="w-6 h-6 text-brand" />
<span className="absolute top-1 left-1 grid place-items-center w-4 h-4 rounded-full bg-brand text-[10px] text-white">
{count.toLocaleString("fa-IR")}
</span>
</Link>
{itemCount > 0 && (
<span className="absolute top-1 left-1 grid place-items-center min-w-4 h-4 rounded-full bg-brand px-0.5 text-[10px] text-white">
{itemCount.toLocaleString("fa-IR")}
</span>
)}
</button>
</div>
</div>
@@ -147,13 +154,27 @@ export function Header() {
{item.name}
</Link>
))}
<a href={SITE.customerUrl} className="py-2">
ورود / ثبت نام
</a>
{isAuthenticated ? (
<AccountMenu
displayName={displayName}
isWebsiteAdmin={isWebsiteAdmin}
compact
onLogout={() => {
logout();
setOpen(false);
}}
/>
) : (
<a href={loginHref} className="py-2">
ورود / ثبت نام
</a>
)}
</div>
</aside>
</div>
)}
<CartPopup open={cartOpen} onClose={() => setCartOpen(false)} />
</header>
);
}