|
@@ -0,0 +1,841 @@ |
|
|
|
|
|
"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 [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<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 [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 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) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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> |
|
|
|
|
|
<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> |
|
|
|
|
|
</Card> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
</div> |
|
|
|
|
|
</Grid> |
|
|
|
|
|
</> |
|
|
|
|
|
); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
export default StaffUtilization; |