mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 10:58:14 +00:00
refactor: remove duplicate header components and consolidate layout
This commit is contained in:
@@ -1,84 +1,92 @@
|
||||
import { Link, Outlet, useLocation } from "react-router-dom";
|
||||
import { AppMenuTabs } from "./AppMenuTabs";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarRail,
|
||||
SidebarTrigger,
|
||||
} from "@/shared/common/ui/sidebar";
|
||||
import Top from "@/record-management/components/common/Top";
|
||||
import { useAuth } from "@/shared/context/AuthContext";
|
||||
|
||||
export const AppLayout = () => {
|
||||
const { pathname } = useLocation();
|
||||
const isAuthPage = pathname === "/";
|
||||
const { user } = useAuth();
|
||||
|
||||
const userRoles = user?.roles?.map((role) => role.key) || [];
|
||||
const isSuperAdmin = userRoles.includes("super_admin");
|
||||
|
||||
// Standalone full-page scroll container for the auth screen — the host
|
||||
// chrome is `overflow: hidden`, so this subtree must scroll itself.
|
||||
if (isAuthPage) {
|
||||
return (
|
||||
<div className="h-dvh w-full overflow-y-auto bg-gray-50">
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* <Top> is a shared component rendered as a full-width `fixed` 64px bar,
|
||||
so the sidebar is offset to start beneath it (top-16) rather than
|
||||
owning the top-left corner. Collapses to an icon rail on desktop; on
|
||||
mobile it's a Sheet drawer opened by the <SidebarTrigger> below (Top's
|
||||
own burger is a module-nav dropdown, not the sidebar toggle). */}
|
||||
<Sidebar collapsible="icon" className="top-14! h-[calc(100svh-4rem)]!">
|
||||
<SidebarHeader className="border-b border-sidebar-border">
|
||||
<Link
|
||||
to="/user-management"
|
||||
className="flex items-center gap-2 px-1 py-1.5"
|
||||
>
|
||||
<img
|
||||
src="/assets/logo.svg"
|
||||
alt="EDR"
|
||||
className="size-7 shrink-0 object-contain"
|
||||
/>
|
||||
<div className="flex flex-col group-data-[collapsible=icon]:hidden">
|
||||
<span className="text-sm font-semibold leading-tight text-sidebar-foreground">
|
||||
User Management
|
||||
</span>
|
||||
<span className="text-[10px] font-medium text-muted-foreground">
|
||||
EDR Freight
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
</SidebarHeader>
|
||||
<SidebarContent className="pb-10">
|
||||
<AppMenuTabs />
|
||||
</SidebarContent>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
|
||||
<SidebarInset className="min-w-0">
|
||||
<Top showRecordManagementShortcut={!isSuperAdmin} />
|
||||
{/* Top provides its own in-flow h-24 spacer clearing the fixed header. */}
|
||||
{/* Mobile-only drawer opener — desktop shows the sidebar/rail directly. */}
|
||||
<div className="flex items-center gap-2 px-3 md:hidden">
|
||||
<SidebarTrigger className="h-9 w-9 rounded-lg" />
|
||||
<span className="text-sm font-medium text-muted-foreground">
|
||||
Menu
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex-1 pb-2 sm:px-4 sm:pb-4 ">
|
||||
<div className="w-full overflow-x-auto">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</>
|
||||
);
|
||||
};
|
||||
import { Link, Outlet, useLocation } from "react-router-dom";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { AppMenuTabs } from "./AppMenuTabs";
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarHeader,
|
||||
SidebarInset,
|
||||
SidebarRail,
|
||||
useSidebar,
|
||||
} from "@/shared/common/ui/sidebar";
|
||||
import Top from "@/record-management/components/common/Top";
|
||||
import { useAuth } from "@/shared/context/AuthContext";
|
||||
|
||||
export const AppLayout = () => {
|
||||
const { pathname } = useLocation();
|
||||
const isAuthPage = pathname === "/";
|
||||
const { toggleSidebar } = useSidebar();
|
||||
const { user } = useAuth();
|
||||
|
||||
const userRoles = user?.roles?.map((role) => role.key) || [];
|
||||
const isSuperAdmin = userRoles.includes("super_admin");
|
||||
|
||||
// Standalone full-page scroll container for the auth screen — the host
|
||||
// chrome is `overflow: hidden`, so this subtree must scroll itself.
|
||||
if (isAuthPage) {
|
||||
return (
|
||||
<div className="h-dvh w-full overflow-y-auto bg-gray-50">
|
||||
<Outlet />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Full-height sidebar owning the left column (back-to-home + brand at the
|
||||
top). <Top> lives inside <SidebarInset>, to the right of the sidebar,
|
||||
and is `sticky` — so it never overlaps the sidebar and re-flows when
|
||||
the sidebar collapses to its icon rail. Top's burger (onToggleSidebar)
|
||||
drives collapse on desktop and the Sheet drawer on mobile. */}
|
||||
<Sidebar collapsible="icon">
|
||||
<SidebarHeader className="gap-1 border-b border-sidebar-border">
|
||||
<Link
|
||||
to="/dashboard/overview"
|
||||
className="flex items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
|
||||
>
|
||||
<ArrowLeft className="size-4 shrink-0" />
|
||||
<span className="group-data-[collapsible=icon]:hidden">
|
||||
Back to home
|
||||
</span>
|
||||
</Link>
|
||||
<Link
|
||||
to="/user-management"
|
||||
className="flex items-center gap-2 px-1 py-2.5"
|
||||
>
|
||||
<img
|
||||
src="/assets/logo.svg"
|
||||
alt="EDR"
|
||||
className="size-7 shrink-0 object-contain"
|
||||
/>
|
||||
<div className="flex flex-col group-data-[collapsible=icon]:hidden">
|
||||
<span className="text-sm font-semibold leading-tight text-sidebar-foreground">
|
||||
User Management
|
||||
</span>
|
||||
<span className="text-[10px] font-medium text-muted-foreground">
|
||||
EDR Freight
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
</SidebarHeader>
|
||||
<SidebarContent className="pb-10">
|
||||
<AppMenuTabs />
|
||||
</SidebarContent>
|
||||
<SidebarRail />
|
||||
</Sidebar>
|
||||
|
||||
{/* Internal scroll container: the sidebar stays fixed and full-height
|
||||
while this column scrolls beneath the sticky <Top> bar. */}
|
||||
<SidebarInset className="h-svh min-w-0 overflow-y-auto">
|
||||
<Top
|
||||
onToggleSidebar={toggleSidebar}
|
||||
showRecordManagementShortcut={!isSuperAdmin}
|
||||
/>
|
||||
<div className="flex-1 pb-2 sm:px-4 sm:pb-4 ">
|
||||
<div className="w-full overflow-x-auto">
|
||||
<Outlet />
|
||||
</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -210,7 +210,7 @@ export default function PositionManagement() {
|
||||
|
||||
return (
|
||||
<div className="p-6 space-y-6">
|
||||
<Card className="col-span-2 shadow-none border-none bg-transparent px-0">
|
||||
<Card className="py-0 col-span-2 shadow-none border-none bg-transparent px-0">
|
||||
<CardHeader className="flex flex-row justify-between items-center px-0">
|
||||
<CardTitle className="text-xl font-semibold ">
|
||||
{t("contentManagement.permissionType")}
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import PositionManagement from "@/user-management/components/position-management/PositionLists";
|
||||
import { t } from "i18next";
|
||||
|
||||
const PositionManagementPage = () => {
|
||||
return (
|
||||
<div className="p-6">
|
||||
<h2 className="text-2xl font-bold mb-4">{t("contentManagement.permissionManagement")}</h2>
|
||||
<PositionManagement />
|
||||
</div>
|
||||
);
|
||||
return <PositionManagement />;
|
||||
};
|
||||
|
||||
export default PositionManagementPage;
|
||||
|
||||
Reference in New Issue
Block a user