| @@ -1,4 +1,7 @@ | |||||
| "use server"; | |||||
| import { cache } from "react"; | import { cache } from "react"; | ||||
| import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||||
| import { BASE_API_URL } from "@/config/api"; | |||||
| export interface CashFlow { | export interface CashFlow { | ||||
| id: number; | id: number; | ||||
| @@ -19,21 +22,5 @@ export const preloadProjects = () => { | |||||
| }; | }; | ||||
| export const fetchProjectsCashFlow = cache(async () => { | export const fetchProjectsCashFlow = cache(async () => { | ||||
| return mockProjects; | |||||
| return serverFetchJson<CashFlow[]>(`${BASE_API_URL}/dashboard/searchCashFlowProject`); | |||||
| }); | }); | ||||
| const mockProjects: CashFlow[] = [ | |||||
| { | |||||
| id: 1, | |||||
| projectCode: "CUST-001", | |||||
| projectName: "Client A", | |||||
| team: "N/A", | |||||
| teamLeader: "N/A", | |||||
| startDate: "5", | |||||
| startDateFrom: "5", | |||||
| startDateTo: "5", | |||||
| targetEndDate: "s", | |||||
| client: "ss", | |||||
| subsidiary: "ss", | |||||
| }, | |||||
| ]; | |||||
| @@ -39,16 +39,28 @@ export interface FinancialSummaryByProjectResult { | |||||
| totalUninvoiced: number; | totalUninvoiced: number; | ||||
| } | } | ||||
| export const searchFinancialSummaryByClient = cache(async (teamId: number) => { | |||||
| return serverFetchJson<FinancialSummaryByClientResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByClient?teamId=${teamId}` | |||||
| ); | |||||
| export const searchFinancialSummaryByClient = cache(async (teamId?: number) => { | |||||
| if (teamId === undefined) { | |||||
| return serverFetchJson<FinancialSummaryByClientResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByClient` | |||||
| ); | |||||
| } else { | |||||
| return serverFetchJson<FinancialSummaryByClientResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByClient?teamId=${teamId}` | |||||
| ); | |||||
| } | |||||
| }); | }); | ||||
| export const searchFinancialSummaryByProject = cache(async (teamId: number) => { | |||||
| export const searchFinancialSummaryByProject = cache(async (teamId?: number, customerId?:number) => { | |||||
| if (teamId === undefined) { | |||||
| return serverFetchJson<FinancialSummaryByProjectResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByProject` | |||||
| ); | |||||
| } else { | |||||
| return serverFetchJson<FinancialSummaryByProjectResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByProject?teamId=${teamId}&customerId=${customerId}` | |||||
| ); | |||||
| } | |||||
| return serverFetchJson<FinancialSummaryByProjectResult[]>( | |||||
| `${BASE_API_URL}/dashboard/searchFinancialSummaryByProject?teamId=${teamId}` | |||||
| ); | |||||
| }); | }); | ||||
| @@ -13,6 +13,7 @@ import { I18nProvider } from "@/i18n"; | |||||
| const pathToLabelMap: { [path: string]: string } = { | const pathToLabelMap: { [path: string]: string } = { | ||||
| "": "Overview", | "": "Overview", | ||||
| "/home": "User Workspace", | "/home": "User Workspace", | ||||
| "/dashboard": "Dashboard", | |||||
| "/projects": "Projects", | "/projects": "Projects", | ||||
| "/projects/create": "Create Project", | "/projects/create": "Create Project", | ||||
| "/projects/createSub": "Sub Project", | "/projects/createSub": "Sub Project", | ||||
| @@ -15,6 +15,7 @@ interface CustomDatagridProps { | |||||
| dataGridHeight?: number | string; | dataGridHeight?: number | string; | ||||
| [key: string]: any; | [key: string]: any; | ||||
| checkboxSelection?: boolean; | checkboxSelection?: boolean; | ||||
| onRowClick?: any; | |||||
| onRowSelectionModelChange?: ( | onRowSelectionModelChange?: ( | ||||
| newSelectionModel: GridRowSelectionModel, | newSelectionModel: GridRowSelectionModel, | ||||
| ) => void; | ) => void; | ||||
| @@ -34,6 +35,7 @@ const CustomDatagrid: React.FC<CustomDatagridProps> = ({ | |||||
| checkboxSelection, // Destructure the new prop | checkboxSelection, // Destructure the new prop | ||||
| onRowSelectionModelChange, // Destructure the new prop | onRowSelectionModelChange, // Destructure the new prop | ||||
| selectionModel, | selectionModel, | ||||
| onRowClick, | |||||
| columnGroupingModel, | columnGroupingModel, | ||||
| pageSize, | pageSize, | ||||
| ...props | ...props | ||||
| @@ -195,6 +197,7 @@ const CustomDatagrid: React.FC<CustomDatagridProps> = ({ | |||||
| rows={rowsWithDefaultValues} | rows={rowsWithDefaultValues} | ||||
| columns={modifiedColumns} | columns={modifiedColumns} | ||||
| editMode="row" | editMode="row" | ||||
| onRowClick={onRowClick} | |||||
| checkboxSelection={checkboxSelection} | checkboxSelection={checkboxSelection} | ||||
| onRowSelectionModelChange={onRowSelectionModelChange} | onRowSelectionModelChange={onRowSelectionModelChange} | ||||
| experimentalFeatures={{ columnGrouping: true }} | experimentalFeatures={{ columnGrouping: true }} | ||||
| @@ -226,6 +229,7 @@ const CustomDatagrid: React.FC<CustomDatagridProps> = ({ | |||||
| rows={rowsWithDefaultValues} | rows={rowsWithDefaultValues} | ||||
| columns={modifiedColumns} | columns={modifiedColumns} | ||||
| editMode="row" | editMode="row" | ||||
| onRowClick={onRowClick} | |||||
| checkboxSelection={checkboxSelection} | checkboxSelection={checkboxSelection} | ||||
| onRowSelectionModelChange={onRowSelectionModelChange} | onRowSelectionModelChange={onRowSelectionModelChange} | ||||
| experimentalFeatures={{ columnGrouping: true }} | experimentalFeatures={{ columnGrouping: true }} | ||||
| @@ -257,6 +261,7 @@ const CustomDatagrid: React.FC<CustomDatagridProps> = ({ | |||||
| rows={rowsWithDefaultValues} | rows={rowsWithDefaultValues} | ||||
| columns={modifiedColumns} | columns={modifiedColumns} | ||||
| editMode="row" | editMode="row" | ||||
| onRowClick={onRowClick} | |||||
| checkboxSelection={checkboxSelection} | checkboxSelection={checkboxSelection} | ||||
| onRowSelectionModelChange={onRowSelectionModelChange} | onRowSelectionModelChange={onRowSelectionModelChange} | ||||
| experimentalFeatures={{ columnGrouping: true }} | experimentalFeatures={{ columnGrouping: true }} | ||||
| @@ -289,6 +294,7 @@ const CustomDatagrid: React.FC<CustomDatagridProps> = ({ | |||||
| rows={rowsWithDefaultValues} | rows={rowsWithDefaultValues} | ||||
| columns={modifiedColumns} | columns={modifiedColumns} | ||||
| editMode="row" | editMode="row" | ||||
| onRowClick={onRowClick} | |||||
| style={{ marginRight: 0 }} | style={{ marginRight: 0 }} | ||||
| checkboxSelection={checkboxSelection} | checkboxSelection={checkboxSelection} | ||||
| onRowSelectionModelChange={onRowSelectionModelChange} | onRowSelectionModelChange={onRowSelectionModelChange} | ||||
| @@ -19,17 +19,34 @@ import SearchBox, { Criterion } from "../SearchBox"; | |||||
| import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
| import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
| import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | ||||
| import { fetchProjectsCashFlow} from "@/app/api/cashflow"; | |||||
| import { Input, Label } from "reactstrap"; | import { Input, Label } from "reactstrap"; | ||||
| import { CashFlow } from "@/app/api/cashflow"; | |||||
| interface Props { | |||||
| projects: CashFlow[]; | |||||
| } | |||||
| type SearchQuery = Partial<Omit<CashFlow, "id">>; | |||||
| type SearchParamNames = keyof SearchQuery; | |||||
| const ProjectCashFlow: React.FC = () => { | const ProjectCashFlow: React.FC = () => { | ||||
| const { t } = useTranslation("projects"); | |||||
| const todayDate = new Date(); | const todayDate = new Date(); | ||||
| const [selectionModel, setSelectionModel]: any[] = React.useState([]); | const [selectionModel, setSelectionModel]: any[] = React.useState([]); | ||||
| const [projectData, setProjectData]: any[] = React.useState([]); | |||||
| const [cashFlowYear, setCashFlowYear]: any[] = React.useState( | const [cashFlowYear, setCashFlowYear]: any[] = React.useState( | ||||
| todayDate.getFullYear(), | todayDate.getFullYear(), | ||||
| ); | ); | ||||
| const [anticipateCashFlowYear, setAnticipateCashFlowYear]: any[] = React.useState( | const [anticipateCashFlowYear, setAnticipateCashFlowYear]: any[] = React.useState( | ||||
| todayDate.getFullYear(), | todayDate.getFullYear(), | ||||
| ); | ); | ||||
| const fetchData = async () => { | |||||
| const cashFlowProject = await fetchProjectsCashFlow(); | |||||
| setProjectData(cashFlowProject) | |||||
| } | |||||
| useEffect(() => { | |||||
| fetchData() | |||||
| }, []); | |||||
| const columns = [ | const columns = [ | ||||
| { | { | ||||
| id: "projectCode", | id: "projectCode", | ||||
| @@ -50,8 +67,8 @@ const ProjectCashFlow: React.FC = () => { | |||||
| flex: 1, | flex: 1, | ||||
| }, | }, | ||||
| { | { | ||||
| id: "teamLeader", | |||||
| field: "teamLeader", | |||||
| id: "teamLead", | |||||
| field: "teamLead", | |||||
| headerName: "Team Leader", | headerName: "Team Leader", | ||||
| flex: 1, | flex: 1, | ||||
| }, | }, | ||||
| @@ -530,8 +547,6 @@ const ProjectCashFlow: React.FC = () => { | |||||
| remarks: "Monthly Manpower Expenditure", | remarks: "Monthly Manpower Expenditure", | ||||
| }, | }, | ||||
| ]; | ]; | ||||
| const [projectData, setProjectData]: any[] = React.useState(rows); | |||||
| const [ledgerData, setLedgerData]: any[] = React.useState(ledgerRows); | const [ledgerData, setLedgerData]: any[] = React.useState(ledgerRows); | ||||
| const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | ||||
| const selectedRowsData = projectData.filter((row: any) => | const selectedRowsData = projectData.filter((row: any) => | ||||
| @@ -540,11 +555,31 @@ const ProjectCashFlow: React.FC = () => { | |||||
| console.log(selectedRowsData); | console.log(selectedRowsData); | ||||
| }; | }; | ||||
| const searchCriteria: Criterion<SearchParamNames>[] = 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], | |||||
| ); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <Suspense fallback={<ProgressCashFlowSearch.Loading />}> | |||||
| {/* <Suspense fallback={<ProgressCashFlowSearch.Loading />}> | |||||
| <ProgressCashFlowSearch /> | <ProgressCashFlowSearch /> | ||||
| </Suspense> | |||||
| </Suspense> */} | |||||
| <SearchBox | |||||
| criteria={searchCriteria} | |||||
| onSearch={(query) => { | |||||
| console.log(query); | |||||
| }} | |||||
| /> | |||||
| <CustomDatagrid | <CustomDatagrid | ||||
| rows={projectData} | rows={projectData} | ||||
| columns={columns} | columns={columns} | ||||
| @@ -53,8 +53,6 @@ const ProjectFinancialCard: React.FC<Props> = ({ | |||||
| : "border-green-200 border-solid"; | : "border-green-200 border-solid"; | ||||
| const selectedBackgroundColor = | const selectedBackgroundColor = | ||||
| ClickedIndex === Index ? "rgb(235 235 235)" : "rgb(255 255 255)"; | ClickedIndex === Index ? "rgb(235 235 235)" : "rgb(255 255 255)"; | ||||
| console.log(ClickedIndex); | |||||
| console.log(Index); | |||||
| return ( | return ( | ||||
| <Card | <Card | ||||
| style={{ | style={{ | ||||
| @@ -84,35 +82,35 @@ const ProjectFinancialCard: React.FC<Props> = ({ | |||||
| Total Fees | Total Fees | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalFees.toLocaleString()} | |||||
| {TotalFees.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Budget | Total Budget | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalBudget.toLocaleString()} | |||||
| {TotalBudget.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Cumulative Expenditure | Total Cumulative Expenditure | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalCumulative.toLocaleString()} | |||||
| {TotalCumulative.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Invoiced Amount | Total Invoiced Amount | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalInvoicedAmount.toLocaleString()} | |||||
| {TotalInvoicedAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| Total Received Amount | Total Received Amount | ||||
| </div> | </div> | ||||
| <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | <div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | ||||
| {TotalReceivedAmount.toLocaleString()} | |||||
| {TotalReceivedAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} | |||||
| </div> | </div> | ||||
| <hr /> | <hr /> | ||||
| <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | <div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | ||||
| @@ -21,6 +21,7 @@ import { Suspense } from "react"; | |||||
| import { fetchFinancialSummaryCard } from "@/app/api/financialsummary"; | import { fetchFinancialSummaryCard } from "@/app/api/financialsummary"; | ||||
| import { searchFinancialSummaryByClient,searchFinancialSummaryByProject } from "@/app/api/financialsummary/actions"; | import { searchFinancialSummaryByClient,searchFinancialSummaryByProject } from "@/app/api/financialsummary/actions"; | ||||
| import ProjectFinancialCard from "./ProjectFinancialCard"; | import ProjectFinancialCard from "./ProjectFinancialCard"; | ||||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||||
| const ProjectFinancialSummary: React.FC = () => { | const ProjectFinancialSummary: React.FC = () => { | ||||
| const [SearchCriteria, setSearchCriteria] = React.useState({}); | const [SearchCriteria, setSearchCriteria] = React.useState({}); | ||||
| @@ -33,16 +34,16 @@ const ProjectFinancialSummary: React.FC = () => { | |||||
| const financialSummaryCard = await fetchFinancialSummaryCard(); | const financialSummaryCard = await fetchFinancialSummaryCard(); | ||||
| setProjectFinancialData(financialSummaryCard) | setProjectFinancialData(financialSummaryCard) | ||||
| } | } | ||||
| const fetchTableData = async (teamId:any) => { | |||||
| const fetchTableData = async (teamId?:any) => { | |||||
| const financialSummaryByClient = await searchFinancialSummaryByClient(teamId); | const financialSummaryByClient = await searchFinancialSummaryByClient(teamId); | ||||
| const financialSummaryByProject = await searchFinancialSummaryByProject(teamId); | |||||
| console.log(financialSummaryByClient) | console.log(financialSummaryByClient) | ||||
| console.log(financialSummaryByProject) | |||||
| // console.log(financialSummaryByProject) | |||||
| setClientFinancialRows(financialSummaryByClient) | setClientFinancialRows(financialSummaryByClient) | ||||
| setProjectFinancialRows(financialSummaryByProject) | |||||
| } | } | ||||
| useEffect(() => { | useEffect(() => { | ||||
| fetchData() | fetchData() | ||||
| fetchTableData(undefined) | |||||
| }, []); | }, []); | ||||
| 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"}, | 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"}, | ||||
| @@ -73,16 +74,9 @@ const ProjectFinancialSummary: React.FC = () => { | |||||
| const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows0); | const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows0); | ||||
| const handleCardClick = (r: any) => { | |||||
| const handleCardClick = (r: any, index:any) => { | |||||
| fetchTableData(r.teamId) | fetchTableData(r.teamId) | ||||
| // setIsCardClickedIndex(r); | |||||
| // if (r === 0) { | |||||
| // setSelectedTeamData(rows0); | |||||
| // } else if (r === 1) { | |||||
| // setSelectedTeamData(rows1); | |||||
| // } else if (r === 2) { | |||||
| // setSelectedTeamData(rows2); | |||||
| // } | |||||
| setIsCardClickedIndex(index) | |||||
| }; | }; | ||||
| const columns = [ | const columns = [ | ||||
| @@ -380,6 +374,16 @@ const columns2 = [ | |||||
| ); | ); | ||||
| console.log(selectedRowsData); | console.log(selectedRowsData); | ||||
| }; | }; | ||||
| const fetchProjectTableData = async (teamId?:any,customerId?:any) => { | |||||
| const financialSummaryByProject = await searchFinancialSummaryByProject(teamId,customerId); | |||||
| setProjectFinancialRows(financialSummaryByProject) | |||||
| } | |||||
| const handleRowClick = (params:any) => { | |||||
| console.log(params.row.teamId); | |||||
| fetchProjectTableData(params.row.teamId,params.row.cid) | |||||
| }; | |||||
| return ( | return ( | ||||
| <Grid item sm> | <Grid item sm> | ||||
| @@ -387,7 +391,7 @@ const columns2 = [ | |||||
| <CardHeader className="text-slate-500" title="Active Project Financial Status"/> | <CardHeader className="text-slate-500" title="Active Project Financial Status"/> | ||||
| <div className="ml-10 mr-10" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'start'}}> | <div className="ml-10 mr-10" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'start'}}> | ||||
| {projectFinancialData.map((record:any, index:any) => ( | {projectFinancialData.map((record:any, index:any) => ( | ||||
| <div className="hover:cursor-pointer ml-4 mt-5 mb-4 inline-block" key={index} onClick={(r) => handleCardClick(record)}> | |||||
| <div className="hover:cursor-pointer ml-4 mt-5 mb-4 inline-block" key={index} onClick={(r) => handleCardClick(record,index)}> | |||||
| <ProjectFinancialCard Title={record.teamName} TotalActiveProjectNumber={record.projectNo} TotalFees={record.totalFee} TotalBudget={record.totalBudget} TotalCumulative={record.cumulativeExpenditure} TotalInvoicedAmount={record.totalInvoiced} TotalReceivedAmount={record.totalReceived} CashFlowStatus={record.cashFlowStatus} CostPerformanceIndex={record.cpi} ClickedIndex={isCardClickedIndex} Index={index}/> | <ProjectFinancialCard Title={record.teamName} TotalActiveProjectNumber={record.projectNo} TotalFees={record.totalFee} TotalBudget={record.totalBudget} TotalCumulative={record.cumulativeExpenditure} TotalInvoicedAmount={record.totalInvoiced} TotalReceivedAmount={record.totalReceived} CashFlowStatus={record.cashFlowStatus} CostPerformanceIndex={record.cpi} ClickedIndex={isCardClickedIndex} Index={index}/> | ||||
| </div> | </div> | ||||
| ))} | ))} | ||||
| @@ -397,7 +401,7 @@ const columns2 = [ | |||||
| <CardHeader className="text-slate-500" title="Financial Status (by Client)"/> | <CardHeader className="text-slate-500" title="Financial Status (by Client)"/> | ||||
| <div style={{display:"inline-block",width:"99%",marginLeft:10}}> | <div style={{display:"inline-block",width:"99%",marginLeft:10}}> | ||||
| {/* <CustomDatagrid rows={clientFinancialRows} columns={columns} columnWidth={200} dataGridHeight={300} checkboxSelection={true} onRowSelectionModelChange={handleSelectionChange} selectionModel={selectionModel}/> */} | {/* <CustomDatagrid rows={clientFinancialRows} columns={columns} columnWidth={200} dataGridHeight={300} checkboxSelection={true} onRowSelectionModelChange={handleSelectionChange} selectionModel={selectionModel}/> */} | ||||
| <CustomDatagrid rows={clientFinancialRows} columns={columns} columnWidth={200} dataGridHeight={300}/> | |||||
| <CustomDatagrid onRowClick={handleRowClick} rows={clientFinancialRows} columns={columns} columnWidth={200} dataGridHeight={300}/> | |||||
| </div> | </div> | ||||
| </Card> | </Card> | ||||
| <Card className="mt-5"> | <Card className="mt-5"> | ||||