Files
trustlab/src/components/Layouts/Public/Navbar.tsx
2025-12-30 12:14:45 +07:00

226 lines
14 KiB
TypeScript

"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { ThemeToggle } from "@/components/common/ThemeToggle";
import { useAuth } from "@/hooks/useAuth";
import { LanguageSwitcher } from "@/components/header/LanguageSwitcher";
import { useTranslations } from "next-intl";
// Helper for smooth scrolling
const scrollToSection = (id: string) => {
const element = document.querySelector(id);
if (!element) return;
const navbarOffset = 80;
const elementPosition = element.getBoundingClientRect().top;
const offsetPosition = elementPosition + window.pageYOffset - navbarOffset;
window.scrollTo({
top: offsetPosition,
behavior: "smooth",
});
};
export default function Navbar() {
const [mobileOpen, setMobileOpen] = useState(false);
const [toolsOpen, setToolsOpen] = useState(false);
const pathname = usePathname();
const { user, logout } = useAuth();
const t = useTranslations("Navigation");
// Theme toggle logic simplified for this component or reused from context
// Assuming we might want to lift theme state up or use a provider.
// For now, I'll add a placeholder toggle or just basic class toggle logic if not globally provided yet.
// Note: The Header.tsx used local state or a store. Let's assume a simple toggle for now.
return (
<nav className="fixed top-0 left-0 right-0 z-50 w-full bg-white/80 dark:bg-gray-900/80 backdrop-blur-lg border-b border-gray-100 dark:border-gray-800">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-20">
{/* Logo */}
{/* Logo */}
<Link href="/" className="flex items-center gap-3">
{/* Using the migrated asset */}
<div className="relative w-10 h-10">
<img src="/images/logo/logo-icon.svg" alt="TrustLab Logo" className="w-full h-full object-contain" />
</div>
<span className="text-xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-gray-900 to-gray-500 dark:from-white dark:to-gray-400">
TrustLab
</span>
</Link>
{/* Desktop Menu */}
<div className="hidden md:flex items-center gap-8 text-sm font-medium">
<Link href="/" className="text-gray-600 dark:text-gray-400 hover:text-brand-500 dark:hover:text-brand-400 transition-colors">{t("home")}</Link>
<a
href="/#features"
onClick={(e) => {
if (pathname === '/') {
e.preventDefault();
scrollToSection('#features');
}
}}
className="text-gray-600 dark:text-gray-400 hover:text-brand-500 dark:hover:text-brand-400 transition-colors cursor-pointer"
>
{t("features")}
</a>
{/* Tools Dropdown */}
<div
className="relative"
onMouseEnter={() => setToolsOpen(true)}
onMouseLeave={() => setToolsOpen(false)}
>
<button
onClick={(e) => {
e.preventDefault();
setToolsOpen(!toolsOpen);
}}
className="flex items-center gap-1 text-gray-600 dark:text-gray-400 hover:text-brand-500 dark:hover:text-brand-400 transition-colors py-2"
>
{t("tools")}
<svg className={`w-4 h-4 transition-transform duration-200 ${toolsOpen ? 'rotate-180' : ''}`} fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7" />
</svg>
</button>
{toolsOpen && (
<div className="absolute left-0 top-full pt-3 w-64 z-50">
<div className="rounded-2xl bg-white dark:bg-gray-800 shadow-xl border border-gray-100 dark:border-gray-700 py-2 overflow-hidden">
<Link href="/tools/chat-id" className="flex items-center gap-3 px-4 py-3 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700/50 hover:text-brand-500 transition-all">
<div className="w-8 h-8 bg-brand-50 dark:bg-brand-500/10 rounded-lg flex items-center justify-center text-brand-500">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z" /></svg>
</div>
<div>
<div className="font-bold">{t("chat_id_finder")}</div>
<div className="text-[10px] text-gray-400">Find your Telegram ID</div>
</div>
</Link>
<Link href="/tools/key-generator" className="flex items-center gap-3 px-4 py-3 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700/50 hover:text-brand-500 transition-all">
<div className="w-8 h-8 bg-blue-50 dark:bg-blue-500/10 rounded-lg flex items-center justify-center text-blue-500">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" /></svg>
</div>
<div>
<div className="font-bold">{t("app_key_generator")}</div>
<div className="text-[10px] text-gray-400">Secure Laravel keys</div>
</div>
</Link>
</div>
</div>
)}
</div>
<Link href="/contact" className="text-gray-600 dark:text-gray-400 hover:text-brand-500 dark:hover:text-brand-400 transition-colors">{t("contact")}</Link>
{user ? (
<Link href="/dashboard" className="text-gray-600 dark:text-gray-400 hover:text-brand-500 dark:hover:text-brand-400 transition-colors font-bold">
Hi, {user.first_name || 'User'}
</Link>
) : (
<Link href="/signin" className="text-gray-600 dark:text-gray-400 hover:text-brand-500 dark:hover:text-brand-400 transition-colors">{t("signin")}</Link>
)}
<LanguageSwitcher />
<ThemeToggle />
{user ? (
<button
onClick={logout}
className="px-5 py-2.5 bg-gray-100 dark:bg-white/5 text-gray-700 dark:text-white rounded-xl font-semibold transition-all hover:bg-gray-200 dark:hover:bg-white/10"
>
{t("signout")}
</button>
) : (
<Link href="/signup" className="px-5 py-2.5 bg-brand-500 hover:bg-brand-600 text-white rounded-xl font-semibold shadow-lg shadow-brand-500/25 transition-all hover:scale-105">
{t("signup")}
</Link>
)}
</div>
{/* Mobile Header Actions */}
<div className="md:hidden flex items-center gap-2">
<LanguageSwitcher />
<ThemeToggle />
<button onClick={() => setMobileOpen(!mobileOpen)} className="p-2 text-gray-600 dark:text-gray-400">
{mobileOpen ? (
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
</svg>
) : (
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16m-7 6h7" />
</svg>
)}
</button>
</div>
</div>
</div>
{/* Mobile Navigation Overlay */}
{mobileOpen && (
<div className="fixed top-0 left-0 w-full h-[100dvh] z-40 md:hidden bg-white dark:bg-gray-900 pt-24 px-6 pb-24 animate-in slide-in-from-top-10 fade-in duration-300 overflow-y-auto">
<div className="flex flex-col gap-6 pb-10">
<div className="flex justify-end">
<button
onClick={() => setMobileOpen(false)}
className="p-2 -mr-2 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
aria-label="Close menu"
>
<span className="text-sm font-medium mr-2">Close</span>
<svg className="inline-block w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<Link href="/" onClick={() => setMobileOpen(false)} className="text-lg font-bold text-gray-900 dark:text-white border-b border-gray-100 dark:border-gray-800 pb-4">{t("home")}</Link>
<a
href="/#features"
onClick={(e) => {
setMobileOpen(false);
if (pathname === '/') {
e.preventDefault();
scrollToSection('#features');
}
}}
className="text-lg font-bold text-gray-900 dark:text-white border-b border-gray-100 dark:border-gray-800 pb-4"
>
{t("features")}
</a>
{/* Mobile Tools (simplified) */}
<div className="space-y-4 border-b border-gray-100 dark:border-gray-800 pb-4">
<div className="text-lg font-bold text-gray-900 dark:text-white">{t("tools")}</div>
<div className="pl-4 space-y-3">
<Link href="/tools/chat-id" onClick={() => setMobileOpen(false)} className="block text-gray-600 dark:text-gray-400 font-medium">{t("chat_id_finder")}</Link>
<Link href="/tools/key-generator" onClick={() => setMobileOpen(false)} className="block text-gray-600 dark:text-gray-400 font-medium">{t("app_key_generator")}</Link>
</div>
</div>
<Link href="/contact" onClick={() => setMobileOpen(false)} className="text-lg font-bold text-gray-900 dark:text-white border-b border-gray-100 dark:border-gray-800 pb-4">{t("contact")}</Link>
{user ? (
<>
<Link href="/dashboard" onClick={() => setMobileOpen(false)} className="text-lg font-bold text-brand-500 border-b border-gray-100 dark:border-gray-800 pb-4">{t("dashboard")}</Link>
<button
onClick={() => {
setMobileOpen(false);
logout();
}}
className="text-lg font-bold text-red-500 text-left"
>
{t("signout")}
</button>
</>
) : (
<>
<Link href="/signin" onClick={() => setMobileOpen(false)} className="text-lg font-bold text-gray-900 dark:text-white border-b border-gray-100 dark:border-gray-800 pb-4">{t("signin")}</Link>
<Link href="/signup" onClick={() => setMobileOpen(false)} className="mt-6 w-full py-4 bg-brand-500 text-white rounded-2xl font-bold text-center shadow-xl shadow-brand-500/20 block">{t("signup")}</Link>
</>
)}
</div>
</div>
)}
</nav>
);
}