260220:1600 20260220 TASK-BEFE-001 Refactor by ADR-014 #3
All checks were successful
Build and Deploy / deploy (push) Successful in 1m35s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m35s
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
"use client";
|
||||
'use client';
|
||||
|
||||
import { UserMenu } from "./user-menu";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { GlobalSearch } from "./global-search";
|
||||
import { NotificationsDropdown } from "./notifications-dropdown";
|
||||
import { UserMenu } from './user-menu';
|
||||
import { GlobalSearch } from './global-search';
|
||||
import { NotificationsDropdown } from './notifications-dropdown';
|
||||
import { MobileSidebar } from './sidebar';
|
||||
|
||||
export function Header() {
|
||||
return (
|
||||
<header className="h-16 border-b bg-white flex items-center justify-between px-6 sticky top-0 z-10">
|
||||
<div className="flex items-center gap-4 flex-1">
|
||||
<h2 className="text-lg font-semibold text-gray-800">LCBP3-DMS</h2>
|
||||
<div className="ml-4 w-full max-w-md">
|
||||
<MobileSidebar />
|
||||
<h2 className="text-lg font-semibold text-gray-800 hidden md:block">LCBP3-DMS</h2>
|
||||
<div className="ml-0 md:ml-4 w-full max-w-md">
|
||||
<GlobalSearch />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
'use client';
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { cn } from '@/lib/utils';
|
||||
import {
|
||||
LayoutDashboard,
|
||||
FileText,
|
||||
@@ -14,10 +14,79 @@ import {
|
||||
Menu,
|
||||
Layers,
|
||||
BookOpen,
|
||||
} from "lucide-react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import { Can } from "@/components/common/can";
|
||||
} from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { useState } from 'react';
|
||||
import { Can } from '@/components/common/can';
|
||||
|
||||
export const mainNavItems = [
|
||||
{
|
||||
title: 'Dashboard',
|
||||
href: '/dashboard',
|
||||
icon: LayoutDashboard,
|
||||
permission: null, // Everyone can see
|
||||
},
|
||||
{
|
||||
title: 'Correspondences',
|
||||
href: '/correspondences',
|
||||
icon: FileText,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: 'RFAs',
|
||||
href: '/rfas',
|
||||
icon: FileCheck,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: 'Drawings',
|
||||
href: '/drawings',
|
||||
icon: PenTool,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: 'Circulations',
|
||||
href: '/circulation',
|
||||
icon: Layers, // Start with generic icon, maybe update import if needed
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: 'Transmittals',
|
||||
href: '/transmittals',
|
||||
icon: FileText,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: 'Search',
|
||||
href: '/search',
|
||||
icon: Search,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: 'Admin Panel',
|
||||
href: '/admin',
|
||||
icon: Shield,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: 'Security',
|
||||
href: '/admin/access-control/roles',
|
||||
icon: Shield,
|
||||
permission: 'system.manage_security',
|
||||
},
|
||||
{
|
||||
title: 'System Logs',
|
||||
href: '/admin/monitoring/system-logs/numbering',
|
||||
icon: Layers,
|
||||
permission: 'system.view_logs',
|
||||
},
|
||||
{
|
||||
title: 'Reference Data',
|
||||
href: '/admin/doc-control/reference',
|
||||
icon: BookOpen,
|
||||
permission: 'master_data.view',
|
||||
},
|
||||
];
|
||||
|
||||
interface SidebarProps {
|
||||
className?: string;
|
||||
@@ -27,94 +96,21 @@ export function Sidebar({ className }: SidebarProps) {
|
||||
const pathname = usePathname();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
title: "Dashboard",
|
||||
href: "/dashboard",
|
||||
icon: LayoutDashboard,
|
||||
permission: null, // Everyone can see
|
||||
},
|
||||
{
|
||||
title: "Correspondences",
|
||||
href: "/correspondences",
|
||||
icon: FileText,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: "RFAs",
|
||||
href: "/rfas",
|
||||
icon: FileCheck,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: "Drawings",
|
||||
href: "/drawings",
|
||||
icon: PenTool,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: "Circulations",
|
||||
href: "/circulation",
|
||||
icon: Layers, // Start with generic icon, maybe update import if needed
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: "Transmittals",
|
||||
href: "/transmittals",
|
||||
icon: FileText,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: "Search",
|
||||
href: "/search",
|
||||
icon: Search,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: "Admin Panel",
|
||||
href: "/admin",
|
||||
icon: Shield,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
title: "Security",
|
||||
href: "/admin/security/roles",
|
||||
icon: Shield,
|
||||
permission: "system.manage_security",
|
||||
},
|
||||
{
|
||||
title: "System Logs",
|
||||
href: "/admin/system-logs/numbering",
|
||||
icon: Layers,
|
||||
permission: "system.view_logs",
|
||||
},
|
||||
{
|
||||
title: "Reference Data",
|
||||
href: "/admin/reference",
|
||||
icon: BookOpen,
|
||||
permission: "master_data.view",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex flex-col h-screen border-r bg-card transition-all duration-300",
|
||||
collapsed ? "w-16" : "w-64",
|
||||
'hidden md:flex flex-col h-screen border-r bg-card transition-all duration-300',
|
||||
collapsed ? 'w-16' : 'w-64',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="h-16 flex items-center justify-between px-4 border-b">
|
||||
{!collapsed && (
|
||||
<span className="text-lg font-bold text-primary truncate">
|
||||
LCBP3 DMS
|
||||
</span>
|
||||
)}
|
||||
{!collapsed && <span className="text-lg font-bold text-primary truncate">LCBP3 DMS</span>}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => setCollapsed(!collapsed)}
|
||||
className={cn("ml-auto", collapsed && "mx-auto")}
|
||||
className={cn('ml-auto', collapsed && 'mx-auto')}
|
||||
>
|
||||
<Menu className="h-5 w-5" />
|
||||
</Button>
|
||||
@@ -122,7 +118,7 @@ export function Sidebar({ className }: SidebarProps) {
|
||||
|
||||
<div className="flex-1 overflow-y-auto py-4">
|
||||
<nav className="grid gap-1 px-2">
|
||||
{navItems.map((item, index) => {
|
||||
{mainNavItems.map((item, index) => {
|
||||
const isActive = pathname.startsWith(item.href);
|
||||
|
||||
const LinkComponent = (
|
||||
@@ -130,9 +126,9 @@ export function Sidebar({ className }: SidebarProps) {
|
||||
key={index}
|
||||
href={item.href}
|
||||
className={cn(
|
||||
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
|
||||
isActive ? "bg-accent text-accent-foreground" : "text-muted-foreground",
|
||||
collapsed && "justify-center px-2"
|
||||
'flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground',
|
||||
isActive ? 'bg-accent text-accent-foreground' : 'text-muted-foreground',
|
||||
collapsed && 'justify-center px-2'
|
||||
)}
|
||||
title={collapsed ? item.title : undefined}
|
||||
>
|
||||
@@ -158,8 +154,8 @@ export function Sidebar({ className }: SidebarProps) {
|
||||
<Link
|
||||
href="/settings"
|
||||
className={cn(
|
||||
"flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
|
||||
collapsed && "justify-center px-2"
|
||||
'flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground',
|
||||
collapsed && 'justify-center px-2'
|
||||
)}
|
||||
title="Settings"
|
||||
>
|
||||
@@ -170,3 +166,70 @@ export function Sidebar({ className }: SidebarProps) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
import { Sheet, SheetContent, SheetTrigger, SheetTitle } from '@/components/ui/sheet';
|
||||
|
||||
export function MobileSidebar() {
|
||||
const pathname = usePathname();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={setOpen}>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="md:hidden">
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle navigation menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="w-64 p-0">
|
||||
<SheetTitle className="sr-only">Mobile Navigation</SheetTitle>
|
||||
<div className="h-16 flex items-center px-4 border-b">
|
||||
<span className="text-lg font-bold text-primary truncate">LCBP3 DMS</span>
|
||||
</div>
|
||||
<div className="flex-1 overflow-y-auto py-4 h-[calc(100vh-4rem)]">
|
||||
<nav className="grid gap-1 px-2">
|
||||
{mainNavItems.map((item, index) => {
|
||||
const isActive = pathname.startsWith(item.href);
|
||||
|
||||
const LinkComponent = (
|
||||
<Link
|
||||
key={index}
|
||||
href={item.href}
|
||||
onClick={() => setOpen(false)}
|
||||
className={cn(
|
||||
'flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground',
|
||||
isActive ? 'bg-accent text-accent-foreground' : 'text-muted-foreground'
|
||||
)}
|
||||
>
|
||||
<item.icon className="h-5 w-5" />
|
||||
<span>{item.title}</span>
|
||||
</Link>
|
||||
);
|
||||
|
||||
if (item.permission) {
|
||||
return (
|
||||
<Can key={index} permission={item.permission}>
|
||||
{LinkComponent}
|
||||
</Can>
|
||||
);
|
||||
}
|
||||
|
||||
return LinkComponent;
|
||||
})}
|
||||
</nav>
|
||||
|
||||
<div className="p-4 mt-auto border-t absolute bottom-0 w-full left-0 bg-background">
|
||||
<Link
|
||||
href="/settings"
|
||||
onClick={() => setOpen(false)}
|
||||
className="flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground"
|
||||
>
|
||||
<Settings className="h-5 w-5" />
|
||||
<span>Settings</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user