選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

2107 行
83 KiB

  1. "use client";
  2. import * as React from "react";
  3. import Grid from "@mui/material/Grid";
  4. import { useState, useEffect, useMemo } from "react";
  5. import Paper from "@mui/material/Paper";
  6. import { TFunction } from "i18next";
  7. import { useTranslation } from "react-i18next";
  8. import { Card, CardHeader } from "@mui/material";
  9. import CustomSearchForm from "../CustomSearchForm/CustomSearchForm";
  10. import CustomDatagrid from "../CustomDatagrid/CustomDatagrid";
  11. import ReactApexChart from "react-apexcharts";
  12. import { ApexOptions } from "apexcharts";
  13. import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
  14. import ReportProblemIcon from "@mui/icons-material/ReportProblem";
  15. import dynamic from "next/dynamic";
  16. import "../../app/global.css";
  17. import { AnyARecord, AnyCnameRecord } from "dns";
  18. import SearchBox, { Criterion } from "../SearchBox";
  19. import ProgressByClientSearch from "@/components/ProgressByClientSearch";
  20. import { Suspense } from "react";
  21. import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch";
  22. import { Input, Label } from "reactstrap";
  23. import Select, { components } from "react-select";
  24. import { DateCalendar } from "@mui/x-date-pickers/DateCalendar";
  25. import { DatePicker } from "@mui/x-date-pickers/DatePicker";
  26. import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
  27. import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
  28. import dayjs, { Dayjs } from "dayjs";
  29. import isBetweenPlugin from "dayjs/plugin/isBetween";
  30. import { PickersDay, PickersDayProps } from "@mui/x-date-pickers/PickersDay";
  31. import { styled } from "@mui/material/styles";
  32. import Holidays from "date-holidays";
  33. import moment from "moment";
  34. import { fetchTeamCombo, fetchweeklyTeamTotalManhours, fetchmonthlyTeamTotalManhours, fetchTotalManhoursByGrade, fetchWeeklyUnsubmit, fetchMonthlyUnsubmit, fetchStaffCombo, fetchDailyIndividualStaffManhours, fetchWeeklyIndividualStaffManhours, fetchMonthlyIndividualStaffManhours } from "@/app/api/staffUtilization";
  35. import { SessionStaff } from "@/config/authConfig";
  36. import { VIEW_DASHBOARD_ALL } from "@/middleware";
  37. import { QrCode } from "@mui/icons-material";
  38. dayjs.extend(isBetweenPlugin);
  39. interface CustomPickerDayProps extends PickersDayProps<Dayjs> {
  40. isSelected: boolean;
  41. isHovered: boolean;
  42. }
  43. const CustomPickersDay = styled(PickersDay, {
  44. shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isHovered",
  45. })<CustomPickerDayProps>(({ theme, isSelected, isHovered, day }) => ({
  46. borderRadius: 0,
  47. ...(isSelected && {
  48. backgroundColor: theme.palette.primary.main,
  49. color: theme.palette.primary.contrastText,
  50. "&:hover, &:focus": {
  51. backgroundColor: theme.palette.primary.main,
  52. },
  53. }),
  54. ...(isHovered && {
  55. backgroundColor: theme.palette.primary[theme.palette.mode],
  56. "&:hover, &:focus": {
  57. backgroundColor: theme.palette.primary[theme.palette.mode],
  58. },
  59. }),
  60. ...(day.day() === 0 && {
  61. borderTopLeftRadius: "50%",
  62. borderBottomLeftRadius: "50%",
  63. }),
  64. ...(day.day() === 6 && {
  65. borderTopRightRadius: "50%",
  66. borderBottomRightRadius: "50%",
  67. }),
  68. })) as React.ComponentType<CustomPickerDayProps>;
  69. const isInSameWeek = (dayA: Dayjs, dayB: Dayjs | null | undefined) => {
  70. if (dayB == null) {
  71. return false;
  72. }
  73. return dayA.isSame(dayB, "week");
  74. };
  75. function Day(
  76. props: PickersDayProps<Dayjs> & {
  77. selectedDay?: Dayjs | null;
  78. hoveredDay?: Dayjs | null;
  79. },
  80. ) {
  81. const { day, selectedDay, hoveredDay, ...other } = props;
  82. return (
  83. <CustomPickersDay
  84. {...other}
  85. day={day}
  86. sx={{ px: 2.5 }}
  87. disableMargin
  88. selected={false}
  89. isSelected={isInSameWeek(day, selectedDay)}
  90. isHovered={isInSameWeek(day, hoveredDay)}
  91. />
  92. );
  93. }
  94. interface Props {
  95. abilities: string[];
  96. staff: SessionStaff;
  97. }
  98. const StaffUtilization: React.FC<Props> = ({ abilities, staff }) => {
  99. const abilityViewDashboardAll = abilities.includes(VIEW_DASHBOARD_ALL)
  100. const todayDate = new Date();
  101. const firstDayOfWeek = new Date();
  102. const lastDayOfWeek = new Date();
  103. firstDayOfWeek.setDate(todayDate.getDate() - todayDate.getDay() + 0);
  104. lastDayOfWeek.setDate(todayDate.getDate() - todayDate.getDay() + 6);
  105. const firstDayOfMonth = new Date(
  106. todayDate.getFullYear(),
  107. todayDate.getMonth(),
  108. 1,
  109. );
  110. const lastDayOfMonth = new Date(
  111. todayDate.getFullYear(),
  112. todayDate.getMonth() + 1,
  113. 0,
  114. );
  115. const [firstDayOfWeekString, setFirstDayOfWeekString] = React.useState(
  116. dayjs(firstDayOfWeek).format("DD MMM YYYY"),
  117. );
  118. const [lastDayOfWeekString, setLastDayOfWeekString] = React.useState(
  119. dayjs(lastDayOfWeek).format("DD MMM YYYY"),
  120. );
  121. const [firstDayOfMonthString, setFirstDayOfMonthString] = React.useState(
  122. dayjs(firstDayOfMonth).format("DD MMM YYYY"),
  123. );
  124. const [lastDayOfMonthString, setLastDayOfMonthString] = React.useState(
  125. dayjs(lastDayOfMonth).format("DD MMM YYYY"),
  126. );
  127. const [selectionModel, setSelectionModel]: any[] = React.useState([]);
  128. const [manHoursSpentPeriod, setManHoursSpentPeriod]: any[] = React.useState(
  129. firstDayOfWeekString + " to " + lastDayOfWeekString,
  130. );
  131. const [unsubmittedTimeSheetSelect, setUnsubmittedTimeSheetSelect]: any =
  132. React.useState("Monthly");
  133. const [teamTotalManhoursSpentSelect, setTeamTotalManhoursSpentSelect]: any =
  134. React.useState("Monthly");
  135. const [staffGradeManhoursSpentSelect, setStaffGradeManhoursSpentSelect]: any =
  136. React.useState("Monthly");
  137. const [
  138. individualStaffManhoursSpentSelect,
  139. setIndividualStaffManhoursSpentSelect,
  140. ]: any = React.useState("Monthly");
  141. const weekDates: any[] = [];
  142. const monthDates: any[] = [];
  143. const currentDate = dayjs();
  144. const sixMonthsAgo = currentDate.subtract(6, "month");
  145. for (let i = 0; i < 7; i++) {
  146. const currentDate = new Date(firstDayOfWeek);
  147. currentDate.setDate(firstDayOfWeek.getDate() + i);
  148. const formattedDate = dayjs(currentDate).format("DD MMM (ddd)");
  149. weekDates.push(formattedDate);
  150. }
  151. for (
  152. let date = sixMonthsAgo.clone();
  153. date.isBefore(currentDate, "month");
  154. date = date.add(1, "month")
  155. ) {
  156. monthDates.push(date.format("MM-YYYY"));
  157. }
  158. monthDates.push(currentDate.format("MM-YYYY"));
  159. // for (let i = firstDayOfMonth.getDate(); i <= lastDayOfMonth.getDate(); i++) {
  160. // const currentDate = new Date(todayDate.getFullYear(), todayDate.getMonth(), i);
  161. // const formattedDate = dayjs(currentDate).format('DD MMM');
  162. // monthDates.push(formattedDate);
  163. // }
  164. const [teamTotalManhoursSpentPeriod, setTeamTotalManhoursSpentPeriod]: any[] =
  165. React.useState(monthDates);
  166. const [
  167. teamTotalManhoursByStaffGrade,
  168. setTeamTotalManhoursByStaffGrade,
  169. ]: any[] = React.useState(weekDates);
  170. const [
  171. individualStaffManhoursSpentPeriod,
  172. setIndividualStaffManhoursSpentPeriod,
  173. ]: any[] = React.useState(weekDates);
  174. const [
  175. unsubmittedTimeSheetPeriod,
  176. setUnsubmittedTimeSheetPeriod,
  177. ]: any[] = React.useState(weekDates);
  178. const [
  179. teamTotalManhoursSpentPlanData,
  180. setTeamTotalManhoursSpentPlanData,
  181. ]: any[] = React.useState([0, 0, 0, 0, 0, 0, 0]);
  182. const [
  183. teamTotalManhoursSpentActualData,
  184. setTeamTotalManhoursSpentActualData,
  185. ]: any[] = React.useState([0, 0, 0, 0, 0, 0, 0]);
  186. const [hoveredDay, setHoveredDay] = React.useState<Dayjs | null>(null);
  187. const [value, setValue] = React.useState<Dayjs>(dayjs().startOf('week'));
  188. const [weeklyValueByStaffGrade, setWeeklyValueByStaffGrade] =
  189. React.useState<Dayjs>(dayjs().startOf('week'));
  190. const [weeklyToValueByStaffGrade, setWeeklyToValueByStaffGrade] =
  191. React.useState<Dayjs>(dayjs().startOf('week').add(6, 'day'));
  192. const [weeklyValueByIndividualStaff, setWeeklyValueByIndividualStaff] =
  193. React.useState<Dayjs>(dayjs().startOf('week'));
  194. const [weeklyUnsubmittedTimeSheet, setWeeklyUnsubmittedTimeSheet] =
  195. React.useState<Dayjs>(dayjs().startOf('week'));
  196. const [staffGradeManhoursSpentValue, setStaffGradeManhoursSpentValue] =
  197. React.useState<Dayjs>(dayjs());
  198. const [totalManHoursMonthlyFromValue, setTotalManHoursMonthlyFromValue] =
  199. React.useState<Dayjs>(dayjs(new Date()).subtract(6, "month"));
  200. const [totalManHoursMonthlyToValue, setTotalManHoursMonthlyToValue] =
  201. React.useState<Dayjs>(dayjs());
  202. const [unsubmitMonthlyFromValue, setUnsubmitMonthlyFromValue] =
  203. React.useState<Dayjs>(dayjs(new Date()));
  204. const [unsubmitMonthlyToValue, setUnsubmitMonthlyToValue] =
  205. React.useState<Dayjs>(dayjs());
  206. const [indivdualManHoursMonthlyFromValue, setIndivdualManHoursMonthlyFromValue] =
  207. React.useState<Dayjs>(dayjs());
  208. const [indivdualManHoursMonthlyToValue, setIndivdualManHoursMonthlyToValue] =
  209. React.useState<Dayjs>(dayjs());
  210. const [
  211. totalManHoursByStaffGradeMonthlyFromValue,
  212. setTotalManHoursByStaffGradeMonthlyFromValue,
  213. ] = React.useState<Dayjs>(dayjs(new Date()).subtract(6, "month"));
  214. const [
  215. totalManHoursByStaffGradeMonthlyToValue,
  216. setTotalManHoursByStaffGradeMonthlyToValue,
  217. ] = React.useState<Dayjs>(dayjs());
  218. const [
  219. totalManHoursByIndividualStaffMonthlyFromValue,
  220. setTotalManHoursByIndividualStaffMonthlyFromValue,
  221. ] = React.useState<Dayjs>(dayjs(new Date()).subtract(6, "month"));
  222. const [
  223. totalManHoursByIndividualStaffMonthlyToValue,
  224. setTotalManHoursByIndividualStaffMonthlyToValue,
  225. ] = React.useState<Dayjs>(dayjs());
  226. const [
  227. totalManHoursByIndividualStaffDailyFromValue,
  228. setTotalManHoursByIndividualStaffDailyFromValue,
  229. ] = React.useState<Dayjs>(dayjs(new Date()));
  230. const [
  231. totalManHoursByIndividualStaffDailyToValue,
  232. setTotalManHoursByIndividualStaffDailyToValue,
  233. ] = React.useState<Dayjs>(dayjs());
  234. const hd = new Holidays('HK');
  235. const currentYear = new Date().getFullYear();
  236. const years = [currentYear - 2, currentYear - 1, currentYear, currentYear + 1, currentYear + 2];
  237. let allHolidays: any[] = [];
  238. years.forEach(year => {
  239. const holidays = hd.getHolidays(year);
  240. allHolidays = allHolidays.concat(holidays);
  241. });
  242. const holidayDates = allHolidays.map(holiday => moment(holiday.date).format('YYYY-MM-DD')).join(',');
  243. const [totalManHoursMaxValue, setTotalManHoursMaxValue] = React.useState(5);
  244. const [totalManHoursByGradeMaxValue, setTotalManHoursByGradeMaxValue] = React.useState(5);
  245. const [individualManhoursMaxValue, setIndividualManhoursMaxValue] = React.useState(12);
  246. const [unsubmittedMaxValue, setUnsubmittedMaxValue] = React.useState(5);
  247. const [totalManhourByGradeActualManhours, setTotalManhourByGradeActualManhours]: any[] = React.useState([]);
  248. const [totalManhourByGradePlannedManhours, setTotalManhourByGradePlannedManhours]: any[] = React.useState([]);
  249. const [gradeNameList, setGradeNameList]: any[] = React.useState([]);
  250. const [teamManhoursTeamOptions, setTeamManhoursTeamOptions]: any[] = React.useState([]);
  251. const [staffOptions, setStaffOptions]: any[] = React.useState([]);
  252. const [teamManhoursTeamId, setTeamManhoursTeamId]: any[] = React.useState(abilityViewDashboardAll ? 0 : staff.teamId);
  253. const [teamUnsubmitTeamId, setTeamUnsubmitTeamId]: any[] = React.useState(abilityViewDashboardAll ? 0 : staff.teamId);
  254. const [staffGradeTeamId, setStaffGradeTeamId]: any[] = React.useState(abilityViewDashboardAll ? 0 : staff.teamId);
  255. const [staffId, setStaffId]: any[] = React.useState(0);
  256. const [unsubmitCount, setUnsubmitCount]: any[] = React.useState([]);
  257. const [currentPageUnsubmitStaffList, setCurrentPageUnsubmitStaffList]: any[] = React.useState([]);
  258. const [currentPageunsubmitCount, setCurrentPageUnsubmitCount]: any[] = React.useState([]);
  259. const [unsubmitStaffList, setUnsubmitStaffList]: any[] = React.useState([]);
  260. const [individualStaffProjectList, setIndividualStaffProjectList]: any[] = React.useState([]);
  261. const [individualStaffProjectCodeList, setIndividualStaffProjectCodeList]: any[] = React.useState([]);
  262. const [individualStaffManhours, setIndividualStaffManhours]: any[] = React.useState([]);
  263. const [individualStaffManhoursPercentage, setIndividualStaffManhoursPercentage]: any[] = React.useState([]);
  264. const [totalNormalConsumption, setTotalNormalConsumption]: any = React.useState('NA');
  265. const [totalOtConsumption, setTotalOtConsumption]: any = React.useState('NA');
  266. const [totalLeaveHours, setTotalLeaveHours]: any = React.useState('NA');
  267. const [currentPage, setCurrentPage] = useState(1);
  268. const recordsPerPage = 10;
  269. const fetchComboData = async () => {
  270. const staffComboList = []
  271. const teamComboList = []
  272. const teamCombo = await fetchTeamCombo();
  273. const staffCombo = await fetchStaffCombo();
  274. if (abilityViewDashboardAll) {
  275. for (var i = 0; i < teamCombo.records.length; i++) {
  276. teamComboList.push({ value: teamCombo.records[i].id, label: teamCombo.records[i].label })
  277. }
  278. } else {
  279. const tempTeam = teamCombo.records.find(team => team.id === staff.teamId)
  280. teamComboList.push({ value: tempTeam?.id, label: tempTeam?.label })
  281. }
  282. for (var i = 0; i < staffCombo.length; i++) {
  283. staffComboList.push({ value: staffCombo[i].id, label: staffCombo[i].label })
  284. }
  285. setTeamManhoursTeamOptions(teamComboList)
  286. setStaffOptions(staffComboList)
  287. }
  288. const fetchWeeklyTeamManhourSpentData = async () => {
  289. const fetchResult = await fetchweeklyTeamTotalManhours(teamManhoursTeamId, value.format('YYYY-MM-DD'));
  290. const weeklyActual = fetchResult[0].weeklyActualTeamTotalManhoursSpent
  291. const weeklyPlanned = fetchResult[0].weeklyPlannedTeamTotalManhoursSpent
  292. const weeklyActualList = []
  293. const weeklyPlannedList = []
  294. var chartMax = 5
  295. for (var i = 0; i < weeklyActual.length; i++) {
  296. if (chartMax < weeklyActual[i].TotalManhourConsumed) {
  297. chartMax = weeklyActual[i].TotalManhourConsumed
  298. }
  299. weeklyActualList.push(weeklyActual[i].TotalManhourConsumed)
  300. }
  301. if (weekDates.length > 0) {
  302. for (var i = 0; i < weeklyPlanned.length; i++) {
  303. const weeklyPlannedSubList = []
  304. const startCount = weeklyPlanned[i].startCount
  305. const endCount = weeklyPlanned[i].endCount
  306. for (var j = 0; j < weeklyPlanned[i].searchDuration; j++) {
  307. if (j >= startCount && j < endCount) {
  308. weeklyPlannedSubList.push(weeklyPlanned[i].AverageManhours)
  309. } else {
  310. weeklyPlannedSubList.push(0)
  311. }
  312. }
  313. weeklyPlannedList.push(weeklyPlannedSubList)
  314. }
  315. if (weeklyPlannedList.length > 0) {
  316. const result = new Array(weeklyPlannedList[0].length).fill(0);
  317. for (const arr of weeklyPlannedList) {
  318. for (let i = 0; i < arr.length; i++) {
  319. result[i] = Number((result[i] + arr[i]).toFixed(2));
  320. if (chartMax < result[i]) {
  321. chartMax = result[i]
  322. }
  323. }
  324. }
  325. setTeamTotalManhoursSpentPlanData(result)
  326. }
  327. else {
  328. const result = new Array(weekDates.length).fill(0);
  329. setTeamTotalManhoursSpentPlanData(result)
  330. }
  331. }
  332. setTeamTotalManhoursSpentActualData(weeklyActualList);
  333. setTotalManHoursMaxValue(chartMax)
  334. }
  335. const fetchMonthlyTeamManhourSpentData = async () => {
  336. const fetchResult = await fetchmonthlyTeamTotalManhours(teamManhoursTeamId, totalManHoursMonthlyFromValue.format('YYYY-MM-DD'), totalManHoursMonthlyToValue.endOf('month').format('YYYY-MM-DD'));
  337. const weeklyActual = fetchResult[0].monthlyActualTeamTotalManhoursSpent
  338. const weeklyPlanned = fetchResult[0].monthlyPlannedTeamTotalManhoursSpent
  339. const weeklyActualList = []
  340. const weeklyPlannedList = []
  341. var chartMax = 5
  342. for (var i = 0; i < weeklyActual.length; i++) {
  343. if (chartMax < weeklyActual[i].TotalManhourConsumed) {
  344. chartMax = weeklyActual[i].TotalManhourConsumed
  345. }
  346. weeklyActualList.push(weeklyActual[i].TotalManhourConsumed)
  347. }
  348. if (weekDates.length > 0) {
  349. for (var i = 0; i < weeklyPlanned.length; i++) {
  350. const weeklyPlannedSubList = []
  351. const startCount = weeklyPlanned[i].startCount
  352. const endCount = weeklyPlanned[i].endCount
  353. for (var j = 0; j < weeklyPlanned[i].searchDuration; j++) {
  354. if (j >= startCount && j < endCount) {
  355. weeklyPlannedSubList.push(weeklyPlanned[i].AverageManhours)
  356. } else {
  357. weeklyPlannedSubList.push(0)
  358. }
  359. }
  360. weeklyPlannedList.push(weeklyPlannedSubList)
  361. }
  362. if (weeklyPlannedList.length > 0) {
  363. const result = new Array(weeklyPlannedList[0].length).fill(0);
  364. for (const arr of weeklyPlannedList) {
  365. for (let i = 0; i < arr.length; i++) {
  366. result[i] = Number((result[i] + arr[i]).toFixed(2));
  367. if (chartMax < result[i]) {
  368. chartMax = result[i]
  369. }
  370. }
  371. }
  372. setTeamTotalManhoursSpentPlanData(result)
  373. } else {
  374. const result = new Array(weekDates.length).fill(0);
  375. setTeamTotalManhoursSpentPlanData(result)
  376. }
  377. }
  378. setTeamTotalManhoursSpentActualData(weeklyActualList);
  379. setTotalManHoursMaxValue(chartMax)
  380. }
  381. const fetchTotalManhoursByGradeData = async () => {
  382. const fetchResult = await fetchTotalManhoursByGrade(weeklyValueByStaffGrade.format('YYYY-MM-DD'), weeklyToValueByStaffGrade.format('YYYY-MM-DD'),staffGradeTeamId);
  383. const actualManhours = fetchResult[0].staffGradeTotalManhours
  384. const plannedManhours = fetchResult[0].staffGradeTotalPlannedManhours
  385. var chartMax = 5
  386. const gradeList = []
  387. const actualList = []
  388. const plannedList = []
  389. var manhours = 0
  390. for (var i = 0; i < actualManhours.length; i++) {
  391. actualList.push(actualManhours[i].manhours.toFixed(2))
  392. gradeList.push(actualManhours[i].gradeName)
  393. if (chartMax < actualManhours[i].manhours) {
  394. chartMax = actualManhours[i].manhours
  395. }
  396. }
  397. if (plannedManhours.length > 0) {
  398. var gradeId = plannedManhours[0].id
  399. for (var i = 0; i < plannedManhours.length; i++) {
  400. if (plannedManhours[i].id === gradeId) {
  401. manhours += (plannedManhours[i].searchDuration - plannedManhours[i].startDiff - plannedManhours[i].endDiff) * plannedManhours[i].avgGradeManhour
  402. if (chartMax < manhours) {
  403. chartMax = manhours
  404. }
  405. if (i === plannedManhours.length - 1) {
  406. plannedList.push(manhours.toFixed(2))
  407. }
  408. } else {
  409. plannedList.push(manhours.toFixed(2))
  410. manhours = 0
  411. gradeId = plannedManhours[i].id
  412. manhours += (plannedManhours[i].searchDuration - plannedManhours[i].startDiff - plannedManhours[i].endDiff) * plannedManhours[i].avgGradeManhour
  413. if (chartMax < manhours) {
  414. chartMax = manhours
  415. }
  416. if (i === plannedManhours.length - 1) {
  417. plannedList.push(manhours.toFixed(2))
  418. }
  419. }
  420. }
  421. }
  422. setGradeNameList(gradeList)
  423. setTotalManhourByGradePlannedManhours(plannedList)
  424. setTotalManhourByGradeActualManhours(actualList);
  425. setTotalManHoursByGradeMaxValue(chartMax)
  426. }
  427. const fetchMonthlyTotalManhoursByGradeData = async () => {
  428. const fetchResult = await fetchTotalManhoursByGrade(totalManHoursMonthlyFromValue.format('YYYY-MM-DD'), totalManHoursMonthlyToValue.endOf('month').format('YYYY-MM-DD'),staffGradeTeamId);
  429. const actualManhours = fetchResult[0].staffGradeTotalManhours
  430. const plannedManhours = fetchResult[0].staffGradeTotalPlannedManhours
  431. var chartMax = 5
  432. const gradeList = []
  433. const actualList = []
  434. const plannedList = []
  435. var manhours = 0
  436. for (var i = 0; i < actualManhours.length; i++) {
  437. actualList.push(actualManhours[i].manhours.toFixed(2))
  438. gradeList.push(actualManhours[i].gradeName)
  439. if (chartMax < actualManhours[i].manhours) {
  440. chartMax = actualManhours[i].manhours
  441. }
  442. }
  443. if (plannedManhours.length > 0) {
  444. var gradeId = plannedManhours[0].id
  445. for (var i = 0; i < plannedManhours.length; i++) {
  446. if (plannedManhours[i].id === gradeId) {
  447. manhours += (plannedManhours[i].searchDuration - plannedManhours[i].startDiff - plannedManhours[i].endDiff) * plannedManhours[i].avgGradeManhour
  448. if (chartMax < manhours) {
  449. chartMax = manhours
  450. }
  451. if (i === plannedManhours.length - 1) {
  452. plannedList.push(manhours.toFixed(2))
  453. }
  454. } else {
  455. plannedList.push(manhours.toFixed(2))
  456. manhours = 0
  457. gradeId = plannedManhours[i].id
  458. manhours += (plannedManhours[i].searchDuration - plannedManhours[i].startDiff - plannedManhours[i].endDiff) * plannedManhours[i].avgGradeManhour
  459. if (chartMax < manhours) {
  460. chartMax = manhours
  461. }
  462. if (i === plannedManhours.length - 1) {
  463. plannedList.push(manhours.toFixed(2))
  464. }
  465. }
  466. }
  467. }
  468. setGradeNameList(gradeList)
  469. setTotalManhourByGradePlannedManhours(plannedList)
  470. setTotalManhourByGradeActualManhours(actualList);
  471. setTotalManHoursByGradeMaxValue(chartMax)
  472. }
  473. const fetchWeeklyUnsubmittedData = async () => {
  474. const fetchResult = await fetchWeeklyUnsubmit(teamUnsubmitTeamId, weeklyUnsubmittedTimeSheet.format('YYYY-MM-DD'), holidayDates);
  475. const result = []
  476. const staffList = []
  477. var maxValue = 5
  478. for (var i = 0; i < fetchResult.length; i++) {
  479. if (maxValue < fetchResult[i].UnsubmittedCount) {
  480. maxValue = fetchResult[i].UnsubmittedCount
  481. }
  482. result.push(fetchResult[i].UnsubmittedCount)
  483. staffList.push(fetchResult[i].name)
  484. }
  485. setUnsubmittedMaxValue(maxValue)
  486. setUnsubmitCount(result)
  487. setUnsubmitStaffList(staffList)
  488. }
  489. const fetchMonthlyUnsubmittedData = async () => {
  490. const fetchResult = await fetchMonthlyUnsubmit(teamUnsubmitTeamId, unsubmitMonthlyFromValue.format('YYYY-MM-DD'), unsubmitMonthlyToValue.endOf('month').format('YYYY-MM-DD'), holidayDates);
  491. const result = []
  492. const staffList = []
  493. var maxValue = 5
  494. for (var i = 0; i < fetchResult.length; i++) {
  495. if (maxValue < fetchResult[i].UnsubmittedCount) {
  496. maxValue = fetchResult[i].UnsubmittedCount
  497. }
  498. result.push(fetchResult[i].UnsubmittedCount)
  499. staffList.push(fetchResult[i].name)
  500. }
  501. setUnsubmittedMaxValue(maxValue)
  502. setUnsubmitCount(result)
  503. setUnsubmitStaffList(staffList)
  504. }
  505. const fetchDailyIndividualManhoursData = async () => {
  506. console.log(weeklyValueByIndividualStaff.add(6, 'days').format('YYYY-MM-DD'))
  507. const fetchResult = await fetchDailyIndividualStaffManhours(staffId, totalManHoursByIndividualStaffDailyFromValue.format('YYYY-MM-DD'));
  508. console.log(fetchResult)
  509. const manhoursResult = fetchResult[0].individualStaffManhoursSpentByDay
  510. const totalResult = fetchResult[0].individualStaffTotalManhoursSpentByDay
  511. const leaveResult = fetchResult[0].individualStaffTotalLeaveHoursByDay
  512. const result = []
  513. const projectList = []
  514. const projectCodeList = []
  515. const percentageList = []
  516. var maxValue = 12
  517. console.log(manhoursResult)
  518. if (manhoursResult.length > 0) {
  519. for (var i = 0; i < manhoursResult.length; i++) {
  520. if (manhoursResult[i].id !== null) {
  521. if (maxValue < manhoursResult[i].manhours) {
  522. maxValue = manhoursResult[i].manhours
  523. }
  524. result.push(manhoursResult[i].manhours)
  525. projectCodeList.push(manhoursResult[i].projectNo)
  526. projectList.push(manhoursResult[i].projectName)
  527. percentageList.push(manhoursResult[i].manhours)
  528. }
  529. }
  530. setIndividualManhoursMaxValue(maxValue)
  531. setIndividualStaffProjectCodeList(projectCodeList)
  532. setIndividualStaffProjectList(projectList)
  533. setIndividualStaffManhours(result)
  534. setIndividualStaffManhoursPercentage(percentageList)
  535. setTotalNormalConsumption(totalResult[0].normalManhours)
  536. setTotalOtConsumption(totalResult[0].otManhours)
  537. setTotalLeaveHours(leaveResult[0].leaveHours)
  538. }
  539. }
  540. const fetchWeeklyIndividualManhoursData = async () => {
  541. console.log(weeklyValueByIndividualStaff)
  542. const fetchResult = await fetchWeeklyIndividualStaffManhours(staffId, weeklyValueByIndividualStaff.format('YYYY-MM-DD'), weeklyValueByIndividualStaff.add(6, 'days').format('YYYY-MM-DD'));
  543. console.log(fetchResult)
  544. const manhoursResult = fetchResult[0].individualStaffManhoursSpentWeekly
  545. const totalResult = fetchResult[0].individualStaffTotalManhoursSpentWeekly
  546. const leaveResult = fetchResult[0].individualStaffTotalLeaveHoursWeekly
  547. const result = []
  548. const projectList = []
  549. const projectCodeList = []
  550. const percentageList = []
  551. var maxValue = 12
  552. if (manhoursResult.length > 0) {
  553. for (var i = 0; i < manhoursResult.length; i++) {
  554. if (maxValue < manhoursResult[i].manhours) {
  555. maxValue = manhoursResult[i].manhours
  556. }
  557. result.push(manhoursResult[i].manhours)
  558. projectCodeList.push(manhoursResult[i].projectNo)
  559. projectList.push(manhoursResult[i].projectName)
  560. percentageList.push(manhoursResult[i].manhours)
  561. }
  562. setIndividualManhoursMaxValue(maxValue)
  563. setIndividualStaffProjectList(projectList)
  564. setIndividualStaffProjectCodeList(projectCodeList)
  565. setIndividualStaffManhours(result)
  566. setIndividualStaffManhoursPercentage(percentageList)
  567. setTotalNormalConsumption(totalResult[0].normalManhours)
  568. setTotalOtConsumption(totalResult[0].otManhours)
  569. setTotalLeaveHours(leaveResult[0].leaveHours)
  570. }
  571. }
  572. const fetchMonthlyIndividualManhoursData = async () => {
  573. const fetchResult = await fetchMonthlyIndividualStaffManhours(staffId, indivdualManHoursMonthlyFromValue.format('YYYY-MM-01'));
  574. const manhoursResult = fetchResult[0].individualStaffManhoursSpentByMonth
  575. const totalResult = fetchResult[0].individualStaffTotalManhoursSpentByMonth
  576. const leaveResult = fetchResult[0].individualStaffTotalLeaveHoursByMonth
  577. const result = []
  578. const projectList = []
  579. const projectCodeList = []
  580. const percentageList = []
  581. var maxValue = 12
  582. if (manhoursResult.length > 0) {
  583. for (var i = 0; i < manhoursResult.length; i++) {
  584. if (maxValue < manhoursResult[i].manhours) {
  585. maxValue = manhoursResult[i].manhours
  586. }
  587. result.push(manhoursResult[i].manhours)
  588. projectCodeList.push(manhoursResult[i].projectNo)
  589. projectList.push(manhoursResult[i].projectName)
  590. percentageList.push(manhoursResult[i].manhours)
  591. }
  592. setIndividualManhoursMaxValue(maxValue)
  593. setIndividualStaffProjectList(projectList)
  594. setIndividualStaffProjectCodeList(projectCodeList)
  595. setIndividualStaffManhours(result)
  596. setIndividualStaffManhoursPercentage(percentageList)
  597. setTotalNormalConsumption(totalResult[0].normalManhours)
  598. setTotalOtConsumption(totalResult[0].otManhours)
  599. setTotalLeaveHours(leaveResult[0].leaveHours)
  600. }
  601. }
  602. const startIndex = (currentPage - 1) * recordsPerPage;
  603. const endIndex = startIndex + recordsPerPage;
  604. useEffect(() => {
  605. const currentPageStaffData = unsubmitStaffList.slice(startIndex, endIndex)
  606. const currentPageData = unsubmitCount.slice(startIndex, endIndex);
  607. console.log(currentPage)
  608. console.log(Math.ceil(unsubmitStaffList.length / recordsPerPage))
  609. setCurrentPageUnsubmitStaffList(currentPageStaffData)
  610. setCurrentPageUnsubmitCount(currentPageData)
  611. }, [unsubmitCount,currentPage]);
  612. const handlePrevPage = () => {
  613. if (currentPage > 1) {
  614. setCurrentPage(currentPage - 1);
  615. }
  616. };
  617. const handleNextPage = () => {
  618. if (endIndex < unsubmitCount.length) {
  619. setCurrentPage(currentPage + 1);
  620. }
  621. };
  622. useEffect(() => {
  623. fetchComboData()
  624. }, []);
  625. useEffect(() => {
  626. if (teamTotalManhoursSpentSelect === "Weekly") {
  627. fetchWeeklyTeamManhourSpentData()
  628. }
  629. }, [value, teamManhoursTeamId]);
  630. useEffect(() => {
  631. if (teamTotalManhoursSpentSelect === "Monthly") {
  632. fetchMonthlyTeamManhourSpentData()
  633. }
  634. }, [totalManHoursMonthlyFromValue, totalManHoursMonthlyToValue, teamManhoursTeamId]);
  635. useEffect(() => {
  636. if (staffGradeManhoursSpentSelect === "Weekly") {
  637. fetchTotalManhoursByGradeData()
  638. }
  639. }, [staffGradeTeamId, weeklyValueByStaffGrade, weeklyToValueByStaffGrade]);
  640. useEffect(() => {
  641. if (staffGradeManhoursSpentSelect === "Monthly") {
  642. fetchMonthlyTotalManhoursByGradeData()
  643. }
  644. }, [staffGradeTeamId, totalManHoursMonthlyFromValue, totalManHoursMonthlyToValue]);
  645. useEffect(() => {
  646. if (unsubmittedTimeSheetSelect === "Weekly") {
  647. fetchWeeklyUnsubmittedData()
  648. }
  649. }, [teamUnsubmitTeamId, weeklyUnsubmittedTimeSheet]);
  650. useEffect(() => {
  651. if (unsubmittedTimeSheetSelect === "Monthly") {
  652. fetchMonthlyUnsubmittedData()
  653. }
  654. }, [teamUnsubmitTeamId, unsubmitMonthlyFromValue, unsubmitMonthlyToValue]);
  655. useEffect(() => {
  656. if (individualStaffManhoursSpentSelect === "Daily") {
  657. fetchDailyIndividualManhoursData()
  658. }
  659. }, [staffId, totalManHoursByIndividualStaffDailyFromValue, individualStaffManhoursSpentSelect]);
  660. useEffect(() => {
  661. if (individualStaffManhoursSpentSelect === "Weekly") {
  662. fetchWeeklyIndividualManhoursData()
  663. }
  664. }, [staffId, weeklyValueByIndividualStaff]);
  665. useEffect(() => {
  666. if (individualStaffManhoursSpentSelect === "Monthly") {
  667. fetchMonthlyIndividualManhoursData()
  668. }
  669. }, [staffId, indivdualManHoursMonthlyFromValue]);
  670. // useEffect(() => {
  671. // console.log(unsubmittedTimeSheetSelect)
  672. // if (unsubmittedTimeSheetSelect === "Monthly" || teamTotalManhoursSpentSelect === "Monthly" || staffGradeManhoursSpentSelect === "Monthly" || individualStaffManhoursSpentSelect === "Monthly") {
  673. // setUnsubmittedTimeSheetSelect("Monthly")
  674. // setTeamTotalManhoursSpentSelect("Monthly")
  675. // setStaffGradeManhoursSpentSelect("Monthly")
  676. // setIndividualStaffManhoursSpentSelect("Monthly")
  677. // } else if (unsubmittedTimeSheetSelect === "Weekly" || teamTotalManhoursSpentSelect === "Weekly" || staffGradeManhoursSpentSelect === "Weekly" || individualStaffManhoursSpentSelect === "Weekly") {
  678. // setUnsubmittedTimeSheetSelect("Weekly")
  679. // setTeamTotalManhoursSpentSelect("Weekly")
  680. // setStaffGradeManhoursSpentSelect("Weekly")
  681. // setIndividualStaffManhoursSpentSelect("Weekly")
  682. // }
  683. // }, [unsubmittedTimeSheetSelect, teamTotalManhoursSpentSelect, staffGradeManhoursSpentSelect, individualStaffManhoursSpentSelect]);
  684. const teamOptions = [
  685. { value: 1, label: "XXX Team" },
  686. { value: 2, label: "YYY Team" },
  687. { value: 3, label: "ZZZ Team" },
  688. ];
  689. const columns = [
  690. {
  691. id: "projectCode",
  692. field: "projectCode",
  693. headerName: "Project Code",
  694. flex: 1,
  695. },
  696. {
  697. id: "projectName",
  698. field: "projectName",
  699. headerName: "Project Name",
  700. flex: 1,
  701. },
  702. {
  703. id: "team",
  704. field: "team",
  705. headerName: "Team",
  706. flex: 1,
  707. },
  708. {
  709. id: "teamLeader",
  710. field: "teamLeader",
  711. headerName: "Team Leader",
  712. flex: 1,
  713. },
  714. {
  715. id: "startDate",
  716. field: "startDate",
  717. headerName: "Start Date",
  718. flex: 1,
  719. },
  720. {
  721. id: "targetEndDate",
  722. field: "targetEndDate",
  723. headerName: "Target End Date",
  724. flex: 1,
  725. },
  726. {
  727. id: "client",
  728. field: "client",
  729. headerName: "Client",
  730. flex: 1,
  731. },
  732. {
  733. id: "subsidiary",
  734. field: "subsidiary",
  735. headerName: "Subsidiary",
  736. flex: 1,
  737. },
  738. ];
  739. const options: ApexOptions = {
  740. tooltip: {
  741. y: {
  742. formatter: function (val) {
  743. return val.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  744. }
  745. }
  746. },
  747. chart: {
  748. height: 350,
  749. type: "line",
  750. },
  751. stroke: {
  752. width: [2, 2],
  753. },
  754. plotOptions: {
  755. bar: {
  756. horizontal: false,
  757. distributed: false,
  758. },
  759. },
  760. dataLabels: {
  761. enabled: true,
  762. },
  763. xaxis: {
  764. categories: teamTotalManhoursSpentPeriod,
  765. },
  766. yaxis: [
  767. {
  768. title: {
  769. text: "Team Total Manhours Spent (Hour)",
  770. },
  771. min: 0,
  772. max: totalManHoursMaxValue,
  773. tickAmount: 5,
  774. labels: {
  775. formatter: function (val) {
  776. return val.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
  777. }
  778. }
  779. },
  780. ],
  781. grid: {
  782. borderColor: "#f1f1f1",
  783. },
  784. annotations: {},
  785. series: [
  786. {
  787. name: "Planned",
  788. type: "line",
  789. color: "#efbe7d",
  790. data: teamTotalManhoursSpentPlanData,
  791. },
  792. {
  793. name: "Actual",
  794. type: "line",
  795. color: "#7cd3f2",
  796. data: teamTotalManhoursSpentActualData,
  797. },
  798. ],
  799. };
  800. const staffGradeOptions: ApexOptions = {
  801. chart: {
  802. height: 350,
  803. type: "bar",
  804. },
  805. stroke: {
  806. width: [2, 2],
  807. },
  808. plotOptions: {
  809. bar: {
  810. horizontal: true,
  811. distributed: false,
  812. },
  813. },
  814. dataLabels: {
  815. enabled: true,
  816. },
  817. xaxis: {
  818. categories: gradeNameList,
  819. },
  820. yaxis: [
  821. {
  822. title: {
  823. text: "Staff Grade",
  824. },
  825. min: 0,
  826. max: totalManHoursByGradeMaxValue,
  827. tickAmount: 5,
  828. },
  829. ],
  830. grid: {
  831. borderColor: "#f1f1f1",
  832. },
  833. annotations: {},
  834. series: [
  835. {
  836. name: "Planned",
  837. type: "bar",
  838. color: "#efbe7d",
  839. data: totalManhourByGradePlannedManhours,
  840. },
  841. {
  842. name: "Actual",
  843. type: "bar",
  844. color: "#00acb1",
  845. data: totalManhourByGradeActualManhours,
  846. },
  847. ],
  848. };
  849. const individualStaffOptions: ApexOptions = {
  850. chart: {
  851. height: 350,
  852. type: "line",
  853. },
  854. stroke: {
  855. width: [1],
  856. },
  857. plotOptions: {
  858. bar: {
  859. horizontal: true,
  860. distributed: false,
  861. },
  862. },
  863. dataLabels: {
  864. enabled: true,
  865. },
  866. xaxis: {
  867. categories: individualStaffProjectCodeList,
  868. },
  869. yaxis: [
  870. {
  871. title: {
  872. text: "Project",
  873. },
  874. min: 0,
  875. max: individualManhoursMaxValue,
  876. tickAmount: 5,
  877. },
  878. ],
  879. grid: {
  880. borderColor: "#f1f1f1",
  881. },
  882. annotations: {},
  883. tooltip: {
  884. x: {
  885. formatter: (value, { series, seriesIndex, dataPointIndex, w }) => {
  886. return individualStaffProjectList[dataPointIndex];
  887. },
  888. },
  889. },
  890. series: [
  891. {
  892. name: "Manhours(Hour)",
  893. type: "bar",
  894. color: "#00acb1",
  895. data: individualStaffManhours,
  896. },
  897. ],
  898. };
  899. const unsubmittedTimeSheetOptions: ApexOptions = {
  900. chart: {
  901. height: 350,
  902. type: "line",
  903. },
  904. stroke: {
  905. width: [1],
  906. },
  907. plotOptions: {
  908. bar: {
  909. horizontal: true,
  910. distributed: false,
  911. },
  912. },
  913. dataLabels: {
  914. enabled: true,
  915. },
  916. xaxis: {
  917. categories: currentPageUnsubmitStaffList,
  918. },
  919. yaxis: [
  920. {
  921. title: {
  922. text: "Staff",
  923. },
  924. min: 0,
  925. max: unsubmittedMaxValue,
  926. tickAmount: 5,
  927. },
  928. ],
  929. grid: {
  930. borderColor: "#f1f1f1",
  931. },
  932. annotations: {},
  933. series: [
  934. {
  935. name: "Unsubmitted Time Sheet",
  936. type: "bar",
  937. color: "#00acb1",
  938. data: currentPageunsubmitCount,
  939. },
  940. ],
  941. };
  942. const teamTotalManhoursSpentOnClick = (r: any) => {
  943. setTeamTotalManhoursSpentSelect(r);
  944. if (r === "Weekly") {
  945. fetchWeeklyTeamManhourSpentData()
  946. setValue(dayjs().startOf('week'));
  947. setTeamTotalManhoursSpentPeriod(weekDates);
  948. } else if (r === "Monthly") {
  949. fetchMonthlyTeamManhourSpentData()
  950. setTeamTotalManhoursSpentPeriod(monthDates);
  951. }
  952. };
  953. const individualStaffManhoursSpentOnClick = (r: any) => {
  954. setIndividualStaffManhoursSpentSelect(r);
  955. // if (r === "Weekly") {
  956. // setValue(dayjs(new Date))
  957. // setTeamTotalManhoursSpentPeriod(weekDates)
  958. // setTeamTotalManhoursSpentPlanData([42,42,42,42,42,0,0])
  959. // setTeamTotalManhoursSpentActualData([45,42,60,42,58,0,0])
  960. // setTotalManHoursMaxValue(75)
  961. // } else if (r === "Monthly") {
  962. // setTeamTotalManhoursSpentPeriod(monthDates)
  963. // setTeamTotalManhoursSpentPlanData([840,840,840,840,840,840])
  964. // setTeamTotalManhoursSpentActualData([900,840,1200,840,1160,840])
  965. // setTotalManHoursMaxValue(1250)
  966. // }
  967. };
  968. const unsubmittedTimeSheetOnClick = (r: any) => {
  969. setUnsubmittedTimeSheetSelect(r);
  970. };
  971. const selectWeeklyPeriod = (r: any) => {
  972. const selectDate = new Date(r);
  973. const firstDayOfWeek = selectDate;
  974. firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0);
  975. const weekDates: any[] = [];
  976. const weekFirstDate = new Date(firstDayOfWeek);
  977. for (let i = 0; i < 7; i++) {
  978. const currentDate = new Date(firstDayOfWeek);
  979. currentDate.setDate(firstDayOfWeek.getDate() + i);
  980. const formattedDate = dayjs(currentDate).format("DD MMM (ddd)");
  981. weekDates.push(formattedDate);
  982. }
  983. setTeamTotalManhoursSpentPeriod(weekDates);
  984. setValue(dayjs(firstDayOfWeek));
  985. };
  986. const selectWeeklyPeriodByStaffGrade = (r: any) => {
  987. const selectDate = new Date(r);
  988. const firstDayOfWeek = selectDate
  989. firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0);
  990. const weekDates: any[] = [];
  991. for (let i = 0; i < 7; i++) {
  992. const currentDate = new Date(firstDayOfWeek);
  993. currentDate.setDate(firstDayOfWeek.getDate() + i);
  994. const formattedDate = dayjs(currentDate).format("DD MMM (ddd)");
  995. weekDates.push(formattedDate);
  996. }
  997. setTeamTotalManhoursByStaffGrade(weekDates);
  998. setWeeklyValueByStaffGrade(dayjs(firstDayOfWeek));
  999. setWeeklyToValueByStaffGrade(dayjs(firstDayOfWeek).add(6, 'day'))
  1000. };
  1001. const selectWeeklyPeriodUnsubmittedTimeSheet = (r: any) => {
  1002. const selectDate = new Date(r);
  1003. const firstDayOfWeek = selectDate;
  1004. firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0);
  1005. const weekDates: any[] = [];
  1006. for (let i = 0; i < 7; i++) {
  1007. const currentDate = new Date(firstDayOfWeek);
  1008. currentDate.setDate(firstDayOfWeek.getDate() + i);
  1009. const formattedDate = dayjs(currentDate).format("DD MMM (ddd)");
  1010. weekDates.push(formattedDate);
  1011. }
  1012. setUnsubmittedTimeSheetPeriod(weekDates);
  1013. setWeeklyUnsubmittedTimeSheet(dayjs(firstDayOfWeek));
  1014. };
  1015. const selectWeeklyPeriodIndividualStaff = (r: any) => {
  1016. const selectDate = new Date(r);
  1017. const firstDayOfWeek = selectDate;
  1018. firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0);
  1019. const weekDates: any[] = [];
  1020. for (let i = 0; i < 7; i++) {
  1021. const currentDate = new Date(firstDayOfWeek);
  1022. currentDate.setDate(firstDayOfWeek.getDate() + i);
  1023. const formattedDate = dayjs(currentDate).format("DD MMM (ddd)");
  1024. weekDates.push(formattedDate);
  1025. }
  1026. setIndividualStaffManhoursSpentPeriod(weekDates);
  1027. setWeeklyValueByIndividualStaff(dayjs(firstDayOfWeek));
  1028. };
  1029. const selectMonthlyPeriodFrom = (r: any) => {
  1030. setTotalManHoursMonthlyFromValue(r)
  1031. const monthDates: any[] = [];
  1032. const monthPlanData: any[] = [];
  1033. const monthActualData: any[] = [];
  1034. const selectFromDate = dayjs(r);
  1035. for (
  1036. let date = selectFromDate.clone();
  1037. date.isBefore(totalManHoursMonthlyToValue, "month");
  1038. date = date.add(1, "month")
  1039. ) {
  1040. monthDates.push(date.format("MM-YYYY"));
  1041. monthPlanData.push(840);
  1042. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1043. }
  1044. monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY"));
  1045. monthPlanData.push(840);
  1046. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1047. setTeamTotalManhoursSpentPlanData(monthPlanData);
  1048. setTeamTotalManhoursSpentActualData(monthActualData);
  1049. setTeamTotalManhoursSpentPeriod(monthDates);
  1050. };
  1051. const selectMonthlyPeriodTo = (r: any) => {
  1052. setTotalManHoursMonthlyToValue(r)
  1053. const monthDates: any[] = [];
  1054. const monthPlanData: any[] = [];
  1055. const monthActualData: any[] = [];
  1056. const selectToDate = dayjs(r);
  1057. for (
  1058. let date = totalManHoursMonthlyFromValue.clone();
  1059. date.isBefore(selectToDate, "month");
  1060. date = date.add(1, "month")
  1061. ) {
  1062. monthDates.push(date.format("MM-YYYY"));
  1063. monthPlanData.push(840);
  1064. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1065. }
  1066. monthDates.push(selectToDate.format("MM-YYYY"));
  1067. monthPlanData.push(840);
  1068. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1069. setTeamTotalManhoursSpentPlanData(monthPlanData);
  1070. setTeamTotalManhoursSpentActualData(monthActualData);
  1071. setTeamTotalManhoursSpentPeriod(monthDates);
  1072. };
  1073. const selectStaffGradeMonthlyPeriodFrom = (r: any) => {
  1074. setTotalManHoursMonthlyFromValue(r)
  1075. const monthDates: any[] = [];
  1076. const monthPlanData: any[] = [];
  1077. const monthActualData: any[] = [];
  1078. const selectFromDate = dayjs(r);
  1079. for (
  1080. let date = selectFromDate.clone();
  1081. date.isBefore(totalManHoursMonthlyToValue, "month");
  1082. date = date.add(1, "month")
  1083. ) {
  1084. monthDates.push(date.format("MM-YYYY"));
  1085. monthPlanData.push(840);
  1086. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1087. }
  1088. monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY"));
  1089. monthPlanData.push(840);
  1090. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1091. // setTeamTotalManhoursSpentPlanData(monthPlanData)
  1092. // setTeamTotalManhoursSpentActualData(monthActualData)
  1093. setTeamTotalManhoursByStaffGrade(weekDates);
  1094. };
  1095. const selectStaffGradeMonthlyPeriodTo = (r: any) => {
  1096. setTotalManHoursMonthlyToValue(r)
  1097. const monthDates: any[] = [];
  1098. const monthPlanData: any[] = [];
  1099. const monthActualData: any[] = [];
  1100. const selectToDate = dayjs(r);
  1101. for (
  1102. let date = totalManHoursMonthlyFromValue.clone();
  1103. date.isBefore(selectToDate, "month");
  1104. date = date.add(1, "month")
  1105. ) {
  1106. monthDates.push(date.format("MM-YYYY"));
  1107. monthPlanData.push(840);
  1108. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1109. }
  1110. monthDates.push(selectToDate.format("MM-YYYY"));
  1111. monthPlanData.push(840);
  1112. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1113. // setTeamTotalManhoursSpentPlanData(monthPlanData)
  1114. // setTeamTotalManhoursSpentActualData(monthActualData)
  1115. setTeamTotalManhoursByStaffGrade(weekDates);
  1116. };
  1117. const selectUnsubmittedTimeSheetMonthlyPeriodFrom = (r: any) => {
  1118. setUnsubmitMonthlyFromValue(r)
  1119. const monthDates: any[] = [];
  1120. const monthPlanData: any[] = [];
  1121. const monthActualData: any[] = [];
  1122. const selectFromDate = dayjs(r);
  1123. for (
  1124. let date = selectFromDate.clone();
  1125. date.isBefore(unsubmitMonthlyToValue, "month");
  1126. date = date.add(1, "month")
  1127. ) {
  1128. monthDates.push(date.format("MM-YYYY"));
  1129. monthPlanData.push(840);
  1130. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1131. }
  1132. monthDates.push(selectFromDate.format("MM-YYYY"));
  1133. monthPlanData.push(840);
  1134. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1135. // setTeamTotalManhoursSpentPlanData(monthPlanData)
  1136. // setTeamTotalManhoursSpentActualData(monthActualData)
  1137. setUnsubmittedTimeSheetPeriod(weekDates);
  1138. };
  1139. const selectIndividualStaffMonthlyPeriodFrom = (r: any) => {
  1140. setIndivdualManHoursMonthlyFromValue(r)
  1141. const monthDates: any[] = [];
  1142. const monthPlanData: any[] = [];
  1143. const monthActualData: any[] = [];
  1144. const selectFromDate = dayjs(r);
  1145. for (
  1146. let date = selectFromDate.clone();
  1147. date.isBefore(indivdualManHoursMonthlyToValue, "month");
  1148. date = date.add(1, "month")
  1149. ) {
  1150. monthDates.push(date.format("MM-YYYY"));
  1151. // monthPlanData.push(840);
  1152. // monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1153. }
  1154. monthDates.push(selectFromDate.format("MM-YYYY"));
  1155. // monthPlanData.push(840);
  1156. // monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1157. // setTeamTotalManhoursSpentPlanData(monthPlanData)
  1158. // setTeamTotalManhoursSpentActualData(monthActualData)
  1159. setIndividualStaffManhoursSpentPeriod(weekDates);
  1160. };
  1161. const selectUnsubmittedTimeSheetMonthlyPeriodTo = (r: any) => {
  1162. setIndivdualManHoursMonthlyToValue(r)
  1163. const monthDates: any[] = [];
  1164. const monthPlanData: any[] = [];
  1165. const monthActualData: any[] = [];
  1166. const selectToDate = dayjs(r);
  1167. for (
  1168. let date = indivdualManHoursMonthlyToValue.clone();
  1169. date.isBefore(selectToDate, "month");
  1170. date = date.add(1, "month")
  1171. ) {
  1172. monthDates.push(date.format("MM-YYYY"));
  1173. monthPlanData.push(840);
  1174. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1175. }
  1176. monthDates.push(selectToDate.format("MM-YYYY"));
  1177. monthPlanData.push(840);
  1178. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1179. // setTeamTotalManhoursSpentPlanData(monthPlanData)
  1180. // setTeamTotalManhoursSpentActualData(monthActualData)
  1181. setUnsubmittedTimeSheetPeriod(weekDates);
  1182. };
  1183. const selectIndividualStaffMonthlyPeriodTo = (r: any) => {
  1184. setTotalManHoursMonthlyToValue(r)
  1185. const monthDates: any[] = [];
  1186. const monthPlanData: any[] = [];
  1187. const monthActualData: any[] = [];
  1188. const selectToDate = dayjs(r);
  1189. for (
  1190. let date = totalManHoursMonthlyFromValue.clone();
  1191. date.isBefore(selectToDate, "month");
  1192. date = date.add(1, "month")
  1193. ) {
  1194. monthDates.push(date.format("MM-YYYY"));
  1195. monthPlanData.push(840);
  1196. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1197. }
  1198. monthDates.push(selectToDate.format("MM-YYYY"));
  1199. monthPlanData.push(840);
  1200. monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840));
  1201. // setTeamTotalManhoursSpentPlanData(monthPlanData)
  1202. // setTeamTotalManhoursSpentActualData(monthActualData)
  1203. setIndividualStaffManhoursSpentPeriod(weekDates);
  1204. };
  1205. const options2: ApexOptions = {
  1206. chart: {
  1207. type: "donut",
  1208. },
  1209. colors: ['#f57f90', '#94f7d6', '#87c5f5', '#ab95f5', '#ab95f5'],
  1210. plotOptions: {
  1211. pie: {
  1212. donut: {
  1213. labels: {
  1214. show: false,
  1215. name: {
  1216. show: true,
  1217. },
  1218. value: {
  1219. show: false,
  1220. fontWeight: 500,
  1221. fontSize: "30px",
  1222. color: "#3e98c7",
  1223. },
  1224. total: {
  1225. show: false,
  1226. showAlways: false,
  1227. label: "Spent",
  1228. fontFamily: "sans-serif",
  1229. formatter: function (val) {
  1230. return val + "%";
  1231. },
  1232. },
  1233. },
  1234. },
  1235. },
  1236. },
  1237. series: individualStaffManhoursPercentage,
  1238. labels: individualStaffProjectList,
  1239. legend: {
  1240. show: false,
  1241. },
  1242. responsive: [
  1243. {
  1244. breakpoint: 480,
  1245. options: {
  1246. chart: {
  1247. width: 200,
  1248. },
  1249. legend: {
  1250. position: "bottom",
  1251. show: false,
  1252. },
  1253. },
  1254. },
  1255. ],
  1256. };
  1257. return (
  1258. <>
  1259. <Grid item sm>
  1260. <div style={{ display: "inline-block", width: "40%" }}>
  1261. <div>
  1262. <Grid item xs={12} md={12} lg={12}>
  1263. <Card>
  1264. <CardHeader
  1265. className="text-slate-500"
  1266. title="Team Total Manhours Spent"
  1267. />
  1268. <div style={{ display: "inline-block", width: "99%" }}>
  1269. <div className="w-fit align-top mr-5 float-right">
  1270. {teamTotalManhoursSpentSelect === "Weekly" && (
  1271. <>
  1272. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-l-md w-32">
  1273. Weekly
  1274. </button>
  1275. <button
  1276. onClick={() => {
  1277. teamTotalManhoursSpentOnClick("Monthly")
  1278. setUnsubmittedTimeSheetSelect("Monthly")
  1279. fetchMonthlyUnsubmittedData()
  1280. setStaffGradeManhoursSpentSelect("Monthly")
  1281. fetchMonthlyTotalManhoursByGradeData()
  1282. setIndividualStaffManhoursSpentSelect("Monthly")
  1283. fetchMonthlyIndividualManhoursData()
  1284. }
  1285. }
  1286. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-r-md w-32"
  1287. >
  1288. Monthly
  1289. </button>
  1290. </>
  1291. )}
  1292. {teamTotalManhoursSpentSelect === "Monthly" && (
  1293. <>
  1294. <button
  1295. onClick={() => {
  1296. teamTotalManhoursSpentOnClick("Weekly")
  1297. setUnsubmittedTimeSheetSelect("Weekly")
  1298. fetchWeeklyUnsubmittedData()
  1299. setStaffGradeManhoursSpentSelect("Weekly")
  1300. fetchTotalManhoursByGradeData()
  1301. setIndividualStaffManhoursSpentSelect("Weekly")
  1302. fetchWeeklyIndividualManhoursData()
  1303. }
  1304. }
  1305. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-l-md w-32"
  1306. >
  1307. Weekly
  1308. </button>
  1309. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-32">
  1310. Monthly
  1311. </button>
  1312. </>
  1313. )}
  1314. </div>
  1315. <div className="inline-block w-fit mt-2">
  1316. {abilityViewDashboardAll &&
  1317. <div className="inline-block">
  1318. <div className="inline-block ml-6">
  1319. <Label className="text-slate-500 font-medium">
  1320. Team:&nbsp;
  1321. </Label>
  1322. </div>
  1323. <div className="inline-block ml-1 w-60">
  1324. <Select
  1325. placeholder="Please select a team"
  1326. options={teamManhoursTeamOptions}
  1327. isClearable={true}
  1328. onChange={(selectedOption: any) => {
  1329. if (selectedOption === null) {
  1330. setTeamManhoursTeamId(null);
  1331. } else {
  1332. setTeamManhoursTeamId(selectedOption.value);
  1333. }
  1334. }}
  1335. />
  1336. </div>
  1337. </div>}
  1338. <div className="ml-6 mt-2" style={{ verticalAlign: "top" }}>
  1339. {/* <Label className="text-slate-500 font-medium ml-6">
  1340. Period:&nbsp;
  1341. </Label> */}
  1342. {teamTotalManhoursSpentSelect === "Weekly" && (
  1343. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1344. <DatePicker
  1345. className="w-72 h-10 align-top"
  1346. label="Period:"
  1347. value={value}
  1348. format="DD-MM-YYYY"
  1349. onChange={(newValue) => {
  1350. selectWeeklyPeriod(newValue)
  1351. }
  1352. }
  1353. showDaysOutsideCurrentMonth
  1354. displayWeekNumber
  1355. slots={{ day: Day }}
  1356. slotProps={{
  1357. day: (ownerState) =>
  1358. ({
  1359. selectedDay: value,
  1360. hoveredDay,
  1361. onPointerEnter: () =>
  1362. setHoveredDay(ownerState.day),
  1363. onPointerLeave: () => setHoveredDay(null),
  1364. }) as any,
  1365. }}
  1366. />
  1367. </LocalizationProvider>
  1368. )}
  1369. {teamTotalManhoursSpentSelect === "Monthly" && (
  1370. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1371. <DatePicker
  1372. className="w-44 h-10 align-top"
  1373. onChange={(newValue) =>
  1374. selectMonthlyPeriodFrom(newValue)
  1375. }
  1376. defaultValue={totalManHoursMonthlyFromValue}
  1377. label={"From"}
  1378. views={["month", "year"]}
  1379. />
  1380. <DatePicker
  1381. className="w-40 h-10 align-top"
  1382. onChange={(newValue) =>
  1383. selectMonthlyPeriodTo(newValue)
  1384. }
  1385. defaultValue={totalManHoursMonthlyToValue}
  1386. label={"To"}
  1387. views={["month", "year"]}
  1388. />
  1389. </LocalizationProvider>
  1390. )}
  1391. </div>
  1392. </div>
  1393. <ReactApexChart
  1394. options={options}
  1395. series={options.series}
  1396. type="line"
  1397. height="400"
  1398. />
  1399. </div>
  1400. </Card>
  1401. </Grid>
  1402. </div>
  1403. <div className="mt-5">
  1404. <Grid item xs={12} md={12} lg={12}>
  1405. <Card>
  1406. <CardHeader
  1407. className="text-slate-500"
  1408. title="Total Manhours Spent by Staff Grade"
  1409. />
  1410. <div style={{ display: "inline-block", width: "99%" }}>
  1411. <div className="w-fit align-top mr-5 float-right">
  1412. {staffGradeManhoursSpentSelect === "Weekly" && (
  1413. <>
  1414. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-l-md w-32">
  1415. Weekly
  1416. </button>
  1417. <button
  1418. onClick={() => {
  1419. teamTotalManhoursSpentOnClick("Monthly")
  1420. setUnsubmittedTimeSheetSelect("Monthly")
  1421. fetchMonthlyUnsubmittedData()
  1422. setStaffGradeManhoursSpentSelect("Monthly")
  1423. fetchMonthlyTotalManhoursByGradeData()
  1424. setIndividualStaffManhoursSpentSelect("Monthly")
  1425. fetchMonthlyIndividualManhoursData()
  1426. }
  1427. }
  1428. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-r-md w-48"
  1429. >
  1430. Monthly
  1431. </button>
  1432. </>
  1433. )}
  1434. {staffGradeManhoursSpentSelect === "Monthly" && (
  1435. <>
  1436. <button
  1437. onClick={() => {
  1438. teamTotalManhoursSpentOnClick("Weekly")
  1439. setUnsubmittedTimeSheetSelect("Weekly")
  1440. fetchWeeklyUnsubmittedData()
  1441. setStaffGradeManhoursSpentSelect("Weekly")
  1442. fetchTotalManhoursByGradeData()
  1443. setIndividualStaffManhoursSpentSelect("Weekly")
  1444. fetchWeeklyIndividualManhoursData()
  1445. }
  1446. }
  1447. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-l-md w-32"
  1448. >
  1449. Weekly
  1450. </button>
  1451. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-48">
  1452. Monthly
  1453. </button>
  1454. </>
  1455. )}
  1456. </div>
  1457. <div className="inline-block w-fit mt-2">
  1458. <div className="inline-block mt-2 ml-6">
  1459. {abilityViewDashboardAll &&
  1460. <div className="inline-block">
  1461. <div className="inline-block ml-6">
  1462. <Label className="text-slate-500 font-medium">
  1463. Team:&nbsp;
  1464. </Label>
  1465. </div>
  1466. <div className="inline-block ml-1 w-60">
  1467. <Select
  1468. placeholder="Please select a team"
  1469. options={teamManhoursTeamOptions}
  1470. isClearable={true}
  1471. onChange={(selectedOption: any) => {
  1472. if (selectedOption === null) {
  1473. setStaffGradeTeamId(null);
  1474. } else {
  1475. setStaffGradeTeamId(selectedOption.value);
  1476. }
  1477. }}
  1478. />
  1479. </div>
  1480. </div>}
  1481. {staffGradeManhoursSpentSelect === "Weekly" && (
  1482. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1483. <DatePicker
  1484. className="w-72 h-10 align-top"
  1485. label="Period:"
  1486. value={weeklyValueByStaffGrade}
  1487. format="DD-MM-YYYY"
  1488. onChange={(newValue) =>
  1489. selectWeeklyPeriodByStaffGrade(newValue)
  1490. }
  1491. showDaysOutsideCurrentMonth
  1492. displayWeekNumber
  1493. slots={{ day: Day }}
  1494. slotProps={{
  1495. day: (ownerState) =>
  1496. ({
  1497. selectedDay: value,
  1498. hoveredDay,
  1499. onPointerEnter: () =>
  1500. setHoveredDay(ownerState.day),
  1501. onPointerLeave: () => setHoveredDay(null),
  1502. }) as any,
  1503. }}
  1504. />
  1505. </LocalizationProvider>
  1506. )}
  1507. {staffGradeManhoursSpentSelect === "Monthly" && (
  1508. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1509. <DatePicker
  1510. className="w-44 h-10 align-top"
  1511. onChange={(newValue) =>
  1512. selectStaffGradeMonthlyPeriodFrom(newValue)
  1513. }
  1514. defaultValue={
  1515. totalManHoursByStaffGradeMonthlyFromValue
  1516. }
  1517. label={"From"}
  1518. views={["month", "year"]}
  1519. />
  1520. <DatePicker
  1521. className="w-40 h-10 align-top"
  1522. onChange={(newValue) =>
  1523. selectStaffGradeMonthlyPeriodTo(newValue)
  1524. }
  1525. defaultValue={
  1526. totalManHoursByStaffGradeMonthlyToValue
  1527. }
  1528. label={"To"}
  1529. views={["month", "year"]}
  1530. />
  1531. </LocalizationProvider>
  1532. )}
  1533. {/* <Label className="text-slate-500 font-medium ml-6">
  1534. Period:&nbsp;
  1535. </Label>
  1536. <Input
  1537. id={'cashFlowYear'}
  1538. value={manHoursSpentPeriod}
  1539. readOnly={true}
  1540. bsSize="lg"
  1541. className="rounded-md text-base w-56 border-slate-200 border-solid text-slate-500 text-center"
  1542. /> */}
  1543. </div>
  1544. </div>
  1545. <ReactApexChart
  1546. options={staffGradeOptions}
  1547. series={staffGradeOptions.series}
  1548. type="bar"
  1549. height="400"
  1550. />
  1551. </div>
  1552. </Card>
  1553. </Grid>
  1554. </div>
  1555. </div>
  1556. <div
  1557. style={{
  1558. display: "inline-block",
  1559. width: "59%",
  1560. verticalAlign: "top",
  1561. marginLeft: 10,
  1562. }}
  1563. >
  1564. <Grid item xs={12} md={12} lg={12}>
  1565. <Card className="mb-5">
  1566. <CardHeader
  1567. className="text-slate-500"
  1568. title="Unsubmitted Time Sheet by Staff"
  1569. />
  1570. <div style={{ display: "inline-block", width: "99%" }}>
  1571. <div className="w-fit align-top mr-5 float-right">
  1572. {unsubmittedTimeSheetSelect === "Weekly" && (
  1573. <>
  1574. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid w-32">
  1575. Weekly
  1576. </button>
  1577. <button
  1578. onClick={() => {
  1579. teamTotalManhoursSpentOnClick("Monthly")
  1580. setUnsubmittedTimeSheetSelect("Monthly")
  1581. fetchMonthlyUnsubmittedData()
  1582. setStaffGradeManhoursSpentSelect("Monthly")
  1583. fetchMonthlyTotalManhoursByGradeData()
  1584. setIndividualStaffManhoursSpentSelect("Monthly")
  1585. fetchMonthlyIndividualManhoursData()
  1586. }
  1587. }
  1588. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-r-md w-32"
  1589. >
  1590. Monthly
  1591. </button>
  1592. </>
  1593. )}
  1594. {unsubmittedTimeSheetSelect === "Monthly" && (
  1595. <>
  1596. <button
  1597. onClick={() => {
  1598. teamTotalManhoursSpentOnClick("Weekly")
  1599. setUnsubmittedTimeSheetSelect("Weekly")
  1600. fetchWeeklyUnsubmittedData()
  1601. setStaffGradeManhoursSpentSelect("Weekly")
  1602. fetchTotalManhoursByGradeData()
  1603. setIndividualStaffManhoursSpentSelect("Weekly")
  1604. fetchWeeklyIndividualManhoursData()
  1605. }
  1606. }
  1607. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid w-32"
  1608. >
  1609. Weekly
  1610. </button>
  1611. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-32">
  1612. Monthly
  1613. </button>
  1614. </>
  1615. )}
  1616. </div>
  1617. <div className="inline-block w-fit mt-2">
  1618. {abilityViewDashboardAll && <div className="inline-block">
  1619. <div className="inline-block ml-6">
  1620. <Label className="text-slate-500 font-medium">
  1621. Team:&nbsp;
  1622. </Label>
  1623. </div>
  1624. <div className="inline-block ml-1 w-60">
  1625. <Select
  1626. placeholder="Please select a team"
  1627. options={teamManhoursTeamOptions}
  1628. isClearable={true}
  1629. onChange={(selectedOption: any) => {
  1630. if (selectedOption === null) {
  1631. setTeamUnsubmitTeamId(null);
  1632. } else {
  1633. setTeamUnsubmitTeamId(selectedOption.value);
  1634. }
  1635. }}
  1636. />
  1637. </div>
  1638. </div>}
  1639. <div className="ml-6 mt-2" style={{ verticalAlign: "top" }}>
  1640. {/* <Label className="text-slate-500 font-medium ml-6">
  1641. Period:&nbsp;
  1642. </Label> */}
  1643. {unsubmittedTimeSheetSelect === "Weekly" && (
  1644. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1645. <DatePicker
  1646. className="w-72 h-10 align-top"
  1647. label="Period:"
  1648. value={value}
  1649. format="DD-MM-YYYY"
  1650. onChange={(newValue) =>
  1651. selectWeeklyPeriodUnsubmittedTimeSheet(newValue)
  1652. }
  1653. showDaysOutsideCurrentMonth
  1654. displayWeekNumber
  1655. slots={{ day: Day }}
  1656. slotProps={{
  1657. day: (ownerState) =>
  1658. ({
  1659. selectedDay: value,
  1660. hoveredDay,
  1661. onPointerEnter: () =>
  1662. setHoveredDay(ownerState.day),
  1663. onPointerLeave: () => setHoveredDay(null),
  1664. }) as any,
  1665. }}
  1666. />
  1667. </LocalizationProvider>
  1668. )}
  1669. {unsubmittedTimeSheetSelect === "Monthly" && (
  1670. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1671. <DatePicker
  1672. className="w-40 h-10 align-top"
  1673. onChange={(newValue) =>
  1674. selectUnsubmittedTimeSheetMonthlyPeriodFrom(newValue)
  1675. }
  1676. defaultValue={
  1677. unsubmitMonthlyFromValue
  1678. }
  1679. label={"On"}
  1680. views={["month", "year"]}
  1681. />
  1682. {/* <DatePicker
  1683. className="w-40 h-10 align-top"
  1684. onChange={(newValue) =>
  1685. selectUnsubmittedTimeSheetMonthlyPeriodTo(newValue)
  1686. }
  1687. defaultValue={
  1688. totalManHoursByIndividualStaffMonthlyToValue
  1689. }
  1690. label={"To"}
  1691. views={["month", "year"]}
  1692. /> */}
  1693. </LocalizationProvider>
  1694. )}
  1695. </div>
  1696. </div>
  1697. <ReactApexChart
  1698. options={unsubmittedTimeSheetOptions}
  1699. series={unsubmittedTimeSheetOptions.series}
  1700. type="bar"
  1701. height="380"
  1702. />
  1703. <div className="float-right mr-4 mb-10">
  1704. {currentPage === 1 && (
  1705. <button className="bg-blue-500 text-white font-bold py-2 px-4 opacity-50 cursor-not-allowed rounded-l">
  1706. Pervious
  1707. </button>
  1708. )}
  1709. {currentPage !== 1 && (
  1710. <button onClick={handlePrevPage} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 outline-none rounded-l">
  1711. Previous
  1712. </button>
  1713. )}
  1714. {endIndex >= unsubmitCount.length && (
  1715. <button className="bg-blue-500 text-white font-bold py-2 px-4 opacity-50 cursor-not-allowed rounded-r mr-2">
  1716. Next
  1717. </button>
  1718. )}
  1719. {endIndex < unsubmitCount.length && (
  1720. <button onClick={handleNextPage} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 outline-none rounded-r mr-2">
  1721. Next
  1722. </button>
  1723. )}
  1724. Page&nbsp;
  1725. {unsubmitCount.length === 0 && (
  1726. 0
  1727. )}
  1728. {unsubmitCount.length > 0 && (
  1729. currentPage
  1730. )}
  1731. &nbsp;of&nbsp;
  1732. {Math.ceil(unsubmitCount.length / recordsPerPage)}
  1733. </div>
  1734. </div>
  1735. </Card>
  1736. <Card>
  1737. <Card>
  1738. <CardHeader
  1739. className="text-slate-500"
  1740. title="Manhours Spent by Individual Staff"
  1741. />
  1742. <div style={{ display: "inline-block", width: "99%" }}>
  1743. <div className="w-fit align-top mr-5 float-right">
  1744. {individualStaffManhoursSpentSelect === "Daily" && (
  1745. <>
  1746. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-l-md w-32">
  1747. Daily
  1748. </button>
  1749. <button
  1750. onClick={() => {
  1751. individualStaffManhoursSpentOnClick("Weekly")
  1752. fetchWeeklyIndividualManhoursData()
  1753. }
  1754. }
  1755. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid w-32"
  1756. >
  1757. Weekly
  1758. </button>
  1759. <button
  1760. onClick={() => {
  1761. individualStaffManhoursSpentOnClick("Monthly")
  1762. fetchMonthlyIndividualManhoursData()
  1763. }
  1764. }
  1765. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-r-md w-32"
  1766. >
  1767. Monthly
  1768. </button>
  1769. </>
  1770. )}
  1771. {individualStaffManhoursSpentSelect === "Weekly" && (
  1772. <>
  1773. {/* <button
  1774. onClick={() => {
  1775. individualStaffManhoursSpentOnClick("Daily")
  1776. fetchDailyIndividualManhoursData()
  1777. }
  1778. }
  1779. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-l-md w-32"
  1780. >
  1781. Daily
  1782. </button> */}
  1783. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid w-32">
  1784. Weekly
  1785. </button>
  1786. <button
  1787. onClick={() => {
  1788. teamTotalManhoursSpentOnClick("Monthly")
  1789. setUnsubmittedTimeSheetSelect("Monthly")
  1790. fetchMonthlyUnsubmittedData()
  1791. setStaffGradeManhoursSpentSelect("Monthly")
  1792. fetchMonthlyTotalManhoursByGradeData()
  1793. setIndividualStaffManhoursSpentSelect("Monthly")
  1794. fetchMonthlyIndividualManhoursData()
  1795. }
  1796. }
  1797. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-r-md w-32"
  1798. >
  1799. Monthly
  1800. </button>
  1801. </>
  1802. )}
  1803. {individualStaffManhoursSpentSelect === "Monthly" && (
  1804. <>
  1805. {/* <button
  1806. onClick={() => {
  1807. individualStaffManhoursSpentOnClick("Daily")
  1808. fetchDailyIndividualManhoursData()
  1809. }
  1810. }
  1811. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid rounded-l-md w-32"
  1812. >
  1813. Daily
  1814. </button> */}
  1815. <button
  1816. onClick={() => {
  1817. teamTotalManhoursSpentOnClick("Weekly")
  1818. setUnsubmittedTimeSheetSelect("Weekly")
  1819. fetchWeeklyUnsubmittedData()
  1820. setStaffGradeManhoursSpentSelect("Weekly")
  1821. fetchTotalManhoursByGradeData()
  1822. setIndividualStaffManhoursSpentSelect("Weekly")
  1823. fetchWeeklyIndividualManhoursData()
  1824. }
  1825. }
  1826. className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid w-32"
  1827. >
  1828. Weekly
  1829. </button>
  1830. <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-32">
  1831. Monthly
  1832. </button>
  1833. </>
  1834. )}
  1835. </div>
  1836. <div className="inline-block w-fit mt-2">
  1837. <div className="inline-block ml-6">
  1838. <Label className="text-slate-500 font-medium">
  1839. Staff Code and Name:&nbsp;
  1840. </Label>
  1841. </div>
  1842. <div className="inline-block ml-1 w-60">
  1843. <Select
  1844. placeholder="Please select a staff"
  1845. options={staffOptions}
  1846. isClearable={true}
  1847. onChange={(selectedOption: any) => {
  1848. if (selectedOption === null) {
  1849. setStaffId(null);
  1850. } else {
  1851. setStaffId(selectedOption.value);
  1852. }
  1853. }}
  1854. />
  1855. </div>
  1856. <div className="ml-6 mt-2" style={{ verticalAlign: "top" }}>
  1857. {/* <Label className="text-slate-500 font-medium ml-6">
  1858. Period:&nbsp;
  1859. </Label> */}
  1860. {individualStaffManhoursSpentSelect === "Daily" && (
  1861. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1862. <DatePicker
  1863. className="w-40 h-10 align-top"
  1864. format="DD-MM-YYYY"
  1865. onChange={(newValue: any) =>
  1866. setTotalManHoursByIndividualStaffDailyFromValue(newValue)
  1867. // selectIndividualStaffMonthlyPeriodFrom(newValue)
  1868. }
  1869. defaultValue={
  1870. totalManHoursByIndividualStaffDailyFromValue
  1871. }
  1872. label={"On"}
  1873. views={["day"]}
  1874. />
  1875. {/* <DatePicker
  1876. className="w-40 h-10 align-top"
  1877. onChange={(newValue) =>
  1878. selectIndividualStaffMonthlyPeriodTo(newValue)
  1879. }
  1880. defaultValue={
  1881. totalManHoursByIndividualStaffDailyToValue
  1882. }
  1883. label={"To"}
  1884. views={["day", "month", "year"]}
  1885. /> */}
  1886. </LocalizationProvider>
  1887. )}
  1888. {individualStaffManhoursSpentSelect === "Weekly" && (
  1889. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1890. <DatePicker
  1891. className="w-72 h-10 align-top"
  1892. label="Period:"
  1893. value={value}
  1894. format="DD-MM-YYYY"
  1895. onChange={(newValue) =>
  1896. selectWeeklyPeriodIndividualStaff(newValue)
  1897. }
  1898. showDaysOutsideCurrentMonth
  1899. displayWeekNumber
  1900. slots={{ day: Day }}
  1901. slotProps={{
  1902. day: (ownerState) =>
  1903. ({
  1904. selectedDay: value,
  1905. hoveredDay,
  1906. onPointerEnter: () =>
  1907. setHoveredDay(ownerState.day),
  1908. onPointerLeave: () => setHoveredDay(null),
  1909. }) as any,
  1910. }}
  1911. />
  1912. </LocalizationProvider>
  1913. )}
  1914. {individualStaffManhoursSpentSelect === "Monthly" && (
  1915. <LocalizationProvider dateAdapter={AdapterDayjs}>
  1916. <DatePicker
  1917. className="w-40 h-10 align-top"
  1918. onChange={(newValue: any) => {
  1919. console.log(newValue)
  1920. setIndivdualManHoursMonthlyFromValue(newValue)
  1921. }
  1922. // selectIndividualStaffMonthlyPeriodFrom(newValue)
  1923. }
  1924. defaultValue={
  1925. indivdualManHoursMonthlyFromValue
  1926. }
  1927. label={"On"}
  1928. views={["month", "year"]}
  1929. />
  1930. {/* <DatePicker
  1931. className="w-40 h-10 align-top"
  1932. onChange={(newValue) =>
  1933. selectIndividualStaffMonthlyPeriodTo(newValue)
  1934. }
  1935. defaultValue={
  1936. totalManHoursByIndividualStaffMonthlyToValue
  1937. }
  1938. label={"To"}
  1939. views={["month", "year"]}
  1940. /> */}
  1941. </LocalizationProvider>
  1942. )}
  1943. </div>
  1944. </div>
  1945. <ReactApexChart
  1946. options={individualStaffOptions}
  1947. series={individualStaffOptions.series}
  1948. type="bar"
  1949. height="380"
  1950. />
  1951. </div>
  1952. </Card>
  1953. <div style={{ display: "inline-block", width: "50%" }}>
  1954. <div
  1955. style={{
  1956. display: "inline-block",
  1957. width: "47%",
  1958. marginTop: 10,
  1959. marginLeft: 10,
  1960. }}
  1961. >
  1962. <Card style={{ height: 90 }}>
  1963. <div className="text-slate-500 text-center text-base">
  1964. Total Normal Hours Spent
  1965. </div>
  1966. <div
  1967. className="text-center w-full text-3xl font-bold"
  1968. style={{ color: "#92c1e9" }}
  1969. >
  1970. {totalNormalConsumption.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
  1971. </div>
  1972. </Card>
  1973. <Card style={{ marginTop: 10, height: 90 }}>
  1974. <div className="text-slate-500 text-center text-base">
  1975. Total Leave Hours
  1976. </div>
  1977. <div
  1978. className="text-center w-full text-3xl font-bold"
  1979. style={{ color: "#898d8d", marginTop: 10 }}
  1980. >
  1981. {totalLeaveHours.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
  1982. </div>
  1983. </Card>
  1984. </div>
  1985. <div
  1986. style={{
  1987. display: "inline-block",
  1988. width: "47%",
  1989. marginTop: 10,
  1990. marginLeft: 10,
  1991. verticalAlign: "top"
  1992. }}
  1993. >
  1994. <Card style={{ height: 90 }}>
  1995. <div className="text-slate-500 text-center text-base">
  1996. Total Other Hours Spent
  1997. </div>
  1998. <div
  1999. className="text-center w-full text-3xl font-bold"
  2000. style={{ color: "#92c1e9" }}
  2001. >
  2002. {totalOtConsumption.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
  2003. </div>
  2004. </Card>
  2005. {/* <Card style={{ marginTop: 10, height: 90 }}>
  2006. <div className="text-slate-500 text-center text-base">
  2007. Remaining Hours
  2008. </div>
  2009. <div
  2010. className="text-center w-full text-3xl font-bold"
  2011. style={{ color: "#898d8d", marginTop: 10 }}
  2012. >
  2013. 0.00
  2014. </div>
  2015. </Card> */}
  2016. </div>
  2017. </div>
  2018. <div style={{ display: "inline-block", width: "50%", verticalAlign: "top", marginTop: 10 }}>
  2019. <Card>
  2020. <CardHeader className="text-slat-500" title="Effort Proportion for individual Staff" />
  2021. <ReactApexChart
  2022. options={options2}
  2023. series={options2.series}
  2024. type="donut"
  2025. />
  2026. </Card>
  2027. </div>
  2028. </Card>
  2029. </Grid>
  2030. </div>
  2031. </Grid>
  2032. </>
  2033. );
  2034. };
  2035. export default StaffUtilization;