| import { NavLink } from "react-router-dom" |
|
|
| const NAV_ITEMS = [ |
| { to: "/", label: "Dashboard", kicker: "Plant status" }, |
| { to: "/live", label: "Live Monitor", kicker: "Camera and upload" }, |
| { to: "/history", label: "History", kicker: "Inspection logs" }, |
| { to: "/analytics", label: "Analytics", kicker: "Trends and charts" }, |
| ] |
|
|
| function navClasses(isActive) { |
| return [ |
| "group relative overflow-hidden rounded-3xl border px-4 py-4 transition duration-300", |
| isActive |
| ? "border-cyan-300/50 bg-cyan-400/10 shadow-[0_16px_40px_rgba(34,211,238,0.12)]" |
| : "border-white/[0.08] bg-white/[0.04] hover:border-white/20 hover:bg-white/[0.07]", |
| ].join(" ") |
| } |
|
|
| export default function Sidebar({ mobileOpen, onClose }) { |
| return ( |
| <> |
| <div |
| className={`fixed inset-0 z-30 bg-slate-950/70 backdrop-blur-sm transition lg:hidden ${ |
| mobileOpen ? "pointer-events-auto opacity-100" : "pointer-events-none opacity-0" |
| }`} |
| onClick={onClose} |
| /> |
| |
| <aside |
| className={`fixed inset-y-0 left-0 z-40 flex w-[320px] max-w-[88vw] flex-col border-r border-white/10 bg-slate-950/[0.92] px-5 py-5 shadow-[0_30px_80px_rgba(2,6,23,0.55)] backdrop-blur-2xl transition duration-300 lg:z-10 lg:translate-x-0 ${ |
| mobileOpen ? "translate-x-0" : "-translate-x-full" |
| }`} |
| > |
| <div className="surface-card p-5"> |
| <div className="flex items-start justify-between gap-4"> |
| <div> |
| <p className="eyebrow">Factory Quality Ops</p> |
| <h2 className="text-2xl font-semibold text-slate-50">Manufacturing Monitoring System</h2> |
| </div> |
| |
| <button |
| type="button" |
| className="inline-flex h-10 w-10 items-center justify-center rounded-2xl border border-white/10 bg-white/5 text-slate-100 transition hover:border-cyan-300/40 hover:bg-cyan-400/10 lg:hidden" |
| onClick={onClose} |
| aria-label="Close navigation" |
| > |
| × |
| </button> |
| </div> |
| |
| <p className="mt-4 text-sm leading-7 text-slate-300"> |
| Real-time steel surface inspection with live monitoring, report history, analytics, |
| and decision support for production teams. |
| </p> |
| </div> |
| |
| <nav className="mt-6 flex flex-col gap-3"> |
| {NAV_ITEMS.map((item, index) => ( |
| <NavLink key={item.to} to={item.to} onClick={onClose} className={({ isActive }) => navClasses(isActive)}> |
| {({ isActive }) => ( |
| <div className="relative flex items-center gap-4"> |
| <div |
| className={`flex h-11 w-11 items-center justify-center rounded-2xl border text-sm font-semibold ${ |
| isActive |
| ? "border-cyan-300/50 bg-cyan-300/[0.15] text-cyan-100" |
| : "border-white/10 bg-white/5 text-slate-300" |
| }`} |
| > |
| {String(index + 1).padStart(2, "0")} |
| </div> |
| |
| <div className="min-w-0"> |
| <p className="text-base font-medium text-slate-50">{item.label}</p> |
| <p className="text-sm text-slate-400">{item.kicker}</p> |
| </div> |
| </div> |
| )} |
| </NavLink> |
| ))} |
| </nav> |
| |
| <div className="mt-auto surface-card p-5"> |
| <p className="eyebrow">Operating Note</p> |
| <p className="mt-4 text-sm leading-7 text-slate-300"> |
| For accurate live results, keep the camera stable and align the steel surface in a clear top view with minimal background. |
| </p> |
| </div> |
| </aside> |
| </> |
| ) |
| } |
|
|