Sfoglia il codice sorgente

update project status by client

tags/Baseline_30082024_FRONTEND_UAT
Mac\David 1 anno fa
parent
commit
3fc5f822d4
5 ha cambiato i file con 82 aggiunte e 31 eliminazioni
  1. +5
    -1
      src/app/(main)/dashboard/ProjectStatusByClient/page.tsx
  2. +11
    -4
      src/app/api/clientprojects/actions.ts
  3. +1
    -1
      src/components/CustomDatagrid/CustomDatagrid.tsx
  4. +57
    -20
      src/components/ProgressByClient/ProgressByClient.tsx
  5. +8
    -5
      src/components/ProgressByClientSearch/ProgressByClientSearch.tsx

+ 5
- 1
src/app/(main)/dashboard/ProjectStatusByClient/page.tsx Vedi File

@@ -1,14 +1,17 @@

import { Metadata } from "next"; import { Metadata } from "next";
import { I18nProvider } from "@/i18n"; import { I18nProvider } from "@/i18n";
import DashboardPage from "@/components/DashboardPage/DashboardPage"; import DashboardPage from "@/components/DashboardPage/DashboardPage";
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton";
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; import ProgressByClientSearch from "@/components/ProgressByClientSearch";
import { Suspense } from "react";
import { Suspense} from "react";
import Tabs, { TabsProps } from "@mui/material/Tabs"; import Tabs, { TabsProps } from "@mui/material/Tabs";
import Tab from "@mui/material/Tab"; import Tab from "@mui/material/Tab";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import ProgressByClient from "@/components/ProgressByClient"; import ProgressByClient from "@/components/ProgressByClient";
import { preloadClientProjects } from "@/app/api/clientprojects"; import { preloadClientProjects } from "@/app/api/clientprojects";
import { ClientProjectResult} from "@/app/api/clientprojects";
import { useSearchParams } from 'next/navigation';


export const metadata: Metadata = { export const metadata: Metadata = {
title: "Project Status by Client", title: "Project Status by Client",
@@ -24,6 +27,7 @@ const ProjectStatusByClient: React.FC = () => {
<Suspense fallback={<ProgressByClientSearch.Loading />}> <Suspense fallback={<ProgressByClientSearch.Loading />}>
<ProgressByClientSearch /> <ProgressByClientSearch />
</Suspense> </Suspense>
<ProgressByClient/>
</I18nProvider> </I18nProvider>
); );
}; };


+ 11
- 4
src/app/api/clientprojects/actions.ts Vedi File

@@ -21,8 +21,15 @@ export interface ClientSubsidiaryProjectResult {
comingPaymentMilestone: string; comingPaymentMilestone: string;
} }


export const fetchAllClientSubsidiaryProjects = cache(async (customerId: number, subsidiaryId: number) => {
return serverFetchJson<ClientSubsidiaryProjectResult[]>(
`${BASE_API_URL}/dashboard/searchCustomerSubsidiaryProject?customerId=${customerId}&subsidiaryId=${subsidiaryId}`
);
export const fetchAllClientSubsidiaryProjects = cache(async (customerId: number, subsidiaryId?: number) => {
if (subsidiaryId === 0){
return serverFetchJson<ClientSubsidiaryProjectResult[]>(
`${BASE_API_URL}/dashboard/searchCustomerSubsidiaryProject?customerId=${customerId}`
);
} else {
return serverFetchJson<ClientSubsidiaryProjectResult[]>(
`${BASE_API_URL}/dashboard/searchCustomerSubsidiaryProject?customerId=${customerId}&subsidiaryId=${subsidiaryId}`
);
}
}); });

+ 1
- 1
src/components/CustomDatagrid/CustomDatagrid.tsx Vedi File

@@ -1,7 +1,7 @@
"use client"; "use client";
import * as React from "react"; import * as React from "react";
import { Card, CardHeader, CardContent, SxProps, Theme } from "@mui/material"; import { Card, CardHeader, CardContent, SxProps, Theme } from "@mui/material";
import { DataGrid, GridColDef, GridRowSelectionModel, GridColumnGroupingModel} from "@mui/x-data-grid";
import { DataGrid, GridColDef, GridRowSelectionModel, GridColumnGroupingModel, useGridApiRef} from "@mui/x-data-grid";
import { darken, lighten, styled } from "@mui/material/styles"; import { darken, lighten, styled } from "@mui/material/styles";
import { useState } from "react"; import { useState } from "react";




+ 57
- 20
src/components/ProgressByClient/ProgressByClient.tsx Vedi File

@@ -21,13 +21,18 @@ import { ClientProjectResult} from "@/app/api/clientprojects";
import { ConstructionOutlined } from "@mui/icons-material"; import { ConstructionOutlined } from "@mui/icons-material";
import ReactApexChart from "react-apexcharts"; import ReactApexChart from "react-apexcharts";
import { ApexOptions } from "apexcharts"; import { ApexOptions } from "apexcharts";
import { useSearchParams } from 'next/navigation';
import { fetchAllClientSubsidiaryProjects} from "@/app/api/clientprojects/actions";
// const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false }); // const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });


interface Props { interface Props {
clientSubsidiaryProjectResult: ClientSubsidiaryProjectResult[];
// clientSubsidiaryProjectResult: ClientSubsidiaryProjectResult[];
} }


const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) => {
const ProgressByClient: React.FC<Props> = () => {
const searchParams = useSearchParams();
const customerId = searchParams.get('customerId');
const subsidiaryId = searchParams.get('subsidiaryId');
const [activeTab, setActiveTab] = useState("financialSummary"); const [activeTab, setActiveTab] = useState("financialSummary");
const [SearchCriteria, setSearchCriteria] = React.useState({}); const [SearchCriteria, setSearchCriteria] = React.useState({});
const { t } = useTranslation("dashboard"); const { t } = useTranslation("dashboard");
@@ -56,6 +61,32 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
const [chartProjectName, setChartProjectName]:any[] = useState([]); const [chartProjectName, setChartProjectName]:any[] = useState([]);
const [chartManhourConsumptionPercentage, setChartManhourConsumptionPercentage]:any[] = useState([]); const [chartManhourConsumptionPercentage, setChartManhourConsumptionPercentage]:any[] = useState([]);
const color = ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"]; const color = ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"];
const [clientSubsidiaryProjectResult, setClientSubsidiaryProjectResult]:any[] = useState([]);

const fetchData = async () => {
if (customerId && subsidiaryId) {
try {
if (subsidiaryId === '-'){
console.log("ss")
const clickResult = await fetchAllClientSubsidiaryProjects(
Number(customerId),Number(0))
console.log(clickResult)
setClientSubsidiaryProjectResult(clickResult);
} else {
const clickResult = await fetchAllClientSubsidiaryProjects(
Number(customerId),
Number(subsidiaryId))
console.log(clickResult)
setClientSubsidiaryProjectResult(clickResult);
}
} catch (error) {
console.error('Error fetching client subsidiary projects:', error);
}
}
}
useEffect(() => { useEffect(() => {
const projectName = [] const projectName = []
const manhourConsumptionPercentage = [] const manhourConsumptionPercentage = []
@@ -68,6 +99,12 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
setChartManhourConsumptionPercentage(manhourConsumptionPercentage) setChartManhourConsumptionPercentage(manhourConsumptionPercentage)
}, [clientSubsidiaryProjectResult]); }, [clientSubsidiaryProjectResult]);


useEffect(() => {
fetchData()
}, [customerId,subsidiaryId]);



const rows2 = [ const rows2 = [
{ {
id: 1, id: 1,
@@ -155,37 +192,37 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
></span> ></span>
); );
}, },
flex: 0.1,
flex:0.1
}, },
{ {
id: "projectName", id: "projectName",
field: "projectName", field: "projectName",
headerName: "Project", headerName: "Project",
flex: 1,
minWidth:300
}, },
{ {
id: "team", id: "team",
field: "team", field: "team",
headerName: "Team", headerName: "Team",
flex: 0.8,
minWidth: 50
}, },
{ {
id: "teamLeader",
field: "teamLeader",
id: "teamLead",
field: "teamLead",
headerName: "Team Leader", headerName: "Team Leader",
flex: 0.8,
minWidth: 70
}, },
{ {
id: "expectedStage", id: "expectedStage",
field: "expectedStage", field: "expectedStage",
headerName: "Expected Stage", headerName: "Expected Stage",
flex: 1,
minWidth: 300
}, },
{ {
id: "budgetedManhour", id: "budgetedManhour",
field: "budgetedManhour", field: "budgetedManhour",
headerName: "Budgeted Manhour", headerName: "Budgeted Manhour",
flex: 0.8,
minWidth: 70
}, },
{ {
id: "spentManhour", id: "spentManhour",
@@ -201,7 +238,7 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
return <span>{params.row.spentManhour}</span>; return <span>{params.row.spentManhour}</span>;
} }
}, },
flex: 0.8,
minWidth: 70
}, },
{ {
id: "remainedManhour", id: "remainedManhour",
@@ -216,13 +253,13 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
return <span>{params.row.remainedManhour}</span>; return <span>{params.row.remainedManhour}</span>;
} }
}, },
flex: 1,
minWidth: 70
}, },
{ {
id: "comingPaymentMilestone", id: "comingPaymentMilestone",
field: "comingPaymentMilestone", field: "comingPaymentMilestone",
headerName: "Coming Payment Milestone", headerName: "Coming Payment Milestone",
flex: 1,
minWidth: 100
}, },
{ {
id: "alert", id: "alert",
@@ -239,7 +276,7 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
return <span></span>; return <span></span>;
} }
}, },
flex: 0.2,
flex:0.1
}, },
]; ];
const optionstest: ApexOptions = { const optionstest: ApexOptions = {
@@ -463,7 +500,7 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
}; };


const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => {
const selectedRowsData:any = clientSubsidiaryProjectResult.filter((row) =>
const selectedRowsData:any = clientSubsidiaryProjectResult.filter((row:any) =>
newSelectionModel.includes(row.projectId), newSelectionModel.includes(row.projectId),
); );
console.log(selectedRowsData); console.log(selectedRowsData);
@@ -533,9 +570,9 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
<CardHeader className="text-slate-500" title="Project Resource Consumption" /> <CardHeader className="text-slate-500" title="Project Resource Consumption" />
<div style={{ display: "inline-block", width: "99%" }}> <div style={{ display: "inline-block", width: "99%" }}>
<ReactApexChart <ReactApexChart
options={optionstest}
series={optionstest.series}
type="line"
options={options}
series={options.series}
type="bar"
height={350} height={350}
/> />
</div> </div>
@@ -590,13 +627,13 @@ const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) =>
Please select the project you want to check. Please select the project you want to check.
</div> </div>
)} )}
{/* {percentageArray.length > 0 && (
{percentageArray.length > 0 && (
<ReactApexChart <ReactApexChart
options={options2} options={options2}
series={percentageArray} series={percentageArray}
type="donut" type="donut"
/> />
)} */}
)}
</Card> </Card>
</Grid> </Grid>
<Grid item xs={12} md={12} lg={12}> <Grid item xs={12} md={12} lg={12}>


+ 8
- 5
src/components/ProgressByClientSearch/ProgressByClientSearch.tsx Vedi File

@@ -1,7 +1,7 @@
"use client"; "use client";


import { ProjectResult } from "@/app/api/projects"; import { ProjectResult } from "@/app/api/projects";
import React, { useMemo, useState, useCallback } from "react";
import React, { useMemo, useState, useCallback, useEffect } from "react";
import SearchBox, { Criterion } from "../SearchBox"; import SearchBox, { Criterion } from "../SearchBox";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import SearchResults, { Column } from "../SearchResults"; import SearchResults, { Column } from "../SearchResults";
@@ -18,6 +18,7 @@ type SearchQuery = Partial<Omit<ClientProjectResult, "id">>;
type SearchParamNames = keyof SearchQuery; type SearchParamNames = keyof SearchQuery;


const ProgressByClientSearch: React.FC<Props> = ({ clientProjects }) => { const ProgressByClientSearch: React.FC<Props> = ({ clientProjects }) => {
const router = useRouter();
const { t } = useTranslation("projects"); const { t } = useTranslation("projects");
const searchParams = useSearchParams() const searchParams = useSearchParams()
// If project searching is done on the server-side, then no need for this. // If project searching is done on the server-side, then no need for this.
@@ -41,9 +42,9 @@ const ProgressByClientSearch: React.FC<Props> = ({ clientProjects }) => {


const onTaskClick = useCallback(async (clientProjectResult: ClientProjectResult) => { const onTaskClick = useCallback(async (clientProjectResult: ClientProjectResult) => {
try { try {
const clickResult = await fetchAllClientSubsidiaryProjects(clientProjectResult.customerId, clientProjectResult.subsidiaryId);
console.log(clickResult);
setClientSubsidiaryProjectResult(clickResult);
router.push(
`/dashboard/ProjectStatusByClient?customerId=${clientProjectResult.customerId}&subsidiaryId=${clientProjectResult.subsidiaryId}`
);
} catch (error) { } catch (error) {
console.error('Error fetching client subsidiary projects:', error); console.error('Error fetching client subsidiary projects:', error);
} }
@@ -86,7 +87,9 @@ const ProgressByClientSearch: React.FC<Props> = ({ clientProjects }) => {
items={filteredProjects} items={filteredProjects}
columns={columns} columns={columns}
/> />
<ProgressByClient clientSubsidiaryProjectResult={clientSubsidiaryProjectResult}/>
{/* {clientSubsidiaryProjectResult.length > 0 && (
<ProgressByClient clientSubsidiaryProjectResult={clientSubsidiaryProjectResult} />
)} */}
</> </>
); );
}; };


Caricamento…
Annulla
Salva