Header.tsx 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { LogOut, Menu, Moon, Sun, User } from "lucide-react";
  2. import { useNavigate } from "react-router-dom";
  3. import { useTranslation } from "react-i18next";
  4. import { Button } from "@/components/ui/button";
  5. import { Breadcrumb } from "./Breadcrumb";
  6. import { LanguageSelector } from "@/components/shared/LanguageSelector";
  7. import { useAuthStore } from "@/stores/auth";
  8. import { useUiStore } from "@/stores/ui";
  9. import { mockMode } from "@/api/mock";
  10. export function Header() {
  11. const { t } = useTranslation();
  12. const navigate = useNavigate();
  13. const { userId, logout } = useAuthStore();
  14. const { theme, toggleTheme, toggleMobileSidebar } = useUiStore();
  15. return (
  16. <header className="glass sticky top-0 z-30 flex h-16 items-center justify-between px-4 md:px-6">
  17. <div className="flex items-center gap-3">
  18. <Button className="md:hidden" variant="ghost" size="icon" onClick={toggleMobileSidebar} aria-label="Open navigation">
  19. <Menu className="h-4 w-4" />
  20. </Button>
  21. <Breadcrumb />
  22. </div>
  23. <div className="flex items-center gap-3">
  24. {mockMode ? (
  25. <div className="hidden items-center gap-2 rounded-md border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-xs text-amber-700 dark:text-amber-200 sm:flex">
  26. {t("auth.mockData")}
  27. </div>
  28. ) : null}
  29. <div className="hidden items-center gap-2 rounded-md border border-border bg-muted/40 px-3 py-2 text-xs text-muted-foreground sm:flex">
  30. <span className="h-2 w-2 rounded-full bg-emerald-400 shadow-[0_0_10px_rgba(16,185,129,0.8)]" />
  31. {t("auth.gateway")}
  32. </div>
  33. <div className="hidden items-center gap-2 text-sm text-muted-foreground sm:flex">
  34. <User className="h-4 w-4" />
  35. <span>{userId || "user"}</span>
  36. </div>
  37. <Button
  38. variant="ghost"
  39. size="icon"
  40. onClick={toggleTheme}
  41. aria-label={theme === "dark" ? t("theme.switchToLight") : t("theme.switchToDark")}
  42. >
  43. {theme === "dark" ? <Sun className="h-4 w-4" /> : <Moon className="h-4 w-4" />}
  44. </Button>
  45. <LanguageSelector />
  46. <Button
  47. variant="ghost"
  48. size="icon"
  49. onClick={() => {
  50. logout();
  51. navigate("/login", { replace: true });
  52. }}
  53. aria-label={t("auth.logout")}
  54. >
  55. <LogOut className="h-4 w-4" />
  56. </Button>
  57. </div>
  58. </header>
  59. );
  60. }