"use client";
import { AnimatePresence, motion, useReducedMotion } from "framer-motion";
import { Menu, ShieldCheck, X } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useLocale, useTranslations } from "next-intl";
import { useEffect, useRef, useState } from "react";
import { Container } from "@/components/layout/container";
import { LocaleToggle } from "@/components/layout/locale-toggle";
import { SiteLogo } from "@/components/layout/site-logo";
import { SoundToggle } from "@/components/sound-toggle";
import { ThemeToggle } from "@/components/theme-toggle";
import { Button } from "@/components/ui/button";
import { buildAdminUrl } from "@/lib/admin-routing";
import { getLocalizedPath, stripLocalePrefix } from "@/lib/locale";
import { toast } from "@/lib/toast";
import { cn } from "@/lib/utils";
const navItems = [
{ key: "home", path: "" },
{ key: "about", path: "/about" },
{ key: "portfolio", path: "/portfolio" },
{ key: "products", path: "/products", disabled: true },
{ key: "contact", path: "/contact" },
];
const disabledDesktopNavItemClassName =
"relative z-10 inline-flex cursor-not-allowed items-center justify-center rounded-pill px-3.5 py-2 text-sm font-medium text-foreground/55 xl:px-4";
const disabledMobileNavItemClassName =
"relative inline-flex cursor-not-allowed items-center justify-center rounded-nested px-4 py-3 text-sm font-medium text-foreground/55";
type SiteHeaderProps = {
lightLogoUrl?: string | null;
darkLogoUrl?: string | null;
defaultLocale: "de" | "en" | "ar";
/**
* Server-computed via `isSuperAdmin()` in the parent layout — this client
* component only decides whether to *render* the Admin shortcut link from
* this flag. It performs no auth check itself and the flag grants no
* access; the real guard lives on each admin page/action server-side.
*/
isSuperAdmin?: boolean;
};
function getDirectionalReveal(direction: "rtl" | "ltr") {
return direction === "rtl"
? {
initial: { opacity: 0, x: -16, clipPath: "inset(0 0 0 100%)", filter: "blur(10px)" },
animate: { opacity: 1, x: 0, y: 0, clipPath: "inset(0 0 0 0)", filter: "blur(0px)" },
}
: {
initial: { opacity: 0, x: 16, clipPath: "inset(0 100% 0 0)", filter: "blur(10px)" },
animate: { opacity: 1, x: 0, y: 0, clipPath: "inset(0 0 0 0)", filter: "blur(0px)" },
};
}
function isNavItemActive(currentPath: string, itemPath: string) {
if (itemPath === "/") {
return currentPath === "/";
}
return currentPath === itemPath || currentPath.startsWith(`${itemPath}/`);
}
function NavLinks({
defaultLocale,
onNavigate,
mobile = false,
}: {
defaultLocale: "de" | "en" | "ar";
onNavigate?: () => void;
mobile?: boolean;
}) {
const locale = useLocale();
const pathname = usePathname();
const t = useTranslations("navigation");
const currentPath = stripLocalePrefix(pathname);
const isArabic = locale === "ar";
const activeIndicatorLayoutId = mobile ? "mobile-site-nav-active-pill" : "site-nav-active-pill";
return (
<>
{navItems.map((item) => (
(() => {
const itemPath = item.path || "/";
const isActive = isNavItemActive(currentPath, itemPath);
const itemLabel = t(item.key);
const soonLabel = t("soon");
if (item.disabled) {
return (
{mobile ? (
{itemLabel}
) : (
<>
{itemLabel}
{soonLabel}
>
)}
);
}
return (
{isActive ? (
) : null}
{itemLabel}
);
})()
))}
>
);
}
export function SiteHeader({
lightLogoUrl,
darkLogoUrl,
defaultLocale,
isSuperAdmin = false,
}: SiteHeaderProps) {
const [isOpen, setIsOpen] = useState(false);
const [isScrolled, setIsScrolled] = useState(false);
const [logoReplayKey, setLogoReplayKey] = useState(0);
const logoClickTimesRef = useRef([]);
const pathname = usePathname();
const locale = useLocale();
const t = useTranslations("navigation");
const reducedMotion = useReducedMotion();
const isArabic = locale === "ar";
const languageDirection = isArabic ? "rtl" : "ltr";
const titleMotion = getDirectionalReveal(languageDirection);
const subtitleMotion = getDirectionalReveal(languageDirection);
const brandSubtitle = isArabic
? "مــــــطـــــــــــــور ويــــــــــب | فــــــــــــريــــــلانــــــســــــر"
: "Webdesigner Bremen | Freelancer";
const desktopControlRailClassName =
"inline-flex items-center gap-1 rounded-pill border border-border/70 bg-background/80 p-1 backdrop-blur-chrome";
const desktopControlButtonClassName =
"h-9 w-9 rounded-pill border border-transparent p-0 text-foreground/80 hover:bg-accent hover:text-foreground";
const mobileControlButtonClassName =
"h-10 w-10 rounded-pill border border-border/70 bg-background text-foreground/80 shadow-xs hover:bg-accent hover:text-foreground";
const adminButtonClassName =
"inline-flex h-9 items-center gap-1.5 rounded-pill border border-border/70 bg-background/80 px-3 text-sm font-medium text-foreground/80 backdrop-blur-chrome transition-colors hover:bg-accent hover:text-foreground";
const mobileAdminButtonClassName =
"flex h-10 w-10 items-center justify-center rounded-pill border border-border/70 bg-background text-foreground/80 shadow-xs transition-colors hover:bg-accent hover:text-foreground";
const adminHref = buildAdminUrl("/");
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 24);
};
handleScroll();
window.addEventListener("scroll", handleScroll, { passive: true });
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
const handleLogoClick = (event: React.MouseEvent) => {
setLogoReplayKey((value) => value + 1);
const now = Date.now();
const recentClicks = logoClickTimesRef.current.filter((time) => now - time < 1200);
const nextClicks = [...recentClicks, now];
logoClickTimesRef.current = nextClicks;
if (nextClicks.length < 3) {
return;
}
logoClickTimesRef.current = [];
event.preventDefault();
toast(t("logoTripleClick"));
};
return (
{isArabic ? (
<>
مــــحـــمــد
{" "}
فــــرواتـــي
>
) : (
<>
MOH
{" "}
FARAWATI
>
)}
{brandSubtitle}
{isSuperAdmin ? (
Admin
) : null}
{isOpen ? (
{navItems.map((item) => {
const itemPath = item.path || "/";
const isActive = isNavItemActive(stripLocalePrefix(pathname), itemPath);
const itemLabel = t(item.key);
const isArabic = locale === "ar";
return (
{item.disabled ? (
{itemLabel}
0{navItems.findIndex((navItem) => navItem.key === item.key) + 1}
) : (
setIsOpen(false)}
>
{itemLabel}
0{navItems.findIndex((navItem) => navItem.key === item.key) + 1}
)}
);
})}
{isSuperAdmin ? (
) : null}
) : null}
);
}