Products, blog, search, mega menu, and home carousels now read live tenant data, and login goes to the customer portal. Co-authored-by: Cursor <cursoragent@cursor.com>
228 lines
8.7 KiB
TypeScript
228 lines
8.7 KiB
TypeScript
"use client";
|
|
|
|
import Link from "next/link";
|
|
import { useState } from "react";
|
|
import { SearchBox } from "@/components/SearchBox";
|
|
import { navLinks } from "@/data/content";
|
|
import type { MegaColumn } from "@/lib/catalog";
|
|
import { CUSTOMER_URL } from "@/lib/site";
|
|
import { IconBag, IconChevronDown, IconClose, IconHeart, IconMenu, IconUser } from "./Icons";
|
|
|
|
type Props = {
|
|
categories?: MegaColumn[];
|
|
};
|
|
|
|
export function Header({ categories = [] }: Props) {
|
|
const [open, setOpen] = useState(false);
|
|
const [mega, setMega] = useState(false);
|
|
const [mobileCats, setMobileCats] = useState(false);
|
|
|
|
const closeAll = () => {
|
|
setOpen(false);
|
|
setMega(false);
|
|
setMobileCats(false);
|
|
};
|
|
|
|
return (
|
|
<header className="sticky top-0 z-40 border-b border-white/50 bg-white/40 backdrop-blur-2xl">
|
|
<div className="container-nn">
|
|
<div className="flex h-[72px] items-center gap-3">
|
|
<button
|
|
type="button"
|
|
className="text-ink lg:hidden"
|
|
onClick={() => setOpen((value) => !value)}
|
|
aria-label={open ? "بستن منو" : "باز کردن منو"}
|
|
>
|
|
{open ? <IconClose /> : <IconMenu />}
|
|
</button>
|
|
|
|
<Link href="/" className="flex items-center gap-2.5">
|
|
<span className="grid size-11 place-items-center rounded-2xl bg-linear-to-br from-purple-600 via-cyan-500 to-rose-500 text-white shadow-card">
|
|
<span className="font-display text-lg leading-none">NN</span>
|
|
</span>
|
|
<span className="leading-tight">
|
|
<span className="font-display block text-[15px] text-purple-700">Nini Naderi</span>
|
|
<span className="block text-sm font-bold text-ink">نینی نادری</span>
|
|
</span>
|
|
</Link>
|
|
|
|
<SearchBox
|
|
className="mx-auto hidden min-w-0 flex-1 max-w-xl md:block"
|
|
inputClassName="h-11 w-full rounded-full border border-line bg-purple-50/60 pr-4 pl-11 text-sm outline-none transition focus:border-purple-500 focus:bg-white"
|
|
/>
|
|
|
|
<div className="ms-auto flex items-center gap-1 sm:gap-2">
|
|
<a
|
|
href={CUSTOMER_URL}
|
|
className="grid size-10 place-items-center rounded-full text-ink hover:bg-purple-50 lg:hidden"
|
|
aria-label="ورود"
|
|
>
|
|
<IconUser />
|
|
</a>
|
|
<a
|
|
href={CUSTOMER_URL}
|
|
className="hidden items-center gap-1.5 rounded-full px-3 py-2 text-sm text-ink hover:bg-purple-50 lg:inline-flex"
|
|
>
|
|
<IconUser />
|
|
ورود
|
|
</a>
|
|
<a
|
|
href={CUSTOMER_URL}
|
|
className="relative grid size-10 place-items-center rounded-full text-ink hover:bg-purple-50"
|
|
aria-label="علاقهمندی"
|
|
>
|
|
<IconHeart />
|
|
</a>
|
|
<a
|
|
href={CUSTOMER_URL}
|
|
className="relative grid size-10 place-items-center rounded-full text-ink hover:bg-purple-50"
|
|
aria-label="سبد خرید"
|
|
>
|
|
<IconBag />
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="pb-3 md:hidden">
|
|
<SearchBox
|
|
placeholder="جستجو در نینی نادری"
|
|
inputClassName="h-10 w-full rounded-full border border-line bg-purple-50/60 pr-4 pl-10 text-sm outline-none"
|
|
onNavigate={closeAll}
|
|
/>
|
|
</div>
|
|
|
|
<nav className="relative hidden h-12 items-center gap-6 text-sm font-medium text-ink lg:flex">
|
|
<div
|
|
className="h-full"
|
|
onMouseEnter={() => setMega(true)}
|
|
onMouseLeave={() => setMega(false)}
|
|
>
|
|
<button
|
|
type="button"
|
|
className="relative flex h-full items-center gap-1 py-3 transition hover:text-purple-700"
|
|
aria-expanded={mega}
|
|
onClick={() => setMega((value) => !value)}
|
|
>
|
|
دستهبندیها
|
|
<IconChevronDown className={`size-4 transition ${mega ? "rotate-180" : ""}`} />
|
|
</button>
|
|
{mega ? <MegaMenu categories={categories} onPick={closeAll} /> : null}
|
|
</div>
|
|
{navLinks.map((link) => (
|
|
<Link
|
|
key={link.label}
|
|
href={link.href}
|
|
className="relative py-3 transition hover:text-purple-700 after:absolute after:right-0 after:bottom-1 after:h-0.5 after:w-0 after:bg-linear-to-l after:from-purple-600 after:to-cyan-500 after:transition-all hover:after:w-full"
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
|
|
{open ? (
|
|
<div className="border-t border-line bg-white lg:hidden">
|
|
<nav className="container-nn flex flex-col py-2 text-sm">
|
|
<button
|
|
type="button"
|
|
className="flex items-center justify-between border-b border-line/70 py-3 text-ink"
|
|
onClick={() => setMobileCats((value) => !value)}
|
|
>
|
|
دستهبندیها
|
|
<IconChevronDown className={`size-4 transition ${mobileCats ? "rotate-180" : ""}`} />
|
|
</button>
|
|
{mobileCats ? (
|
|
<div className="space-y-3 border-b border-line/70 py-3">
|
|
{categories.map((column) => (
|
|
<div key={column.id}>
|
|
<Link href={column.href} onClick={closeAll} className="block text-sm font-bold text-purple-700">
|
|
{column.name}
|
|
</Link>
|
|
{column.children.length ? (
|
|
<div className="mt-2 grid grid-cols-2 gap-2">
|
|
{column.children.map((child) => (
|
|
<Link
|
|
key={child.id}
|
|
href={child.href}
|
|
onClick={closeAll}
|
|
className="rounded-2xl bg-purple-50/70 px-3 py-2 text-xs font-bold"
|
|
>
|
|
{child.name}
|
|
</Link>
|
|
))}
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : null}
|
|
{navLinks.map((link) => (
|
|
<Link
|
|
key={link.label}
|
|
href={link.href}
|
|
onClick={closeAll}
|
|
className="border-b border-line/70 py-3 text-ink"
|
|
>
|
|
{link.label}
|
|
</Link>
|
|
))}
|
|
<a href={CUSTOMER_URL} onClick={closeAll} className="py-3 text-ink">
|
|
ورود / ثبت نام
|
|
</a>
|
|
</nav>
|
|
</div>
|
|
) : null}
|
|
</header>
|
|
);
|
|
}
|
|
|
|
function MegaMenu({ categories, onPick }: { categories: MegaColumn[]; onPick: () => void }) {
|
|
return (
|
|
<div className="absolute top-full right-0 z-50 w-[min(52rem,calc(100vw-2rem))] pt-2">
|
|
<div className="rounded-3xl border border-white/80 bg-white/95 p-5 shadow-card backdrop-blur-[80px]">
|
|
<div className="mb-4 flex items-end justify-between">
|
|
<div>
|
|
<p className="font-display text-xs text-cyan-600">Categories</p>
|
|
<p className="text-base font-bold">خرید بر اساس دسته</p>
|
|
</div>
|
|
<Link href="/products" onClick={onPick} className="text-xs font-medium text-purple-700">
|
|
مشاهده همه
|
|
</Link>
|
|
</div>
|
|
{categories.length ? (
|
|
<div className="grid gap-5 sm:grid-cols-2 lg:grid-cols-3">
|
|
{categories.map((column) => (
|
|
<div key={column.id}>
|
|
<Link
|
|
href={column.href}
|
|
onClick={onPick}
|
|
className="block text-sm font-bold text-purple-700 hover:text-purple-800"
|
|
>
|
|
{column.name}
|
|
</Link>
|
|
{column.children.length ? (
|
|
<ul className="mt-2 space-y-1.5">
|
|
{column.children.map((child) => (
|
|
<li key={child.id}>
|
|
<Link
|
|
href={child.href}
|
|
onClick={onPick}
|
|
className="block rounded-xl px-2 py-1 text-sm text-muted transition hover:bg-purple-50 hover:text-ink"
|
|
>
|
|
{child.name}
|
|
</Link>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
) : null}
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<p className="text-sm text-muted">دستهبندیها بهزودی اینجا میآیند.</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|