瀏覽代碼

update

tags/Baseline_30082024_FRONTEND_UAT
Mac\David 1 年之前
父節點
當前提交
085f5bfa2d
共有 8 個文件被更改,包括 321 次插入211 次删除
  1. +2
    -1
      src/app/(main)/dashboard/ProjectStatusByClient/page.tsx
  2. +28
    -0
      src/app/api/clientprojects/actions.ts
  3. +76
    -43
      src/app/api/clientprojects/index.ts
  4. +168
    -142
      src/components/ProgressByClient/ProgressByClient.tsx
  5. +41
    -19
      src/components/ProgressByClientSearch/ProgressByClientSearch.tsx
  6. +3
    -4
      src/components/ProgressByClientSearch/ProgressByClientSearchWrapper.tsx
  7. +2
    -2
      src/components/ProgressByTeam/ProgressByTeam.tsx
  8. +1
    -0
      src/components/ProjectSearch/ProjectSearch.tsx

+ 2
- 1
src/app/(main)/dashboard/ProjectStatusByClient/page.tsx 查看文件

@@ -8,12 +8,14 @@ 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";


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


const ProjectStatusByClient: React.FC = () => { const ProjectStatusByClient: React.FC = () => {
preloadClientProjects();
return ( return (
<I18nProvider namespaces={["dashboard"]}> <I18nProvider namespaces={["dashboard"]}>
<Typography variant="h4" marginInlineEnd={2}> <Typography variant="h4" marginInlineEnd={2}>
@@ -22,7 +24,6 @@ const ProjectStatusByClient: React.FC = () => {
<Suspense fallback={<ProgressByClientSearch.Loading />}> <Suspense fallback={<ProgressByClientSearch.Loading />}>
<ProgressByClientSearch /> <ProgressByClientSearch />
</Suspense> </Suspense>
<ProgressByClient />
</I18nProvider> </I18nProvider>
); );
}; };


+ 28
- 0
src/app/api/clientprojects/actions.ts 查看文件

@@ -0,0 +1,28 @@
"use server";

import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { Dayjs } from "dayjs";
import { cache } from "react";


export interface ClientSubsidiaryProjectResult {
color: string;
projectId: number;
projectCode: string;
projectName: string;
team: string;
teamLead: string;
expectedStage: string;
budgetedManhour: number;
spentManhour: number;
remainedManhour: number;
manhourConsumptionPercentage: number;
comingPaymentMilestone: string;
}

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

+ 76
- 43
src/app/api/clientprojects/index.ts 查看文件

@@ -1,53 +1,86 @@
import { cache } from "react"; import { cache } from "react";
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import "server-only";



export interface ClientProjectResult { export interface ClientProjectResult {
id: number; id: number;
clientCode: string;
clientName: string;
SubsidiaryClientCode: string;
SubsidiaryClientName: string;
NoOfProjects: number;
customerId: number;
customerCode: string;
customerName: string;
subsidiaryId: number;
subsidiaryCode: string;
subsidiaryName: string;
projectNo: number;
} }


export const preloadProjects = () => {
fetchClientProjects();
// export interface ClientSubsidiaryProjectResult {
// projectId: number;
// projectCode: string;
// projectName: string;
// team: string;
// teamLead: string;
// expectedStage: string;
// budgetedManhour: number;
// spentManhour: number;
// remainedManhour: number;
// manhourConsumptionPercentage: number;
// comingPaymentMilestone: string;
// }

export const preloadClientProjects = () => {
fetchAllClientProjects();
}; };


export const fetchClientProjects = cache(async () => {
return mockProjects;
// export const fetchClientProjects = cache(async () => {
// return mockProjects;
// });

export const fetchAllClientProjects = cache(async () => {
return serverFetchJson<ClientProjectResult[]>(`${BASE_API_URL}/dashboard/searchCustomerSubsidiary`);
}); });


const mockProjects: ClientProjectResult[] = [
{
id: 1,
clientCode: "CUST-001",
clientName: "Client A",
SubsidiaryClientCode: "N/A",
SubsidiaryClientName: "N/A",
NoOfProjects: 5,
},
{
id: 2,
clientCode: "CUST-001",
clientName: "Client A",
SubsidiaryClientCode: "SUBS-001",
SubsidiaryClientName: "Subsidiary A",
NoOfProjects: 5,
},
{
id: 3,
clientCode: "CUST-001",
clientName: "Client A",
SubsidiaryClientCode: "SUBS-002",
SubsidiaryClientName: "Subsidiary B",
NoOfProjects: 3,
},
{
id: 4,
clientCode: "CUST-001",
clientName: "Client A",
SubsidiaryClientCode: "SUBS-003",
SubsidiaryClientName: "Subsidiary C",
NoOfProjects: 1,
},
];
// export const fetchAllClientSubsidiaryProjects = cache(async (customerId: number, subsidiaryId: number) => {
// return serverFetchJson<ClientSubsidiaryProjectResult>(
// `${BASE_API_URL}/dashboard/searchCustomerSubsidiaryProject/?${customerId}&${subsidiaryId}`,
// {
// next: { tags: [`allClientSubsidiaryProjects`] },
// },
// );
// });

// const mockProjects: ClientProjectResult[] = [
// {
// id: 1,
// clientCode: "CUST-001",
// clientName: "Client A",
// SubsidiaryClientCode: "N/A",
// SubsidiaryClientName: "N/A",
// NoOfProjects: 5,
// },
// {
// id: 2,
// clientCode: "CUST-001",
// clientName: "Client A",
// SubsidiaryClientCode: "SUBS-001",
// SubsidiaryClientName: "Subsidiary A",
// NoOfProjects: 5,
// },
// {
// id: 3,
// clientCode: "CUST-001",
// clientName: "Client A",
// SubsidiaryClientCode: "SUBS-002",
// SubsidiaryClientName: "Subsidiary B",
// NoOfProjects: 3,
// },
// {
// id: 4,
// clientCode: "CUST-001",
// clientName: "Client A",
// SubsidiaryClientCode: "SUBS-003",
// SubsidiaryClientName: "Subsidiary C",
// NoOfProjects: 1,
// },
// ];

+ 168
- 142
src/components/ProgressByClient/ProgressByClient.tsx 查看文件

@@ -8,8 +8,6 @@ import { useTranslation } from "react-i18next";
import { Card, CardHeader } from "@mui/material"; import { Card, CardHeader } from "@mui/material";
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; import CustomSearchForm from "../CustomSearchForm/CustomSearchForm";
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; import CustomDatagrid from "../CustomDatagrid/CustomDatagrid";
// import ReactApexChart from "react-apexcharts";
import { ApexOptions } from "apexcharts";
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; import ReportProblemIcon from "@mui/icons-material/ReportProblem";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
@@ -18,9 +16,18 @@ import { AnyARecord, AnyCnameRecord } from "dns";
import SearchBox, { Criterion } from "../SearchBox"; import SearchBox, { Criterion } from "../SearchBox";
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; import ProgressByClientSearch from "@/components/ProgressByClientSearch";
import { Suspense } from "react"; import { Suspense } from "react";
const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });
import { ClientSubsidiaryProjectResult } from "@/app/api/clientprojects/actions";
import { ClientProjectResult} from "@/app/api/clientprojects";
import { ConstructionOutlined } from "@mui/icons-material";
import ReactApexChart from "react-apexcharts";
import { ApexOptions } from "apexcharts";
// const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });

interface Props {
clientSubsidiaryProjectResult: ClientSubsidiaryProjectResult[];
}


const ProgressByClient: React.FC = () => {
const ProgressByClient: React.FC<Props> = ({ clientSubsidiaryProjectResult }) => {
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");
@@ -45,42 +52,22 @@ const ProgressByClient: React.FC = () => {
const [checkboxDemo, setCheckboxDemo] = useState(false); const [checkboxDemo, setCheckboxDemo] = useState(false);
const [receiptFromDate, setReceiptFromDate] = useState(null); const [receiptFromDate, setReceiptFromDate] = useState(null);
const [receiptToDate, setReceiptToDate] = 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 [selectedRows, setSelectedRows]:any[] = useState([]);
const [chartProjectName, setChartProjectName]:any[] = useState([]);
const [chartManhourConsumptionPercentage, setChartManhourConsumptionPercentage]:any[] = useState([]);
const color = ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"];
useEffect(() => {
const projectName = []
const manhourConsumptionPercentage = []
for (let i = 0; i < clientSubsidiaryProjectResult.length; i++){
clientSubsidiaryProjectResult[i].color = color[i]
projectName.push(clientSubsidiaryProjectResult[i].projectName)
manhourConsumptionPercentage.push(clientSubsidiaryProjectResult[i].manhourConsumptionPercentage)
}
setChartProjectName(projectName)
setChartManhourConsumptionPercentage(manhourConsumptionPercentage)
}, [clientSubsidiaryProjectResult]);

const rows2 = [ const rows2 = [
{ {
id: 1, id: 1,
@@ -149,39 +136,12 @@ const ProgressByClient: React.FC = () => {
}, },
]; ];


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 = [ const columns2 = [
{ {
id: "color", id: "color",
field: "color", field: "color",
headerName: "", headerName: "",
renderCell: (params: any) => {
renderCell: (param: any) => {
return ( return (
<span <span
className="dot" className="dot"
@@ -189,7 +149,7 @@ const ProgressByClient: React.FC = () => {
height: "15px", height: "15px",
width: "15px", width: "15px",
borderRadius: "50%", borderRadius: "50%",
backgroundColor: `${params.row.color}`,
backgroundColor: `${param.row.color}`,
display: "inline-block", display: "inline-block",
}} }}
></span> ></span>
@@ -198,8 +158,8 @@ const ProgressByClient: React.FC = () => {
flex: 0.1, flex: 0.1,
}, },
{ {
id: "project",
field: "project",
id: "projectName",
field: "projectName",
headerName: "Project", headerName: "Project",
flex: 1, flex: 1,
}, },
@@ -216,9 +176,9 @@ const ProgressByClient: React.FC = () => {
flex: 0.8, flex: 0.8,
}, },
{ {
id: "currentStage",
field: "currentStage",
headerName: "Current Stage",
id: "expectedStage",
field: "expectedStage",
headerName: "Expected Stage",
flex: 1, flex: 1,
}, },
{ {
@@ -237,6 +197,7 @@ const ProgressByClient: React.FC = () => {
<span className="text-red-300">{params.row.spentManhour}</span> <span className="text-red-300">{params.row.spentManhour}</span>
); );
} else { } else {
console.log(params)
return <span>{params.row.spentManhour}</span>; return <span>{params.row.spentManhour}</span>;
} }
}, },
@@ -281,63 +242,130 @@ const ProgressByClient: React.FC = () => {
flex: 0.2, flex: 0.2,
}, },
]; ];

const InputFields = [
{
id: "clientCode",
label: "Client Code",
type: "text",
value: clientCode,
setValue: setClientCode,
const optionstest: ApexOptions = {
chart: {
height: 350,
type: "line",
}, },
{
id: "clientName",
label: "Client Name",
type: "text",
value: clientName,
setValue: setClientName,
stroke: {
width: [0, 0, 2, 2],
}, },
{
id: "subsidiaryClientCode",
label: "Subsidiary Client Code",
type: "text",
value: subsidiaryClientCode,
setValue: setSubsidiaryClientCode,
plotOptions: {
bar: {
horizontal: false,
distributed: false,
},
}, },
{
id: "subsidiaryClientName",
label: "Subsidiary Client Name",
type: "text",
value: subsidiaryClientName,
setValue: setSubsidiaryClientName,
dataLabels: {
enabled: false,
}, },
// { 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],
xaxis: {
categories: [
"Q1",
"Q2",
"Q3",
"Q4",
"Q5",
"Q6",
"Q7",
"Q8",
"Q9",
"Q10",
"Q11",
"Q12",
],
}, },
];

const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [
{
name: "Project Resource Consumption Percentage",
data: [80, 55, 40, 65, 70],
yaxis: [
{
title: {
text: "Monthly Income and Expenditure(HKD)",
},
min: 0,
max: 350000,
tickAmount: 5,
labels: {
formatter: function (val) {
return val.toLocaleString()
}
}
},
{
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,
labels: {
formatter: function (val) {
return val.toLocaleString()
}
}
},
{
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 options2: ApexOptions = { const options2: ApexOptions = {
chart: { chart: {
@@ -396,6 +424,10 @@ const ProgressByClient: React.FC = () => {
type: "bar", type: "bar",
height: 350, height: 350,
}, },
series: [{
name: "Project Resource Consumption Percentage",
data: chartManhourConsumptionPercentage,
},],
colors: ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"], colors: ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"],
plotOptions: { plotOptions: {
bar: { bar: {
@@ -407,13 +439,7 @@ const ProgressByClient: React.FC = () => {
enabled: false, enabled: false,
}, },
xaxis: { xaxis: {
categories: [
"Consultancy Project 123",
"Consultancy Project 456",
"Construction Project A",
"Construction Project B",
"Construction Project C",
],
categories: chartProjectName,
}, },
yaxis: { yaxis: {
title: { title: {
@@ -437,8 +463,8 @@ const ProgressByClient: React.FC = () => {
}; };


const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => {
const selectedRowsData = rows2.filter((row) =>
newSelectionModel.includes(row.id),
const selectedRowsData:any = clientSubsidiaryProjectResult.filter((row) =>
newSelectionModel.includes(row.projectId),
); );
console.log(selectedRowsData); console.log(selectedRowsData);
const projectArray = []; const projectArray = [];
@@ -450,10 +476,10 @@ const ProgressByClient: React.FC = () => {
if (i === selectedRowsData.length && i > 0) { if (i === selectedRowsData.length && i > 0) {
projectArray.push("Remained"); projectArray.push("Remained");
} else if (selectedRowsData.length > 0) { } else if (selectedRowsData.length > 0) {
projectArray.push(selectedRowsData[i].project);
projectArray.push(selectedRowsData[i].projectName);
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour);
totalSpent += Number(selectedRowsData[i].spentManhour); totalSpent += Number(selectedRowsData[i].spentManhour);
pieChartColorArray.push(selectedRowsData[i].color);
pieChartColorArray.push(color[i]);
} }
} }
for (let i = 0; i <= selectedRowsData.length; i++) { for (let i = 0; i <= selectedRowsData.length; i++) {
@@ -507,9 +533,9 @@ const ProgressByClient: React.FC = () => {
<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={options}
series={series}
type="bar"
options={optionstest}
series={optionstest.series}
type="line"
height={350} height={350}
/> />
</div> </div>
@@ -530,7 +556,7 @@ const ProgressByClient: React.FC = () => {
style={{ display: "inline-block", width: "99%", marginLeft: 10 }} style={{ display: "inline-block", width: "99%", marginLeft: 10 }}
> >
<CustomDatagrid <CustomDatagrid
rows={rows2}
rows={clientSubsidiaryProjectResult}
columns={columns2} columns={columns2}
columnWidth={200} columnWidth={200}
dataGridHeight={300} dataGridHeight={300}
@@ -564,13 +590,13 @@ const ProgressByClient: React.FC = () => {
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}>


+ 41
- 19
src/components/ProgressByClientSearch/ProgressByClientSearch.tsx 查看文件

@@ -5,35 +5,50 @@ import React, { useMemo, useState, useCallback } 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";
import { ClientProjectResult } from "@/app/api/clientprojects";
import EditNote from "@mui/icons-material/EditNote";
import { ClientProjectResult} from "@/app/api/clientprojects";
import { fetchAllClientSubsidiaryProjects} from "@/app/api/clientprojects/actions";
import VisibilityIcon from '@mui/icons-material/Visibility';
import { useRouter, useSearchParams } from "next/navigation"; import { useRouter, useSearchParams } from "next/navigation";
import ProgressByClient from "@/components/ProgressByClient";


interface Props { interface Props {
projects: ClientProjectResult[];
clientProjects: ClientProjectResult[];
} }
type SearchQuery = Partial<Omit<ClientProjectResult, "id">>; type SearchQuery = Partial<Omit<ClientProjectResult, "id">>;
type SearchParamNames = keyof SearchQuery; type SearchParamNames = keyof SearchQuery;


const ProgressByClientSearch: React.FC<Props> = ({ projects }) => {
const ProgressByClientSearch: React.FC<Props> = ({ clientProjects }) => {
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.
const [filteredProjects, setFilteredProjects] = useState(projects);
const [filteredProjects, setFilteredProjects] = useState(clientProjects);
const [clientSubsidiaryProjectResult, setClientSubsidiaryProjectResult]:any[] = useState([]);


const searchCriteria: Criterion<SearchParamNames>[] = useMemo( const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
() => [ () => [
{ label: "Client Code", paramName: "clientCode", type: "text" },
{ label: "Client Name", paramName: "clientName", type: "text" },
{ label: "Client Code", paramName: "customerCode", type: "text" },
{ label: "Client Name", paramName: "customerName", type: "text" },
], ],
[t], [t],
); );


const onTaskClick = useCallback((clientProjectResult: ClientProjectResult) => {
const params = new URLSearchParams(searchParams.toString())
params.set("id", clientProjectResult.id.toString())
console.log(clientProjectResult)
}, []);
// const onTaskClick = useCallback((clientProjectResult: ClientProjectResult) => {
// const clickResult = fetchAllClientSubsidiaryProjects(clientProjectResult.customerId, clientProjectResult.subsidiaryId)
// console.log(clickResult)
// setClientSubsidiaryProjectResult(clickResult)
// }, []);

const onTaskClick = useCallback(async (clientProjectResult: ClientProjectResult) => {
try {
const clickResult = await fetchAllClientSubsidiaryProjects(clientProjectResult.customerId, clientProjectResult.subsidiaryId);
console.log(clickResult);
setClientSubsidiaryProjectResult(clickResult);
} catch (error) {
console.error('Error fetching client subsidiary projects:', error);
}
}, []);



const columns = useMemo<Column<ClientProjectResult>[]>( const columns = useMemo<Column<ClientProjectResult>[]>(
() => [ () => [
@@ -41,13 +56,13 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => {
name: "id", name: "id",
label: t("Details"), label: t("Details"),
onClick: onTaskClick, onClick: onTaskClick,
buttonIcon: <EditNote />,
buttonIcon: <VisibilityIcon />,
}, },
{ name: "clientCode", label: t("Client Code") },
{ name: "clientName", label: t("Client Name") },
{ name: "SubsidiaryClientCode", label: t("Subsidiary Code") },
{ name: "SubsidiaryClientName", label: t("Subisdiary") },
{ name: "NoOfProjects", label: t("No. of Projects") },
{ name: "customerCode", label: t("Client Code") },
{ name: "customerName", label: t("Client Name") },
{ name: "subsidiaryCode", label: t("Subsidiary Code") },
{ name: "subsidiaryName", label: t("Subisdiary") },
{ name: "projectNo", label: t("No. of Projects") },
], ],
[onTaskClick, t], [onTaskClick, t],
// [t], // [t],
@@ -58,13 +73,20 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => {
<SearchBox <SearchBox
criteria={searchCriteria} criteria={searchCriteria}
onSearch={(query) => { onSearch={(query) => {
console.log(query);
setFilteredProjects(
clientProjects.filter(
(cp) =>
cp.customerCode.toLowerCase().includes(query.customerCode.toLowerCase()) &&
cp.customerName.toLowerCase().includes(query.customerName.toLowerCase())
),
);
}} }}
/> />
<SearchResults<ClientProjectResult> <SearchResults<ClientProjectResult>
items={filteredProjects} items={filteredProjects}
columns={columns} columns={columns}
/> />
<ProgressByClient clientSubsidiaryProjectResult={clientSubsidiaryProjectResult}/>
</> </>
); );
}; };


+ 3
- 4
src/components/ProgressByClientSearch/ProgressByClientSearchWrapper.tsx 查看文件

@@ -1,4 +1,4 @@
import { fetchClientProjects } from "@/app/api/clientprojects";
import { fetchAllClientProjects } from "@/app/api/clientprojects";
import React from "react"; import React from "react";
import ProgressByClientSearch from "./ProgressByClientSearch"; import ProgressByClientSearch from "./ProgressByClientSearch";
import ProgressByClientSearchLoading from "./ProgressByClientSearchLoading"; import ProgressByClientSearchLoading from "./ProgressByClientSearchLoading";
@@ -8,9 +8,8 @@ interface SubComponents {
} }


const ProgressByClientSearchWrapper: React.FC & SubComponents = async () => { const ProgressByClientSearchWrapper: React.FC & SubComponents = async () => {
const clentprojects = await fetchClientProjects();

return <ProgressByClientSearch projects={clentprojects} />;
const clientprojects = await fetchAllClientProjects();
return <ProgressByClientSearch clientProjects={clientprojects} />;
}; };


ProgressByClientSearchWrapper.Loading = ProgressByClientSearchLoading; ProgressByClientSearchWrapper.Loading = ProgressByClientSearchLoading;


+ 2
- 2
src/components/ProgressByTeam/ProgressByTeam.tsx 查看文件

@@ -8,7 +8,7 @@ import { useTranslation } from "react-i18next";
import { Card, CardHeader } from "@mui/material"; import { Card, CardHeader } from "@mui/material";
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; import CustomSearchForm from "../CustomSearchForm/CustomSearchForm";
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; import CustomDatagrid from "../CustomDatagrid/CustomDatagrid";
// import ReactApexChart from "react-apexcharts";
import ReactApexChart from "react-apexcharts";
import { ApexOptions } from "apexcharts"; import { ApexOptions } from "apexcharts";
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; import ReportProblemIcon from "@mui/icons-material/ReportProblem";
@@ -18,7 +18,7 @@ import { AnyARecord, AnyCnameRecord } from "dns";
import SearchBox, { Criterion } from "../SearchBox"; import SearchBox, { Criterion } from "../SearchBox";
import ProgressByTeamSearch from "@/components/ProgressByTeamSearch"; import ProgressByTeamSearch from "@/components/ProgressByTeamSearch";
import { Suspense } from "react"; import { Suspense } from "react";
const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });
// const ReactApexChart = dynamic(() => import('react-apexcharts'), { ssr: false });


const ProgressByTeam: React.FC = () => { const ProgressByTeam: React.FC = () => {
const [activeTab, setActiveTab] = useState("financialSummary"); const [activeTab, setActiveTab] = useState("financialSummary");


+ 1
- 0
src/components/ProjectSearch/ProjectSearch.tsx 查看文件

@@ -20,6 +20,7 @@ type SearchParamNames = keyof SearchQuery;
const ProjectSearch: React.FC<Props> = ({ projects, projectCategories }) => { const ProjectSearch: React.FC<Props> = ({ projects, projectCategories }) => {
const router = useRouter(); const router = useRouter();
const { t } = useTranslation("projects"); const { t } = useTranslation("projects");
console.log(projects)


const [filteredProjects, setFilteredProjects] = useState(projects); const [filteredProjects, setFilteredProjects] = useState(projects);




Loading…
取消
儲存