"use client"; import * as React from "react"; import Grid from "@mui/material/Grid"; import { useState, useEffect, useMemo } from "react"; import Paper from "@mui/material/Paper"; import { TFunction } from "i18next"; import { useTranslation } from "react-i18next"; import { Card, CardHeader } from "@mui/material"; import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; import ReactApexChart from "react-apexcharts"; import { ApexOptions } from "apexcharts"; import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; import ReportProblemIcon from "@mui/icons-material/ReportProblem"; import dynamic from "next/dynamic"; import "../../app/global.css"; import { AnyARecord, AnyCnameRecord } from "dns"; import SearchBox, { Criterion } from "../SearchBox"; import ProgressByClientSearch from "@/components/ProgressByClientSearch"; import { Suspense } from "react"; import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; import { Input, Label } from "reactstrap"; import Select, { components } from "react-select"; import { DateCalendar } from "@mui/x-date-pickers/DateCalendar"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import dayjs, { Dayjs } from "dayjs"; import isBetweenPlugin from "dayjs/plugin/isBetween"; import { PickersDay, PickersDayProps } from "@mui/x-date-pickers/PickersDay"; import { styled } from "@mui/material/styles"; dayjs.extend(isBetweenPlugin); interface CustomPickerDayProps extends PickersDayProps { isSelected: boolean; isHovered: boolean; } const CustomPickersDay = styled(PickersDay, { shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isHovered", })(({ theme, isSelected, isHovered, day }) => ({ borderRadius: 0, ...(isSelected && { backgroundColor: theme.palette.primary.main, color: theme.palette.primary.contrastText, "&:hover, &:focus": { backgroundColor: theme.palette.primary.main, }, }), ...(isHovered && { backgroundColor: theme.palette.primary[theme.palette.mode], "&:hover, &:focus": { backgroundColor: theme.palette.primary[theme.palette.mode], }, }), ...(day.day() === 0 && { borderTopLeftRadius: "50%", borderBottomLeftRadius: "50%", }), ...(day.day() === 6 && { borderTopRightRadius: "50%", borderBottomRightRadius: "50%", }), })) as React.ComponentType; const isInSameWeek = (dayA: Dayjs, dayB: Dayjs | null | undefined) => { if (dayB == null) { return false; } return dayA.isSame(dayB, "week"); }; function Day( props: PickersDayProps & { selectedDay?: Dayjs | null; hoveredDay?: Dayjs | null; }, ) { const { day, selectedDay, hoveredDay, ...other } = props; return ( ); } const StaffUtilization: React.FC = () => { const todayDate = new Date(); const firstDayOfWeek = new Date(); const lastDayOfWeek = new Date(); firstDayOfWeek.setDate(todayDate.getDate() - todayDate.getDay() + 1); lastDayOfWeek.setDate(todayDate.getDate() - todayDate.getDay() + 7); const firstDayOfMonth = new Date( todayDate.getFullYear(), todayDate.getMonth(), 1, ); const lastDayOfMonth = new Date( todayDate.getFullYear(), todayDate.getMonth() + 1, 0, ); const [firstDayOfWeekString, setFirstDayOfWeekString] = React.useState( dayjs(firstDayOfWeek).format("DD MMM YYYY"), ); const [lastDayOfWeekString, setLastDayOfWeekString] = React.useState( dayjs(lastDayOfWeek).format("DD MMM YYYY"), ); const [firstDayOfMonthString, setFirstDayOfMonthString] = React.useState( dayjs(firstDayOfMonth).format("DD MMM YYYY"), ); const [lastDayOfMonthString, setLastDayOfMonthString] = React.useState( dayjs(lastDayOfMonth).format("DD MMM YYYY"), ); const [selectionModel, setSelectionModel]: any[] = React.useState([]); const [manHoursSpentPeriod, setManHoursSpentPeriod]: any[] = React.useState( firstDayOfWeekString + " to " + lastDayOfWeekString, ); const [teamTotalManhoursSpentSelect, setTeamTotalManhoursSpentSelect]: any = React.useState("Weekly"); const [staffGradeManhoursSpentSelect, setStaffGradeManhoursSpentSelect]: any = React.useState("Weekly"); const [ individualStaffManhoursSpentSelect, setIndividualStaffManhoursSpentSelect, ]: any = React.useState("Daily"); const weekDates: any[] = []; const monthDates: any[] = []; const currentDate = dayjs(); const sixMonthsAgo = currentDate.subtract(6, "month"); for (let i = 0; i < 7; i++) { const currentDate = new Date(firstDayOfWeek); currentDate.setDate(firstDayOfWeek.getDate() + i); const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); weekDates.push(formattedDate); } for ( let date = sixMonthsAgo.clone(); date.isBefore(currentDate, "month"); date = date.add(1, "month") ) { monthDates.push(date.format("MM-YYYY")); } monthDates.push(currentDate.format("MM-YYYY")); // for (let i = firstDayOfMonth.getDate(); i <= lastDayOfMonth.getDate(); i++) { // const currentDate = new Date(todayDate.getFullYear(), todayDate.getMonth(), i); // const formattedDate = dayjs(currentDate).format('DD MMM'); // monthDates.push(formattedDate); // } const [teamTotalManhoursSpentPeriod, setTeamTotalManhoursSpentPeriod]: any[] = React.useState(weekDates); const [ teamTotalManhoursByStaffGrade, setTeamTotalManhoursByStaffGrade, ]: any[] = React.useState(weekDates); const [ individualStaffManhoursSpentPeriod, setIndividualStaffManhoursSpentPeriod, ]: any[] = React.useState(weekDates); const [ teamTotalManhoursSpentPlanData, setTeamTotalManhoursSpentPlanData, ]: any[] = React.useState([42, 42, 42, 42, 42, 0, 0]); const [ teamTotalManhoursSpentActualData, setTeamTotalManhoursSpentActualData, ]: any[] = React.useState([45, 42, 60, 42, 58, 0, 0]); const [hoveredDay, setHoveredDay] = React.useState(null); const [value, setValue] = React.useState(dayjs()); const [weeklyValueByStaffGrade, setWeeklyValueByStaffGrade] = React.useState(dayjs()); const [weeklyValueByIndividualStaff, setWeeklyValueByIndividualStaff] = React.useState(dayjs()); const [staffGradeManhoursSpentValue, setStaffGradeManhoursSpentValue] = React.useState(dayjs()); const [totalManHoursMonthlyFromValue, setTotalManHoursMonthlyFromValue] = React.useState(dayjs(new Date()).subtract(6, "month")); const [totalManHoursMonthlyToValue, setTotalManHoursMonthlyToValue] = React.useState(dayjs()); const [ totalManHoursByStaffGradeMonthlyFromValue, setTotalManHoursByStaffGradeMonthlyFromValue, ] = React.useState(dayjs(new Date()).subtract(6, "month")); const [ totalManHoursByStaffGradeMonthlyToValue, setTotalManHoursByStaffGradeMonthlyToValue, ] = React.useState(dayjs()); const [ totalManHoursByIndividualStaffMonthlyFromValue, setTotalManHoursByIndividualStaffMonthlyFromValue, ] = React.useState(dayjs(new Date()).subtract(6, "month")); const [ totalManHoursByIndividualStaffMonthlyToValue, setTotalManHoursByIndividualStaffMonthlyToValue, ] = React.useState(dayjs()); const [ totalManHoursByIndividualStaffDailyFromValue, setTotalManHoursByIndividualStaffDailyFromValue, ] = React.useState(dayjs(new Date()).subtract(6, "day")); const [ totalManHoursByIndividualStaffDailyToValue, setTotalManHoursByIndividualStaffDailyToValue, ] = React.useState(dayjs()); const [totalManHoursMaxValue, setTotalManHoursMaxValue] = React.useState(75); const teamOptions = [ { value: 1, label: "XXX Team" }, { value: 2, label: "YYY Team" }, { value: 3, label: "ZZZ Team" }, ]; const columns = [ { id: "projectCode", field: "projectCode", headerName: "Project Code", flex: 1, }, { id: "projectName", field: "projectName", headerName: "Project Name", flex: 1, }, { id: "team", field: "team", headerName: "Team", flex: 1, }, { id: "teamLeader", field: "teamLeader", headerName: "Team Leader", flex: 1, }, { id: "startDate", field: "startDate", headerName: "Start Date", flex: 1, }, { id: "targetEndDate", field: "targetEndDate", headerName: "Target End Date", flex: 1, }, { id: "client", field: "client", headerName: "Client", flex: 1, }, { id: "subsidiary", field: "subsidiary", headerName: "Subsidiary", flex: 1, }, ]; const options: ApexOptions = { chart: { height: 350, type: "line", }, stroke: { width: [2, 2], }, plotOptions: { bar: { horizontal: false, distributed: false, }, }, dataLabels: { enabled: true, }, xaxis: { categories: teamTotalManhoursSpentPeriod, }, yaxis: [ { title: { text: "Team Total Manhours Spent (Hour)", }, min: 0, max: totalManHoursMaxValue, tickAmount: 5, }, ], grid: { borderColor: "#f1f1f1", }, annotations: {}, series: [ { name: "Planned", type: "line", color: "#efbe7d", data: teamTotalManhoursSpentPlanData, }, { name: "Actual", type: "line", color: "#7cd3f2", data: teamTotalManhoursSpentActualData, }, ], }; const staffGradeOptions: ApexOptions = { chart: { height: 350, type: "line", }, stroke: { width: [2, 2], }, plotOptions: { bar: { horizontal: true, distributed: false, }, }, dataLabels: { enabled: true, }, xaxis: { categories: [ "Grade 1: A. QS / QS Trainee", "Grade 2: QS", "Grade 3: Senior QS", "Grade 4: Manager", "Grade 5: Director", ], }, yaxis: [ { title: { text: "Staff Grade", }, min: 0, max: 60, tickAmount: 5, }, ], grid: { borderColor: "#f1f1f1", }, annotations: {}, series: [ { name: "Planned", type: "bar", color: "#efbe7d", data: [35, 45, 35, 20, 10], }, { name: "Actual", type: "bar", color: "#00acb1", data: [25, 26, 33, 20, 11], }, ], }; const individualStaffOptions: ApexOptions = { chart: { height: 350, type: "line", }, stroke: { width: [1], }, plotOptions: { bar: { horizontal: true, distributed: false, }, }, dataLabels: { enabled: true, }, xaxis: { categories: [ "Consultancy Project 123 (CUST-001, Subsidiary A)", "Consultancy Project 456 (CUST-001, Subsidiary A)", "Construction Project A (CUST-001, Subsidiary A)", "Construction Project B (CUST-001, Subsidiary A)", "Construction Project C (CUST-001, Subsidiary A)", ], }, yaxis: [ { title: { text: "Project", }, min: 0, max: 12, tickAmount: 5, }, ], grid: { borderColor: "#f1f1f1", }, annotations: {}, series: [ { name: "Manhours(Hour)", type: "bar", color: "#00acb1", data: [12, 12, 11, 12, 0], }, ], }; const teamTotalManhoursSpentOnClick = (r: any) => { setTeamTotalManhoursSpentSelect(r); if (r === "Weekly") { setValue(dayjs(new Date())); setTeamTotalManhoursSpentPeriod(weekDates); setTeamTotalManhoursSpentPlanData([42, 42, 42, 42, 42, 0, 0]); setTeamTotalManhoursSpentActualData([45, 42, 60, 42, 58, 0, 0]); setTotalManHoursMaxValue(75); } else if (r === "Monthly") { setTeamTotalManhoursSpentPeriod(monthDates); setTeamTotalManhoursSpentPlanData([840, 840, 840, 840, 840, 840]); setTeamTotalManhoursSpentActualData([900, 840, 1200, 840, 1160, 840]); setTotalManHoursMaxValue(1250); } }; const individualStaffManhoursSpentOnClick = (r: any) => { setIndividualStaffManhoursSpentSelect(r); // if (r === "Weekly") { // setValue(dayjs(new Date)) // setTeamTotalManhoursSpentPeriod(weekDates) // setTeamTotalManhoursSpentPlanData([42,42,42,42,42,0,0]) // setTeamTotalManhoursSpentActualData([45,42,60,42,58,0,0]) // setTotalManHoursMaxValue(75) // } else if (r === "Monthly") { // setTeamTotalManhoursSpentPeriod(monthDates) // setTeamTotalManhoursSpentPlanData([840,840,840,840,840,840]) // setTeamTotalManhoursSpentActualData([900,840,1200,840,1160,840]) // setTotalManHoursMaxValue(1250) // } }; const selectWeeklyPeriod = (r: any) => { const selectDate = new Date(r); const firstDayOfWeek = new Date(); firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0); const weekDates: any[] = []; for (let i = 0; i < 7; i++) { const currentDate = new Date(firstDayOfWeek); currentDate.setDate(firstDayOfWeek.getDate() + i); const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); weekDates.push(formattedDate); } setTeamTotalManhoursSpentPeriod(weekDates); setValue(dayjs(firstDayOfWeek)); }; const selectWeeklyPeriodByStaffGrade = (r: any) => { const selectDate = new Date(r); const firstDayOfWeek = new Date(); firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0); const weekDates: any[] = []; for (let i = 0; i < 7; i++) { const currentDate = new Date(firstDayOfWeek); currentDate.setDate(firstDayOfWeek.getDate() + i); const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); weekDates.push(formattedDate); } setTeamTotalManhoursByStaffGrade(weekDates); setWeeklyValueByStaffGrade(dayjs(firstDayOfWeek)); }; const selectWeeklyPeriodIndividualStaff = (r: any) => { const selectDate = new Date(r); const firstDayOfWeek = new Date(); firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0); const weekDates: any[] = []; for (let i = 0; i < 7; i++) { const currentDate = new Date(firstDayOfWeek); currentDate.setDate(firstDayOfWeek.getDate() + i); const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); weekDates.push(formattedDate); } setIndividualStaffManhoursSpentPeriod(weekDates); setWeeklyValueByIndividualStaff(dayjs(firstDayOfWeek)); }; const selectMonthlyPeriodFrom = (r: any) => { const monthDates: any[] = []; const monthPlanData: any[] = []; const monthActualData: any[] = []; const selectFromDate = dayjs(r); for ( let date = selectFromDate.clone(); date.isBefore(totalManHoursMonthlyToValue, "month"); date = date.add(1, "month") ) { monthDates.push(date.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); } monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); setTeamTotalManhoursSpentPlanData(monthPlanData); setTeamTotalManhoursSpentActualData(monthActualData); setTeamTotalManhoursSpentPeriod(monthDates); }; const selectMonthlyPeriodTo = (r: any) => { const monthDates: any[] = []; const monthPlanData: any[] = []; const monthActualData: any[] = []; const selectToDate = dayjs(r); for ( let date = totalManHoursMonthlyFromValue.clone(); date.isBefore(selectToDate, "month"); date = date.add(1, "month") ) { monthDates.push(date.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); } monthDates.push(selectToDate.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); setTeamTotalManhoursSpentPlanData(monthPlanData); setTeamTotalManhoursSpentActualData(monthActualData); setTeamTotalManhoursSpentPeriod(monthDates); }; const selectStaffGradeMonthlyPeriodFrom = (r: any) => { const monthDates: any[] = []; const monthPlanData: any[] = []; const monthActualData: any[] = []; const selectFromDate = dayjs(r); for ( let date = selectFromDate.clone(); date.isBefore(totalManHoursMonthlyToValue, "month"); date = date.add(1, "month") ) { monthDates.push(date.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); } monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); // setTeamTotalManhoursSpentPlanData(monthPlanData) // setTeamTotalManhoursSpentActualData(monthActualData) setTeamTotalManhoursByStaffGrade(weekDates); }; const selectStaffGradeMonthlyPeriodTo = (r: any) => { const monthDates: any[] = []; const monthPlanData: any[] = []; const monthActualData: any[] = []; const selectToDate = dayjs(r); for ( let date = totalManHoursMonthlyFromValue.clone(); date.isBefore(selectToDate, "month"); date = date.add(1, "month") ) { monthDates.push(date.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); } monthDates.push(selectToDate.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); // setTeamTotalManhoursSpentPlanData(monthPlanData) // setTeamTotalManhoursSpentActualData(monthActualData) setTeamTotalManhoursByStaffGrade(weekDates); }; const selectIndividualStaffMonthlyPeriodFrom = (r: any) => { const monthDates: any[] = []; const monthPlanData: any[] = []; const monthActualData: any[] = []; const selectFromDate = dayjs(r); for ( let date = selectFromDate.clone(); date.isBefore(totalManHoursMonthlyToValue, "month"); date = date.add(1, "month") ) { monthDates.push(date.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); } monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); // setTeamTotalManhoursSpentPlanData(monthPlanData) // setTeamTotalManhoursSpentActualData(monthActualData) setIndividualStaffManhoursSpentPeriod(weekDates); }; const selectIndividualStaffMonthlyPeriodTo = (r: any) => { const monthDates: any[] = []; const monthPlanData: any[] = []; const monthActualData: any[] = []; const selectToDate = dayjs(r); for ( let date = totalManHoursMonthlyFromValue.clone(); date.isBefore(selectToDate, "month"); date = date.add(1, "month") ) { monthDates.push(date.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); } monthDates.push(selectToDate.format("MM-YYYY")); monthPlanData.push(840); monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); // setTeamTotalManhoursSpentPlanData(monthPlanData) // setTeamTotalManhoursSpentActualData(monthActualData) setIndividualStaffManhoursSpentPeriod(weekDates); }; const options2: ApexOptions = { chart: { type: "donut", }, colors: ['#f57f90','#94f7d6','#87c5f5','#ab95f5','#ab95f5'], plotOptions: { pie: { donut: { labels: { show: true, name: { show: true, }, value: { show: false, fontWeight: 500, fontSize: "30px", color: "#3e98c7", }, total: { show: false, showAlways: true, label: "Spent", fontFamily: "sans-serif", formatter: function (val) { return val + "%"; }, }, }, }, }, }, series:[23.5,25.5,25.5,25.5], labels: ["Consultancy Project 123","Consultancy Project ABC","Consultancy Project A","Consultancy Project B"], legend: { show: false, }, responsive: [ { breakpoint: 480, options: { chart: { width: 200, }, legend: { position: "bottom", show: false, }, }, }, ], }; return ( <>
{teamTotalManhoursSpentSelect === "Weekly" && ( <> )} {teamTotalManhoursSpentSelect === "Monthly" && ( <> )}
*/}
{individualStaffManhoursSpentSelect === "Daily" && ( <> )} {individualStaffManhoursSpentSelect === "Weekly" && ( <> )} {individualStaffManhoursSpentSelect === "Monthly" && ( <> )}