133 lines
3.7 KiB
TypeScript
133 lines
3.7 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef, useState } from "react";
|
|
import { useAuth } from "@/app/providers/auth-provider";
|
|
import { createAuthHandoff } from "@/lib/meshkee/api";
|
|
import { displayName } from "@/lib/meshkee/format";
|
|
import {
|
|
businessDashboardUrl,
|
|
customerLoginUrl,
|
|
customerProfileUrl,
|
|
} from "@/lib/meshkee/urls";
|
|
|
|
export function UserMenu() {
|
|
const { user, isAuthenticated, isWebsiteAdmin, logout, getAccessToken } = useAuth();
|
|
const [open, setOpen] = useState(false);
|
|
const [handingOff, setHandingOff] = useState(false);
|
|
const rootRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
const onClick = (event: MouseEvent) => {
|
|
if (!rootRef.current?.contains(event.target as Node)) setOpen(false);
|
|
};
|
|
document.addEventListener("mousedown", onClick);
|
|
return () => document.removeEventListener("mousedown", onClick);
|
|
}, []);
|
|
|
|
if (!isAuthenticated || !user) {
|
|
return (
|
|
<a
|
|
className="header-icon-btn"
|
|
href={customerLoginUrl("/")}
|
|
aria-label="ورود"
|
|
title="ورود"
|
|
>
|
|
<UserIcon />
|
|
</a>
|
|
);
|
|
}
|
|
|
|
const name = displayName(user);
|
|
|
|
async function openBusinessAdmin(event: React.MouseEvent<HTMLAnchorElement>) {
|
|
if (
|
|
event.metaKey ||
|
|
event.ctrlKey ||
|
|
event.shiftKey ||
|
|
event.altKey ||
|
|
event.button !== 0
|
|
) {
|
|
return;
|
|
}
|
|
event.preventDefault();
|
|
const target = businessDashboardUrl();
|
|
const popup = window.open("about:blank", "_blank");
|
|
setHandingOff(true);
|
|
try {
|
|
const token = getAccessToken();
|
|
const { ticket } = await createAuthHandoff(token || "");
|
|
const url = new URL(target);
|
|
if (ticket) url.searchParams.set("handoff", ticket);
|
|
if (popup) {
|
|
popup.opener = null;
|
|
popup.location.replace(url.toString());
|
|
} else {
|
|
window.open(url.toString(), "_blank", "noopener,noreferrer");
|
|
}
|
|
} catch {
|
|
if (popup) popup.location.replace(target);
|
|
else window.open(target, "_blank", "noopener,noreferrer");
|
|
} finally {
|
|
setHandingOff(false);
|
|
setOpen(false);
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="user-menu" ref={rootRef}>
|
|
<button
|
|
type="button"
|
|
className="header-icon-btn"
|
|
aria-expanded={open}
|
|
aria-haspopup="menu"
|
|
aria-label={`${name} عزیز`}
|
|
title={`${name} عزیز`}
|
|
onClick={() => setOpen((value) => !value)}
|
|
>
|
|
<UserIcon />
|
|
</button>
|
|
{open ? (
|
|
<div className="user-menu-dropdown" role="menu">
|
|
<p className="user-menu-greeting">{name} عزیز</p>
|
|
<a role="menuitem" href={customerProfileUrl()} onClick={() => setOpen(false)}>
|
|
پروفایل من
|
|
</a>
|
|
{isWebsiteAdmin ? (
|
|
<a
|
|
role="menuitem"
|
|
href={businessDashboardUrl()}
|
|
onClick={(event) => void openBusinessAdmin(event)}
|
|
>
|
|
{handingOff ? "در حال انتقال…" : "مدیریت وبسایت"}
|
|
</a>
|
|
) : null}
|
|
<button
|
|
type="button"
|
|
role="menuitem"
|
|
onClick={() => {
|
|
logout();
|
|
setOpen(false);
|
|
}}
|
|
>
|
|
خروج
|
|
</button>
|
|
</div>
|
|
) : null}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function UserIcon() {
|
|
return (
|
|
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" aria-hidden="true">
|
|
<circle cx="12" cy="8" r="3.25" stroke="currentColor" strokeWidth="1.6" />
|
|
<path
|
|
d="M5.75 18.5c1.55-2.45 3.7-3.7 6.25-3.7s4.7 1.25 6.25 3.7"
|
|
stroke="currentColor"
|
|
strokeWidth="1.6"
|
|
strokeLinecap="round"
|
|
/>
|
|
</svg>
|
|
);
|
|
}
|