Initial Next.js clone of Pars Elevator (plift.ir).
RTL Meshkee storefront with home/about/contact/products/blog, API auth/contact/blog wiring, and SEO sitemap-config. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useAuth } from "@/components/AuthProvider";
|
||||
|
||||
export function UserMenu() {
|
||||
const { user, loading, label, isAdmin, loginUrl, profileUrl, businessUrl, logout } =
|
||||
useAuth();
|
||||
const [open, setOpen] = useState(false);
|
||||
const rootRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const onDoc = (e: MouseEvent) => {
|
||||
if (!rootRef.current?.contains(e.target as Node)) setOpen(false);
|
||||
};
|
||||
document.addEventListener("mousedown", onDoc);
|
||||
return () => document.removeEventListener("mousedown", onDoc);
|
||||
}, []);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<span className="hidden text-[13px] text-[#999] sm:inline-flex">...</span>
|
||||
);
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return (
|
||||
<a
|
||||
href={loginUrl}
|
||||
className="inline-flex items-center gap-1.5 text-[13px] text-[#373737] transition hover:text-primary"
|
||||
>
|
||||
<LoginIcon />
|
||||
ورود
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={rootRef} className="relative">
|
||||
<button
|
||||
type="button"
|
||||
className="inline-flex max-w-[180px] items-center gap-1.5 text-[13px] text-[#373737] transition hover:text-primary"
|
||||
aria-expanded={open}
|
||||
onClick={() => setOpen((v) => !v)}
|
||||
>
|
||||
<UserIcon />
|
||||
<span className="truncate">{label}</span>
|
||||
</button>
|
||||
{open && (
|
||||
<div className="absolute top-full left-0 z-50 mt-2 min-w-[180px] border border-[#eee] bg-white py-1 shadow-[0_12px_40px_rgba(0,0,0,0.12)]">
|
||||
<a
|
||||
href={profileUrl}
|
||||
className="block px-4 py-2.5 text-[13px] text-dark transition hover:bg-[#f7f7f7]"
|
||||
onClick={() => setOpen(false)}
|
||||
>
|
||||
پروفایل من
|
||||
</a>
|
||||
{isAdmin && (
|
||||
<a
|
||||
href={businessUrl}
|
||||
className="block px-4 py-2.5 text-[13px] text-dark transition hover:bg-[#f7f7f7]"
|
||||
onClick={() => setOpen(false)}
|
||||
>
|
||||
مدیریت وبسایت
|
||||
</a>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="block w-full px-4 py-2.5 text-start text-[13px] text-dark transition hover:bg-[#f7f7f7]"
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
logout();
|
||||
}}
|
||||
>
|
||||
خروج
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function LoginIcon() {
|
||||
return (
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden>
|
||||
<path
|
||||
d="M10 17l5-5-5-5"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.6"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M15 12H3"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.6"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
<path
|
||||
d="M21 19V5a2 2 0 0 0-2-2h-4"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.6"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function UserIcon() {
|
||||
return (
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden>
|
||||
<circle cx="12" cy="8" r="3.5" stroke="currentColor" strokeWidth="1.6" />
|
||||
<path
|
||||
d="M5 19.5c1.8-3.2 4.2-4.5 7-4.5s5.2 1.3 7 4.5"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.6"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user