Files
dashboards/components/CustomerShell.tsx
T

134 lines
4.1 KiB
TypeScript

"use client";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import { useState } from "react";
import AccountMenu from "@/components/AccountMenu";
import { useAuth } from "@/components/AuthProvider";
import { customerNavItems } from "@/data/customer-nav";
import { en } from "@/lib/i18n/en";
import { getAdminDashboardOrigin } from "@/lib/host";
import { openBusinessDashboardAsUser } from "@/lib/session-handoff";
import { getDisplayName } from "@/lib/userName";
import styles from "./DashboardShell.module.css";
const websiteUrl =
process.env.NEXT_PUBLIC_WEBSITE_URL?.replace(/\/$/, "") ||
"http://localhost:3000";
export default function CustomerShell({
children,
}: {
children: React.ReactNode;
}) {
const pathname = usePathname();
const router = useRouter();
const { user, logout, isBusinessOwner, isSuperAdmin } = useAuth();
const [menuOpen, setMenuOpen] = useState(false);
const displayName = getDisplayName(user);
const publicPath = pathname.startsWith("/customer")
? pathname.replace(/^\/customer/, "") || "/"
: pathname;
return (
<div className={styles.shell}>
<aside className={`${styles.sidebar} ${menuOpen ? styles.sidebarOpen : ""}`}>
<div className={styles.brand}>
<img src="/images/icons/logo.png" alt="" width={48} height={48} />
<div className={styles.brandText}>
<span>{en.brandName}</span>
<strong>{en.customerBrandSubtitle}</strong>
</div>
</div>
<nav className={styles.nav} aria-label="Account">
{customerNavItems.map((item) => {
const active =
item.href === "/"
? publicPath === "/"
: publicPath === item.href ||
publicPath.startsWith(`${item.href}/`);
return (
<Link
key={item.label}
href={item.href}
className={`${styles.navItem} ${active ? styles.navItemActive : ""}`}
onClick={() => setMenuOpen(false)}
>
<img src={item.icon} alt="" width={18} height={18} />
<span>{item.label}</span>
</Link>
);
})}
</nav>
<div className={styles.sidebarFoot}>
<p className={styles.userLabel}>{displayName}</p>
{isSuperAdmin ? (
<a
href={`${getAdminDashboardOrigin()}/`}
className={styles.siteLink}
>
{en.openAdminDashboard}
</a>
) : null}
{isBusinessOwner ? (
<button
type="button"
className={styles.siteLink}
onClick={() => openBusinessDashboardAsUser("/profile")}
>
{en.openBusinessDashboard}
</button>
) : null}
<a href={websiteUrl} className={styles.siteLink}>
{en.viewWebsite}
</a>
<button
type="button"
className={`outline-btn ${styles.logoutBtn}`}
onClick={() => {
logout();
router.replace("/login");
}}
>
{en.logOut}
</button>
</div>
</aside>
{menuOpen ? (
<button
type="button"
className={styles.backdrop}
aria-label="Close menu"
onClick={() => setMenuOpen(false)}
/>
) : null}
<div className={styles.main}>
<header className={styles.topbar}>
<button
type="button"
className={styles.menuBtn}
aria-label="Open menu"
onClick={() => setMenuOpen(true)}
>
<img src="/images/icons/menu.svg" alt="" width={22} height={22} />
</button>
<div className={styles.topbarCopy}>
<p className={styles.eyebrow}>{en.customerEyebrow}</p>
<p className={styles.topbarHint}>{en.customerHint}</p>
</div>
<div className={styles.topbarActions}>
<AccountMenu />
</div>
</header>
<div className={styles.content}>{children}</div>
</div>
</div>
);
}