Переглянути джерело

added staff utilization page

tags/Baseline_30082024_FRONTEND_UAT
MSI\User 1 рік тому
джерело
коміт
15ac350dcb
4 змінених файлів з 872 додано та 0 видалено
  1. +28
    -0
      src/app/(main)/dashboard/StaffUtilization/page.tsx
  2. +2
    -0
      src/components/NavigationContent/NavigationContent.tsx
  3. +841
    -0
      src/components/StaffUtilization/StaffUtilization.tsx
  4. +1
    -0
      src/components/StaffUtilization/index.ts

+ 28
- 0
src/app/(main)/dashboard/StaffUtilization/page.tsx Переглянути файл

@@ -0,0 +1,28 @@
import { Metadata } from "next";
import { I18nProvider } from "@/i18n";
import DashboardPage from "@/components/DashboardPage/DashboardPage";
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton";
import ProgressByClientSearch from "@/components/ProgressByClientSearch";
import { Suspense} from "react";
import Tabs, { TabsProps } from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import Typography from "@mui/material/Typography";
import StaffUtilizationComponent from "@/components/StaffUtilization";

export const metadata: Metadata = {
title: "Project Status by Client",
};


const StaffUtilization: React.FC = () => {

return (
<I18nProvider namespaces={["dashboard"]}>
<Typography variant="h4" marginInlineEnd={2}>
Staff Utilization
</Typography>
<StaffUtilizationComponent/>
</I18nProvider>
);
};
export default StaffUtilization;

+ 2
- 0
src/components/NavigationContent/NavigationContent.tsx Переглянути файл

@@ -11,6 +11,7 @@ import SummarizeIcon from '@mui/icons-material/Summarize';
import PaymentsIcon from '@mui/icons-material/Payments';
import AccountTreeIcon from '@mui/icons-material/AccountTree';
import RequestQuote from "@mui/icons-material/RequestQuote";
import PeopleIcon from '@mui/icons-material/People';
import Task from "@mui/icons-material/Task";
import Assignment from "@mui/icons-material/Assignment";
import Settings from "@mui/icons-material/Settings";
@@ -38,6 +39,7 @@ const navigationItems: NavigationItem[] = [
{ icon: <PaymentsIcon />, label: "Company / Team Cash Flow", path: "/dashboard/CompanyTeamCashFlow" },
{ icon: <PaymentsIcon />, label: "Project Cash Flow", path: "/dashboard/ProjectCashFlow" },
{ icon: <AccountTreeIcon />, label: "Project Status by Client", path: "/dashboard/ProjectStatusByClient" },
{ icon: <PeopleIcon />, label: "Staff Utilization", path: "/dashboard/StaffUtilization" },
]},
{ icon: <RequestQuote />, label: "Staff Reimbursement", path: "/staffReimbursement", children: [
{ icon: <RequestQuote />, label: "ClaimApproval", path: "/staffReimbursement/ClaimApproval"},


+ 841
- 0
src/components/StaffUtilization/StaffUtilization.tsx Переглянути файл

@@ -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:&nbsp;
</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:&nbsp;
</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:&nbsp;
</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:&nbsp;
</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:&nbsp;
</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;

+ 1
- 0
src/components/StaffUtilization/index.ts Переглянути файл

@@ -0,0 +1 @@
export { default } from "./StaffUtilization";

Завантаження…
Відмінити
Зберегти