Files
dns-autoresolver/web/src/components/Layout.tsx
T

97 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { ReactNode } from "react"
import { NavLink, useLocation, useNavigate } from "react-router-dom"
import { BellRing, CalendarClock, Globe, LogOut, Users, LayoutTemplate, SquareTerminal } from "lucide-react"
import { useAuth } from "@/auth/AuthContext"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"
const NAV = [
{ to: "/domains", label: "Domains", icon: Globe },
{ to: "/accounts", label: "Accounts", icon: Users },
{ to: "/templates", label: "Templates", icon: LayoutTemplate },
{ to: "/schedule", label: "Schedule", icon: CalendarClock },
{ to: "/channels", label: "Channels", icon: BellRing },
] as const
export function Layout({ children }: { children: ReactNode }) {
const location = useLocation()
const navigate = useNavigate()
const { user, logout } = useAuth()
async function onLogout() {
await logout()
navigate("/login", { replace: true })
}
return (
<div className="flex h-screen w-full overflow-hidden bg-background text-foreground">
<aside className="flex w-60 shrink-0 flex-col border-r border-sidebar-border bg-sidebar text-sidebar-foreground">
<div className="flex items-center gap-2 border-b border-sidebar-border px-4 py-4">
<SquareTerminal className="size-4 text-primary" strokeWidth={1.75} />
<div className="flex flex-col leading-none">
<span className="text-sm font-semibold tracking-tight">
DNS Autoresolver
</span>
<span className="font-dns text-[10px] tracking-wider text-muted-foreground uppercase">
console
</span>
</div>
</div>
<nav className="flex-1 space-y-0.5 overflow-y-auto px-2 py-3">
{NAV.map(({ to, label, icon: Icon }) => (
<NavLink
key={to}
to={to}
className={({ isActive }) =>
cn(
"group flex items-center gap-2.5 rounded-md border-l-2 border-transparent px-2.5 py-2 text-sm font-medium text-muted-foreground transition-colors",
"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
isActive &&
"border-primary bg-sidebar-accent text-sidebar-accent-foreground",
)
}
>
<Icon className="size-4 shrink-0" strokeWidth={1.75} />
<span className="flex-1">{label}</span>
<span className="font-dns text-[10px] text-muted-foreground/60 group-hover:text-muted-foreground">
{to}
</span>
</NavLink>
))}
</nav>
<div className="flex items-center justify-between border-t border-sidebar-border px-4 py-3 font-dns text-[11px] text-muted-foreground">
<span>v0.1.0-dev</span>
<span className="flex items-center gap-1.5">
<span
className="size-1.5 rounded-full"
style={{ background: "var(--diff-insync)" }}
aria-hidden
/>
in sync
</span>
</div>
</aside>
<div className="flex flex-1 flex-col overflow-hidden">
<header className="flex h-11 shrink-0 items-center justify-between border-b border-border px-6">
<span className="font-dns text-xs text-muted-foreground">
{location.pathname}
</span>
{user && (
<div className="flex items-center gap-3">
<span className="font-dns text-xs text-muted-foreground">{user.email}</span>
<Button variant="ghost" size="sm" onClick={onLogout}>
<LogOut className="size-3.5" strokeWidth={1.75} />
Выйти
</Button>
</div>
)}
</header>
<main className="flex-1 overflow-auto">{children}</main>
</div>
</div>
)
}