diff --git a/app/components/layout/Sidebar.tsx b/app/components/layout/Sidebar.tsx index c7dfc47..5e1c3e8 100644 --- a/app/components/layout/Sidebar.tsx +++ b/app/components/layout/Sidebar.tsx @@ -1,116 +1,226 @@ "use client"; -import Link from "next/link"; +import Link from "next/link"; import { usePathname } from "next/navigation"; +import { useState, useEffect, createContext, useContext } from "react"; import { getStoredUser } from "@/src/lib/auth"; import Logo from "@/src/utils/logo"; +import BrandIcon from "@/src/utils/brandIcon"; + + //ــــــــــــــ Drawer Context + +const DrawerCtx = createContext<{ + open: boolean; + setOpen: (v: boolean) => void; +}>({ open: false, setOpen: () => {} }); + +export function useSidebarDrawer() { + return useContext(DrawerCtx); +} + +export function SidebarProvider({ children }: { children: React.ReactNode }) { + const [open, setOpen] = useState(false); + return ( + + {children} + + ); +} + +/* ══════════════════════════════════════════ + Nav items +══════════════════════════════════════════ */ const navSections = [ { label: "الرئيسية", items: [ - { href: "/dashboard", label: "Dashboard", icon: "ti-layout-dashboard", permission: "read-dashboard" }, - { href: "/dashboard/users", label: "Users", icon: "ti-users", permission: "read-user" }, + { href: "/dashboard", label: "Dashboard", icon: "ti-layout-dashboard", permission: "read-dashboard" }, + { href: "/dashboard/users", label: "Users", icon: "ti-users", permission: "read-user" }, ], }, { label: "الأسطول", items: [ - { href: "/dashboard/cars", label: "Cars", icon: "ti-car", permission: "read-car" }, - { href: "/dashboard/drivers", label: "Drivers", icon: "ti-steering-wheel",permission: "read-driver" }, - { href: "/dashboard/trips", label: "Trips", icon: "ti-route", permission: "read-trip" }, + { href: "/dashboard/cars", label: "Cars", icon: "ti-car", permission: "read-car" }, + { href: "/dashboard/drivers", label: "Drivers", icon: "ti-steering-wheel", permission: "read-driver" }, + { href: "/dashboard/trips", label: "Trips", icon: "ti-route", permission: "read-trip" }, ], }, { label: "العمليات", items: [ - { href: "/dashboard/orders", label: "Orders", icon: "ti-package", permission: "read-order" }, - { href: "/dashboard/clients", label: "Clients", icon: "ti-users-group", permission: "read-client" }, - { href: "/dashboard/branches", label: "Branches", icon: "ti-building", permission: "read-branch" }, - { href: "/dashboard/roles", label: "Roles", icon: "ti-shield", permission: "read-role" }, - { href: "/dashboard/role_permission", label: "Roles & Permission", icon: "ti-shield", permission: "manage-role-permissions" }, - { href: "/dashboard/audit", label: "Audit", icon: "ti-clipboard-list", permission: "read-audit" }, + { href: "/dashboard/orders", label: "Orders", icon: "ti-package", permission: "read-order" }, + { href: "/dashboard/clients", label: "Clients", icon: "ti-users-group", permission: "read-client" }, + { href: "/dashboard/branches", label: "Branches", icon: "ti-building", permission: "read-branch" }, + { href: "/dashboard/roles", label: "Roles", icon: "ti-shield", permission: "read-role" }, + { href: "/dashboard/role_permission", label: "Roles & Permission", icon: "ti-shield", permission: "manage-role-permissions" }, + { href: "/dashboard/audit", label: "Audit", icon: "ti-clipboard-list", permission: "read-audit" }, ], }, ]; +/* ══════════════════════════════════════════ + Brand Icon +══════════════════════════════════════════ */ + + +export function BrandIconButton({ onClick }: { onClick: () => void }) { + return ( + + ); +} + +const GRAD = "linear-gradient(175deg, #1E3A8A 0%, #1D4ED8 60%, #1565C0 100%)"; + +/* ══════════════════════════════════════════ + Sidebar + ⚠️ NO display property in any inline style here + globals.css controls ALL display with !important +══════════════════════════════════════════ */ export function Sidebar() { const pathname = usePathname(); const user = getStoredUser(); const permissions = user?.permissions ?? navSections.flatMap(s => s.items.map(i => i.permission)); + const { open, setOpen } = useSidebarDrawer(); + + useEffect(() => { setOpen(false); }, [pathname, setOpen]); + + useEffect(() => { + document.body.style.overflow = open ? "hidden" : ""; + return () => { document.body.style.overflow = ""; }; + }, [open]); return ( <> - {/* - Full sidebar — visible lg+. - No `left`/`right` is set anywhere: placement comes purely from - document order + `dir="rtl"` on . A flex row in RTL lays - its first child against the inline-start edge, which is - physically the RIGHT of the screen. Because is - still the first child in DashboardLayout, it now renders on - the right automatically — no positional CSS to flip. - */} + {/* ══ 1. Full sidebar — lg+ ══*/} - {/* - Compact icon rail — md and below (replaces the old behavior of - hiding the sidebar entirely under `lg`). Fixed to the - inline-end... no: fixed to the RIGHT edge explicitly, because a - `position: fixed` element takes no part in flex flow and so - gets no automatic RTL placement from document order. This is - exactly the kind of element logical properties exist for: - `inset-inline-end: 0` means "right in RTL, left in LTR" - without a manual swap if direction ever toggles. - */} + {/* ══ 2. Compact rail */} + + {/* mobile drower*/} + + {/* open drower*/} + {open && ( +
setOpen(false)} + aria-hidden="true" + style={{ + position: "fixed", + top: 0, left: 0, right: 0, bottom: 0, + background: "rgba(0,0,0,0.5)", + zIndex: 40, + }} /> + )} + + {/* Drawer panel */} + ); } +/* ══════════════════════════════════════════ + SidebarContent +══════════════════════════════════════════ */ function SidebarContent({ - pathname, - permissions, - user, - compact, + pathname, permissions, user, compact, }: { pathname: string; permissions: string[]; @@ -119,40 +229,28 @@ function SidebarContent({ }) { return ( <> - {/* Logo */}
- + {compact ? : }
- {/* Nav sections */} -