Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 

477 righe
16 KiB

  1. import Divider from "@mui/material/Divider";
  2. import Box from "@mui/material/Box";
  3. import React from "react";
  4. import List from "@mui/material/List";
  5. import ListItemButton from "@mui/material/ListItemButton";
  6. import ListItemText from "@mui/material/ListItemText";
  7. import ListItemIcon from "@mui/material/ListItemIcon";
  8. import WorkHistory from "@mui/icons-material/WorkHistory";
  9. import Dashboard from "@mui/icons-material/Dashboard";
  10. import SummarizeIcon from "@mui/icons-material/Summarize";
  11. import PaymentsIcon from "@mui/icons-material/Payments";
  12. import AccountTreeIcon from "@mui/icons-material/AccountTree";
  13. import RequestQuote from "@mui/icons-material/RequestQuote";
  14. import PeopleIcon from "@mui/icons-material/People";
  15. import Task from "@mui/icons-material/Task";
  16. import Assignment from "@mui/icons-material/Assignment";
  17. import Settings from "@mui/icons-material/Settings";
  18. import Analytics from "@mui/icons-material/Analytics";
  19. import Payments from "@mui/icons-material/Payments";
  20. import Staff from "@mui/icons-material/PeopleAlt";
  21. import Company from "@mui/icons-material/Store";
  22. import Department from "@mui/icons-material/Diversity3";
  23. import Position from "@mui/icons-material/Paragliding";
  24. import Salary from "@mui/icons-material/AttachMoney";
  25. import Team from "@mui/icons-material/Paragliding";
  26. import Holiday from "@mui/icons-material/CalendarMonth";
  27. import { useTranslation } from "react-i18next";
  28. import { usePathname } from "next/navigation";
  29. import Link from "next/link";
  30. import { NAVIGATION_CONTENT_WIDTH } from "@/config/uiConfig";
  31. import Logo from "../Logo";
  32. import GroupIcon from "@mui/icons-material/Group";
  33. import BusinessIcon from "@mui/icons-material/Business";
  34. import ViewWeekIcon from "@mui/icons-material/ViewWeek";
  35. import ManageAccountsIcon from "@mui/icons-material/ManageAccounts";
  36. import EmojiEventsIcon from "@mui/icons-material/EmojiEvents";
  37. import FileUploadIcon from '@mui/icons-material/FileUpload';
  38. import {
  39. IMPORT_INVOICE,
  40. IMPORT_RECEIPT,
  41. MAINTAIN_PROJECT,
  42. MAINTAIN_TASK_TEMPLATE,
  43. MAINTAIN_USER,
  44. VIEW_DASHBOARD_ALL,
  45. VIEW_DASHBOARD_SELF,
  46. VIEW_PROJECT,
  47. VIEW_CLIENT,
  48. VIEW_SUBSIDIARY,
  49. VIEW_STAFF,
  50. VIEW_COMPANY,
  51. VIEW_SKILL,
  52. VIEW_DEPARTMENT,
  53. VIEW_POSITION,
  54. VIEW_SALARY,
  55. VIEW_TEAM,
  56. VIEW_GROUP,
  57. VIEW_HOLIDAY,
  58. MAINTAIN_CLIENT,
  59. MAINTAIN_SUBSIDIARY,
  60. MAINTAIN_STAFF,
  61. MAINTAIN_COMPANY,
  62. MAINTAIN_SKILL,
  63. MAINTAIN_DEPARTMENT,
  64. MAINTAIN_POSITION,
  65. MAINTAIN_SALARY,
  66. MAINTAIN_TEAM,
  67. MAINTAIN_GROUP,
  68. MAINTAIN_HOLIDAY,
  69. VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING,
  70. GENERATE_LATE_START_REPORT,
  71. GENERATE_PROJECT_POTENTIAL_DELAY_REPORT,
  72. GENERATE_RESOURCE_OVERCONSUMPTION_REPORT,
  73. GENERATE_COST_ANT_EXPENSE_REPORT,
  74. GENERATE_PROJECT_COMPLETION_REPORT,
  75. GENERATE_PROJECT_PANDL_REPORT,
  76. GENERATE_FINANCIAL_STATUS_REPORT,
  77. GENERATE_PROJECT_CASH_FLOW_REPORT,
  78. GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT,
  79. GENERATE_CROSS_TEAM_CHARGE_REPORT
  80. } from "@/middleware";
  81. import { SessionWithAbilities } from "../AppBar/NavigationToggle";
  82. import { authOptions } from "@/config/authConfig";
  83. import { getServerSession } from "next-auth";
  84. import useIsMobile from "@/app/utils/useIsMobile";
  85. interface NavigationItem {
  86. icon: React.ReactNode;
  87. label: string;
  88. path: string;
  89. isHidden?: boolean;
  90. showOnMobile?: boolean;
  91. children?: NavigationItem[];
  92. }
  93. interface Props {
  94. abilities?: string[];
  95. username?: string;
  96. }
  97. const NavigationContent: React.FC<Props> = ({ abilities, username }) => {
  98. const navigationItems: NavigationItem[] = [
  99. {
  100. icon: <WorkHistory />,
  101. label: "User Workspace",
  102. path: "/home",
  103. showOnMobile: true,
  104. },
  105. {
  106. icon: <Dashboard />,
  107. label: "Dashboard",
  108. path: "",
  109. isHidden: ![VIEW_DASHBOARD_ALL, VIEW_DASHBOARD_SELF].some((ability) =>
  110. abilities!.includes(ability),
  111. ),
  112. children: [
  113. {
  114. icon: <SummarizeIcon />,
  115. label: "Financial Summary",
  116. path: "/dashboard/ProjectFinancialSummary",
  117. },
  118. {
  119. icon: <PaymentsIcon />,
  120. label: "Company / Team Cash Flow",
  121. path: "/dashboard/CompanyTeamCashFlow",
  122. },
  123. {
  124. icon: <PaymentsIcon />,
  125. label: "Project Cash Flow",
  126. path: "/dashboard/ProjectCashFlow",
  127. },
  128. {
  129. icon: <AccountTreeIcon />,
  130. label: "Project Status by Client",
  131. path: "/dashboard/ProjectStatusByClient",
  132. },
  133. {
  134. icon: <AccountTreeIcon />,
  135. label: "Project Status by Team",
  136. path: "/dashboard/ProjectStatusByTeam",
  137. },
  138. {
  139. icon: <AccountTreeIcon />,
  140. label: "Project Resource Consumption Ranking",
  141. path: "/dashboard/ProjectResourceConsumptionRanking",
  142. isHidden: ![VIEW_PROJECT_RESOURCE_CONSUMPTION_RANKING].some((ability) =>
  143. abilities!.includes(ability),
  144. )
  145. },
  146. {
  147. icon: <PeopleIcon />,
  148. label: "Staff Utilization",
  149. path: "/dashboard/StaffUtilization",
  150. },
  151. {
  152. icon: <ViewWeekIcon />,
  153. label: "Project Resource Summary",
  154. path: "/dashboard/ProjectResourceSummary",
  155. },
  156. ],
  157. },
  158. // No Claim function in Breaur, will be implement later
  159. // {
  160. // icon: <RequestQuote />,
  161. // label: "Staff Reimbursement",
  162. // path: "/staffReimbursement",
  163. // children: [
  164. // {
  165. // icon: <RequestQuote />,
  166. // label: "Claim Approval",
  167. // path: "/staffReimbursement/ClaimApproval",
  168. // },
  169. // {
  170. // icon: <RequestQuote />,
  171. // label: "Claim Summary",
  172. // path: "/staffReimbursement/ClaimSummary",
  173. // },
  174. // ],
  175. // },
  176. { icon: <Assignment />, label: "Project Management", path: "/projects", isHidden: ![MAINTAIN_PROJECT].some((ability) => abilities?.includes(ability)) },
  177. { icon: <Task />, label: "Task Template", path: "/tasks", isHidden: ![MAINTAIN_TASK_TEMPLATE].some((ability) => abilities?.includes(ability)) },
  178. {
  179. icon: <Payments />,
  180. label: "Invoice",
  181. path: "/invoice",
  182. isHidden: ![IMPORT_INVOICE, IMPORT_RECEIPT].some((ability) =>
  183. abilities!.includes(ability),
  184. ),
  185. },
  186. {
  187. icon: <Analytics />,
  188. label: "Analysis Report",
  189. path: "",
  190. isHidden: ![
  191. GENERATE_LATE_START_REPORT,
  192. GENERATE_PROJECT_POTENTIAL_DELAY_REPORT,
  193. GENERATE_RESOURCE_OVERCONSUMPTION_REPORT,
  194. GENERATE_COST_ANT_EXPENSE_REPORT,
  195. GENERATE_PROJECT_COMPLETION_REPORT,
  196. GENERATE_PROJECT_PANDL_REPORT,
  197. GENERATE_FINANCIAL_STATUS_REPORT,
  198. GENERATE_PROJECT_CASH_FLOW_REPORT,
  199. GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT,
  200. GENERATE_CROSS_TEAM_CHARGE_REPORT
  201. ].some((ability) =>
  202. abilities!.includes(ability),
  203. ),
  204. children: [
  205. {
  206. icon: <Analytics />,
  207. label: "Late Start Report",
  208. path: "/analytics/LateStartReport",
  209. isHidden: ![GENERATE_LATE_START_REPORT].some((ability) =>
  210. abilities!.includes(ability),
  211. ),
  212. },
  213. {
  214. icon: <Analytics />,
  215. label: "Project Potential Delay Report",
  216. path: "/analytics/ProjectPotentialDelayReport",
  217. isHidden: ![GENERATE_PROJECT_POTENTIAL_DELAY_REPORT].some((ability) =>
  218. abilities!.includes(ability),
  219. ),
  220. },
  221. {
  222. icon: <Analytics />,
  223. label: "Resource Overconsumption Report",
  224. path: "/analytics/ResourceOverconsumptionReport",
  225. isHidden: ![GENERATE_RESOURCE_OVERCONSUMPTION_REPORT].some((ability) =>
  226. abilities!.includes(ability),
  227. ),
  228. },
  229. {
  230. icon: <Analytics />,
  231. label: "Cost and Expense Report",
  232. path: "/analytics/CostandExpenseReport",
  233. isHidden: ![GENERATE_COST_ANT_EXPENSE_REPORT].some((ability) =>
  234. abilities!.includes(ability),
  235. ),
  236. },
  237. {
  238. icon: <Analytics />,
  239. label: "Project Completion Report",
  240. path: "/analytics/ProjectCompletionReport",
  241. isHidden: ![GENERATE_PROJECT_COMPLETION_REPORT].some((ability) =>
  242. abilities!.includes(ability),
  243. ),
  244. },
  245. // {
  246. // icon: <Analytics />,
  247. // label: "Completion Report with Outstanding Un-billed Hours Report",
  248. // path: "/analytics/ProjectCompletionReportWO",
  249. // },
  250. // {
  251. // icon: <Analytics />,
  252. // label: "Project Claims Report",
  253. // path: "/analytics/ProjectClaimsReport",
  254. // },
  255. {
  256. icon: <Analytics />,
  257. label: "Project P&L Report",
  258. path: "/analytics/ProjectPandLReport",
  259. isHidden: ![GENERATE_PROJECT_COMPLETION_REPORT].some((ability) =>
  260. abilities!.includes(ability),
  261. ),
  262. },
  263. {
  264. icon: <Analytics />,
  265. label: "Financial Status Report",
  266. path: "/analytics/FinancialStatusReport",
  267. isHidden: ![GENERATE_FINANCIAL_STATUS_REPORT].some((ability) =>
  268. abilities!.includes(ability),
  269. ),
  270. },
  271. {
  272. icon: <Analytics />,
  273. label: "Project Cash Flow Report",
  274. path: "/analytics/ProjectCashFlowReport",
  275. isHidden: ![GENERATE_PROJECT_CASH_FLOW_REPORT].some((ability) =>
  276. abilities!.includes(ability),
  277. ),
  278. },
  279. {
  280. icon: <Analytics />,
  281. label: "Staff Monthly Work Hours Analysis Report",
  282. path: "/analytics/StaffMonthlyWorkHoursAnalysisReport",
  283. isHidden: ![GENERATE_STAFF_MONTHLY_WORK_HOURS_ANALYSIS_REPORT].some((ability) =>
  284. abilities!.includes(ability),
  285. ),
  286. },
  287. {
  288. icon: <Analytics />,
  289. label: "Cross Team Charge Report",
  290. path: "/analytics/CrossTeamChargeReport",
  291. isHidden: ![GENERATE_CROSS_TEAM_CHARGE_REPORT].some((ability) =>
  292. abilities!.includes(ability),
  293. ),
  294. },
  295. ],
  296. },
  297. {
  298. icon: <Settings />,
  299. label: "Setting",
  300. path: "",
  301. isHidden: ![
  302. VIEW_CLIENT,
  303. VIEW_SUBSIDIARY,
  304. VIEW_STAFF,
  305. VIEW_COMPANY,
  306. VIEW_SKILL,
  307. VIEW_DEPARTMENT,
  308. VIEW_POSITION,
  309. VIEW_SALARY,
  310. VIEW_TEAM,
  311. VIEW_GROUP,
  312. VIEW_HOLIDAY,
  313. MAINTAIN_CLIENT,
  314. MAINTAIN_SUBSIDIARY,
  315. MAINTAIN_STAFF,
  316. MAINTAIN_COMPANY,
  317. MAINTAIN_SKILL,
  318. MAINTAIN_DEPARTMENT,
  319. MAINTAIN_POSITION,
  320. MAINTAIN_SALARY,
  321. MAINTAIN_TEAM,
  322. MAINTAIN_GROUP,
  323. MAINTAIN_HOLIDAY
  324. ].some((ability) =>
  325. abilities!.includes(ability),
  326. ),
  327. children: [
  328. {
  329. icon: <GroupIcon />,
  330. label: "Client",
  331. path: "/settings/customer",
  332. isHidden: ![VIEW_CLIENT, MAINTAIN_CLIENT].some((ability) => abilities!.includes(ability),),
  333. },
  334. {
  335. icon: <BusinessIcon />,
  336. label: "Subsidiary",
  337. path: "/settings/subsidiary",
  338. isHidden: ![VIEW_SUBSIDIARY, MAINTAIN_SUBSIDIARY].some((ability) => abilities!.includes(ability),),
  339. },
  340. {
  341. icon: <Staff />,
  342. label: "Staff",
  343. path: "/settings/staff",
  344. isHidden: ![VIEW_STAFF, MAINTAIN_STAFF].some((ability) => abilities!.includes(ability),),
  345. },
  346. {
  347. icon: <Company />,
  348. label: "Company",
  349. path: "/settings/company",
  350. isHidden: ![VIEW_COMPANY, MAINTAIN_COMPANY].some((ability) => abilities!.includes(ability),),
  351. },
  352. {
  353. icon: <EmojiEventsIcon />,
  354. label: "Skill",
  355. path: "/settings/skill",
  356. isHidden: ![VIEW_SKILL, MAINTAIN_SKILL].some((ability) => abilities!.includes(ability),),
  357. },
  358. {
  359. icon: <Department />,
  360. label: "Department",
  361. path: "/settings/department",
  362. isHidden: ![VIEW_DEPARTMENT, MAINTAIN_DEPARTMENT].some((ability) => abilities!.includes(ability),),
  363. },
  364. {
  365. icon: <Position />,
  366. label: "Position",
  367. path: "/settings/position",
  368. isHidden: ![VIEW_POSITION, MAINTAIN_POSITION].some((ability) => abilities!.includes(ability),),
  369. },
  370. {
  371. icon: <Salary />,
  372. label: "Salary",
  373. path: "/settings/salary",
  374. isHidden: ![VIEW_SALARY, MAINTAIN_SALARY].some((ability) => abilities!.includes(ability),),
  375. },
  376. {
  377. icon: <Team />,
  378. label: "Team",
  379. path: "/settings/team",
  380. isHidden: ![VIEW_TEAM, MAINTAIN_TEAM].some((ability) => abilities!.includes(ability),),
  381. },
  382. // { icon: <ManageAccountsIcon />, label: "User", path: "/settings/user" },
  383. {
  384. icon: <ManageAccountsIcon />,
  385. label: "User Group",
  386. path: "/settings/group",
  387. isHidden: ![VIEW_GROUP, MAINTAIN_GROUP].some((ability) => abilities!.includes(ability),),
  388. },
  389. {
  390. icon: <Holiday />,
  391. label: "Holiday",
  392. path: "/settings/holiday",
  393. isHidden: ![VIEW_HOLIDAY, MAINTAIN_HOLIDAY].some((ability) => abilities!.includes(ability),),
  394. },
  395. { icon: <FileUploadIcon />, label: "Import Excel File", path: "/settings/import", isHidden: username !== "2fi" },
  396. ],
  397. },
  398. ];
  399. const isMobile = useIsMobile();
  400. const { t } = useTranslation("common");
  401. const pathname = usePathname();
  402. const [openItems, setOpenItems] = React.useState<string[]>([]);
  403. const toggleItem = (label: string) => {
  404. setOpenItems((prevOpenItems) =>
  405. prevOpenItems.includes(label)
  406. ? prevOpenItems.filter((item) => item !== label)
  407. : [...prevOpenItems, label],
  408. );
  409. };
  410. const renderNavigationItem = (item: NavigationItem) => {
  411. const isOpen = openItems.includes(item.label);
  412. return (
  413. <Box
  414. key={`${item.label}-${item.path}`}
  415. component={Link}
  416. href={item.path}
  417. sx={{ textDecoration: "none", color: "inherit" }}
  418. >
  419. <ListItemButton
  420. selected={pathname.includes(item.label)}
  421. onClick={() => item.children && toggleItem(item.label)}
  422. >
  423. <ListItemIcon>{item.icon}</ListItemIcon>
  424. <ListItemText primary={t(item.label)} />
  425. </ListItemButton>
  426. {item.children && isOpen && (
  427. <List sx={{ pl: 2 }}>
  428. {item.children.map((child) => (!child.isHidden && renderNavigationItem(child)))}
  429. </List>
  430. )}
  431. </Box>
  432. );
  433. };
  434. return (
  435. <Box sx={{ width: NAVIGATION_CONTENT_WIDTH }}>
  436. <Box sx={{ p: 3, display: "flex" }}>
  437. <Logo height={60} />
  438. {/* <button className="float-right bg-transparent border-transparent" >
  439. <ArrowCircleLeftRoundedIcon className="text-slate-400 hover:text-blue-400 hover:cursor-pointer " style={{ fontSize: '35px' }} />
  440. </button> */}
  441. </Box>
  442. <Divider />
  443. <List component="nav">
  444. {navigationItems
  445. .filter(
  446. (item) => !item.isHidden && (isMobile ? item.showOnMobile : true),
  447. )
  448. .map((item) => renderNavigationItem(item))}
  449. {/* {navigationItems.map(({ icon, label, path }, index) => {
  450. return (
  451. <Box
  452. key={`${label}-${index}`}
  453. component={Link}
  454. href={path}
  455. sx={{ textDecoration: "none", color: "inherit" }}
  456. >
  457. <ListItemButton selected={pathname.includes(path)}>
  458. <ListItemIcon>{icon}</ListItemIcon>
  459. <ListItemText primary={t(label)} />
  460. </ListItemButton>
  461. </Box>
  462. );
  463. })} */}
  464. </List>
  465. </Box>
  466. );
  467. };
  468. export default NavigationContent;