@@ -8,12 +8,14 @@ import Tabs, { TabsProps } from "@mui/material/Tabs"; | |||
import Tab from "@mui/material/Tab"; | |||
import Typography from "@mui/material/Typography"; | |||
import ProgressByClient from "@/components/ProgressByClient"; | |||
import { preloadClientProjects } from "@/app/api/clientprojects"; | |||
export const metadata: Metadata = { | |||
title: "Project Status by Client", | |||
}; | |||
const ProjectStatusByClient: React.FC = () => { | |||
preloadClientProjects(); | |||
return ( | |||
<I18nProvider namespaces={["dashboard"]}> | |||
<Typography variant="h4" marginInlineEnd={2}> | |||
@@ -22,7 +24,6 @@ const ProjectStatusByClient: React.FC = () => { | |||
<Suspense fallback={<ProgressByClientSearch.Loading />}> | |||
<ProgressByClientSearch /> | |||
</Suspense> | |||
<ProgressByClient /> | |||
</I18nProvider> | |||
); | |||
}; | |||
@@ -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}` | |||
); | |||
}); |
@@ -1,53 +1,86 @@ | |||
import { cache } from "react"; | |||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
import { BASE_API_URL } from "@/config/api"; | |||
import "server-only"; | |||
export interface ClientProjectResult { | |||
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, | |||
// }, | |||
// ]; |
@@ -8,8 +8,6 @@ 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"; | |||
@@ -18,9 +16,18 @@ import { AnyARecord, AnyCnameRecord } from "dns"; | |||
import SearchBox, { Criterion } from "../SearchBox"; | |||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | |||
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 [SearchCriteria, setSearchCriteria] = React.useState({}); | |||
const { t } = useTranslation("dashboard"); | |||
@@ -45,42 +52,22 @@ const ProgressByClient: React.FC = () => { | |||
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 [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 = [ | |||
{ | |||
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 = [ | |||
{ | |||
id: "color", | |||
field: "color", | |||
headerName: "", | |||
renderCell: (params: any) => { | |||
renderCell: (param: any) => { | |||
return ( | |||
<span | |||
className="dot" | |||
@@ -189,7 +149,7 @@ const ProgressByClient: React.FC = () => { | |||
height: "15px", | |||
width: "15px", | |||
borderRadius: "50%", | |||
backgroundColor: `${params.row.color}`, | |||
backgroundColor: `${param.row.color}`, | |||
display: "inline-block", | |||
}} | |||
></span> | |||
@@ -198,8 +158,8 @@ const ProgressByClient: React.FC = () => { | |||
flex: 0.1, | |||
}, | |||
{ | |||
id: "project", | |||
field: "project", | |||
id: "projectName", | |||
field: "projectName", | |||
headerName: "Project", | |||
flex: 1, | |||
}, | |||
@@ -216,9 +176,9 @@ const ProgressByClient: React.FC = () => { | |||
flex: 0.8, | |||
}, | |||
{ | |||
id: "currentStage", | |||
field: "currentStage", | |||
headerName: "Current Stage", | |||
id: "expectedStage", | |||
field: "expectedStage", | |||
headerName: "Expected Stage", | |||
flex: 1, | |||
}, | |||
{ | |||
@@ -237,6 +197,7 @@ const ProgressByClient: React.FC = () => { | |||
<span className="text-red-300">{params.row.spentManhour}</span> | |||
); | |||
} else { | |||
console.log(params) | |||
return <span>{params.row.spentManhour}</span>; | |||
} | |||
}, | |||
@@ -281,63 +242,130 @@ const ProgressByClient: React.FC = () => { | |||
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 = { | |||
chart: { | |||
@@ -396,6 +424,10 @@ const ProgressByClient: React.FC = () => { | |||
type: "bar", | |||
height: 350, | |||
}, | |||
series: [{ | |||
name: "Project Resource Consumption Percentage", | |||
data: chartManhourConsumptionPercentage, | |||
},], | |||
colors: ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"], | |||
plotOptions: { | |||
bar: { | |||
@@ -407,13 +439,7 @@ const ProgressByClient: React.FC = () => { | |||
enabled: false, | |||
}, | |||
xaxis: { | |||
categories: [ | |||
"Consultancy Project 123", | |||
"Consultancy Project 456", | |||
"Construction Project A", | |||
"Construction Project B", | |||
"Construction Project C", | |||
], | |||
categories: chartProjectName, | |||
}, | |||
yaxis: { | |||
title: { | |||
@@ -437,8 +463,8 @@ const ProgressByClient: React.FC = () => { | |||
}; | |||
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); | |||
const projectArray = []; | |||
@@ -450,10 +476,10 @@ const ProgressByClient: React.FC = () => { | |||
if (i === selectedRowsData.length && i > 0) { | |||
projectArray.push("Remained"); | |||
} else if (selectedRowsData.length > 0) { | |||
projectArray.push(selectedRowsData[i].project); | |||
projectArray.push(selectedRowsData[i].projectName); | |||
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); | |||
totalSpent += Number(selectedRowsData[i].spentManhour); | |||
pieChartColorArray.push(selectedRowsData[i].color); | |||
pieChartColorArray.push(color[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" /> | |||
<div style={{ display: "inline-block", width: "99%" }}> | |||
<ReactApexChart | |||
options={options} | |||
series={series} | |||
type="bar" | |||
options={optionstest} | |||
series={optionstest.series} | |||
type="line" | |||
height={350} | |||
/> | |||
</div> | |||
@@ -530,7 +556,7 @@ const ProgressByClient: React.FC = () => { | |||
style={{ display: "inline-block", width: "99%", marginLeft: 10 }} | |||
> | |||
<CustomDatagrid | |||
rows={rows2} | |||
rows={clientSubsidiaryProjectResult} | |||
columns={columns2} | |||
columnWidth={200} | |||
dataGridHeight={300} | |||
@@ -564,13 +590,13 @@ const ProgressByClient: React.FC = () => { | |||
Please select the project you want to check. | |||
</div> | |||
)} | |||
{percentageArray.length > 0 && ( | |||
{/* {percentageArray.length > 0 && ( | |||
<ReactApexChart | |||
options={options2} | |||
series={percentageArray} | |||
type="donut" | |||
/> | |||
)} | |||
)} */} | |||
</Card> | |||
</Grid> | |||
<Grid item xs={12} md={12} lg={12}> | |||
@@ -5,35 +5,50 @@ import React, { useMemo, useState, useCallback } from "react"; | |||
import SearchBox, { Criterion } from "../SearchBox"; | |||
import { useTranslation } from "react-i18next"; | |||
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 ProgressByClient from "@/components/ProgressByClient"; | |||
interface Props { | |||
projects: ClientProjectResult[]; | |||
clientProjects: ClientProjectResult[]; | |||
} | |||
type SearchQuery = Partial<Omit<ClientProjectResult, "id">>; | |||
type SearchParamNames = keyof SearchQuery; | |||
const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | |||
const ProgressByClientSearch: React.FC<Props> = ({ clientProjects }) => { | |||
const { t } = useTranslation("projects"); | |||
const searchParams = useSearchParams() | |||
// 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( | |||
() => [ | |||
{ 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], | |||
); | |||
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>[]>( | |||
() => [ | |||
@@ -41,13 +56,13 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | |||
name: "id", | |||
label: t("Details"), | |||
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], | |||
// [t], | |||
@@ -58,13 +73,20 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | |||
<SearchBox | |||
criteria={searchCriteria} | |||
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> | |||
items={filteredProjects} | |||
columns={columns} | |||
/> | |||
<ProgressByClient clientSubsidiaryProjectResult={clientSubsidiaryProjectResult}/> | |||
</> | |||
); | |||
}; | |||
@@ -1,4 +1,4 @@ | |||
import { fetchClientProjects } from "@/app/api/clientprojects"; | |||
import { fetchAllClientProjects } from "@/app/api/clientprojects"; | |||
import React from "react"; | |||
import ProgressByClientSearch from "./ProgressByClientSearch"; | |||
import ProgressByClientSearchLoading from "./ProgressByClientSearchLoading"; | |||
@@ -8,9 +8,8 @@ interface SubComponents { | |||
} | |||
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; | |||
@@ -8,7 +8,7 @@ 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 ReactApexChart from "react-apexcharts"; | |||
import { ApexOptions } from "apexcharts"; | |||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; | |||
@@ -18,7 +18,7 @@ import { AnyARecord, AnyCnameRecord } from "dns"; | |||
import SearchBox, { Criterion } from "../SearchBox"; | |||
import ProgressByTeamSearch from "@/components/ProgressByTeamSearch"; | |||
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 [activeTab, setActiveTab] = useState("financialSummary"); | |||
@@ -20,6 +20,7 @@ type SearchParamNames = keyof SearchQuery; | |||
const ProjectSearch: React.FC<Props> = ({ projects, projectCategories }) => { | |||
const router = useRouter(); | |||
const { t } = useTranslation("projects"); | |||
console.log(projects) | |||
const [filteredProjects, setFilteredProjects] = useState(projects); | |||