diff --git a/src/app/(main)/NotInUse/page.tsx b/src/app/(main)/NotInUse/page.tsx deleted file mode 100644 index a710195..0000000 --- a/src/app/(main)/NotInUse/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Metadata } from "next"; -import { I18nProvider } from "@/i18n"; -import UserWorkspacePage from "@/components/UserWorkspacePage/UserWorkspacePage"; - -export const metadata: Metadata = { - title: "User Workspace", -}; - -const Home: React.FC = async () => { - return ( - - - - ); -}; - -export default Home; diff --git a/src/app/(main)/home/page.tsx b/src/app/(main)/dashboard/page.tsx similarity index 55% rename from src/app/(main)/home/page.tsx rename to src/app/(main)/dashboard/page.tsx index fe49aa6..9d40019 100644 --- a/src/app/(main)/home/page.tsx +++ b/src/app/(main)/dashboard/page.tsx @@ -1,26 +1,30 @@ import { Metadata } from "next"; import { I18nProvider } from "@/i18n"; -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 { getServerI18n } from "@/i18n"; import DashboardPage from "@/components/DashboardPage"; +import { SearchParams } from "@/app/utils/fetchUtil"; export const metadata: Metadata = { title: "Dashboard", }; -// type Props = { -// test: string -// } -const Dashboard: React.FC = async () => { +type Props = { + +} & SearchParams + +const Dashboard: React.FC = async ({ + searchParams +}) => { const { t } = await getServerI18n("dashboard"); return ( - + }> + + ) }; diff --git a/src/app/(main)/home/CompanyTeamCashFlow/page.tsx b/src/app/(main)/home/CompanyTeamCashFlow/page.tsx deleted file mode 100644 index 3a6079d..0000000 --- a/src/app/(main)/home/CompanyTeamCashFlow/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Metadata } from "next"; -import { I18nProvider } from "@/i18n"; -import DashboardPage from "@/components/DashboardPage/DashboardPage"; -import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; -import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; -import { Suspense } from "react"; -import Tabs, { TabsProps } from "@mui/material/Tabs"; -import Tab from "@mui/material/Tab"; -import Typography from "@mui/material/Typography"; -import CompanyTeamCashFlowComponent from "@/components/CompanyTeamCashFlow"; - -export const metadata: Metadata = { - title: "Project Status by Client", -}; - -const CompanyTeamCashFlow: React.FC = () => { - return ( - - - Company / Team Cash Flow - - - - ); -}; -export default CompanyTeamCashFlow; diff --git a/src/app/(main)/home/ProjectCashFlow/page.tsx b/src/app/(main)/home/ProjectCashFlow/page.tsx deleted file mode 100644 index 2e87f44..0000000 --- a/src/app/(main)/home/ProjectCashFlow/page.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { Metadata } from "next"; -import { I18nProvider } from "@/i18n"; -import DashboardPage from "@/components/DashboardPage/DashboardPage"; -import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; -import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; -import { Suspense } from "react"; -import Tabs, { TabsProps } from "@mui/material/Tabs"; -import Tab from "@mui/material/Tab"; -import Typography from "@mui/material/Typography"; -import ProjectCashFlowComponent from "@/components/ProjectCashFlow"; - -export const metadata: Metadata = { - title: "Project Status by Client", -}; - -const ProjectCashFlow: React.FC = () => { - return ( - - - Project Cash Flow - - {/* }> - - */} - - - ); -}; -export default ProjectCashFlow; diff --git a/src/app/(main)/home/ProjectFinancialSummary/page.tsx b/src/app/(main)/home/ProjectFinancialSummary/page.tsx deleted file mode 100644 index 3549f77..0000000 --- a/src/app/(main)/home/ProjectFinancialSummary/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -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 ProjectFinancialSummaryComponents from "@/components/ProjectFinancialSummary"; - -export const metadata: Metadata = { - title: "Project Status by Client", -}; - -const ProjectFinancialSummary: React.FC = () => { - return ( - - - Project Financial Summary - - - - ); -}; -export default ProjectFinancialSummary; diff --git a/src/app/(main)/home/ProjectStatusByClient/page.tsx b/src/app/(main)/home/ProjectStatusByClient/page.tsx deleted file mode 100644 index 4ca47da..0000000 --- a/src/app/(main)/home/ProjectStatusByClient/page.tsx +++ /dev/null @@ -1,29 +0,0 @@ -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 ProgressByClient from "@/components/ProgressByClient"; - -export const metadata: Metadata = { - title: "Project Status by Client", -}; - -const ProjectStatusByClient: React.FC = () => { - return ( - - - Project Status by Client - - }> - - - - - ); -}; -export default ProjectStatusByClient; diff --git a/src/app/(main)/home/StaffUtilization/page.tsx b/src/app/(main)/home/StaffUtilization/page.tsx deleted file mode 100644 index 2ddea02..0000000 --- a/src/app/(main)/home/StaffUtilization/page.tsx +++ /dev/null @@ -1,26 +0,0 @@ -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 ( - - - Staff Utilization - - - - ); -}; -export default StaffUtilization; diff --git a/src/app/(main)/settings/user/page.tsx b/src/app/(main)/settings/user/page.tsx index 1cfb841..a7a9ef1 100644 --- a/src/app/(main)/settings/user/page.tsx +++ b/src/app/(main)/settings/user/page.tsx @@ -13,7 +13,6 @@ const User: React.FC = () => { User <> - {/* */} ); }; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6c2083e..222a275 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -17,7 +17,7 @@ export default async function RootLayout({ return ( - {children} + {children} ); diff --git a/src/app/page.tsx b/src/app/page.tsx index 844c060..9271349 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,7 @@ import { permanentRedirect } from "next/navigation"; const Home: React.FC = async () => { - permanentRedirect("/home"); + permanentRedirect("/dashboard"); }; export default Home; diff --git a/src/app/utils/fetchUtil.ts b/src/app/utils/fetchUtil.ts index 718dd30..40f6669 100644 --- a/src/app/utils/fetchUtil.ts +++ b/src/app/utils/fetchUtil.ts @@ -3,6 +3,10 @@ import { getServerSession } from "next-auth"; import { headers } from "next/headers"; import { redirect } from "next/navigation"; +export type SearchParams = { + searchParams: { [key: string]: string | string[] | undefined }; +} + export const serverFetch: typeof fetch = async (input, init) => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const session = await getServerSession(authOptions); diff --git a/src/components/AssignedProjectGrid/AssignedProjectGrid.tsx b/src/components/AssignedProjectGrid/AssignedProjectGrid.tsx deleted file mode 100644 index a41fc77..0000000 --- a/src/components/AssignedProjectGrid/AssignedProjectGrid.tsx +++ /dev/null @@ -1,247 +0,0 @@ -import * as React from "react"; -import { - Card, - CardHeader, - CardContent, - SxProps, - Theme, - Tabs, - Tab, - Box, - Typography, - Grid, - Link, -} from "@mui/material"; -import { DataGrid, GridColDef } from "@mui/x-data-grid"; -import { darken, lighten, styled } from "@mui/material/styles"; -import { ThemeProvider } from "@emotion/react"; -import { TAB_THEME } from "@/theme/colorConst"; -import AllProjectGrid from "../UserWorkspacePage/ProjectGrid"; - -interface AssignedProjectGridProps { - Title?: string; - // rows: any[]; - // columns: any[]; - columnWidth?: number; - Style?: boolean; - sx?: SxProps; - height?: number; - [key: string]: any; -} - -interface TabPanelProps { - children?: React.ReactNode; - index: number; - value: number; -} - -function CustomTabPanel(props: TabPanelProps) { - const { children, value, index, ...other } = props; - - return ( - - ); -} - -function a11yProps(index: number) { - return { - id: `simple-tab-${index}`, - "aria-controls": `simple-tabpanel-${index}`, - }; -} - -const AssignedProjectGrid: React.FC = ({ - Title, - rows, - columns, - columnWidth, - Style = true, - sx, - height, - ...props -}) => { - // const modifiedColumns = columns.map((column) => { - // return { - // ...column, - // width: columnWidth ?? 150, - // }; - // }); - - // const rowsWithDefaultValues = rows.map((row) => { - // return { ...row }; - // }); - - const getBackgroundColor = (color: string, mode: "light" | "dark") => - mode === "dark" ? darken(color, 0.7) : lighten(color, 0.7); - - const getHoverBackgroundColor = (color: string, mode: "light" | "dark") => - mode === "dark" ? darken(color, 0.6) : lighten(color, 0.6); - - const getSelectedBackgroundColor = (color: string, mode: "light" | "dark") => - mode === "dark" ? darken(color, 0.5) : lighten(color, 0.5); - - const getSelectedHoverBackgroundColor = ( - color: string, - mode: "light" | "dark", - ) => (mode === "dark" ? darken(color, 0.4) : lighten(color, 0.4)); - - const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ - "& .super-app-theme--Open": { - backgroundColor: getBackgroundColor( - theme.palette.info.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getHoverBackgroundColor( - theme.palette.info.main, - theme.palette.mode, - ), - }, - "&.Mui-selected": { - backgroundColor: getSelectedBackgroundColor( - theme.palette.info.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getSelectedHoverBackgroundColor( - theme.palette.info.main, - theme.palette.mode, - ), - }, - }, - }, - "& .super-app-theme--finish": { - backgroundColor: getBackgroundColor( - theme.palette.success.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getHoverBackgroundColor( - theme.palette.success.main, - theme.palette.mode, - ), - }, - "&.Mui-selected": { - backgroundColor: getSelectedBackgroundColor( - theme.palette.success.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getSelectedHoverBackgroundColor( - theme.palette.success.main, - theme.palette.mode, - ), - }, - }, - }, - "& .super-app-theme--danger": { - backgroundColor: getBackgroundColor( - theme.palette.warning.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getHoverBackgroundColor( - theme.palette.warning.main, - theme.palette.mode, - ), - }, - "&.Mui-selected": { - backgroundColor: getSelectedBackgroundColor( - theme.palette.warning.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getSelectedHoverBackgroundColor( - theme.palette.warning.main, - theme.palette.mode, - ), - }, - }, - }, - "& .super-app-theme--warning": { - backgroundColor: getBackgroundColor( - theme.palette.error.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getHoverBackgroundColor( - theme.palette.error.main, - theme.palette.mode, - ), - }, - "&.Mui-selected": { - backgroundColor: getSelectedBackgroundColor( - theme.palette.error.main, - theme.palette.mode, - ), - "&:hover": { - backgroundColor: getSelectedHoverBackgroundColor( - theme.palette.error.main, - theme.palette.mode, - ), - }, - }, - }, - })); - - const [value, setValue] = React.useState(0); - - const handleChange = (event: React.SyntheticEvent, newValue: number) => { - setValue(newValue); - }; - - return ( -
- - {Title && } - -
- - - - - - - - - {/* - Item {value} - - - Item {value} - - - Item {value} - */} - -
-
- -
-
- ); -}; - -export default AssignedProjectGrid; diff --git a/src/components/AssignedProjectGrid/index.ts b/src/components/AssignedProjectGrid/index.ts deleted file mode 100644 index 7192046..0000000 --- a/src/components/AssignedProjectGrid/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./AssignedProjectGrid"; diff --git a/src/components/CompanyTeamCashFlow/CompanyTeamCashFlow.tsx b/src/components/CompanyTeamCashFlow/CompanyTeamCashFlow.tsx deleted file mode 100644 index 6d255a4..0000000 --- a/src/components/CompanyTeamCashFlow/CompanyTeamCashFlow.tsx +++ /dev/null @@ -1,306 +0,0 @@ -"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"; - -const CompanyTeamCashFlow: React.FC = () => { - const todayDate = new Date(); - const [selectionModel, setSelectionModel]: any[] = React.useState([]); - const [cashFlowYear, setCashFlowYear]: any[] = React.useState( - todayDate.getFullYear(), - ); - - 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 ledgerColumns = [ - { - id: "date", - field: "date", - headerName: "Date", - flex: 0.5, - }, - { - id: "expenditure", - field: "expenditure", - headerName: "Expenditure (HKD)", - flex: 0.6, - }, - { - id: "income", - field: "income", - headerName: "Income (HKD)", - flex: 0.6, - }, - { - id: "cashFlowBalance", - field: "cashFlowBalance", - headerName: "Cash Flow Balance (HKD)", - flex: 0.6, - }, - { - id: "remarks", - field: "remarks", - headerName: "Remarks", - flex: 1, - }, - ]; - - const options: ApexOptions = { - chart: { - height: 350, - type: "line", - }, - stroke: { - width: [0, 0, 2, 2], - }, - plotOptions: { - bar: { - horizontal: false, - distributed: false, - }, - }, - dataLabels: { - enabled: false, - }, - xaxis: { - categories: [ - "Q1", - "Q2", - "Q3", - "Q4", - "Q5", - "Q6", - "Q7", - "Q8", - "Q9", - "Q10", - "Q11", - "Q12", - ], - }, - yaxis: [ - { - title: { - text: "Monthly Income and Expenditure(HKD)", - }, - min: 0, - max: 3700000, - tickAmount: 5, - }, - { - show: false, - seriesName: "Monthly_Expenditure", - title: { - text: "Monthly Expenditure (HKD)", - }, - min: 0, - max: 3700000, - tickAmount: 5, - }, - { - seriesName: "Cumulative_Income", - opposite: true, - title: { - text: "Cumulative Income and Expenditure(HKD)", - }, - min: 0, - max: 21000000, - tickAmount: 5, - }, - { - show: false, - seriesName: "Cumulative_Expenditure", - opposite: true, - title: { - text: "Cumulative Expenditure (HKD)", - }, - min: 0, - max: 21000000, - tickAmount: 5, - }, - ], - grid: { - borderColor: "#f1f1f1", - }, - annotations: {}, - series: [ - { - name: "Monthly_Income", - type: "column", - color: "#ffde91", - data: [ - 1280000, 170000, 3600000, 2400000, 1000000, 1800000, 1800000, 1200000, - 1250000, 1200000, 600000, 2400000, - ], - }, - { - name: "Monthly_Expenditure", - type: "column", - color: "#82b59a", - data: [ - 1200000, 1400000, 2000000, 1400000, 1450000, 1800000, 1200000, - 1400000, 1200000, 1600000, 2000000, 1600000, - ], - }, - { - name: "Cumulative_Income", - type: "line", - color: "#EE6D7A", - data: [ - 500000, 3000000, 7000000, 9000000, 10000000, 13000000, 14000000, - 16000000, 17000000, 17500000, 18000000, 20000000, - ], - }, - { - name: "Cumulative_Expenditure", - type: "line", - color: "#7cd3f2", - data: [ - 400000, 2800000, 4000000, 5200000, 7100000, 8000000, 10000000, - 11000000, 12100000, 14000000, 15400000, 17200000, - ], - }, - ], - }; - - return ( - <> - -
- - - -
-
- - -
-
- -
-
- -
-
- -
-
- { - onChange(e.target.value); - }} - > - {field.options?.map((option) => ( - - {option.id !== undefined - ? option.label - : JSON.stringify(option)} - - ))} - - )} - /> - - - ); - } else if (field.type === "date") { - return ( - - - - { - setFromDate(newValue); - }} - /> - - - - ); - } else if (field.type === "checkbox") { - return ( - - { - if (typeof field.setValue === "function") { - field.setValue(event.target.checked); - setCheckbox1(event.target.checked); - } - }} - color="primary" - /> - } - label={ - - {field.label} - - } - /> - - ); - } else if (field.type === "dateRange") { - return ( - - - - - - setDayRangeFromDate(newValue)} - /> - - - - - To - - - - - setDayRangeToDate(newValue)} - /> - - - - - - ); - } - return ( - - - - ); - })} - - - - - - - - - - - - - ); -}; - -const CustomSearchForm: FC = ({ - applySearch, - fields, - title, - sx, -}) => { - const Title = title || "Searching Criteria"; - - const handleSubmit = (data: any) => { - if (applySearch) { - applySearch(data); - } else { - console.log("applySearch function is null"); - } - }; - - const handleFormReset = () => { - console.log("Form Reset"); - }; - - return ( - - - - - ); -}; - -export default CustomSearchForm; diff --git a/src/components/CustomSearchForm/index.ts b/src/components/CustomSearchForm/index.ts deleted file mode 100644 index 51718f8..0000000 --- a/src/components/CustomSearchForm/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./CustomSearchForm"; diff --git a/src/components/ProgressByClientSearch/ProgressByClientSearchLoading.tsx b/src/components/DashboardPage/DashboardLoading.tsx similarity index 87% rename from src/components/ProgressByClientSearch/ProgressByClientSearchLoading.tsx rename to src/components/DashboardPage/DashboardLoading.tsx index dd33fa0..568a2ef 100644 --- a/src/components/ProgressByClientSearch/ProgressByClientSearchLoading.tsx +++ b/src/components/DashboardPage/DashboardLoading.tsx @@ -5,7 +5,7 @@ import Stack from "@mui/material/Stack"; import React from "react"; // Can make this nicer -export const ProgressByClientSearchLoading: React.FC = () => { +export const DashboardLoading: React.FC = () => { return ( <> @@ -16,14 +16,14 @@ export const ProgressByClientSearchLoading: React.FC = () => { - + EditUser @@ -37,4 +37,4 @@ export const ProgressByClientSearchLoading: React.FC = () => { ); }; -export default ProgressByClientSearchLoading; +export default DashboardLoading; diff --git a/src/components/DashboardPage/DashboardPage.tsx b/src/components/DashboardPage/DashboardPage.tsx index a6c23ca..c7e073d 100644 --- a/src/components/DashboardPage/DashboardPage.tsx +++ b/src/components/DashboardPage/DashboardPage.tsx @@ -1,20 +1,10 @@ "use client"; -import Grid from "@mui/material/Grid"; -import Paper from "@mui/material/Paper"; -import { TFunction } from "i18next"; import { useTranslation } from "react-i18next"; -import PageTitle from "../PageTitle/PageTitle"; -import DashboardTabButton from "./DashboardTabButton"; import { ThemeProvider } from "@mui/material/styles"; import theme from "../../theme"; -import Tabs, { TabsProps } from "@mui/material/Tabs"; -import Tab from "@mui/material/Tab"; -import React, { useCallback, useState } from "react"; +import { TabsProps } from "@mui/material/Tabs"; +import React, { useCallback, useEffect, useState } from "react"; import { useRouter } from "next/navigation"; -import ProgressByClient from "./ProgressByClient"; -import ProgressByClientSearch from "@/components/ProgressByClientSearch"; -import { Suspense } from "react"; -import { getSession } from "next-auth/react"; type Props = { abilities: string[] @@ -22,36 +12,18 @@ type Props = { const DashboardPage: React.FC = ({ abilities }) => { - const [tabIndex, setTabIndex] = useState(0); const { t } = useTranslation("dashboard"); const router = useRouter(); - window.localStorage.setItem("abilities", JSON.stringify(abilities)) - const handleCancel = () => { - router.back(); - }; - const handleTabChange = useCallback>( - (_e, newValue) => { - setTabIndex(newValue); - }, - [], - ); + useEffect(()=> { + window.localStorage.setItem("abilities", JSON.stringify(abilities)) + }) + return ( - - - {/* - - - */} - - {tabIndex === 2 && } - {/* - - - - - */} + <> + + ); }; diff --git a/src/components/DashboardPage/DashboardTabButton.tsx b/src/components/DashboardPage/DashboardTabButton.tsx deleted file mode 100644 index 1f95098..0000000 --- a/src/components/DashboardPage/DashboardTabButton.tsx +++ /dev/null @@ -1,77 +0,0 @@ -"use client"; -import Grid from "@mui/material/Grid"; -import { useState, useCallback } from "react"; -import Paper from "@mui/material/Paper"; -import { TFunction } from "i18next"; -import { useTranslation } from "react-i18next"; -import PageTitle from "../PageTitle/PageTitle"; -import ProgressByClient from "./ProgressByClient"; -import Tabs, { TabsProps } from "@mui/material/Tabs"; -import Tab from "@mui/material/Tab"; -import "../../app/global.css"; - -const DashboardTabButton: React.FC = () => { - const [activeTab, setActiveTab] = useState("financialSummary"); - const { t } = useTranslation("dashboard"); - const renderContent = () => { - switch (activeTab) { - case "financialSummary": - return
Project Financial Summary
; - case "cashFlow": - return
Project Cash Flow
; - case "progressByClient": - return ; - case "resourceUtilization": - return
Project Resource Utilization
; - case "staffUtilization": - return
Staff Utilization
; - default: - return
Project Financial Summary
; - } - }; - const [tabIndex, setTabIndex] = useState(0); - const handleTabChange = useCallback>( - (_e, newValue) => { - setTabIndex(newValue); - }, - [], - ); - return ( - // - //
- // {activeTab !== 'financialSummary' ? - // : - // - // } - // {activeTab !== 'cashFlow' ? - // : - // - // } - // {activeTab !== 'progressByClient' ? - // : - // - // } - // {activeTab !== 'resourceUtilization' ? - // : - // - // } - // {activeTab !== 'staffUtilization' ? - // : - // - // } - //
- //
- // {renderContent()} - //
- //
- - - - - - - - ); -}; - -export default DashboardTabButton; diff --git a/src/components/DashboardPage/DashboardWrapper.tsx b/src/components/DashboardPage/DashboardWrapper.tsx index cbe82fb..9c23d60 100644 --- a/src/components/DashboardPage/DashboardWrapper.tsx +++ b/src/components/DashboardPage/DashboardWrapper.tsx @@ -1,18 +1,38 @@ import { authOptions } from "@/config/authConfig" import { getServerSession, Session } from "next-auth" import DashboardPage from "./DashboardPage" +import { Typography } from "@mui/material" +import { I18nProvider, getServerI18n } from "@/i18n"; +import DashboardLoading from "./DashboardLoading"; export type SessionWithAbilities = { abilities: string[] } & Session | null -const DashboardWrapper: React.FC = async () => { - const session: SessionWithAbilities = await getServerSession(authOptions) +interface SubComponents { + Loading: typeof DashboardLoading; + } + +type Props = { + searchParams: { [key: string]: string | string[] | undefined }; + } + +const DashboardWrapper: React.FC & SubComponents = async ({ + searchParams +}) => { + + const { t } = await getServerI18n("dashboard"); + const session: SessionWithAbilities = await getServerSession(authOptions) return ( - + <> + {t("Dashboard")} + + ) } +DashboardWrapper.Loading = DashboardLoading; + export default DashboardWrapper \ No newline at end of file diff --git a/src/components/DashboardPage/ProgressByClient.tsx b/src/components/DashboardPage/ProgressByClient.tsx deleted file mode 100644 index 6475c03..0000000 --- a/src/components/DashboardPage/ProgressByClient.tsx +++ /dev/null @@ -1,493 +0,0 @@ -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 } from "dns"; -import SearchBox, { Criterion } from "../SearchBox"; -import ProgressByClientSearch from "@/components/ProgressByClientSearch"; -import { Suspense } from "react"; - -const ProgressByClient: React.FC = () => { - const [activeTab, setActiveTab] = useState("financialSummary"); - const [SearchCriteria, setSearchCriteria] = React.useState({}); - const { t } = useTranslation("dashboard"); - - const [clientCode, setClientCode] = useState(""); - const [clientName, setClientName] = useState(""); - const [subsidiaryClientCode, setSubsidiaryClientCode] = useState(""); - const [subsidiaryClientName, setSubsidiaryClientName] = useState(""); - const [projectArray, setProjectArray]: any[] = useState([]); - const [percentageArray, setPercentageArray]: any[] = useState([]); - const [selectionModel, setSelectionModel]: any[] = React.useState([]); - const [dropdownDemo, setDropdownDemo] = useState(""); - const [dateDemo, setDateDemo] = useState(null); - const [checkboxDemo, setCheckboxDemo] = useState(false); - const [receiptFromDate, setReceiptFromDate] = useState(null); - const [receiptToDate, setReceiptToDate] = useState(null); - const [selectedRows, setSelectedRows] = useState([]); - const rows = [ - { - id: 1, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "N/A", - clientSubsidiaryName: "N/A", - noOfProjects: "5", - }, - { - id: 2, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "SUBS-001", - clientSubsidiaryName: "Subsidiary A", - noOfProjects: "5", - }, - { - id: 3, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "SUBS-002", - clientSubsidiaryName: "Subsidiary B", - noOfProjects: "3", - }, - { - id: 4, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "SUBS-003", - clientSubsidiaryName: "Subsidiary C", - noOfProjects: "1", - }, - ]; - const rows2 = [ - { - id: 1, - project: "Consultancy Project 123", - team: "XXX", - teamLeader: "XXX", - currentStage: "Contract Documentation", - budgetedManhour: "200.00", - spentManhour: "120.00", - remainedManhour: "80.00", - comingPaymentMilestone: "31/03/2024", - alert: false, - }, - { - id: 2, - project: "Consultancy Project 456", - team: "XXX", - teamLeader: "XXX", - currentStage: "Report Preparation", - budgetedManhour: "400.00", - spentManhour: "200.00", - remainedManhour: "200.00", - comingPaymentMilestone: "20/02/2024", - alert: false, - }, - { - id: 3, - project: "Construction Project A", - team: "YYY", - teamLeader: "YYY", - currentStage: "Construction", - budgetedManhour: "187.50", - spentManhour: "200.00", - remainedManhour: "12.50", - comingPaymentMilestone: "13/12/2023", - alert: true, - }, - { - id: 4, - project: "Construction Project B", - team: "XXX", - teamLeader: "XXX", - currentStage: "Post Construction", - budgetedManhour: "100.00", - spentManhour: "40.00", - remainedManhour: "60.00", - comingPaymentMilestone: "05/01/2024", - alert: false, - }, - { - id: 5, - project: "Construction Project C", - team: "YYY", - teamLeader: "YYY", - currentStage: "Construction", - budgetedManhour: "300.00", - spentManhour: "150.00", - remainedManhour: "150.00", - comingPaymentMilestone: "31/03/2024", - alert: false, - }, - ]; - - const columns = [ - { - id: "clientCode", - field: "clientCode", - headerName: "Client Code", - flex: 1, - }, - { - id: "clientName", - field: "clientName", - headerName: "Client Name", - flex: 1, - }, - { - id: "clientSubsidiaryCode", - field: "clientSubsidiaryCode", - headerName: "Client Subsidiary Code", - flex: 1, - }, - { - id: "noOfProjects", - field: "noOfProjects", - headerName: "No. of Projects", - flex: 1, - }, - ]; - - const columns2 = [ - { - id: "project", - field: "project", - headerName: "Project", - flex: 1, - }, - { - id: "team", - field: "team", - headerName: "Team", - flex: 1, - }, - { - id: "teamLeader", - field: "teamLeader", - headerName: "Team Leader", - flex: 1, - }, - { - id: "currentStage", - field: "currentStage", - headerName: "Current Stage", - flex: 1, - }, - { - id: "budgetedManhour", - field: "budgetedManhour", - headerName: "Budgeted Manhour", - flex: 1, - }, - { - id: "spentManhour", - field: "spentManhour", - headerName: "Spent Manhour", - renderCell: (params: any) => { - if (params.row.budgetedManhour - params.row.spentManhour <= 0) { - return ( - {params.row.spentManhour} - ); - } else { - return {params.row.spentManhour}; - } - }, - flex: 1, - }, - { - id: "remainedManhour", - field: "remainedManhour", - headerName: "Remained Manhour", - renderCell: (params: any) => { - if (params.row.budgetedManhour - params.row.spentManhour <= 0) { - return ( - ({params.row.remainedManhour}) - ); - } else { - return {params.row.remainedManhour}; - } - }, - flex: 1, - }, - { - id: "comingPaymentMilestone", - field: "comingPaymentMilestone", - headerName: "Coming Payment Milestone", - flex: 1, - }, - { - id: "alert", - field: "alert", - headerName: "Alert", - renderCell: (params: any) => { - if (params.row.alert === true) { - return ( - - - - ); - } else { - return ; - } - }, - flex: 1, - }, - ]; - - const InputFields = [ - { - id: "clientCode", - label: "Client Code", - type: "text", - value: clientCode, - setValue: setClientCode, - }, - { - id: "clientName", - label: "Client Name", - type: "text", - value: clientName, - setValue: setClientName, - }, - { - id: "subsidiaryClientCode", - label: "Subsidiary Client Code", - type: "text", - value: subsidiaryClientCode, - setValue: setSubsidiaryClientCode, - }, - { - id: "subsidiaryClientName", - label: "Subsidiary Client Name", - type: "text", - value: subsidiaryClientName, - setValue: setSubsidiaryClientName, - }, - // { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo }, - // { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo }, - // { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo }, - // { id: ['receiptFromDate','receiptToDate'], label: ["收貨日期","收貨日期"], value: [receiptFromDate ? receiptFromDate : null, receiptToDate ? receiptToDate : null], - // setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' }, - ]; - - const stageDeadline = [ - "31/03/2024", - "20/02/2024", - "01/12/2023", - "05/01/2024", - "31/03/2023", - ]; - - const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [ - { - data: [17.1, 28.6, 5.7, 48.6], - }, - ]; - - const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [ - { - name: "Current Stage Completion Percentage", - data: [80, 55, 40, 65, 70], - }, - ]; - - const options2: ApexOptions = { - chart: { - type: "donut", - }, - plotOptions: { - pie: { - donut: { - labels: { - show: false, - }, - }, - }, - }, - labels: [projectArray], - legend: { - show: false, - }, - responsive: [ - { - breakpoint: 480, - options: { - chart: { - width: 200, - }, - legend: { - position: "bottom", - show: false, - }, - }, - }, - ], - }; - - const options: ApexOptions = { - chart: { - type: "bar", - height: 350, - }, - colors: ["#FF4560", "#00E396", "#008FFB", "#775DD0", "#FEB019"], - plotOptions: { - bar: { - horizontal: true, - distributed: true, - }, - }, - dataLabels: { - enabled: false, - }, - xaxis: { - categories: [ - "Consultancy Project 123", - "Consultancy Project 456", - "Construction Project A", - "Construction Project B", - "Construction Project C", - ], - }, - yaxis: { - title: { - text: "Projects", - }, - labels: { - maxWidth: 200, - style: { - cssClass: "apexcharts-yaxis-label", - }, - }, - }, - title: { - text: "Current Stage Completion Percentage", - align: "center", - }, - grid: { - borderColor: "#f1f1f1", - }, - annotations: {}, - }; - - const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { - const selectedRowsData = rows2.filter((row) => - newSelectionModel.includes(row.id), - ); - console.log(selectedRowsData); - const projectArray: any[] = []; - let otherPercentage = 100; - let totalBudgetManhour = 0; - const percentageArray = []; - for (let i = 0; i <= selectedRowsData.length; i++) { - if (i === selectedRowsData.length) { - projectArray.push("Other"); - } else { - projectArray.push(selectedRowsData[i].project); - totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); - } - } - for (let i = 0; i <= selectedRowsData.length; i++) { - if (i === selectedRowsData.length) { - percentageArray.push(otherPercentage); - } else { - const percentage = ( - (Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) * - 100 - ).toFixed(1); - percentageArray.push(Number(percentage)); - otherPercentage -= Number(percentage); - } - } - setSelectionModel(newSelectionModel); - setProjectArray(projectArray); - setPercentageArray(percentageArray); - }; - - const applySearch = (data: any) => { - console.log(data); - setSearchCriteria(data); - }; - return ( - - {/* */} - {/* */} -
- - - -
- -
- {/*
-

Stage Deadline

- {stageDeadline.map((date, index) => { - const marginTop = index === 0 ? 25 : 20; - return ( -

{date}

- ); - })} -
*/} - -
- -
-
-
-
-
- - - - - - -
-
- ); -}; - -export default ProgressByClient; diff --git a/src/components/EnterLeave/EnterLeaveModal.tsx b/src/components/EnterLeave/EnterLeaveModal.tsx index a42322c..95a0a12 100644 --- a/src/components/EnterLeave/EnterLeaveModal.tsx +++ b/src/components/EnterLeave/EnterLeaveModal.tsx @@ -1,28 +1,9 @@ "use client"; -// import { testing } from "@/app/api/timesheets"; -import Grid from "@mui/material/Grid"; -import Paper from "@mui/material/Paper"; import { useState } from "react"; -import { useTranslation } from "react-i18next"; -import AssignedProjectGrid from "../AssignedProjectGrid/AssignedProjectGrid"; -import PageTitle from "../PageTitle/PageTitle"; -import { Suspense } from "react"; import Button from "@mui/material/Button"; -import Stack from "@mui/material/Stack"; -import { Add } from "@mui/icons-material"; -import Link from "next/link"; -import { t } from "i18next"; import { Card, Modal, Typography } from "@mui/material"; -import CustomModal from "../CustomModal/CustomModal"; -import { PROJECT_MODAL_STYLE } from "@/theme/colorConst"; -import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; -import { DataGrid } from "@mui/x-data-grid"; import TimesheetInputGrid from "./LeaveInputGrid"; -import { BASE_API_URL } from "@/config/api"; - -// import { fetchLeaves } from "@/app/api/leave"; - interface EnterTimesheetModalProps { isOpen: boolean; onClose: () => void; diff --git a/src/components/EnterTimesheet/EnterTimesheetModal.tsx b/src/components/EnterTimesheet/EnterTimesheetModal.tsx index c63a905..d994a40 100644 --- a/src/components/EnterTimesheet/EnterTimesheetModal.tsx +++ b/src/components/EnterTimesheet/EnterTimesheetModal.tsx @@ -1,23 +1,9 @@ "use client"; -// import { testing } from "@/app/api/timesheets"; -import Grid from "@mui/material/Grid"; -import Paper from "@mui/material/Paper"; import { useState } from "react"; -import { useTranslation } from "react-i18next"; -import AssignedProjectGrid from "../AssignedProjectGrid/AssignedProjectGrid"; -import PageTitle from "../PageTitle/PageTitle"; -import { Suspense } from "react"; import Button from "@mui/material/Button"; -import Stack from "@mui/material/Stack"; -import { Add } from "@mui/icons-material"; -import Link from "next/link"; import { t } from "i18next"; import { Card, Modal, Typography } from "@mui/material"; -import CustomModal from "../CustomModal/CustomModal"; -import { PROJECT_MODAL_STYLE } from "@/theme/colorConst"; -import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; -import { DataGrid } from "@mui/x-data-grid"; import TimesheetInputGrid from "./TimesheetInputGrid"; import { BASE_API_URL } from "@/config/api"; diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx index 9bd005f..45790f0 100644 --- a/src/components/NavigationContent/NavigationContent.tsx +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -33,8 +33,6 @@ interface NavigationItem { } const NavigationContent: React.FC = () => { - // const abilities = window.localStorage.getItem("abilites") - // console.log(abilities) const navigationItems: NavigationItem[] = [ { icon: , @@ -245,16 +243,16 @@ const NavigationContent: React.FC = () => { const pathname = usePathname(); const [openItems, setOpenItems] = React.useState([]); - const toggleItem = (path: string) => { + const toggleItem = (label: string) => { setOpenItems((prevOpenItems) => - prevOpenItems.includes(path) - ? prevOpenItems.filter((item) => item !== path) - : [...prevOpenItems, path], + prevOpenItems.includes(label) + ? prevOpenItems.filter((item) => item !== label) + : [...prevOpenItems, label], ); }; const renderNavigationItem = (item: NavigationItem) => { - const isOpen = openItems.includes(item.path); + const isOpen = openItems.includes(item.label); return ( { sx={{ textDecoration: "none", color: "inherit" }} > item.children && toggleItem(item.path)} + selected={pathname.includes(item.label)} + onClick={() => item.children && toggleItem(item.label)} > {item.icon} diff --git a/src/components/ProgressByClient/ProgressByClient.tsx b/src/components/ProgressByClient/ProgressByClient.tsx deleted file mode 100644 index 939f5d3..0000000 --- a/src/components/ProgressByClient/ProgressByClient.tsx +++ /dev/null @@ -1,643 +0,0 @@ -"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"; - -const ProgressByClient: React.FC = () => { - const [activeTab, setActiveTab] = useState("financialSummary"); - const [SearchCriteria, setSearchCriteria] = React.useState({}); - const { t } = useTranslation("dashboard"); - - const [clientCode, setClientCode] = useState(""); - const [clientName, setClientName] = useState(""); - const [subsidiaryClientCode, setSubsidiaryClientCode] = useState(""); - const [subsidiaryClientName, setSubsidiaryClientName] = useState(""); - const [projectArray, setProjectArray]: any[] = useState([]); - const [percentageArray, setPercentageArray]: any[] = useState([]); - const [colorArray, setColorArray]: any[] = useState([]); - const [selectionModel, setSelectionModel]: any[] = React.useState([]); - const [pieChartColor, setPieChartColor]: any[] = React.useState([]); - const [totalSpentPercentage, setTotalSpentPercentage]: any = React.useState(); - const [projectBudgetManhour, setProjectBudgetManhour]: any = - React.useState("-"); - const [actualManhourSpent, setActualManhourSpent]: any = React.useState("-"); - const [remainedManhour, setRemainedManhour]: any = React.useState("-"); - const [lastUpdate, setLastUpdate]: any = React.useState("-"); - const [dropdownDemo, setDropdownDemo] = useState(""); - const [dateDemo, setDateDemo] = useState(null); - const [checkboxDemo, setCheckboxDemo] = useState(false); - const [receiptFromDate, setReceiptFromDate] = useState(null); - const [receiptToDate, setReceiptToDate] = useState(null); - const [selectedRows, setSelectedRows] = useState([]); - const rows = [ - { - id: 1, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "N/A", - clientSubsidiaryName: "N/A", - noOfProjects: "5", - }, - { - id: 2, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "SUBS-001", - clientSubsidiaryName: "Subsidiary A", - noOfProjects: "5", - }, - { - id: 3, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "SUBS-002", - clientSubsidiaryName: "Subsidiary B", - noOfProjects: "3", - }, - { - id: 4, - clientCode: "CUST-001", - clientName: "Client A", - clientSubsidiaryCode: "SUBS-003", - clientSubsidiaryName: "Subsidiary C", - noOfProjects: "1", - }, - ]; - //['#f57f90', '#94f7d6', '#87c5f5', '#ab95f5', '#fcd68b'] - const rows2 = [ - { - id: 1, - project: "Consultancy Project 123", - team: "XXX", - teamLeader: "XXX", - currentStage: "Contract Documentation", - budgetedManhour: "200.00", - spentManhour: "120.00", - remainedManhour: "80.00", - comingPaymentMilestone: "31/03/2024", - alert: false, - color: "#f57f90", - }, - { - id: 2, - project: "Consultancy Project 456", - team: "XXX", - teamLeader: "XXX", - currentStage: "Report Preparation", - budgetedManhour: "400.00", - spentManhour: "200.00", - remainedManhour: "200.00", - comingPaymentMilestone: "20/02/2024", - alert: false, - color: "#94f7d6", - }, - { - id: 3, - project: "Construction Project A", - team: "YYY", - teamLeader: "YYY", - currentStage: "Construction", - budgetedManhour: "187.50", - spentManhour: "200.00", - remainedManhour: "12.50", - comingPaymentMilestone: "13/12/2023", - alert: true, - color: "#87c5f5", - }, - { - id: 4, - project: "Construction Project B", - team: "XXX", - teamLeader: "XXX", - currentStage: "Post Construction", - budgetedManhour: "100.00", - spentManhour: "40.00", - remainedManhour: "60.00", - comingPaymentMilestone: "05/01/2024", - alert: false, - color: "#ab95f5", - }, - { - id: 5, - project: "Construction Project C", - team: "YYY", - teamLeader: "YYY", - currentStage: "Construction", - budgetedManhour: "300.00", - spentManhour: "150.00", - remainedManhour: "150.00", - comingPaymentMilestone: "31/03/2024", - alert: false, - color: "#fcd68b", - }, - ]; - - const columns = [ - { - id: "clientCode", - field: "clientCode", - headerName: "Client Code", - flex: 1, - }, - { - id: "clientName", - field: "clientName", - headerName: "Client Name", - flex: 1, - }, - { - id: "clientSubsidiaryCode", - field: "clientSubsidiaryCode", - headerName: "Client Subsidiary Code", - flex: 1, - }, - { - id: "noOfProjects", - field: "noOfProjects", - headerName: "No. of Projects", - flex: 1, - }, - ]; - - const columns2 = [ - { - id: "color", - field: "color", - headerName: "", - renderCell: (params: any) => { - return ( - - ); - }, - flex: 0.1, - }, - { - id: "project", - field: "project", - headerName: "Project", - flex: 1, - }, - { - id: "team", - field: "team", - headerName: "Team", - flex: 0.8, - }, - { - id: "teamLeader", - field: "teamLeader", - headerName: "Team Leader", - flex: 0.8, - }, - { - id: "currentStage", - field: "currentStage", - headerName: "Current Stage", - flex: 1, - }, - { - id: "budgetedManhour", - field: "budgetedManhour", - headerName: "Budgeted Manhour", - flex: 0.8, - }, - { - id: "spentManhour", - field: "spentManhour", - headerName: "Spent Manhour", - renderCell: (params: any) => { - if (params.row.budgetedManhour - params.row.spentManhour <= 0) { - return ( - {params.row.spentManhour} - ); - } else { - return {params.row.spentManhour}; - } - }, - flex: 0.8, - }, - { - id: "remainedManhour", - field: "remainedManhour", - headerName: "Remained Manhour", - renderCell: (params: any) => { - if (params.row.budgetedManhour - params.row.spentManhour <= 0) { - return ( - ({params.row.remainedManhour}) - ); - } else { - return {params.row.remainedManhour}; - } - }, - flex: 1, - }, - { - id: "comingPaymentMilestone", - field: "comingPaymentMilestone", - headerName: "Coming Payment Milestone", - flex: 1, - }, - { - id: "alert", - field: "alert", - headerName: "Alert", - renderCell: (params: any) => { - if (params.row.alert === true) { - return ( - - - - ); - } else { - return ; - } - }, - flex: 0.2, - }, - ]; - - const InputFields = [ - { - id: "clientCode", - label: "Client Code", - type: "text", - value: clientCode, - setValue: setClientCode, - }, - { - id: "clientName", - label: "Client Name", - type: "text", - value: clientName, - setValue: setClientName, - }, - { - id: "subsidiaryClientCode", - label: "Subsidiary Client Code", - type: "text", - value: subsidiaryClientCode, - setValue: setSubsidiaryClientCode, - }, - { - id: "subsidiaryClientName", - label: "Subsidiary Client Name", - type: "text", - value: subsidiaryClientName, - setValue: setSubsidiaryClientName, - }, - // { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo }, - // { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo }, - // { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo }, - // { id: ['receiptFromDate','receiptToDate'], label: ["收貨日期","收貨日期"], value: [receiptFromDate ? receiptFromDate : null, receiptToDate ? receiptToDate : null], - // setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' }, - ]; - - const stageDeadline = [ - "31/03/2024", - "20/02/2024", - "01/12/2023", - "05/01/2024", - "31/03/2023", - ]; - - const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [ - { - data: [17.1, 28.6, 5.7, 48.6], - }, - ]; - - const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [ - { - name: "Current Stage Completion Percentage", - data: [80, 55, 40, 65, 70], - }, - ]; - - const options2: ApexOptions = { - chart: { - type: "donut", - }, - colors: colorArray, - plotOptions: { - pie: { - donut: { - labels: { - show: true, - name: { - show: true, - }, - value: { - show: true, - fontWeight: 500, - fontSize: "30px", - color: "#3e98c7", - }, - total: { - show: true, - showAlways: true, - label: "Spent", - fontFamily: "sans-serif", - formatter: function (val) { - return totalSpentPercentage + "%"; - }, - }, - }, - }, - }, - }, - labels: projectArray, - legend: { - show: false, - }, - responsive: [ - { - breakpoint: 480, - options: { - chart: { - width: 200, - }, - legend: { - position: "bottom", - show: false, - }, - }, - }, - ], - }; - - const options: ApexOptions = { - chart: { - type: "bar", - height: 350, - }, - colors: ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"], - plotOptions: { - bar: { - horizontal: true, - distributed: true, - }, - }, - dataLabels: { - enabled: false, - }, - xaxis: { - categories: [ - "Consultancy Project 123", - "Consultancy Project 456", - "Construction Project A", - "Construction Project B", - "Construction Project C", - ], - }, - yaxis: { - title: { - text: "Projects", - }, - labels: { - maxWidth: 200, - style: { - cssClass: "apexcharts-yaxis-label", - }, - }, - }, - title: { - text: "Current Stage Completion Percentage", - align: "center", - }, - grid: { - borderColor: "#f1f1f1", - }, - annotations: {}, - }; - - const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { - const selectedRowsData = rows2.filter((row) => - newSelectionModel.includes(row.id), - ); - console.log(selectedRowsData); - const projectArray = []; - const pieChartColorArray = []; - let totalSpent = 0; - let totalBudgetManhour = 0; - const percentageArray = []; - for (let i = 0; i <= selectedRowsData.length; i++) { - if (i === selectedRowsData.length && i > 0) { - projectArray.push("Remained"); - } else if (selectedRowsData.length > 0) { - projectArray.push(selectedRowsData[i].project); - totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); - totalSpent += Number(selectedRowsData[i].spentManhour); - pieChartColorArray.push(selectedRowsData[i].color); - } - } - for (let i = 0; i <= selectedRowsData.length; i++) { - if (i === selectedRowsData.length && i > 0) { - const remainedManhour = totalBudgetManhour - totalSpent; - percentageArray.push( - Number(((remainedManhour / totalBudgetManhour) * 100).toFixed(1)), - ); - } else if (selectedRowsData.length > 0) { - const percentage = ( - (Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) * - 100 - ).toFixed(1); - percentageArray.push(Number(percentage)); - } - } - setProjectBudgetManhour(totalBudgetManhour.toFixed(2)); - setActualManhourSpent(totalSpent.toFixed(2)); - setRemainedManhour((totalBudgetManhour - totalSpent).toFixed(2)); - setLastUpdate(new Date().toLocaleDateString("en-GB")); - setSelectionModel(newSelectionModel); - console.log(projectArray); - setProjectArray(projectArray); - setPercentageArray(percentageArray); - console.log(percentageArray); - setTotalSpentPercentage( - ((totalSpent / totalBudgetManhour) * 100).toFixed(1), - ); - if (projectArray.length > 0 && projectArray.includes("Remained")) { - const nonLastRecordColors = pieChartColorArray; - setColorArray([ - ...nonLastRecordColors.slice(0, projectArray.length - 1), - "#a3a3a3", - ]); - } else { - setColorArray(pieChartColorArray); - } - }; - - const applySearch = (data: any) => { - console.log(data); - setSearchCriteria(data); - }; - return ( - - {/* */} - {/* */} -
- - - -
- -
- {/*
-

Stage Deadline

- {stageDeadline.map((date, index) => { - const marginTop = index === 0 ? 25 : 20; - return ( -

{date}

- ); - })} -
*/} - -
- -
-
-
-
-
- - - - {percentageArray.length === 0 && ( -
- Please select the project you want to check. -
- )} - {percentageArray.length > 0 && ( - - )} -
-
- - -
-
- Project Budget Manhour -
-
- {projectBudgetManhour} -
-
-
-
-
- Actual Manhour Spent -
-
- {actualManhourSpent} -
-
-
-
-
- Remained Manhour -
-
- {remainedManhour} -
-
-
-
-
- Last Update -
-
- {lastUpdate} -
-
-
-
-
-
- ); -}; - -export default ProgressByClient; diff --git a/src/components/ProgressByClient/index.ts b/src/components/ProgressByClient/index.ts deleted file mode 100644 index 3b2ccf9..0000000 --- a/src/components/ProgressByClient/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ProgressByClient"; diff --git a/src/components/ProgressByClientSearch/ProgressByClientSearch.tsx b/src/components/ProgressByClientSearch/ProgressByClientSearch.tsx deleted file mode 100644 index 7ddbb00..0000000 --- a/src/components/ProgressByClientSearch/ProgressByClientSearch.tsx +++ /dev/null @@ -1,57 +0,0 @@ -"use client"; - -import { ProjectResult } from "@/app/api/projects"; -import React, { useMemo, useState } from "react"; -import SearchBox, { Criterion } from "../SearchBox"; -import { useTranslation } from "react-i18next"; -import SearchResults, { Column } from "../SearchResults"; -import { ClientProjectResult } from "@/app/api/clientprojects"; - -interface Props { - projects: ClientProjectResult[]; -} -type SearchQuery = Partial>; -type SearchParamNames = keyof SearchQuery; - -const ProgressByClientSearch: React.FC = ({ projects }) => { - const { t } = useTranslation("projects"); - - // If project searching is done on the server-side, then no need for this. - const [filteredProjects, setFilteredProjects] = useState(projects); - - const searchCriteria: Criterion[] = useMemo( - () => [ - { label: "Client Code", paramName: "clientCode", type: "text" }, - { label: "Client Name", paramName: "clientName", type: "text" }, - ], - [t], - ); - - const columns = useMemo[]>( - () => [ - { name: "clientCode", label: t("Project Code") }, - { name: "clientName", label: t("Project Name") }, - { name: "SubsidiaryClientCode", label: t("Project Category") }, - { name: "SubsidiaryClientName", label: t("Team") }, - { name: "NoOfProjects", label: t("Client") }, - ], - [t], - ); - - return ( - <> - { - console.log(query); - }} - /> - - items={filteredProjects} - columns={columns} - /> - - ); -}; - -export default ProgressByClientSearch; diff --git a/src/components/ProgressByClientSearch/ProgressByClientSearchWrapper.tsx b/src/components/ProgressByClientSearch/ProgressByClientSearchWrapper.tsx deleted file mode 100644 index b644fb4..0000000 --- a/src/components/ProgressByClientSearch/ProgressByClientSearchWrapper.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { fetchClientProjects } from "@/app/api/clientprojects"; -import React from "react"; -import ProgressByClientSearch from "./ProgressByClientSearch"; -import ProgressByClientSearchLoading from "./ProgressByClientSearchLoading"; - -interface SubComponents { - Loading: typeof ProgressByClientSearchLoading; -} - -const ProgressByClientSearchWrapper: React.FC & SubComponents = async () => { - const clentprojects = await fetchClientProjects(); - - return ; -}; - -ProgressByClientSearchWrapper.Loading = ProgressByClientSearchLoading; - -export default ProgressByClientSearchWrapper; diff --git a/src/components/ProgressByClientSearch/index.ts b/src/components/ProgressByClientSearch/index.ts deleted file mode 100644 index 4fdbe22..0000000 --- a/src/components/ProgressByClientSearch/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ProgressByClientSearchWrapper"; diff --git a/src/components/ProgressCashFlowSearch/ProgressCashFlowSearch.tsx b/src/components/ProgressCashFlowSearch/ProgressCashFlowSearch.tsx deleted file mode 100644 index 845c874..0000000 --- a/src/components/ProgressCashFlowSearch/ProgressCashFlowSearch.tsx +++ /dev/null @@ -1,156 +0,0 @@ -"use client"; - -import { ProjectResult } from "@/app/api/projects"; -import React, { useMemo, useState } from "react"; -import SearchBox, { Criterion } from "../SearchBox"; -import { useTranslation } from "react-i18next"; -import SearchResults, { Column } from "../SearchResults"; -import { CashFlow } from "@/app/api/cashflow"; -import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; -import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; -import ProjectCashFlow from "../ProjectCashFlow"; - -interface Props { - projects: CashFlow[]; -} -type SearchQuery = Partial>; -type SearchParamNames = keyof SearchQuery; - -const ProgressByClientSearch: React.FC = ({ projects }) => { - const { t } = useTranslation("projects"); - const [selectionModel, setSelectionModel]: any[] = React.useState([]); - 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 rows = [ - { - id: 1, - projectCode: "M1001", - projectName: "Consultancy Project A", - team: "XXX", - teamLeader: "XXX", - startDate: "01/07/2022", - targetEndDate: "01/04/2024", - client: "Client B", - subsidiary: "N/A", - }, - { - id: 2, - projectCode: "M1301", - projectName: "Consultancy Project AAAA", - team: "XXX", - teamLeader: "XXX", - startDate: "01/09/2022", - targetEndDate: "20/02/2024", - client: "Client C", - subsidiary: "Subsidiary A", - }, - { - id: 3, - projectCode: "M1354", - projectName: "Consultancy Project BBB", - team: "YYY", - teamLeader: "YYY", - startDate: "01/02/2023", - targetEndDate: "31/01/2024", - client: "Client D", - subsidiary: "Subsidiary C", - }, - ]; - const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows); - const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { - const selectedRowsData = selectedTeamData.filter((row: any) => - newSelectionModel.includes(row.id), - ); - console.log(selectedRowsData); - }; - - // If project searching is done on the server-side, then no need for this. - const [filteredProjects, setFilteredProjects] = useState(projects); - - const searchCriteria: Criterion[] = useMemo( - () => [ - { label: "Project Code", paramName: "projectCode", type: "text" }, - { label: "Project Name", paramName: "projectName", type: "text" }, - { - label: "Start Date From", - label2: "Start Date To", - paramName: "startDateFrom", - type: "dateRange", - }, - ], - [t], - ); - - // const columns = useMemo[]>( - // () => [ - // { name: "clientCode", label: t("Project Code") }, - // { name: "clientName", label: t("Project Name") }, - // { name: "SubsidiaryClientCode", label: t("Project Category") }, - // { name: "SubsidiaryClientName", label: t("Team") }, - // { name: "NoOfProjects", label: t("Client") }, - // ], - // [t], - // ); - - return ( - <> - { - console.log(query); - }} - /> - {/* */} - - ); -}; - -export default ProgressByClientSearch; diff --git a/src/components/ProgressCashFlowSearch/ProgressCashFlowSearchLoading.tsx b/src/components/ProgressCashFlowSearch/ProgressCashFlowSearchLoading.tsx deleted file mode 100644 index 7d25500..0000000 --- a/src/components/ProgressCashFlowSearch/ProgressCashFlowSearchLoading.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import Card from "@mui/material/Card"; -import CardContent from "@mui/material/CardContent"; -import Skeleton from "@mui/material/Skeleton"; -import Stack from "@mui/material/Stack"; -import React from "react"; - -// Can make this nicer -export const ProgressCashFlowSearchLoading: React.FC = () => { - return ( - <> - - - - - - - - - - - - - - - - - - - - - - ); -}; - -export default ProgressCashFlowSearchLoading; diff --git a/src/components/ProgressCashFlowSearch/ProgressCashFlowSearchWrapper.tsx b/src/components/ProgressCashFlowSearch/ProgressCashFlowSearchWrapper.tsx deleted file mode 100644 index 8e99756..0000000 --- a/src/components/ProgressCashFlowSearch/ProgressCashFlowSearchWrapper.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { fetchProjectsCashFlow } from "@/app/api/cashflow"; -import React from "react"; -import ProgressCashFlowSearch from "./ProgressCashFlowSearch"; -import ProgressCashFlowSearchSearchLoading from "./ProgressCashFlowSearchLoading"; - -interface SubComponents { - Loading: typeof ProgressCashFlowSearchSearchLoading; -} - -const ProgressCashFlowSearchWrapper: React.FC & SubComponents = async () => { - const clentprojects = await fetchProjectsCashFlow(); - - return ; -}; - -ProgressCashFlowSearchWrapper.Loading = ProgressCashFlowSearchSearchLoading; - -export default ProgressCashFlowSearchWrapper; diff --git a/src/components/ProgressCashFlowSearch/index.ts b/src/components/ProgressCashFlowSearch/index.ts deleted file mode 100644 index 417711b..0000000 --- a/src/components/ProgressCashFlowSearch/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ProgressCashFlowSearchWrapper"; diff --git a/src/components/ProjectCashFlow/ProjectCashFlow.tsx b/src/components/ProjectCashFlow/ProjectCashFlow.tsx deleted file mode 100644 index 5eb455c..0000000 --- a/src/components/ProjectCashFlow/ProjectCashFlow.tsx +++ /dev/null @@ -1,638 +0,0 @@ -"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"; - -const ProjectCashFlow: React.FC = () => { - const todayDate = new Date(); - const [selectionModel, setSelectionModel]: any[] = React.useState([]); - const [cashFlowYear, setCashFlowYear]: any[] = React.useState( - todayDate.getFullYear(), - ); - 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 ledgerColumns = [ - { - id: "date", - field: "date", - headerName: "Date", - flex: 0.5, - }, - { - id: "expenditure", - field: "expenditure", - headerName: "Expenditure (HKD)", - flex: 0.6, - }, - { - id: "income", - field: "income", - headerName: "Income (HKD)", - flex: 0.6, - }, - { - id: "cashFlowBalance", - field: "cashFlowBalance", - headerName: "Cash Flow Balance (HKD)", - flex: 0.6, - }, - { - id: "remarks", - field: "remarks", - headerName: "Remarks", - flex: 1, - }, - ]; - - const options: ApexOptions = { - chart: { - height: 350, - type: "line", - }, - stroke: { - width: [0, 0, 2, 2], - }, - plotOptions: { - bar: { - horizontal: false, - distributed: false, - }, - }, - dataLabels: { - enabled: false, - }, - xaxis: { - categories: [ - "Q1", - "Q2", - "Q3", - "Q4", - "Q5", - "Q6", - "Q7", - "Q8", - "Q9", - "Q10", - "Q11", - "Q12", - ], - }, - yaxis: [ - { - title: { - text: "Monthly Income and Expenditure(HKD)", - }, - min: 0, - max: 350000, - tickAmount: 5, - }, - { - show: false, - seriesName: "Monthly_Expenditure", - title: { - text: "Monthly Expenditure (HKD)", - }, - min: 0, - max: 350000, - tickAmount: 5, - }, - { - seriesName: "Cumulative_Income", - opposite: true, - title: { - text: "Cumulative Income and Expenditure(HKD)", - }, - min: 0, - max: 850000, - tickAmount: 5, - }, - { - show: false, - seriesName: "Cumulative_Expenditure", - opposite: true, - title: { - text: "Cumulative Expenditure (HKD)", - }, - min: 0, - max: 850000, - tickAmount: 5, - }, - ], - grid: { - borderColor: "#f1f1f1", - }, - annotations: {}, - series: [ - { - name: "Monthly_Income", - type: "column", - color: "#ffde91", - data: [0, 110000, 0, 0, 185000, 0, 0, 189000, 0, 0, 300000, 0], - }, - { - name: "Monthly_Expenditure", - type: "column", - color: "#82b59a", - data: [ - 0, 160000, 120000, 120000, 55000, 55000, 55000, 55000, 55000, 70000, - 55000, 55000, - ], - }, - { - name: "Cumulative_Income", - type: "line", - color: "#EE6D7A", - data: [ - 0, 100000, 100000, 100000, 300000, 300000, 300000, 500000, 500000, - 500000, 800000, 800000, - ], - }, - { - name: "Cumulative_Expenditure", - type: "line", - color: "#7cd3f2", - data: [ - 0, 198000, 240000, 400000, 410000, 430000, 510000, 580000, 600000, - 710000, 730000, 790000, - ], - }, - ], - }; - - const accountsReceivableOptions: ApexOptions = { - colors: ["#20E647"], - series: [80], - chart: { - height: 350, - type: "radialBar", - }, - plotOptions: { - radialBar: { - hollow: { - size: "70%", - background: "#ffffff", - }, - track: { - dropShadow: { - enabled: true, - top: 2, - left: 0, - blur: 4, - opacity: 0.15, - }, - }, - dataLabels: { - name: { - show: false, - }, - value: { - color: "#3e98c7", - fontSize: "3em", - show: true, - }, - }, - }, - }, - fill: { - type: "gradient", - gradient: { - shade: "dark", - type: "vertical", - gradientToColors: ["#87D4F9"], - stops: [0, 100], - }, - }, - stroke: { - lineCap: "round", - }, - labels: ["AccountsReceivable"], - }; - - const expenditureOptions: ApexOptions = { - colors: ["#20E647"], - series: [95], - chart: { - height: 350, - type: "radialBar", - }, - plotOptions: { - radialBar: { - hollow: { - size: "70%", - background: "#ffffff", - }, - track: { - dropShadow: { - enabled: true, - top: 2, - left: 0, - blur: 4, - opacity: 0.15, - }, - }, - dataLabels: { - name: { - show: false, - }, - value: { - color: "#3e98c7", - fontSize: "3em", - show: true, - }, - }, - }, - }, - fill: { - type: "gradient", - gradient: { - shade: "dark", - type: "vertical", - gradientToColors: ["#87D4F9"], - stops: [0, 100], - }, - }, - stroke: { - lineCap: "round", - }, - labels: ["AccountsReceivable"], - }; - - const rows = [ - { - id: 1, - projectCode: "M1001", - projectName: "Consultancy Project A", - team: "XXX", - teamLeader: "XXX", - startDate: "01/07/2022", - targetEndDate: "01/04/2024", - client: "Client B", - subsidiary: "N/A", - }, - { - id: 2, - projectCode: "M1301", - projectName: "Consultancy Project AAAA", - team: "XXX", - teamLeader: "XXX", - startDate: "01/09/2022", - targetEndDate: "20/02/2024", - client: "Client C", - subsidiary: "Subsidiary A", - }, - { - id: 3, - projectCode: "M1354", - projectName: "Consultancy Project BBB", - team: "YYY", - teamLeader: "YYY", - startDate: "01/02/2023", - targetEndDate: "31/01/2024", - client: "Client D", - subsidiary: "Subsidiary C", - }, - ]; - - const ledgerRows = [ - { - id: 1, - date: "Feb 2023", - expenditure: "-", - income: "100,000.00", - cashFlowBalance: "100,000.00", - remarks: "Payment Milestone 1 (10%)", - }, - { - id: 2, - date: "Feb 2023", - expenditure: "160,000.00", - income: "-", - cashFlowBalance: "(60,000.00)", - remarks: "Monthly Manpower Expenditure", - }, - { - id: 3, - date: "Mar 2023", - expenditure: "160,000.00", - income: "-", - cashFlowBalance: "(180,000.00)", - remarks: "Monthly Manpower Expenditure", - }, - { - id: 4, - date: "Apr 2023", - expenditure: "120,000.00", - income: "-", - cashFlowBalance: "(300,000.00)", - remarks: "Monthly Manpower Expenditure", - }, - { - id: 5, - date: "May 2023", - expenditure: "-", - income: "200,000.00", - cashFlowBalance: "(100,000.00)", - remarks: "Payment Milestone 2 (20%)", - }, - { - id: 6, - date: "May 2023", - expenditure: "40,000.00", - income: "-", - cashFlowBalance: "(140,000.00)", - remarks: "Monthly Manpower Expenditure", - }, - ]; - - const [projectData, setProjectData]: any[] = React.useState(rows); - const [ledgerData, setLedgerData]: any[] = React.useState(ledgerRows); - const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { - const selectedRowsData = projectData.filter((row: any) => - newSelectionModel.includes(row.id), - ); - console.log(selectedRowsData); - }; - - return ( - <> - }> - - - - -
- - - -
-
- - -
-
- -
-
- -
- -
-
-
-
-
- - - - - -
- Total A. Receivable -
-
- 1,000,000.00 -
-
-
- Amount Received -
-
- 800,000.00 -
-
-
- Remaining Balance -
-
- 200,000.00 -
-
-
-
-
-
- - - - - -
- Budgeted Expenditure -
-
- 800,000.00 -
-
-
- Actual Expenditure -
-
- 760,000.00 -
-
-
- Remaining Balance -
-
- 40,000.00 -
-
-
-
-
-
- - - -
- -
-
-
-
-
- - ); -}; - -export default ProjectCashFlow; diff --git a/src/components/ProjectCashFlow/index.ts b/src/components/ProjectCashFlow/index.ts deleted file mode 100644 index af238d3..0000000 --- a/src/components/ProjectCashFlow/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ProjectCashFlow"; diff --git a/src/components/ProjectFinancialSummary/ProjectFinancialCard.tsx b/src/components/ProjectFinancialSummary/ProjectFinancialCard.tsx deleted file mode 100644 index 25ff90e..0000000 --- a/src/components/ProjectFinancialSummary/ProjectFinancialCard.tsx +++ /dev/null @@ -1,173 +0,0 @@ -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"; - -interface Props { - Title: string; - TotalActiveProjectNumber: string; - TotalFees: string; - TotalBudget: string; - TotalCumulative: string; - TotalInvoicedAmount: string; - TotalReceivedAmount: string; - CashFlowStatus: string; - CostPerformanceIndex: string; - ClickedIndex: number; - Index: number; -} - -const ProjectFinancialCard: React.FC = ({ - Title, - TotalActiveProjectNumber, - TotalFees, - TotalBudget, - TotalCumulative, - TotalInvoicedAmount, - TotalReceivedAmount, - CashFlowStatus, - CostPerformanceIndex, - ClickedIndex, - Index, -}) => { - const [SearchCriteria, setSearchCriteria] = React.useState({}); - const { t } = useTranslation("dashboard"); - const borderColor = - CashFlowStatus === "Negative" - ? "border-red-300 border-solid" - : "border-green-200 border-solid"; - const selectedBackgroundColor = - ClickedIndex === Index ? "rgb(235 235 235)" : "rgb(255 255 255)"; - console.log(ClickedIndex); - console.log(Index); - return ( - -
- {Title} -
-
-
- Total Active Project -
-
- {TotalActiveProjectNumber} -
-
-
- Total Fees -
-
- {TotalFees} -
-
-
- Total Budget -
-
- {TotalBudget} -
-
-
- Total Cumulative Expenditure -
-
- {TotalCumulative} -
-
-
- Total Invoiced Amount -
-
- {TotalInvoicedAmount} -
-
-
- Total Received Amount -
-
- {TotalReceivedAmount} -
-
-
- Cash Flow Status -
- {CashFlowStatus === "Negative" && ( - <> -
- {CashFlowStatus} -
-
- - )} - {CashFlowStatus === "Positive" && ( - <> -
- {CashFlowStatus} -
-
- - )} -
- Cost Performance Index (CPI) -
- {Number(CostPerformanceIndex) < 1 && ( - <> -
- {CostPerformanceIndex} -
- - )} - {Number(CostPerformanceIndex) >= 1 && ( - <> -
- {CostPerformanceIndex} -
- - )} -
- ); -}; - -export default ProjectFinancialCard; diff --git a/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx b/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx deleted file mode 100644 index e9839c9..0000000 --- a/src/components/ProjectFinancialSummary/ProjectFinancialSummary.tsx +++ /dev/null @@ -1,465 +0,0 @@ -"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 ProjectFinancialCard from "./ProjectFinancialCard"; - -const ProjectFinancialSummary: React.FC = () => { - const [SearchCriteria, setSearchCriteria] = React.useState({}); - const { t } = useTranslation("dashboard"); - const [selectionModel, setSelectionModel]: any[] = React.useState([]); - const projectFinancialData = [ - { - id: 1, - title: "All Teams", - activeProject: "147", - fees: "22,800,000.00", - budget: "18,240,000.00", - cumulativeExpenditure: "17,950,000.00", - invoicedAmount: "18,240,000.00", - receivedAmount: "10,900,000.00", - cashFlowStatus: "Negative", - CPI: "0.69", - }, - { - id: 2, - title: "XXX Team", - activeProject: "25", - fees: "1,500,000.00", - budget: "1,200,000.00", - cumulativeExpenditure: "1,250,000.00", - invoicedAmount: "900,000.00", - receivedAmount: "650,000.00", - cashFlowStatus: "Negative", - CPI: "0.72", - }, - { - id: 3, - title: "YYY Team", - activeProject: "35", - fees: "5,000,000.00", - budget: "4,000,000.00", - cumulativeExpenditure: "3,200,000.00", - invoicedAmount: "3,500,000.00", - receivedAmount: "3,500,000.00", - cashFlowStatus: "Positive", - CPI: "1.09", - }, - { - id: 4, - title: "ZZZ Team", - activeProject: "50", - fees: "3,500,000.00", - budget: "2,800,000.00", - cumulativeExpenditure: "5,600,000.00", - invoicedAmount: "2,500,000.00", - receivedAmount: "2,200,000.00", - cashFlowStatus: "Negative", - CPI: "0.45", - }, - { - id: 5, - title: "AAA Team", - activeProject: "15", - fees: "4,800,000.00", - budget: "3,840,000.00", - cumulativeExpenditure: "2,500,000.00", - invoicedAmount: "1,500,000.00", - receivedAmount: "750,000.00", - cashFlowStatus: "Negative", - CPI: "0.60", - }, - { - id: 6, - title: "BBB Team", - activeProject: "22", - fees: "8,000,000.00", - budget: "6,400,000.00", - cumulativeExpenditure: "5,400,000.00", - invoicedAmount: "4,000,000.00", - receivedAmount: "3,800,000.00", - cashFlowStatus: "Negative", - CPI: "0.74", - }, - ]; - - const rows0 = [{id: 1,projectCode:"M1201",projectName:"Consultancy Project C", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "01/05/2024", client:"Client A", subsidiary:"N/A"}, - {id: 2,projectCode:"M1321",projectName:"Consultancy Project CCC", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "20/01/2024", client:"Client E", subsidiary:"Subsidiary B"}, - {id: 3,projectCode:"M1001",projectName:"Consultancy Project A", team:"YYY", teamLeader:"YYY", startDate:"01/07/2022", targetEndDate: "01/04/2024", client:"Client B", subsidiary:"N/A"}, - {id: 4,projectCode:"M1301",projectName:"Consultancy Project AAAA", team:"YYY", teamLeader:"YYY", startDate:"01/09/2022", targetEndDate: "20/02/2024", client:"Client C", subsidiary:"Subsidiary A"}, - {id: 5,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} - ] - - const rows1 = [{id: 1,projectCode:"M1201",projectName:"Consultancy Project C", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "01/05/2024", client:"Client A", subsidiary:"N/A"}, - {id: 2,projectCode:"M1321",projectName:"Consultancy Project CCC", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "20/01/2024", client:"Client E", subsidiary:"Subsidiary B"}, - ] - - const rows2 = [{id: 3,projectCode:"M1001",projectName:"Consultancy Project A", team:"YYY", teamLeader:"YYY", startDate:"01/07/2022", targetEndDate: "01/04/2024", client:"Client B", subsidiary:"N/A"}, - {id: 4,projectCode:"M1301",projectName:"Consultancy Project AAAA", team:"YYY", teamLeader:"YYY", startDate:"01/09/2022", targetEndDate: "20/02/2024", client:"Client C", subsidiary:"Subsidiary A"}, - {id: 5,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} - ] - - const projectFinancialRows = [{id: 1,projectCode:"M1354",projectName:"Consultanct Project BBB",clientName:"Client D",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"} - ] - - const clientFinancialRows =[{id: 1,clientCode:"Cust-02",clientName:"Client B",totalProjectInvolved:"1",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"}, - {id: 2,clientCode:"Cust-03",clientName:"Client C",totalProjectInvolved:"1",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"}, - {id: 3,clientCode:"Cust-04",clientName:"Client D",totalProjectInvolved:"4",cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00"} - ] - - const [isCardClickedIndex, setIsCardClickedIndex] = React.useState(0); - - const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows0); - - const handleCardClick = (r: any) => { - setIsCardClickedIndex(r); - if (r === 0) { - setSelectedTeamData(rows0); - } else if (r === 1) { - setSelectedTeamData(rows1); - } else if (r === 2) { - setSelectedTeamData(rows2); - } - }; - - const columns = [ - { - id: 'clientCode', - field: 'clientCode', - headerName: "Client Code", - flex: 0.7, - }, - { - id: 'clientName', - field: 'clientName', - headerName: "Client Name", - flex: 1, - }, - { - id: 'totalProjectInvolved', - field: 'totalProjectInvolved', - headerName: "Total Project Involved", - flex: 1, - }, - { - id: 'cashFlowStatus', - field: 'cashFlowStatus', - headerName: "Cash Flow Status", - flex: 1, - renderCell: (params:any) => { - if (params.row.cashFlowStatus === "Positive") { - return ( - {params.row.cashFlowStatus} - ) - } else if (params.row.cashFlowStatus === "Negative") { - return ( - {params.row.cashFlowStatus} - ) - } - }, - }, - { - id: 'cpi', - field: 'cpi', - headerName: "CPI", - flex: 0.7, - renderCell: (params:any) => { - if (params.row.cpi >= 1) { - return ( - {params.row.cpi} - ) - } else if (params.row.cpi < 1) { - return ( - {params.row.cpi} - ) - } - }, - }, - { - id: 'totalFees', - field: 'totalFees', - headerName: "Total Fees (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalFees} - ) - }, - }, - { - id: 'totalBudget', - field: 'totalBudget', - headerName: "Total Budget (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalBudget} - ) - }, - }, - { - id: 'totalCumulativeExpenditure', - field: 'totalCumulativeExpenditure', - headerName: "Total Cumulative Expenditure (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalCumulativeExpenditure} - ) - }, - }, - { - id: 'totalInvoicedAmount', - field: 'totalInvoicedAmount', - headerName: "Total Invoiced Amount (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalInvoicedAmount} - ) - }, - }, - { - id: 'totalUnInvoicedAmount', - field: 'totalUnInvoicedAmount', - headerName: "Total Un-invoiced Amount (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalUnInvoicedAmount} - ) - }, - }, - { - id: 'totalReceivedAmount', - field: 'totalReceivedAmount', - headerName: "Total Received Amount (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalReceivedAmount} - ) - }, - }, - - // { - // 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 columns2 = [ - { - id: 'projectCode', - field: 'projectCode', - headerName: "Project Code", - flex: 0.7, - }, - { - id: 'projectName', - field: 'projectName', - headerName: "Project Name", - flex: 1, - }, - { - id: 'clientName', - field: 'clientName', - headerName: "Client Name", - flex: 1, - }, - { - id: 'cashFlowStatus', - field: 'cashFlowStatus', - headerName: "Cash Flow Status", - flex: 1, - renderCell: (params:any) => { - if (params.row.cashFlowStatus === "Positive") { - return ( - {params.row.cashFlowStatus} - ) - } else if (params.row.cashFlowStatus === "Negative") { - return ( - {params.row.cashFlowStatus} - ) - } - }, - }, - { - id: "cpi", - field: "cpi", - headerName: "CPI", - flex: 0.7, - renderCell: (params: any) => { - if (params.row.cpi >= 1) { - return {params.row.cpi}; - } else if (params.row.cpi < 1) { - return {params.row.cpi}; - } - }, - }, - -{ - id: 'totalFees', - field: 'totalFees', - headerName: "Total Fees (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalFees} - ) - }, -}, -{ - id: 'totalBudget', - field: 'totalBudget', - headerName: "Total Budget (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalBudget} - ) -}, -}, -{ - id: 'totalCumulativeExpenditure', - field: 'totalCumulativeExpenditure', - headerName: "Total Cumulative Expenditure (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalCumulativeExpenditure} - ) - }, -}, -{ - id: 'totalInvoicedAmount', - field: 'totalInvoicedAmount', - headerName: "Total Invoiced Amount (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalInvoicedAmount} - ) - }, -}, -{ - id: 'totalUnInvoicedAmount', - field: 'totalUnInvoicedAmount', - headerName: "Total Un-invoiced Amount (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalUnInvoicedAmount} - ) - }, -}, -{ - id: 'totalReceivedAmount', - field: 'totalReceivedAmount', - headerName: "Total Received Amount (HKD)", - flex: 1, - renderCell: (params:any) => { - return ( - ${params.row.totalReceivedAmount} - ) - }, -}, -]; - - const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { - const selectedRowsData = selectedTeamData.filter((row: any) => - newSelectionModel.includes(row.id), - ); - console.log(selectedRowsData); - }; - - return ( - - - -
- {projectFinancialData.map((record, index) => ( -
handleCardClick(index)}> - -
- ))} -
-
- - -
- {/* */} - -
-
- - -
- -
-
-
- ); -}; - -export default ProjectFinancialSummary; diff --git a/src/components/ProjectFinancialSummary/index.ts b/src/components/ProjectFinancialSummary/index.ts deleted file mode 100644 index 724bb4a..0000000 --- a/src/components/ProjectFinancialSummary/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./ProjectFinancialSummary"; diff --git a/src/components/StaffUtilization/StaffUtilization.tsx b/src/components/StaffUtilization/StaffUtilization.tsx deleted file mode 100644 index 81dde4b..0000000 --- a/src/components/StaffUtilization/StaffUtilization.tsx +++ /dev/null @@ -1,1203 +0,0 @@ -"use client"; -import * as React from "react"; -import Grid from "@mui/material/Grid"; -import { useState, useEffect, useMemo } from "react"; -import Paper from "@mui/material/Paper"; -import { TFunction } from "i18next"; -import { useTranslation } from "react-i18next"; -import { Card, CardHeader } from "@mui/material"; -import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; -import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; -import ReactApexChart from "react-apexcharts"; -import { ApexOptions } from "apexcharts"; -import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; -import ReportProblemIcon from "@mui/icons-material/ReportProblem"; -import dynamic from "next/dynamic"; -import "../../app/global.css"; -import { AnyARecord, AnyCnameRecord } from "dns"; -import SearchBox, { Criterion } from "../SearchBox"; -import ProgressByClientSearch from "@/components/ProgressByClientSearch"; -import { Suspense } from "react"; -import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; -import { Input, Label } from "reactstrap"; -import Select, { components } from "react-select"; -import { DateCalendar } from "@mui/x-date-pickers/DateCalendar"; -import { DatePicker } from "@mui/x-date-pickers/DatePicker"; -import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; -import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; -import dayjs, { Dayjs } from "dayjs"; -import isBetweenPlugin from "dayjs/plugin/isBetween"; -import { PickersDay, PickersDayProps } from "@mui/x-date-pickers/PickersDay"; -import { styled } from "@mui/material/styles"; - -dayjs.extend(isBetweenPlugin); -interface CustomPickerDayProps extends PickersDayProps { - isSelected: boolean; - isHovered: boolean; -} - -const CustomPickersDay = styled(PickersDay, { - shouldForwardProp: (prop) => prop !== "isSelected" && prop !== "isHovered", -})(({ theme, isSelected, isHovered, day }) => ({ - borderRadius: 0, - ...(isSelected && { - backgroundColor: theme.palette.primary.main, - color: theme.palette.primary.contrastText, - "&:hover, &:focus": { - backgroundColor: theme.palette.primary.main, - }, - }), - ...(isHovered && { - backgroundColor: theme.palette.primary[theme.palette.mode], - "&:hover, &:focus": { - backgroundColor: theme.palette.primary[theme.palette.mode], - }, - }), - ...(day.day() === 0 && { - borderTopLeftRadius: "50%", - borderBottomLeftRadius: "50%", - }), - ...(day.day() === 6 && { - borderTopRightRadius: "50%", - borderBottomRightRadius: "50%", - }), -})) as React.ComponentType; - -const isInSameWeek = (dayA: Dayjs, dayB: Dayjs | null | undefined) => { - if (dayB == null) { - return false; - } - - return dayA.isSame(dayB, "week"); -}; - -function Day( - props: PickersDayProps & { - selectedDay?: Dayjs | null; - hoveredDay?: Dayjs | null; - }, -) { - const { day, selectedDay, hoveredDay, ...other } = props; - - return ( - - ); -} - -const StaffUtilization: React.FC = () => { - const todayDate = new Date(); - const firstDayOfWeek = new Date(); - const lastDayOfWeek = new Date(); - firstDayOfWeek.setDate(todayDate.getDate() - todayDate.getDay() + 1); - lastDayOfWeek.setDate(todayDate.getDate() - todayDate.getDay() + 7); - const firstDayOfMonth = new Date( - todayDate.getFullYear(), - todayDate.getMonth(), - 1, - ); - const lastDayOfMonth = new Date( - todayDate.getFullYear(), - todayDate.getMonth() + 1, - 0, - ); - const [firstDayOfWeekString, setFirstDayOfWeekString] = React.useState( - dayjs(firstDayOfWeek).format("DD MMM YYYY"), - ); - const [lastDayOfWeekString, setLastDayOfWeekString] = React.useState( - dayjs(lastDayOfWeek).format("DD MMM YYYY"), - ); - const [firstDayOfMonthString, setFirstDayOfMonthString] = React.useState( - dayjs(firstDayOfMonth).format("DD MMM YYYY"), - ); - const [lastDayOfMonthString, setLastDayOfMonthString] = React.useState( - dayjs(lastDayOfMonth).format("DD MMM YYYY"), - ); - const [selectionModel, setSelectionModel]: any[] = React.useState([]); - const [manHoursSpentPeriod, setManHoursSpentPeriod]: any[] = React.useState( - firstDayOfWeekString + " to " + lastDayOfWeekString, - ); - const [teamTotalManhoursSpentSelect, setTeamTotalManhoursSpentSelect]: any = - React.useState("Weekly"); - const [staffGradeManhoursSpentSelect, setStaffGradeManhoursSpentSelect]: any = - React.useState("Weekly"); - const [ - individualStaffManhoursSpentSelect, - setIndividualStaffManhoursSpentSelect, - ]: any = React.useState("Daily"); - const weekDates: any[] = []; - const monthDates: any[] = []; - const currentDate = dayjs(); - const sixMonthsAgo = currentDate.subtract(6, "month"); - for (let i = 0; i < 7; i++) { - const currentDate = new Date(firstDayOfWeek); - currentDate.setDate(firstDayOfWeek.getDate() + i); - const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); - weekDates.push(formattedDate); - } - for ( - let date = sixMonthsAgo.clone(); - date.isBefore(currentDate, "month"); - date = date.add(1, "month") - ) { - monthDates.push(date.format("MM-YYYY")); - } - monthDates.push(currentDate.format("MM-YYYY")); - // for (let i = firstDayOfMonth.getDate(); i <= lastDayOfMonth.getDate(); i++) { - // const currentDate = new Date(todayDate.getFullYear(), todayDate.getMonth(), i); - // const formattedDate = dayjs(currentDate).format('DD MMM'); - // monthDates.push(formattedDate); - // } - const [teamTotalManhoursSpentPeriod, setTeamTotalManhoursSpentPeriod]: any[] = - React.useState(weekDates); - const [ - teamTotalManhoursByStaffGrade, - setTeamTotalManhoursByStaffGrade, - ]: any[] = React.useState(weekDates); - const [ - individualStaffManhoursSpentPeriod, - setIndividualStaffManhoursSpentPeriod, - ]: any[] = React.useState(weekDates); - const [ - teamTotalManhoursSpentPlanData, - setTeamTotalManhoursSpentPlanData, - ]: any[] = React.useState([42, 42, 42, 42, 42, 0, 0]); - const [ - teamTotalManhoursSpentActualData, - setTeamTotalManhoursSpentActualData, - ]: any[] = React.useState([45, 42, 60, 42, 58, 0, 0]); - const [hoveredDay, setHoveredDay] = React.useState(null); - const [value, setValue] = React.useState(dayjs()); - const [weeklyValueByStaffGrade, setWeeklyValueByStaffGrade] = - React.useState(dayjs()); - const [weeklyValueByIndividualStaff, setWeeklyValueByIndividualStaff] = - React.useState(dayjs()); - const [staffGradeManhoursSpentValue, setStaffGradeManhoursSpentValue] = - React.useState(dayjs()); - const [totalManHoursMonthlyFromValue, setTotalManHoursMonthlyFromValue] = - React.useState(dayjs(new Date()).subtract(6, "month")); - const [totalManHoursMonthlyToValue, setTotalManHoursMonthlyToValue] = - React.useState(dayjs()); - const [ - totalManHoursByStaffGradeMonthlyFromValue, - setTotalManHoursByStaffGradeMonthlyFromValue, - ] = React.useState(dayjs(new Date()).subtract(6, "month")); - const [ - totalManHoursByStaffGradeMonthlyToValue, - setTotalManHoursByStaffGradeMonthlyToValue, - ] = React.useState(dayjs()); - const [ - totalManHoursByIndividualStaffMonthlyFromValue, - setTotalManHoursByIndividualStaffMonthlyFromValue, - ] = React.useState(dayjs(new Date()).subtract(6, "month")); - const [ - totalManHoursByIndividualStaffMonthlyToValue, - setTotalManHoursByIndividualStaffMonthlyToValue, - ] = React.useState(dayjs()); - const [ - totalManHoursByIndividualStaffDailyFromValue, - setTotalManHoursByIndividualStaffDailyFromValue, - ] = React.useState(dayjs(new Date()).subtract(6, "day")); - const [ - totalManHoursByIndividualStaffDailyToValue, - setTotalManHoursByIndividualStaffDailyToValue, - ] = React.useState(dayjs()); - const [totalManHoursMaxValue, setTotalManHoursMaxValue] = React.useState(75); - - const teamOptions = [ - { value: 1, label: "XXX Team" }, - { value: 2, label: "YYY Team" }, - { value: 3, label: "ZZZ Team" }, - ]; - - const columns = [ - { - id: "projectCode", - field: "projectCode", - headerName: "Project Code", - flex: 1, - }, - { - id: "projectName", - field: "projectName", - headerName: "Project Name", - flex: 1, - }, - { - id: "team", - field: "team", - headerName: "Team", - flex: 1, - }, - { - id: "teamLeader", - field: "teamLeader", - headerName: "Team Leader", - flex: 1, - }, - { - id: "startDate", - field: "startDate", - headerName: "Start Date", - flex: 1, - }, - { - id: "targetEndDate", - field: "targetEndDate", - headerName: "Target End Date", - flex: 1, - }, - { - id: "client", - field: "client", - headerName: "Client", - flex: 1, - }, - { - id: "subsidiary", - field: "subsidiary", - headerName: "Subsidiary", - flex: 1, - }, - ]; - - const options: ApexOptions = { - chart: { - height: 350, - type: "line", - }, - stroke: { - width: [2, 2], - }, - plotOptions: { - bar: { - horizontal: false, - distributed: false, - }, - }, - dataLabels: { - enabled: true, - }, - xaxis: { - categories: teamTotalManhoursSpentPeriod, - }, - yaxis: [ - { - title: { - text: "Team Total Manhours Spent (Hour)", - }, - min: 0, - max: totalManHoursMaxValue, - tickAmount: 5, - }, - ], - grid: { - borderColor: "#f1f1f1", - }, - annotations: {}, - series: [ - { - name: "Planned", - type: "line", - color: "#efbe7d", - data: teamTotalManhoursSpentPlanData, - }, - { - name: "Actual", - type: "line", - color: "#7cd3f2", - data: teamTotalManhoursSpentActualData, - }, - ], - }; - - const staffGradeOptions: ApexOptions = { - chart: { - height: 350, - type: "line", - }, - stroke: { - width: [2, 2], - }, - plotOptions: { - bar: { - horizontal: true, - distributed: false, - }, - }, - dataLabels: { - enabled: true, - }, - xaxis: { - categories: [ - "Grade 1: A. QS / QS Trainee", - "Grade 2: QS", - "Grade 3: Senior QS", - "Grade 4: Manager", - "Grade 5: Director", - ], - }, - yaxis: [ - { - title: { - text: "Staff Grade", - }, - min: 0, - max: 60, - tickAmount: 5, - }, - ], - grid: { - borderColor: "#f1f1f1", - }, - annotations: {}, - series: [ - { - name: "Planned", - type: "bar", - color: "#efbe7d", - data: [35, 45, 35, 20, 10], - }, - { - name: "Actual", - type: "bar", - color: "#00acb1", - data: [25, 26, 33, 20, 11], - }, - ], - }; - - const individualStaffOptions: ApexOptions = { - chart: { - height: 350, - type: "line", - }, - stroke: { - width: [1], - }, - plotOptions: { - bar: { - horizontal: true, - distributed: false, - }, - }, - dataLabels: { - enabled: true, - }, - xaxis: { - categories: [ - "Consultancy Project 123 (CUST-001, Subsidiary A)", - "Consultancy Project 456 (CUST-001, Subsidiary A)", - "Construction Project A (CUST-001, Subsidiary A)", - "Construction Project B (CUST-001, Subsidiary A)", - "Construction Project C (CUST-001, Subsidiary A)", - ], - }, - yaxis: [ - { - title: { - text: "Project", - }, - min: 0, - max: 12, - tickAmount: 5, - }, - ], - grid: { - borderColor: "#f1f1f1", - }, - annotations: {}, - series: [ - { - name: "Manhours(Hour)", - type: "bar", - color: "#00acb1", - data: [12, 12, 11, 12, 0], - }, - ], - }; - - const teamTotalManhoursSpentOnClick = (r: any) => { - setTeamTotalManhoursSpentSelect(r); - if (r === "Weekly") { - setValue(dayjs(new Date())); - setTeamTotalManhoursSpentPeriod(weekDates); - setTeamTotalManhoursSpentPlanData([42, 42, 42, 42, 42, 0, 0]); - setTeamTotalManhoursSpentActualData([45, 42, 60, 42, 58, 0, 0]); - setTotalManHoursMaxValue(75); - } else if (r === "Monthly") { - setTeamTotalManhoursSpentPeriod(monthDates); - setTeamTotalManhoursSpentPlanData([840, 840, 840, 840, 840, 840]); - setTeamTotalManhoursSpentActualData([900, 840, 1200, 840, 1160, 840]); - setTotalManHoursMaxValue(1250); - } - }; - - const individualStaffManhoursSpentOnClick = (r: any) => { - setIndividualStaffManhoursSpentSelect(r); - // if (r === "Weekly") { - // setValue(dayjs(new Date)) - // setTeamTotalManhoursSpentPeriod(weekDates) - // setTeamTotalManhoursSpentPlanData([42,42,42,42,42,0,0]) - // setTeamTotalManhoursSpentActualData([45,42,60,42,58,0,0]) - // setTotalManHoursMaxValue(75) - // } else if (r === "Monthly") { - // setTeamTotalManhoursSpentPeriod(monthDates) - // setTeamTotalManhoursSpentPlanData([840,840,840,840,840,840]) - // setTeamTotalManhoursSpentActualData([900,840,1200,840,1160,840]) - // setTotalManHoursMaxValue(1250) - // } - }; - - const selectWeeklyPeriod = (r: any) => { - const selectDate = new Date(r); - const firstDayOfWeek = new Date(); - firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0); - const weekDates: any[] = []; - for (let i = 0; i < 7; i++) { - const currentDate = new Date(firstDayOfWeek); - currentDate.setDate(firstDayOfWeek.getDate() + i); - const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); - weekDates.push(formattedDate); - } - setTeamTotalManhoursSpentPeriod(weekDates); - setValue(dayjs(firstDayOfWeek)); - }; - - const selectWeeklyPeriodByStaffGrade = (r: any) => { - const selectDate = new Date(r); - const firstDayOfWeek = new Date(); - firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0); - const weekDates: any[] = []; - for (let i = 0; i < 7; i++) { - const currentDate = new Date(firstDayOfWeek); - currentDate.setDate(firstDayOfWeek.getDate() + i); - const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); - weekDates.push(formattedDate); - } - setTeamTotalManhoursByStaffGrade(weekDates); - setWeeklyValueByStaffGrade(dayjs(firstDayOfWeek)); - }; - - const selectWeeklyPeriodIndividualStaff = (r: any) => { - const selectDate = new Date(r); - const firstDayOfWeek = new Date(); - firstDayOfWeek.setDate(selectDate.getDate() - selectDate.getDay() + 0); - const weekDates: any[] = []; - for (let i = 0; i < 7; i++) { - const currentDate = new Date(firstDayOfWeek); - currentDate.setDate(firstDayOfWeek.getDate() + i); - const formattedDate = dayjs(currentDate).format("DD MMM (ddd)"); - weekDates.push(formattedDate); - } - setIndividualStaffManhoursSpentPeriod(weekDates); - setWeeklyValueByIndividualStaff(dayjs(firstDayOfWeek)); - }; - - const selectMonthlyPeriodFrom = (r: any) => { - const monthDates: any[] = []; - const monthPlanData: any[] = []; - const monthActualData: any[] = []; - const selectFromDate = dayjs(r); - for ( - let date = selectFromDate.clone(); - date.isBefore(totalManHoursMonthlyToValue, "month"); - date = date.add(1, "month") - ) { - monthDates.push(date.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - } - monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - setTeamTotalManhoursSpentPlanData(monthPlanData); - setTeamTotalManhoursSpentActualData(monthActualData); - setTeamTotalManhoursSpentPeriod(monthDates); - }; - - const selectMonthlyPeriodTo = (r: any) => { - const monthDates: any[] = []; - const monthPlanData: any[] = []; - const monthActualData: any[] = []; - const selectToDate = dayjs(r); - for ( - let date = totalManHoursMonthlyFromValue.clone(); - date.isBefore(selectToDate, "month"); - date = date.add(1, "month") - ) { - monthDates.push(date.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - } - monthDates.push(selectToDate.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - setTeamTotalManhoursSpentPlanData(monthPlanData); - setTeamTotalManhoursSpentActualData(monthActualData); - setTeamTotalManhoursSpentPeriod(monthDates); - }; - - const selectStaffGradeMonthlyPeriodFrom = (r: any) => { - const monthDates: any[] = []; - const monthPlanData: any[] = []; - const monthActualData: any[] = []; - const selectFromDate = dayjs(r); - for ( - let date = selectFromDate.clone(); - date.isBefore(totalManHoursMonthlyToValue, "month"); - date = date.add(1, "month") - ) { - monthDates.push(date.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - } - monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - // setTeamTotalManhoursSpentPlanData(monthPlanData) - // setTeamTotalManhoursSpentActualData(monthActualData) - setTeamTotalManhoursByStaffGrade(weekDates); - }; - - const selectStaffGradeMonthlyPeriodTo = (r: any) => { - const monthDates: any[] = []; - const monthPlanData: any[] = []; - const monthActualData: any[] = []; - const selectToDate = dayjs(r); - for ( - let date = totalManHoursMonthlyFromValue.clone(); - date.isBefore(selectToDate, "month"); - date = date.add(1, "month") - ) { - monthDates.push(date.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - } - monthDates.push(selectToDate.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - // setTeamTotalManhoursSpentPlanData(monthPlanData) - // setTeamTotalManhoursSpentActualData(monthActualData) - setTeamTotalManhoursByStaffGrade(weekDates); - }; - - const selectIndividualStaffMonthlyPeriodFrom = (r: any) => { - const monthDates: any[] = []; - const monthPlanData: any[] = []; - const monthActualData: any[] = []; - const selectFromDate = dayjs(r); - for ( - let date = selectFromDate.clone(); - date.isBefore(totalManHoursMonthlyToValue, "month"); - date = date.add(1, "month") - ) { - monthDates.push(date.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - } - monthDates.push(totalManHoursMonthlyToValue.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - // setTeamTotalManhoursSpentPlanData(monthPlanData) - // setTeamTotalManhoursSpentActualData(monthActualData) - setIndividualStaffManhoursSpentPeriod(weekDates); - }; - - const selectIndividualStaffMonthlyPeriodTo = (r: any) => { - const monthDates: any[] = []; - const monthPlanData: any[] = []; - const monthActualData: any[] = []; - const selectToDate = dayjs(r); - for ( - let date = totalManHoursMonthlyFromValue.clone(); - date.isBefore(selectToDate, "month"); - date = date.add(1, "month") - ) { - monthDates.push(date.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - } - monthDates.push(selectToDate.format("MM-YYYY")); - monthPlanData.push(840); - monthActualData.push(Math.floor(Math.random() * (1200 - 840) + 840)); - // setTeamTotalManhoursSpentPlanData(monthPlanData) - // setTeamTotalManhoursSpentActualData(monthActualData) - setIndividualStaffManhoursSpentPeriod(weekDates); - }; - - const options2: ApexOptions = { - chart: { - type: "donut", - }, - colors: ['#f57f90','#94f7d6','#87c5f5','#ab95f5','#ab95f5'], - plotOptions: { - pie: { - donut: { - labels: { - show: true, - name: { - show: true, - }, - value: { - show: false, - fontWeight: 500, - fontSize: "30px", - color: "#3e98c7", - }, - total: { - show: false, - showAlways: true, - label: "Spent", - fontFamily: "sans-serif", - formatter: function (val) { - return val + "%"; - }, - }, - }, - }, - }, - }, - series:[23.5,25.5,25.5,25.5], - labels: ["Consultancy Project 123","Consultancy Project ABC","Consultancy Project A","Consultancy Project B"], - legend: { - show: false, - }, - responsive: [ - { - breakpoint: 480, - options: { - chart: { - width: 200, - }, - legend: { - position: "bottom", - show: false, - }, - }, - }, - ], - }; - - return ( - <> - -
-
- - - -
-
- {teamTotalManhoursSpentSelect === "Weekly" && ( - <> - - - - )} - {teamTotalManhoursSpentSelect === "Monthly" && ( - <> - - - - )} -
-
-
- -
-
- */} -
-
- -
-
-
-
-
-
- - - - -
-
- {individualStaffManhoursSpentSelect === "Daily" && ( - <> - - - - - )} - {individualStaffManhoursSpentSelect === "Weekly" && ( - <> - - - - - )} - {individualStaffManhoursSpentSelect === "Monthly" && ( - <> - - - - - )} -
-
-
- -
-
-