| import { useState } from "react"; |
| import { Link, useLocation } from "wouter"; |
| import { Sparkles, Image as ImageIcon, Video, Key, LogIn, LogOut, User, Shield } from "lucide-react"; |
| import { cn } from "@/lib/utils"; |
| import { SettingsButton } from "@/components/SettingsDialog"; |
| import { useLang } from "@/contexts/LanguageContext"; |
| import { useAuth } from "@/contexts/AuthContext"; |
| import { AuthModal } from "@/components/AuthModal"; |
|
|
| export function Navbar() { |
| const [location] = useLocation(); |
| const { lang, setLang, t } = useLang(); |
| const { user, isSignedIn, isAdmin, signOut } = useAuth(); |
| const [authOpen, setAuthOpen] = useState(false); |
|
|
| return ( |
| <> |
| <nav className="border-b border-border/50 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 sticky top-0 z-50"> |
| <div className="container mx-auto px-4 h-16 flex items-center justify-between"> |
| <Link href="/" className="flex items-center gap-2 no-underline"> |
| <div className="w-8 h-8 rounded-lg bg-primary/20 flex items-center justify-center border border-primary/30 text-primary"> |
| <Sparkles className="w-4 h-4" /> |
| </div> |
| <span className="font-semibold text-lg tracking-tight bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent"> |
| {t.appName} |
| </span> |
| </Link> |
| |
| <div className="flex items-center gap-1"> |
| <Link href="/" className={cn( |
| "px-4 py-2 rounded-md text-sm font-medium transition-colors hover:text-foreground", |
| location === "/" ? "bg-secondary text-foreground" : "text-muted-foreground" |
| )}> |
| <div className="flex items-center gap-2"> |
| <Sparkles className="w-4 h-4" /> |
| <span>{t.navCreate}</span> |
| </div> |
| </Link> |
| <Link href="/history" className={cn( |
| "px-4 py-2 rounded-md text-sm font-medium transition-colors hover:text-foreground", |
| location === "/history" ? "bg-secondary text-foreground" : "text-muted-foreground" |
| )}> |
| <div className="flex items-center gap-2"> |
| <ImageIcon className="w-4 h-4" /> |
| <span className="hidden sm:inline">{t.navHistory}</span> |
| </div> |
| </Link> |
| <Link href="/video" className={cn( |
| "px-4 py-2 rounded-md text-sm font-medium transition-colors hover:text-foreground", |
| location === "/video" ? "bg-secondary text-foreground" : "text-muted-foreground" |
| )}> |
| <div className="flex items-center gap-2"> |
| <Video className="w-4 h-4" /> |
| <span className="hidden sm:inline">{t.navVideo}</span> |
| </div> |
| </Link> |
| |
| {isSignedIn && ( |
| <Link href="/api-keys" className={cn( |
| "px-4 py-2 rounded-md text-sm font-medium transition-colors hover:text-foreground", |
| location === "/api-keys" ? "bg-secondary text-foreground" : "text-muted-foreground" |
| )}> |
| <div className="flex items-center gap-2"> |
| <Key className="w-4 h-4" /> |
| <span className="hidden sm:inline">{t.navApiKeys}</span> |
| </div> |
| </Link> |
| )} |
| |
| {isAdmin && ( |
| <Link href="/admin" className={cn( |
| "px-4 py-2 rounded-md text-sm font-medium transition-colors hover:text-foreground", |
| location === "/admin" ? "bg-secondary text-foreground" : "text-muted-foreground" |
| )}> |
| <div className="flex items-center gap-2"> |
| <Shield className="w-4 h-4 text-yellow-400" /> |
| <span className="hidden sm:inline">{t.navAdmin}</span> |
| </div> |
| </Link> |
| )} |
| |
| <button |
| onClick={() => setLang(lang === "zh" ? "en" : "zh")} |
| className="px-3 py-1.5 rounded-md text-xs font-semibold border border-border/60 text-muted-foreground hover:text-foreground hover:border-primary/50 transition-colors ml-1" |
| title={lang === "zh" ? "Switch to English" : "切換為繁體中文"} |
| > |
| {lang === "zh" ? "EN" : "中"} |
| </button> |
| |
| {isSignedIn ? ( |
| <div className="flex items-center gap-2 ml-1"> |
| <div className="flex items-center gap-2 px-2 py-1 rounded-md"> |
| <div className="w-6 h-6 rounded-full bg-primary/20 border border-primary/30 flex items-center justify-center"> |
| <User className="w-3 h-3 text-primary" /> |
| </div> |
| <span className="text-xs text-muted-foreground hidden md:inline max-w-[100px] truncate"> |
| {user?.displayName || user?.email?.split("@")[0] || ""} |
| </span> |
| </div> |
| <button |
| onClick={signOut} |
| className="flex items-center gap-1.5 px-2 py-1.5 rounded-md text-xs text-muted-foreground hover:text-foreground hover:bg-secondary transition-colors" |
| title={t.navSignOut} |
| > |
| <LogOut className="w-3.5 h-3.5" /> |
| <span className="hidden sm:inline">{t.navSignOut}</span> |
| </button> |
| </div> |
| ) : ( |
| <button |
| onClick={() => setAuthOpen(true)} |
| className="flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-secondary transition-colors ml-1" |
| > |
| <LogIn className="w-4 h-4" /> |
| <span className="hidden sm:inline">{t.navSignIn}</span> |
| </button> |
| )} |
| |
| <div className="ml-1"> |
| <SettingsButton /> |
| </div> |
| </div> |
| </div> |
| </nav> |
| |
| <AuthModal open={authOpen} onOpenChange={setAuthOpen} /> |
| </> |
| ); |
| } |
|
|