|
- "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<Dayjs> {
- isSelected: boolean;
- isHovered: boolean;
- }
-
- const CustomPickersDay = styled(PickersDay, {
- shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isHovered",
- })<CustomPickerDayProps>(({ 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<CustomPickerDayProps>;
-
- const isInSameWeek = (dayA: Dayjs, dayB: Dayjs | null | undefined) => {
- if (dayB == null) {
- return false;
- }
-
- return dayA.isSame(dayB, "week");
- };
-
- function Day(
- props: PickersDayProps<Dayjs> & {
- selectedDay?: Dayjs | null;
- hoveredDay?: Dayjs | null;
- },
- ) {
- const { day, selectedDay, hoveredDay, ...other } = props;
-
- return (
- <CustomPickersDay
- {...other}
- day={day}
- sx={{ px: 2.5 }}
- disableMargin
- selected={false}
- isSelected={isInSameWeek(day, selectedDay)}
- isHovered={isInSameWeek(day, hoveredDay)}
- />
- );
- }
-
- 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 [unsubmittedTimeSheetSelect, setUnsubmittedTimeSheetSelect]: any =
- React.useState("Weekly");
- 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 [
- unsubmittedTimeSheetPeriod,
- setUnsubmittedTimeSheetPeriod,
- ]: 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<Dayjs | null>(null);
- const [value, setValue] = React.useState<Dayjs | null>(dayjs());
- const [weeklyValueByStaffGrade, setWeeklyValueByStaffGrade] =
- React.useState<Dayjs | null>(dayjs());
- const [weeklyValueByIndividualStaff, setWeeklyValueByIndividualStaff] =
- React.useState<Dayjs | null>(dayjs());
- const [weeklyUnsubmittedTimeSheet, setWeeklyUnsubmittedTimeSheet ] =
- React.useState<Dayjs | null>(dayjs());
- const [staffGradeManhoursSpentValue, setStaffGradeManhoursSpentValue] =
- React.useState<Dayjs | null>(dayjs());
- const [totalManHoursMonthlyFromValue, setTotalManHoursMonthlyFromValue] =
- React.useState<Dayjs>(dayjs(new Date()).subtract(6, "month"));
- const [totalManHoursMonthlyToValue, setTotalManHoursMonthlyToValue] =
- React.useState<Dayjs>(dayjs());
- const [
- totalManHoursByStaffGradeMonthlyFromValue,
- setTotalManHoursByStaffGradeMonthlyFromValue,
- ] = React.useState<Dayjs>(dayjs(new Date()).subtract(6, "month"));
- const [
- totalManHoursByStaffGradeMonthlyToValue,
- setTotalManHoursByStaffGradeMonthlyToValue,
- ] = React.useState<Dayjs>(dayjs());
- const [
- totalManHoursByIndividualStaffMonthlyFromValue,
- setTotalManHoursByIndividualStaffMonthlyFromValue,
- ] = React.useState<Dayjs>(dayjs(new Date()).subtract(6, "month"));
- const [
- totalManHoursByIndividualStaffMonthlyToValue,
- setTotalManHoursByIndividualStaffMonthlyToValue,
- ] = React.useState<Dayjs>(dayjs());
- const [
- totalManHoursByIndividualStaffDailyFromValue,
- setTotalManHoursByIndividualStaffDailyFromValue,
- ] = React.useState<Dayjs>(dayjs(new Date()).subtract(6, "day"));
- const [
- totalManHoursByIndividualStaffDailyToValue,
- setTotalManHoursByIndividualStaffDailyToValue,
- ] = React.useState<Dayjs>(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 unsubmittedTimeSheetOptions: ApexOptions = {
- chart: {
- height: 350,
- type: "line",
- },
- stroke: {
- width: [1],
- },
- plotOptions: {
- bar: {
- horizontal: true,
- distributed: false,
- },
- },
- dataLabels: {
- enabled: true,
- },
- xaxis: {
- categories: [
- "001-Staff A",
- "002-Staff B",
- "005-Staff E",
- "006-Staff F",
- "007-Staff G",
- ],
- },
- yaxis: [
- {
- title: {
- text: "Staff",
- },
- min: 0,
- max: 12,
- tickAmount: 5,
- },
- ],
- grid: {
- borderColor: "#f1f1f1",
- },
- annotations: {},
- series: [
- {
- name: "Unsubmitted Time Sheet",
- type: "bar",
- color: "#00acb1",
- data: [2, 2, 1, 5, 1],
- },
- ],
- };
-
- 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 unsubmittedTimeSheetOnClick = (r: any) => {
- setUnsubmittedTimeSheetSelect(r);
- };
-
- 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 selectWeeklyPeriodUnsubmittedTimeSheet = (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);
- }
- setUnsubmittedTimeSheetPeriod(weekDates);
- setWeeklyUnsubmittedTimeSheet(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 selectUnsubmittedTimeSheetMonthlyPeriodFrom = (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)
- setUnsubmittedTimeSheetPeriod(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 selectUnsubmittedTimeSheetMonthlyPeriodTo = (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)
- setUnsubmittedTimeSheetPeriod(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 (
- <>
- <Grid item sm>
- <div style={{ display: "inline-block", width: "40%" }}>
- <div>
- <Grid item xs={12} md={12} lg={12}>
- <Card>
- <CardHeader
- className="text-slate-500"
- title="Team Total Manhours Spent"
- />
- <div style={{ display: "inline-block", width: "99%" }}>
- <div className="w-fit align-top mr-5 float-right">
- {teamTotalManhoursSpentSelect === "Weekly" && (
- <>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-l-md w-32">
- Weekly
- </button>
- <button
- onClick={() =>
- teamTotalManhoursSpentOnClick("Monthly")
- }
- 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"
- >
- Monthly
- </button>
- </>
- )}
- {teamTotalManhoursSpentSelect === "Monthly" && (
- <>
- <button
- onClick={() =>
- teamTotalManhoursSpentOnClick("Weekly")
- }
- 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"
- >
- Weekly
- </button>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-32">
- Monthly
- </button>
- </>
- )}
- </div>
- <div className="inline-block w-fit mt-2">
- <div className="inline-block ml-6">
- <Label className="text-slate-500 font-medium">
- Team:
- </Label>
- </div>
- <div className="inline-block ml-1 w-60">
- <Select
- placeholder="All Team"
- options={teamOptions}
- isClearable={true}
- />
- </div>
- <div className="ml-6 mt-2" style={{ verticalAlign: "top" }}>
- {/* <Label className="text-slate-500 font-medium ml-6">
- Period:
- </Label> */}
- {teamTotalManhoursSpentSelect === "Weekly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-72 h-10 align-top"
- label="Period:"
- value={value}
- format="DD-MM-YYYY"
- onChange={(newValue) =>
- selectWeeklyPeriod(newValue)
- }
- showDaysOutsideCurrentMonth
- displayWeekNumber
- slots={{ day: Day }}
- slotProps={{
- day: (ownerState) =>
- ({
- selectedDay: value,
- hoveredDay,
- onPointerEnter: () =>
- setHoveredDay(ownerState.day),
- onPointerLeave: () => setHoveredDay(null),
- }) as any,
- }}
- />
- </LocalizationProvider>
- )}
- {teamTotalManhoursSpentSelect === "Monthly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectMonthlyPeriodFrom(newValue)
- }
- defaultValue={totalManHoursMonthlyFromValue}
- label={"Form"}
- views={["month", "year"]}
- />
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectMonthlyPeriodTo(newValue)
- }
- defaultValue={totalManHoursMonthlyToValue}
- label={"To"}
- views={["month", "year"]}
- />
- </LocalizationProvider>
- )}
- </div>
- </div>
-
- <ReactApexChart
- options={options}
- series={options.series}
- type="line"
- height="400"
- />
- </div>
- </Card>
- </Grid>
- </div>
- <div className="mt-5">
- <Grid item xs={12} md={12} lg={12}>
- <Card>
- <CardHeader
- className="text-slate-500"
- title="Total Manhours Spent by Staff Grade"
- />
- <div style={{ display: "inline-block", width: "99%" }}>
- <div className="w-fit align-top mr-5 float-right">
- {staffGradeManhoursSpentSelect === "Weekly" && (
- <>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-l-md w-32">
- Weekly
- </button>
- <button
- onClick={() =>
- setStaffGradeManhoursSpentSelect("Monthly")
- }
- 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"
- >
- Monthly
- </button>
- </>
- )}
- {staffGradeManhoursSpentSelect === "Monthly" && (
- <>
- <button
- onClick={() =>
- setStaffGradeManhoursSpentSelect("Weekly")
- }
- 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"
- >
- Weekly
- </button>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-48">
- Monthly
- </button>
- </>
- )}
- </div>
- <div className="inline-block w-fit mt-2">
- <div className="inline-block mt-2 ml-6">
- {staffGradeManhoursSpentSelect === "Weekly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-72 h-10 align-top"
- label="Period:"
- value={value}
- format="DD-MM-YYYY"
- onChange={(newValue) =>
- selectWeeklyPeriodByStaffGrade(newValue)
- }
- showDaysOutsideCurrentMonth
- displayWeekNumber
- slots={{ day: Day }}
- slotProps={{
- day: (ownerState) =>
- ({
- selectedDay: value,
- hoveredDay,
- onPointerEnter: () =>
- setHoveredDay(ownerState.day),
- onPointerLeave: () => setHoveredDay(null),
- }) as any,
- }}
- />
- </LocalizationProvider>
- )}
- {staffGradeManhoursSpentSelect === "Monthly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectStaffGradeMonthlyPeriodFrom(newValue)
- }
- defaultValue={
- totalManHoursByStaffGradeMonthlyFromValue
- }
- label={"Form"}
- views={["month", "year"]}
- />
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectStaffGradeMonthlyPeriodTo(newValue)
- }
- defaultValue={
- totalManHoursByStaffGradeMonthlyToValue
- }
- label={"To"}
- views={["month", "year"]}
- />
- </LocalizationProvider>
- )}
- {/* <Label className="text-slate-500 font-medium ml-6">
- Period:
- </Label>
- <Input
- id={'cashFlowYear'}
- value={manHoursSpentPeriod}
- readOnly={true}
- bsSize="lg"
- className="rounded-md text-base w-56 border-slate-200 border-solid text-slate-500 text-center"
- /> */}
- </div>
- </div>
- <ReactApexChart
- options={staffGradeOptions}
- series={staffGradeOptions.series}
- type="bar"
- height="400"
- />
- </div>
- </Card>
- </Grid>
- </div>
- </div>
- <div
- style={{
- display: "inline-block",
- width: "59%",
- verticalAlign: "top",
- marginLeft: 10,
- }}
- >
- <Grid item xs={12} md={12} lg={12}>
- <Card className="mb-5">
- <CardHeader
- className="text-slate-500"
- title="Unsubmitted Time Sheet by Staff"
- />
- <div style={{ display: "inline-block", width: "99%" }}>
- <div className="w-fit align-top mr-5 float-right">
- {unsubmittedTimeSheetSelect === "Weekly" && (
- <>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid w-32">
- Weekly
- </button>
- <button
- onClick={() =>
- unsubmittedTimeSheetOnClick("Monthly")
- }
- 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"
- >
- Monthly
- </button>
- </>
- )}
- {unsubmittedTimeSheetSelect === "Monthly" && (
- <>
- <button
- onClick={() =>
- unsubmittedTimeSheetOnClick("Weekly")
- }
- className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid w-32"
- >
- Weekly
- </button>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-32">
- Monthly
- </button>
- </>
- )}
- </div>
- <div className="inline-block w-fit mt-2">
- <div className="inline-block ml-6">
- <Label className="text-slate-500 font-medium">
- Team:
- </Label>
- </div>
- <div className="inline-block ml-1 w-60">
- <Select
- placeholder="Team"
- options={teamOptions}
- isClearable={true}
- />
- </div>
- <div className="ml-6 mt-2" style={{ verticalAlign: "top" }}>
- {/* <Label className="text-slate-500 font-medium ml-6">
- Period:
- </Label> */}
- {unsubmittedTimeSheetSelect === "Weekly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-72 h-10 align-top"
- label="Period:"
- value={value}
- format="DD-MM-YYYY"
- onChange={(newValue) =>
- selectWeeklyPeriodUnsubmittedTimeSheet(newValue)
- }
- showDaysOutsideCurrentMonth
- displayWeekNumber
- slots={{ day: Day }}
- slotProps={{
- day: (ownerState) =>
- ({
- selectedDay: value,
- hoveredDay,
- onPointerEnter: () =>
- setHoveredDay(ownerState.day),
- onPointerLeave: () => setHoveredDay(null),
- }) as any,
- }}
- />
- </LocalizationProvider>
- )}
- {unsubmittedTimeSheetSelect === "Monthly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectUnsubmittedTimeSheetMonthlyPeriodFrom(newValue)
- }
- defaultValue={
- totalManHoursByIndividualStaffMonthlyFromValue
- }
- label={"Form"}
- views={["month", "year"]}
- />
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectUnsubmittedTimeSheetMonthlyPeriodTo(newValue)
- }
- defaultValue={
- totalManHoursByIndividualStaffMonthlyToValue
- }
- label={"To"}
- views={["month", "year"]}
- />
- </LocalizationProvider>
- )}
- </div>
- </div>
-
- <ReactApexChart
- options={unsubmittedTimeSheetOptions}
- series={unsubmittedTimeSheetOptions.series}
- type="bar"
- height="380"
- />
- </div>
- </Card>
- <Card>
- <Card>
- <CardHeader
- className="text-slate-500"
- title="Manhours Spent by Individual Staff"
- />
- <div style={{ display: "inline-block", width: "99%" }}>
- <div className="w-fit align-top mr-5 float-right">
- {individualStaffManhoursSpentSelect === "Daily" && (
- <>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-l-md w-32">
- Daily
- </button>
- <button
- onClick={() =>
- individualStaffManhoursSpentOnClick("Weekly")
- }
- className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid w-32"
- >
- Weekly
- </button>
- <button
- onClick={() =>
- individualStaffManhoursSpentOnClick("Monthly")
- }
- 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"
- >
- Monthly
- </button>
- </>
- )}
- {individualStaffManhoursSpentSelect === "Weekly" && (
- <>
- <button
- onClick={() =>
- individualStaffManhoursSpentOnClick("Daily")
- }
- 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"
- >
- Daily
- </button>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid w-32">
- Weekly
- </button>
- <button
- onClick={() =>
- individualStaffManhoursSpentOnClick("Monthly")
- }
- 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"
- >
- Monthly
- </button>
- </>
- )}
- {individualStaffManhoursSpentSelect === "Monthly" && (
- <>
- <button
- onClick={() =>
- individualStaffManhoursSpentOnClick("Daily")
- }
- 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"
- >
- Daily
- </button>
- <button
- onClick={() =>
- individualStaffManhoursSpentOnClick("Weekly")
- }
- className="hover:cursor-pointer hover:bg-violet-50 text-lg bg-transparent border-violet-500 text-violet-500 border-solid w-32"
- >
- Weekly
- </button>
- <button className="text-lg bg-violet-100 border-violet-500 text-violet-500 border-solid rounded-r-md w-32">
- Monthly
- </button>
- </>
- )}
- </div>
- <div className="inline-block w-fit mt-2">
- <div className="inline-block ml-6">
- <Label className="text-slate-500 font-medium">
- Staff Code and Name:
- </Label>
- </div>
- <div className="inline-block ml-1 w-60">
- <Select
- placeholder="00338-Chris Wong"
- options={teamOptions}
- isClearable={true}
- />
- </div>
- <div className="ml-6 mt-2" style={{ verticalAlign: "top" }}>
- {/* <Label className="text-slate-500 font-medium ml-6">
- Period:
- </Label> */}
- {individualStaffManhoursSpentSelect === "Daily" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectIndividualStaffMonthlyPeriodFrom(newValue)
- }
- defaultValue={
- totalManHoursByIndividualStaffDailyFromValue
- }
- label={"Form"}
- views={["day", "month", "year"]}
- />
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectIndividualStaffMonthlyPeriodTo(newValue)
- }
- defaultValue={
- totalManHoursByIndividualStaffDailyToValue
- }
- label={"To"}
- views={["day", "month", "year"]}
- />
- </LocalizationProvider>
- )}
- {individualStaffManhoursSpentSelect === "Weekly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-72 h-10 align-top"
- label="Period:"
- value={value}
- format="DD-MM-YYYY"
- onChange={(newValue) =>
- selectWeeklyPeriodIndividualStaff(newValue)
- }
- showDaysOutsideCurrentMonth
- displayWeekNumber
- slots={{ day: Day }}
- slotProps={{
- day: (ownerState) =>
- ({
- selectedDay: value,
- hoveredDay,
- onPointerEnter: () =>
- setHoveredDay(ownerState.day),
- onPointerLeave: () => setHoveredDay(null),
- }) as any,
- }}
- />
- </LocalizationProvider>
- )}
- {individualStaffManhoursSpentSelect === "Monthly" && (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectIndividualStaffMonthlyPeriodFrom(newValue)
- }
- defaultValue={
- totalManHoursByIndividualStaffMonthlyFromValue
- }
- label={"Form"}
- views={["month", "year"]}
- />
- <DatePicker
- className="w-40 h-10 align-top"
- onChange={(newValue) =>
- selectIndividualStaffMonthlyPeriodTo(newValue)
- }
- defaultValue={
- totalManHoursByIndividualStaffMonthlyToValue
- }
- label={"To"}
- views={["month", "year"]}
- />
- </LocalizationProvider>
- )}
- </div>
- </div>
-
- <ReactApexChart
- options={individualStaffOptions}
- series={individualStaffOptions.series}
- type="bar"
- height="380"
- />
- </div>
- </Card>
- <div style={{ display: "inline-block", width: "50%" }}>
- <div
- style={{
- display: "inline-block",
- width: "47%",
- marginTop: 10,
- marginLeft: 10,
- }}
- >
- <Card style={{ height: 90 }}>
- <div className="text-slate-500 text-center text-base">
- Total Normal Hours Spent
- </div>
- <div
- className="text-center w-full text-3xl font-bold"
- style={{ color: "#92c1e9" }}
- >
- 40.00
- </div>
- </Card>
- <Card style={{ marginTop: 10, height: 90 }}>
- <div className="text-slate-500 text-center text-base">
- Total Leave Hours
- </div>
- <div
- className="text-center w-full text-3xl font-bold"
- style={{ color: "#898d8d", marginTop: 10 }}
- >
- 0.00
- </div>
- </Card>
- </div>
- <div
- style={{
- display: "inline-block",
- width: "47%",
- marginTop: 10,
- marginLeft: 10,
- }}
- >
- <Card style={{ height: 90 }}>
- <div className="text-slate-500 text-center text-base">
- Total Other Hours Spent
- </div>
- <div
- className="text-center w-full text-3xl font-bold"
- style={{ color: "#92c1e9" }}
- >
- 7.00
- </div>
- </Card>
- <Card style={{ marginTop: 10, height: 90 }}>
- <div className="text-slate-500 text-center text-base">
- Remaining Hours
- </div>
- <div
- className="text-center w-full text-3xl font-bold"
- style={{ color: "#898d8d", marginTop: 10 }}
- >
- 0.00
- </div>
- </Card>
- </div>
- </div>
- <div style={{ display: "inline-block", width: "50%",verticalAlign:"top",marginTop:10}}>
- <Card>
- <CardHeader className="text-slat-500" title="Effort Proportion for individual Staff"/>
- <ReactApexChart
- options={options2}
- series={options2.series}
- type="donut"
- />
- </Card>
- </div>
- </Card>
- </Grid>
- </div>
- </Grid>
- </>
- );
- };
-
- export default StaffUtilization;
|