소스 검색

improve resource summary dashboard

tags/Baseline_30082024_FRONTEND_UAT
Mac\David 1 년 전
부모
커밋
8c374579aa
4개의 변경된 파일331개의 추가작업 그리고 144개의 파일을 삭제
  1. +19
    -0
      src/app/api/resourcesummary/actions.ts
  2. +7
    -38
      src/app/api/resourcesummary/index.ts
  3. +284
    -101
      src/components/ProjectResourceSummary/ProjectResourceSummary.tsx
  4. +21
    -5
      src/components/ProjectResourceSummarySearch/ProjectResourceSummarySearch.tsx

+ 19
- 0
src/app/api/resourcesummary/actions.ts 파일 보기

@@ -0,0 +1,19 @@
"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 ResourceSummaryDetailsResult {
summaryInformation: any[];
summaryMainStage: any[];
summarySubStage: any[];
}

export const fetchResourceSummaryDetailResult = cache(async (projectId: number) => {
return serverFetchJson<ResourceSummaryDetailsResult[]>(
`${BASE_API_URL}/dashboard/searchProjectResourcesSummaryDetails?projectId=${projectId}`
)
});

+ 7
- 38
src/app/api/resourcesummary/index.ts 파일 보기

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

export interface ResourceSummaryResult {
id: number;
projectCode: string;
projectName: string;
clientCode: string;
clientName: string;
clientCodeAndName: string;
customerCode: string;
customerName: string;
customerCodeAndName: string;
}

export const preloadProjects = () => {
@@ -14,40 +17,6 @@ export const preloadProjects = () => {
};

export const fetchResourceSummary = cache(async () => {
return mockProjects;
return serverFetchJson<ResourceSummaryResult[]>(`${BASE_API_URL}/dashboard/searchProjectResourcesSummary`);
});

const mockProjects: ResourceSummaryResult[] = [
{
id: 1,
projectCode: 'C-1001-001',
projectName: 'Consultancy Project A',
clientCode: 'Client-001',
clientName: 'AAA Construction',
clientCodeAndName: 'Client-001 - AAA Construction',
},
{
id: 2,
projectCode: 'C-1002-001',
projectName: 'Consultancy Project B',
clientCode: 'Client-001',
clientName: 'AAA Construction',
clientCodeAndName: 'Client-001 - AAA Construction',
},
{
id: 3,
projectCode: 'C-1003-001',
projectName: 'Consultancy Project C',
clientCode: 'Client-002',
clientName: 'BBB Construction',
clientCodeAndName: 'Client-002 - BBB Construction',
},
{
id: 4,
projectCode: 'C-1004-001',
projectName: 'Consultancy Project D',
clientCode: 'Client-002',
clientName: 'BBB Construction',
clientCodeAndName: 'Client-002 - BBB Construction',
},
];

+ 284
- 101
src/components/ProjectResourceSummary/ProjectResourceSummary.tsx 파일 보기

@@ -31,9 +31,13 @@ import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import { useSearchParams } from 'next/navigation';
import {fetchResourceSummaryDetailResult} from "@/app/api/resourcesummary/actions";


const ProjectResourceSummary: React.FC = () => {
const searchParams = useSearchParams();
const projectId = searchParams.get('projectId');
const [SearchCriteria, setSearchCriteria] = React.useState({});
const { t } = useTranslation("dashboard");
const [selectionModel, setSelectionModel]: any[] = React.useState([]);
@@ -43,8 +47,11 @@ const ProjectResourceSummary: React.FC = () => {
const [plannedResources, setPlannedResources]:any = React.useState(0);
const [actualResourcesSpent, setActualResourcesSpent]:any = React.useState(0);
const [remainingResources, setRemainingResources]:any = React.useState(0);
const [dataList, setDataList]:any = React.useState();
const [rows,setRows]:any[] = React.useState([]);

function createData(stage:any, taskCount:any, g1Planned:any, g1Actual:any, g2Planned:any, g2Actual:any, g3Planned:any, g3Actual:any, g4Planned:any, g4Actual:any, g5Planned:any, g5Actual:any, totalPlanned:any, totalActual:any, task:any) {
//[subStage, subTaskCount, subTotalPlanned, subTotalActual, subG1Planned, subG1Actual, subG2Planned, subG2Actual, subG3Planned, subG3Actual, subG4Planned, subG4Actual, subG5Planned, subG5Actual]:any[]
function createData([stage, taskCount, totalPlanned, totalActual, g1Planned, g1Actual, g2Planned, g2Actual, g3Planned, g3Actual, g4Planned, g4Actual, g5Planned, g5Actual]: any[], task:any[]) {
return {
stage,
taskCount,
@@ -61,9 +68,103 @@ const ProjectResourceSummary: React.FC = () => {
totalPlanned,
totalActual,
task:task
// subStage,
// subTaskCount,
// subTotalPlanned,
// subTotalActual,
// subG1Planned,
// subG1Actual,
// subG2Planned,
// subG2Actual,
// subG3Planned,
// subG3Actual,
// subG4Planned,
// subG4Actual,
// subG5Planned,
// subG5Actual
}
}

const fetchData = async () => {
var intProjectId = 0
if (projectId !== null) {
intProjectId = parseInt(projectId);
}
if (intProjectId !== 0) {
const result = await fetchResourceSummaryDetailResult(intProjectId);
setProjectName(result[0].summaryInformation[0].projectCodeAndName)
setProjectFee(result[0].summaryInformation[0].totalFee)
setStatus(result[0].summaryInformation[0].status)
setPlannedResources(result[0].summaryInformation[0].plannedResources)
setActualResourcesSpent(result[0].summaryInformation[0].resourcesSpent)
setRemainingResources(result[0].summaryInformation[0].remainingResources)
console.log(result);
const mainStageResult = result[0].summaryMainStage
const subStageResult = result[0].summarySubStage
const mainStageFullList = []
const subStageFullList = []
var tgID = mainStageResult[0].id
var tID = subStageResult[0].id
var subTgId = subStageResult[0].tgId
var firstTg = true
var firstT = true
var mainStageList = []
var subStageList = []
var subStageSecondLayerList = []
var arrayNumber = 0
for (var i = 0; i < subStageResult.length ; i++) {
if (subStageResult[i].id !== tID) {
subStageSecondLayerList.push(subStageList)
if (subStageResult[i].tgId !== subTgId) {
subStageFullList.push(subStageSecondLayerList)
subStageSecondLayerList = []
subTgId = subStageResult[i].tgId
}
tID = subStageResult[i].id
firstT = true
subStageList = []
}
if (firstT === true) {
subStageList.push(subStageResult[i].name)
subStageList.push(subStageResult[i].taskCount)
subStageList.push(subStageResult[i].totalPlannedResource)
subStageList.push(subStageResult[i].totalActualResourcesSpent)
firstT = false
}
if (subStageResult[i].id === tID) {
subStageList.push(subStageResult[i].plannedResources)
subStageList.push(subStageResult[i].actualResourcesSpent)
}
}
console.log(subStageFullList)
for (var i = 0; i < mainStageResult.length; i++) {
if (mainStageResult[i].id !== tgID) {
mainStageFullList.push(createData(mainStageList,subStageFullList[arrayNumber]))
arrayNumber += 1
tgID = mainStageResult[i].id
firstTg = true
mainStageList = []
}
if (firstTg === true) {
mainStageList.push(mainStageResult[i].name)
mainStageList.push(mainStageResult[i].taskCount)
mainStageList.push(mainStageResult[i].totalPlannedResources)
mainStageList.push(mainStageResult[i].totalActualResourcesSpent)
firstTg = false
}
if (mainStageResult[i].id === tgID) {
mainStageList.push(mainStageResult[i].plannedResources)
mainStageList.push(mainStageResult[i].actualResourcesSpent)
}
}
setRows(mainStageFullList)
}
}
useEffect(() => {
fetchData()
}, [projectId]);

function createTaskData(stage:any, taskCount:any, g1Planned:any, g1Actual:any, g2Planned:any, g2Actual:any, g3Planned:any, g3Actual:any, g4Planned:any, g4Actual:any, g5Planned:any, g5Actual:any, totalPlanned:any, totalActual:any) {
return {
stage,
@@ -90,30 +191,30 @@ const ProjectResourceSummary: React.FC = () => {
{stage:"1.4 Attend design co-ordiantion / project",taskCount:"-",g1Planned:"-",g1Actual:"29.00",g2Planned:"-", g2Actual:"9.00", g3Planned:"-", g3Actual:"7.00", g4Planned: "-", g4Actual:"2.00", g5Planned:"-", g5Actual:"1.00", totalPlanned:"-", totalActual:"48.00"},
{stage:"1.5 Prepare / Review RIC",taskCount:"-",g1Planned:"-",g1Actual:"88.00",g2Planned:"-", g2Actual:"27.00", g3Planned:"-", g3Actual:"21.00", g4Planned: "-", g4Actual:"5.00", g5Planned:"-", g5Actual:"1.00", totalPlanned:"-", totalActual:"141.75"}
]

const task2Rows:any = [
]

const task3Rows:any = [
]

const task4Rows:any = [
]

const task5Rows:any = [
]

const task6Rows:any = [
]

const rows = [
createData("Stage 1 - Design & Cost Planning / Estimating","5","576.00","576.00","192.00", "180.00", "144.00", "140.00", "38.40", "38.00", "9.60", "9.75", "960.00", "943.75",task1Rows),
createData("Stage 2 - Tender Documentation","11", "384.00", "382.00", "128.00", "130.00", "96.00", "79.00", "25.60", "25.00", "6.40", "4.00", "640.00", "620.00",task2Rows),
createData("Stage 3 - Tender Analysis & Report & Contract Documentation","7", "384.00", "300.00", "128.00", "130.00", "96.00", "79.00", "25.60", "25.00", "6.40", "4.00", "640.00", "538.00",task3Rows),
createData("Stage 4 - Construction", "13", "480.00", "400.00", "160.00", "160.00", "120.00", "128.00", "32.00", "25.00", "8.00", "3.00", "800.00", "716.00",task4Rows),
createData("Stage 5 - Miscellaneous", "4", "96.00", "-", "32.00", "-", "24.00", "-0", "6.40", "-", "1.600", "-", "160.00", "-",task5Rows),
createData("","Total", "1920.00", "1658.00", "640.00", "600.00", "480.00", "426.00", "128.00", "113.00", "32.00", "20.75", "3,200.00", "2817.75",task6Rows),
const data:any = [
"Stage 1 - Design & Cost Planning / Estimating",
"5",
"576.00",
"576.00",
"192.00",
"180.00",
"144.00",
"140.00",
"38.40",
"38.00",
"9.60",
"9.75",
"960.00",
"943.75",
];
// const rows = [
// createData(data,task1Rows),
// // createData("Stage 2 - Tender Documentation","11", "384.00", "382.00", "128.00", "130.00", "96.00", "79.00", "25.60", "25.00", "6.40", "4.00", "640.00", "620.00",task2Rows),
// // createData("Stage 3 - Tender Analysis & Report & Contract Documentation","7", "384.00", "300.00", "128.00", "130.00", "96.00", "79.00", "25.60", "25.00", "6.40", "4.00", "640.00", "538.00",task3Rows),
// // createData("Stage 4 - Construction", "13", "480.00", "400.00", "160.00", "160.00", "120.00", "128.00", "32.00", "25.00", "8.00", "3.00", "800.00", "716.00",task4Rows),
// // createData("Stage 5 - Miscellaneous", "4", "96.00", "-", "32.00", "-", "24.00", "-0", "6.40", "-", "1.600", "-", "160.00", "-",task5Rows),
// // createData("","Total", "1920.00", "1658.00", "640.00", "600.00", "480.00", "426.00", "128.00", "113.00", "32.00", "20.75", "3,200.00", "2817.75",task6Rows),
// ];

// const taskRows = [
// createTaskData("1.1 Preparation of preliminary...","-","-","172.00","-","54.00","-","42.00","-","12.00","-","3.00","-","283.00"),
@@ -139,144 +240,224 @@ const ProjectResourceSummary: React.FC = () => {
</TableCell>
<TableCell style={{fontSize:10}}>{row.stage}</TableCell>
<TableCell style={{fontSize:10}}>{row.taskCount}</TableCell>
<TableCell style={{fontSize:10}}>{row.g1Planned}</TableCell>
<TableCell style={{fontSize:10}}>{row.g1Actual}</TableCell>
<TableCell style={{fontSize:10}}>{row.g2Planned}</TableCell>
<TableCell style={{fontSize:10}}>{row.g2Actual}</TableCell>
<TableCell style={{fontSize:10}}>{row.g3Planned}</TableCell>
<TableCell style={{fontSize:10}}>{row.g3Actual}</TableCell>
<TableCell style={{fontSize:10}}>{row.g4Planned}</TableCell>
<TableCell style={{fontSize:10}}>{row.g4Actual}</TableCell>
<TableCell style={{fontSize:10}}>{row.g5Planned}</TableCell>
<TableCell style={{fontSize:10}}>{row.g5Actual}</TableCell>
<TableCell style={{fontSize:10}}>{row.totalPlanned}</TableCell>
<TableCell style={{fontSize:10}}>{row.totalActual}</TableCell>
<TableCell style={{fontSize:10}}>{row.g1Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g1Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g2Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g2Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g3Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g3Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g4Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g4Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g5Planned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.g5Actual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.totalPlanned.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
<TableCell style={{fontSize:10}}>{row.totalActual.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
{row.task.map((taskRow:any) => (
<>
<TableRow style={{backgroundColor:"#f0f3f7"}}>
<TableRow key={taskRow[0]} style={{backgroundColor:"#f0f3f7"}}>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell colSpan={1}/>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell colSpan={1}/>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.stage}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[0]}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.taskCount}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[1]}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g1Planned}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[4].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g1Actual}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[5].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g2Planned}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[6].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g2Actual}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[7].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g3Planned}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[8].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g3Actual}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[9].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g4Planned}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[10].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g4Actual}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[11].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g5Planned}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[12].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.g5Actual}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[13].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.totalPlanned}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[2].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
<TableCell style={{ paddingBottom: 0, paddingTop: 0}} colSpan={1}>
<Collapse in={open} timeout="auto" unmountOnExit style={{marginLeft:-17, marginRight:-17}}>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow.totalActual}</TableCell>
<Box sx={{ margin: 0 }}>
<Table size="small" aria-label="tasks">
<TableBody>
<TableRow>
<TableCell style={{fontSize:10}} colSpan={1}>{taskRow[3].toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</TableCell>
</TableRow>
</TableBody>
</Table>
</Box>
</Collapse>
</TableCell>
</TableRow>
</>
))}
{/* <TableRow>
<TableCell style={{ paddingBottom: 0, paddingTop: 0, borderStyle:"dotted"}} colSpan={15}>
<Collapse in={open} timeout="auto" unmountOnExit style={{borderStyle:"dotted", marginLeft:-17, marginRight:-17}}>
<Box sx={{ margin: 1 }}>
{row.task.map((taskRow:any) => (
<TableRow key={taskRow.stage}>
<TableCell style={{borderStyle:"dotted"}}/>
<TableCell style={{fontSize:10, borderStyle:"dotted"}}>{taskRow.stage}</TableCell>
<TableCell style={{fontSize:10, borderStyle:"dotted"}}>{taskRow.taskCount}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g1Planned}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g1Actual}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g2Planned}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g2Actual}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g3Planned}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g3Actual}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g4Planned}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g4Actual}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g5Planned}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.g5Actual}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.totalPlanned}</TableCell>
<TableCell style={{fontSize:10}}>{taskRow.totalActual}</TableCell>
</TableRow>
))}
</Box>
</Collapse>
</TableCell>
</TableRow> */}
</React.Fragment>
);
}

useEffect(() => {
setProjectName("C-1001-001 - Consultancy Project A")
const fee = 2000000
setProjectFee(fee.toLocaleString())
setStatus("Within Budget / Overconsumption")
const plannedResourcesInt = 3200
setPlannedResources(plannedResourcesInt.toLocaleString())
const actualResourcesSpentInt = 2817.75
setActualResourcesSpent(actualResourcesSpentInt.toLocaleString())
const remainingResourcesInt = 382.25
setRemainingResources(remainingResourcesInt.toLocaleString())
}, [])

const projectResourcesRows = [
{id: 1,stage:"Stage 1 - Design & Cost Planning / Estimating",taskCount:"5",g1Planned:"576.00",g1Actual:"576.00",g2Planned:"192.00", g2Actual:"180.00", g3Planned:"144.00", g3Actual:"140.00", g4Planned: "38.40", g4Actual:"38S.00", g5Planned:"9.60", g5Actual:"9.75", totalPlanned:"960.00", totalActual:"943.75"},
{id: 2,stage:"1.1 Preparation of preliminary...",taskCount:"-",g1Planned:"-",g1Actual:"172.00",g2Planned:"-", g2Actual:"54.00", g3Planned:"-", g3Actual:"42.00", g4Planned: "-", g4Actual:"12.00", g5Planned:"-", g5Actual:"3.00", totalPlanned:"-", totalActual:"283.00"},
@@ -440,7 +621,7 @@ const columns2 = [
</u>
</div>
<div style={{fontSize:"1em"}}>
HKD {projectFee}
HKD ${projectFee.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
</div>
</div>
<div style={{ display: "inline-block", width: "33%"}}>
@@ -460,7 +641,7 @@ const columns2 = [
</u>
</div>
<div style={{fontSize:"1em"}}>
{plannedResources} Manhours
{plannedResources.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} Manhours
</div>
</div>
<div style={{ display: "inline-block", width: "33%"}}>
@@ -470,7 +651,7 @@ const columns2 = [
</u>
</div>
<div style={{fontSize:"1em"}}>
{actualResourcesSpent} Manhours
{actualResourcesSpent.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} Manhours
</div>
</div>
<div style={{ display: "inline-block", width: "33%"}}>
@@ -480,14 +661,14 @@ const columns2 = [
</u>
</div>
<div style={{fontSize:"1em"}}>
{remainingResources} Manhours
{remainingResources.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} Manhours
</div>
</div>
</div>
{/* <div style={{display:"inline-block",width:"99%",marginLeft:10}}>
<CustomDatagrid rows={projectResourcesRows} columns={columns2} columnWidth={200} dataGridHeight={480} pageSize={100} columnGroupingModel={columnGroupingModel} sx={{fontSize:10}}/>
</div> */}
<div style={{display:"inline-block",width:"99%",marginLeft:10, marginRight:10, marginTop:10}}>
{/* <div style={{display:"inline-block",width:"99%",marginLeft:10, marginRight:10, marginTop:10}}> */}
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
@@ -533,16 +714,18 @@ const columns2 = [
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
{rows.map((row:any) => (
<Row key={row.stage} row={row} />
))}
</TableBody>
</Table>
</TableContainer>
</div>
{/* </div> */}
</Card>
</Grid>
);
};

export default ProjectResourceSummary;



+ 21
- 5
src/components/ProjectResourceSummarySearch/ProjectResourceSummarySearch.tsx 파일 보기

@@ -20,6 +20,7 @@ type SearchParamNames = keyof SearchQuery;

const ProjectResourceSummarySearch: React.FC<Props> = ({ projects }) => {
const { t } = useTranslation("projects");
const router = useRouter();
const searchParams = useSearchParams()
// If project searching is done on the server-side, then no need for this.
const [filteredProjects, setFilteredProjects] = useState(projects);
@@ -28,14 +29,21 @@ const ProjectResourceSummarySearch: React.FC<Props> = ({ projects }) => {
() => [
{ label: "Project Code", paramName: "projectCode", type: "text" },
{ label: "Project Name", paramName: "projectName", type: "text" },
{ 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((resourceSummaryResult: ResourceSummaryResult) => {
console.log(resourceSummaryResult)
try {
console.log(resourceSummaryResult)
router.push(
`/dashboard/ProjectResourceSummary?projectId=${resourceSummaryResult.id}`
);
} catch (error) {
console.error('Error fetching team projects:', error);
}
}, []);


@@ -49,7 +57,7 @@ const ProjectResourceSummarySearch: React.FC<Props> = ({ projects }) => {
},
{ name: "projectCode", label: t("Project Code") },
{ name: "projectName", label: t("Project Name") },
{ name: "clientCodeAndName", label: t("Client Code And Name") },
{ name: "customerCodeAndName", label: t("Client Code And Name") },
],
[onTaskClick, t],
// [t],
@@ -60,7 +68,15 @@ const ProjectResourceSummarySearch: React.FC<Props> = ({ projects }) => {
<SearchBox
criteria={searchCriteria}
onSearch={(query) => {
console.log(query);
setFilteredProjects(
projects.filter(
(cp) =>
cp.projectCode.toLowerCase().includes(query.projectCode.toLowerCase()) &&
cp.projectName.toLowerCase().includes(query.projectName.toLowerCase()) &&
cp.customerCodeAndName.toLowerCase().includes(query.customerCode.toLowerCase()) &&
cp.customerCodeAndName.toLowerCase().includes(query.customerName.toLowerCase())
),
);
}}
/>
<SearchResults<ResourceSummaryResult>


불러오는 중...
취소
저장