diff --git a/src/app/api/scheduling/index.ts b/src/app/api/scheduling/index.ts index 4171c56..435bb1e 100644 --- a/src/app/api/scheduling/index.ts +++ b/src/app/api/scheduling/index.ts @@ -9,6 +9,7 @@ export type ScheduleType = "all" | "rough" | "detailed" | "manual"; export interface RoughProdScheduleResult { id: number; scheduleAt: number[]; + produceAt: number[]; schedulePeriod: number[]; schedulePeriodTo: number[]; totalEstProdCount: number; @@ -80,6 +81,7 @@ export interface RoughProdScheduleLineResultByBomByDate { // Detailed export interface DetailedProdScheduleResult { id: number; + produceAt: number[]; scheduleAt: number[]; totalEstProdCount: number; totalFGType: number; diff --git a/src/authorities.ts b/src/authorities.ts new file mode 100644 index 0000000..46e56b7 --- /dev/null +++ b/src/authorities.ts @@ -0,0 +1,7 @@ +export const [VIEW_USER, VIEW_DO, MAINTAIN_USER, VIEW_GROUP, MAINTAIN_GROUP] = [ + "VIEW_USER", + "VIEW_DO", + "MAINTAIN_USER", + "VIEW_GROUP", + "MAINTAIN_GROUP", +]; diff --git a/src/authorties.ts b/src/authorties.ts deleted file mode 100644 index 0950252..0000000 --- a/src/authorties.ts +++ /dev/null @@ -1,6 +0,0 @@ -export const [VIEW_USER, MAINTAIN_USER, VIEW_GROUP, MAINTAIN_GROUP] = [ - "VIEW_USER", - "MAINTAIN_USER", - "VIEW_GROUP", - "MAINTAIN_GROUP", -]; diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx index a614269..17d178a 100644 --- a/src/components/NavigationContent/NavigationContent.tsx +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -1,3 +1,4 @@ +import { useSession } from "next-auth/react"; import Divider from "@mui/material/Divider"; import Box from "@mui/material/Box"; import React, { useEffect } from "react"; @@ -24,6 +25,15 @@ import { usePathname } from "next/navigation"; import Link from "next/link"; import { NAVIGATION_CONTENT_WIDTH } from "@/config/uiConfig"; import Logo from "../Logo"; +import { + VIEW_USER, + VIEW_DO, + MAINTAIN_USER, + VIEW_GROUP, + MAINTAIN_GROUP, + // Add more authorities as needed, e.g.: + // VIEW_PO, MAINTAIN_PO, VIEW_INVENTORY, etc. +} from "../../authorities"; interface NavigationItem { icon: React.ReactNode; @@ -31,9 +41,22 @@ interface NavigationItem { path: string; children?: NavigationItem[]; isHidden?: true | undefined; + requiredAbility?: string | string[]; } const NavigationContent: React.FC = () => { + const { data: session, status } = useSession(); + const abilities = session?.user?.abilities ?? []; + + // Helper: check if user has required permission + const hasAbility = (required?: string | string[]): boolean => { + if (!required) return true; // no requirement → always show + if (Array.isArray(required)) { + return required.some(ability => abilities.includes(ability)); + } + return abilities.includes(required); + }; + const navigationItems: NavigationItem[] = [ { icon: , @@ -108,49 +131,12 @@ const NavigationContent: React.FC = () => { }, ], }, - // { - // icon: , - // label: "Production", - // path: "", - // children: [ - // { - // icon: , - // label: "Job Order", - // path: "", - // }, - // { - // icon: , - // label: "Job Order Traceablity ", - // path: "", - // }, - // { - // icon: , - // label: "Work Order", - // path: "", - // }, - // { - // icon: , - // label: "Work Order Traceablity ", - // path: "", - // }, - // ], - // }, - // { - // icon: , - // label: "Quality Control Log", - // path: "", - // children: [ - // { - // icon: , - // label: "Quality Control Log", - // path: "", - // }, - // ], - // }, { icon: , label: "Delivery", path: "", + //requiredAbility: VIEW_DO, + requiredAbility: VIEW_USER, children: [ { icon: , @@ -248,16 +234,19 @@ const NavigationContent: React.FC = () => { icon: , label: "Settings", path: "", + requiredAbility: [VIEW_USER, VIEW_GROUP], children: [ { icon: , label: "User", path: "/settings/user", + requiredAbility: VIEW_USER, }, { icon: , label: "User Group", path: "/settings/user", + requiredAbility: VIEW_GROUP, }, // { // icon: , @@ -360,7 +349,12 @@ const NavigationContent: React.FC = () => { }; const renderNavigationItem = (item: NavigationItem) => { + if (!hasAbility(item.requiredAbility)) { + return null; + } + const isOpen = openItems.includes(item.label); + const hasVisibleChildren = item.children?.some(child => hasAbility(child.requiredAbility)); return ( { {item.icon} - {item.children && isOpen && ( + {item.children && isOpen && hasVisibleChildren && ( {item.children.map( (child) => !child.isHidden && renderNavigationItem(child), @@ -387,6 +381,10 @@ const NavigationContent: React.FC = () => { ); }; + if (status === "loading") { + return Loading...; + } + return ( @@ -397,7 +395,9 @@ const NavigationContent: React.FC = () => { - {navigationItems.map((item) => renderNavigationItem(item))} + {navigationItems + .map(renderNavigationItem) + .filter(Boolean)} {/* {navigationItems.map(({ icon, label, path }, index) => { return (