Files
hoomat-store/app/components/user-menu.tsx
T

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>
);
}