DRISHTI-ITMS / components /Shell.tsx
Harp404
DRISHTI ITMS — frontend (Next.js); backend on Modal via NEXT_PUBLIC_LOCAL_URL
8c07df8
Raw History Blame Contribute Delete
3.06 kB
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { LayoutDashboard, UploadCloud, ShieldAlert, Cctv, Map as MapIcon, Radio, FlaskConical } from "lucide-react";
import { cn } from "@/lib/utils";
import { Badge } from "@/components/ui/badge";
const NAV = [
{ href: "/", label: "Command Center", icon: LayoutDashboard },
{ href: "/upload", label: "Upload & Analyze", icon: UploadCloud },
{ href: "/violations", label: "Violations", icon: ShieldAlert },
{ href: "/cameras", label: "Live Cameras", icon: Cctv },
{ href: "/playground", label: "Model Playground", icon: FlaskConical },
{ href: "/map", label: "Hotspot Map", icon: MapIcon },
];
export default function Shell({ children }: { children: React.ReactNode }) {
const path = usePathname();
return (
<div className="flex min-h-full">
<aside className="w-64 shrink-0 border-r border-border bg-card p-4 flex flex-col gap-1.5">
<div className="px-2 py-3 mb-2">
<div className="text-xl font-extrabold tracking-wide flex items-center gap-2">
<Radio className="size-5 text-accent" />
DRISHTI<span className="text-accent">·</span>ITMS
</div>
<div className="text-xs text-muted-foreground mt-1 pl-7">
AI Traffic Violation Enforcement
</div>
</div>
{NAV.map((n) => {
const active = path === n.href;
const Icon = n.icon;
return (
<Link
key={n.href}
href={n.href}
className={cn(
"flex items-center gap-3 px-3 py-2 rounded-lg text-sm font-medium transition-colors",
active ? "bg-accent/15 text-accent" : "text-muted-foreground hover:bg-secondary hover:text-foreground"
)}
>
<Icon className="size-4 shrink-0" />
{n.label}
</Link>
);
})}
<div className="mt-auto rounded-lg border border-border bg-secondary/50 p-3 text-xs text-muted-foreground">
<div className="flex items-center gap-2 mb-1">
<span className="size-2 rounded-full bg-[var(--success)] animate-pulse" /> Engine online
</div>
Any-camera enforcement · edge + cloud
</div>
</aside>
<main className="flex-1 min-w-0">
<header className="h-14 border-b border-border bg-card/60 backdrop-blur flex items-center justify-between px-6 sticky top-0 z-30">
<div className="text-sm text-muted-foreground">
Bengaluru Traffic Police · ASTraM-compatible
</div>
<div className="flex items-center gap-3 text-sm">
<Badge variant="success" className="gap-1.5">
<span className="size-1.5 rounded-full bg-[var(--success)] animate-pulse" /> Live
</Badge>
<span className="text-muted-foreground">Officer: aman</span>
</div>
</header>
<div className="p-6">{children}</div>
</main>
</div>
);
}