"use client";
import { useEffect, useMemo, useState } from "react";
import { usePathname, useRouter } from "next/navigation";
import Link from "next/link";
import PropTypes from "prop-types";
import ProviderIcon from "@/shared/components/ProviderIcon";
import HeaderMenu from "@/shared/components/HeaderMenu";
import HeaderLanguage from "@/shared/components/HeaderLanguage";
import ThemeToggle from "@/shared/components/ThemeToggle";
import DonateModal from "@/shared/components/DonateModal";
import { useHeaderSearchStore } from "@/store/headerSearchStore";
import { OAUTH_PROVIDERS, APIKEY_PROVIDERS } from "@/shared/constants/config";
import { MEDIA_PROVIDER_KINDS, AI_PROVIDERS } from "@/shared/constants/providers";
import { translate } from "@/i18n/runtime";
const getPageInfo = (pathname) => {
if (!pathname) return { title: "", description: "", breadcrumbs: [] };
// Media provider detail: /dashboard/media-providers/[kind]/[id]
const mediaDetailMatch = pathname.match(/\/media-providers\/([^/]+)\/([^/]+)$/);
if (mediaDetailMatch) {
const kindId = mediaDetailMatch[1];
const providerId = mediaDetailMatch[2];
const kindConfig = MEDIA_PROVIDER_KINDS.find((k) => k.id === kindId);
const provider = AI_PROVIDERS[providerId];
return {
title: provider?.name || providerId,
description: "",
breadcrumbs: [
{ label: "Media Providers", href: `/dashboard/media-providers/${kindId}` },
{ label: kindConfig?.label || kindId, href: `/dashboard/media-providers/${kindId}` },
{ label: provider?.name || providerId, image: `/providers/${providerId}.png` },
],
};
}
// Media provider kind: /dashboard/media-providers/[kind]
const mediaKindMatch = pathname.match(/\/media-providers\/([^/]+)$/);
if (mediaKindMatch) {
const kindId = mediaKindMatch[1];
const kindConfig = MEDIA_PROVIDER_KINDS.find((k) => k.id === kindId);
return {
title: kindConfig?.label || kindId,
description: `Manage your ${kindConfig?.label || kindId} providers`,
icon: kindConfig?.icon || "perm_media",
breadcrumbs: [],
};
}
// Provider detail page: /dashboard/providers/[id]
const providerMatch = pathname.match(/\/providers\/([^/]+)$/);
if (providerMatch) {
const providerId = providerMatch[1];
const providerInfo =
OAUTH_PROVIDERS[providerId] || APIKEY_PROVIDERS[providerId];
if (providerInfo) {
return {
title: providerInfo.name,
description: "",
breadcrumbs: [
{ label: "Providers", href: "/dashboard/providers" },
{
label: providerInfo.name,
image: `/providers/${providerInfo.id}.png`,
},
],
};
}
}
if (pathname.includes("/providers") && !pathname.includes("/media-providers"))
return {
title: "Providers",
description: "Manage your AI provider connections",
icon: "dns",
breadcrumbs: [],
};
if (pathname.includes("/combos"))
return {
title: "Combos",
description: "Model combos with fallback",
icon: "layers",
breadcrumbs: [],
};
if (pathname.includes("/usage"))
return {
title: "Usage & Analytics",
description:
"Monitor your API usage, token consumption, and request logs",
icon: "bar_chart",
breadcrumbs: [],
};
if (pathname.includes("/auth-files"))
return {
title: "Auth Files",
description: "Map provider credentials stored in the local database",
icon: "vpn_key",
breadcrumbs: [],
};
if (pathname.includes("/quota"))
return {
title: "Quota Tracker",
description: "Track and manage your API quota limits",
icon: "data_usage",
breadcrumbs: [],
};
if (pathname.includes("/mitm"))
return {
title: "MITM Proxy",
description: "Intercept CLI tool traffic and route through 9Router",
icon: "security",
breadcrumbs: [],
};
if (pathname.includes("/cli-tools"))
return {
title: "CLI Tools",
description: "Configure CLI tools",
icon: "terminal",
breadcrumbs: [],
};
if (pathname.includes("/proxy-pools"))
return {
title: "Proxy Pools",
description: "Manage your proxy pool configurations",
icon: "lan",
breadcrumbs: [],
};
if (pathname.includes("/skills"))
return {
title: "Agent Skills",
description: "Copy a link and paste to your AI to use 9Router — no install needed",
icon: "extension",
breadcrumbs: [],
};
if (pathname.includes("/endpoint"))
return {
title: "Endpoint",
description: "API endpoint configuration",
icon: "api",
breadcrumbs: [],
};
if (pathname.includes("/profile"))
return {
title: "Settings",
description: "Manage your preferences",
icon: "settings",
breadcrumbs: [],
};
if (pathname.includes("/translator"))
return {
title: "Translator",
description: "Debug translation flow between formats",
icon: "translate",
breadcrumbs: [],
};
if (pathname.includes("/console-log"))
return {
title: "Console Log",
description: "Live server console output",
icon: "monitor",
breadcrumbs: [],
};
if (pathname === "/dashboard")
return {
title: "Endpoint",
description: "API endpoint configuration",
icon: "api",
breadcrumbs: [],
};
return { title: "", description: "", breadcrumbs: [] };
};
export default function Header({ onMenuClick, showMenuButton = true }) {
const pathname = usePathname();
const router = useRouter();
const [displayName, setDisplayName] = useState("");
const [loginMethod, setLoginMethod] = useState("");
const [donateOpen, setDonateOpen] = useState(false);
// Memoize page info to prevent unnecessary recalculations
const pageInfo = useMemo(() => getPageInfo(pathname), [pathname]);
const { title, description, icon, breadcrumbs } = pageInfo;
useEffect(() => {
let cancelled = false;
async function loadAuthStatus() {
try {
const res = await fetch("/api/auth/status", { cache: "no-store" });
if (!res.ok) return;
const data = await res.json();
if (!cancelled) {
setDisplayName(data?.displayName || data?.oidcName || data?.oidcEmail || "");
setLoginMethod(data?.loginMethod || "");
}
} catch {
if (!cancelled) {
setDisplayName("");
setLoginMethod("");
}
}
}
loadAuthStatus();
return () => {
cancelled = true;
};
}, []);
const handleLogout = async () => {
try {
const res = await fetch("/api/auth/logout", { method: "POST" });
if (res.ok) {
router.push("/login");
router.refresh();
}
} catch (err) {
console.error("Failed to logout:", err);
}
};
return (
{translate(description)}
{translate(crumb.label)}
{translate(title)}