ThreadCount Community edition
Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
"use client";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
/* The console's left rail: where you are, who you are, and the way out. Plain anchors rather
|
||||
* than Next links on purpose — every page under /ops is force-dynamic and behind a cookie, and a
|
||||
* prefetched copy fetched before a state change would be the stale one. */
|
||||
const NAV = [
|
||||
{ href: "/ops", label: "Overview" },
|
||||
{ href: "/ops/facilities", label: "Facilities" },
|
||||
{ href: "/ops/controls", label: "Controls" },
|
||||
{ href: "/ops/security", label: "Your sign-in" },
|
||||
];
|
||||
|
||||
export function Rail({ name, email, role, viaSso, totpEnabled }: { name: string; email: string; role: string; viaSso: boolean; totpEnabled: boolean }) {
|
||||
const path = usePathname() || "/ops";
|
||||
const active = (href: string) => (href === "/ops" ? path === "/ops" : path.startsWith(href));
|
||||
return (
|
||||
<aside style={{ width: 212, flex: "none", borderRight: "2px solid var(--color-text)", background: "var(--color-surface)", padding: "20px 0" }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: 8, padding: "0 16px 18px" }}>
|
||||
<div style={{ width: 14, height: 14, background: "var(--color-accent)" }} />
|
||||
<b style={{ fontSize: 17, fontWeight: 800 }}>ThreadCount ops</b>
|
||||
</div>
|
||||
<div style={{ padding: "0 16px 14px", fontSize: 11.5, color: "var(--color-neutral-600)", borderBottom: "1px solid var(--color-divider)", marginBottom: 10 }}>
|
||||
<b style={{ display: "block", color: "var(--color-neutral-800)", fontWeight: 600 }}>Signed in as {name}</b>
|
||||
{email} · {role.toLowerCase()} · {viaSso ? "single sign-on" : "password"}
|
||||
</div>
|
||||
<nav style={{ display: "flex", flexDirection: "column" }} aria-label="Console">
|
||||
{NAV.map((n) => (
|
||||
<a key={n.href} href={n.href} aria-current={active(n.href) ? "page" : undefined}
|
||||
style={{ padding: "9px 16px", fontWeight: 600, textDecoration: "none", color: active(n.href) ? "var(--color-text)" : "var(--color-neutral-700)", background: active(n.href) ? "var(--color-neutral-200)" : "transparent", borderLeft: `3px solid ${active(n.href) ? "var(--color-accent)" : "transparent"}` }}>
|
||||
{n.label}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
{!totpEnabled && (
|
||||
<div style={{ margin: "14px 12px 0", padding: "8px 10px", borderLeft: "4px solid var(--color-accent)", background: "var(--color-bg)", fontSize: 12, lineHeight: 1.5 }}>
|
||||
Second factor not yet enrolled. <a href="/ops/security" style={{ fontWeight: 700 }}>Set it up.</a>
|
||||
</div>
|
||||
)}
|
||||
<form action="/api/ops/auth/logout" method="post" style={{ padding: "18px 16px 0" }}>
|
||||
<button className="btn" type="submit" style={{ width: "100%" }}>Sign out</button>
|
||||
</form>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user