Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 

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