repositories
loading repo index
repositories
loading repo index
repository
loading code, commits, and activity
certificates
stars
latest
clone command
git clone gitlawb://did:key:z6Mkqhmm...XL9c/certificatesgit clone gitlawb://did:key:z6Mkqhmm.../certificates019974a8sync from playground15h ago| #1 | import { NavLink, Outlet, useNavigate } from "react-router-dom"; |
| #2 | import { useAuth } from "../contexts/AuthContext"; |
| #3 | import { |
| #4 | LayoutDashboard, |
| #5 | FilePlus, |
| #6 | Upload, |
| #7 | List, |
| #8 | Palette, |
| #9 | LogOut, |
| #10 | ShieldCheck, |
| #11 | FileImage, |
| #12 | } from "lucide-react"; |
| #13 | |
| #14 | const links = [ |
| #15 | { to: "/admin/dashboard", label: "Dashboard", icon: LayoutDashboard }, |
| #16 | { to: "/admin/issue", label: "Issue Cert", icon: FilePlus }, |
| #17 | { to: "/admin/upload", label: "Upload Cert", icon: FileImage }, |
| #18 | { to: "/admin/bulk", label: "Bulk Import", icon: Upload }, |
| #19 | { to: "/admin/certs", label: "All Certs", icon: List }, |
| #20 | { to: "/admin/templates", label: "Templates", icon: Palette }, |
| #21 | ]; |
| #22 | |
| #23 | export default function AdminLayout() { |
| #24 | const { logout, user } = useAuth(); |
| #25 | const navigate = useNavigate(); |
| #26 | |
| #27 | const handleLogout = async () => { |
| #28 | await logout(); |
| #29 | navigate("/admin"); |
| #30 | }; |
| #31 | |
| #32 | return ( |
| #33 | <div className="flex min-h-screen bg-gray-50"> |
| #34 | {/* Sidebar */} |
| #35 | <aside className="w-64 bg-gray-900 text-white flex flex-col shrink-0"> |
| #36 | <div className="p-5 border-b border-gray-800"> |
| #37 | <div className="flex items-center gap-2"> |
| #38 | <ShieldCheck className="w-6 h-6 text-emerald-400" /> |
| #39 | <span className="font-bold text-lg">CertAdmin</span> |
| #40 | </div> |
| #41 | <p className="text-xs text-gray-400 mt-1 truncate">{user?.email}</p> |
| #42 | </div> |
| #43 | <nav className="flex-1 p-3 space-y-1"> |
| #44 | {links.map(({ to, label, icon: Icon }) => ( |
| #45 | <NavLink |
| #46 | key={to} |
| #47 | to={to} |
| #48 | className={({ isActive }) => |
| #49 | `flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-colors ${ |
| #50 | isActive |
| #51 | ? "bg-emerald-600 text-white" |
| #52 | : "text-gray-300 hover:bg-gray-800 hover:text-white" |
| #53 | }` |
| #54 | } |
| #55 | > |
| #56 | <Icon className="w-4 h-4" /> |
| #57 | {label} |
| #58 | </NavLink> |
| #59 | ))} |
| #60 | </nav> |
| #61 | <div className="p-3 border-t border-gray-800 space-y-1"> |
| #62 | <a |
| #63 | href="/#/" |
| #64 | className="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-400 hover:bg-gray-800 hover:text-white transition-colors" |
| #65 | > |
| #66 | <ShieldCheck className="w-4 h-4" /> |
| #67 | View Public Site |
| #68 | </a> |
| #69 | <button |
| #70 | onClick={handleLogout} |
| #71 | className="flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium text-gray-400 hover:bg-gray-800 hover:text-white w-full transition-colors" |
| #72 | > |
| #73 | <LogOut className="w-4 h-4" /> |
| #74 | Sign Out |
| #75 | </button> |
| #76 | </div> |
| #77 | </aside> |
| #78 | |
| #79 | {/* Main content */} |
| #80 | <main className="flex-1 overflow-auto"> |
| #81 | <div className="max-w-6xl mx-auto p-6"> |
| #82 | <Outlet /> |
| #83 | </div> |
| #84 | </main> |
| #85 | </div> |
| #86 | ); |
| #87 | } |
| #88 |