You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

494 lines
13 KiB

  1. import * as React from "react";
  2. import Grid from "@mui/material/Grid";
  3. import { useState, useEffect, useMemo } from "react";
  4. import Paper from "@mui/material/Paper";
  5. import { TFunction } from "i18next";
  6. import { useTranslation } from "react-i18next";
  7. import { Card, CardHeader } from "@mui/material";
  8. import CustomSearchForm from "../CustomSearchForm/CustomSearchForm";
  9. import CustomDatagrid from "../CustomDatagrid/CustomDatagrid";
  10. import ReactApexChart from "react-apexcharts";
  11. import { ApexOptions } from "apexcharts";
  12. import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid";
  13. import ReportProblemIcon from "@mui/icons-material/ReportProblem";
  14. import dynamic from "next/dynamic";
  15. import "../../app/global.css";
  16. import { AnyARecord } from "dns";
  17. import SearchBox, { Criterion } from "../SearchBox";
  18. import ProgressByClientSearch from "@/components/ProgressByClientSearch";
  19. import { Suspense } from "react";
  20. const ProgressByClient: React.FC = () => {
  21. const [activeTab, setActiveTab] = useState("financialSummary");
  22. const [SearchCriteria, setSearchCriteria] = React.useState({});
  23. const { t } = useTranslation("dashboard");
  24. const [clientCode, setClientCode] = useState("");
  25. const [clientName, setClientName] = useState("");
  26. const [subsidiaryClientCode, setSubsidiaryClientCode] = useState("");
  27. const [subsidiaryClientName, setSubsidiaryClientName] = useState("");
  28. const [projectArray, setProjectArray]: any[] = useState([]);
  29. const [percentageArray, setPercentageArray]: any[] = useState([]);
  30. const [selectionModel, setSelectionModel]: any[] = React.useState([]);
  31. const [dropdownDemo, setDropdownDemo] = useState("");
  32. const [dateDemo, setDateDemo] = useState(null);
  33. const [checkboxDemo, setCheckboxDemo] = useState(false);
  34. const [receiptFromDate, setReceiptFromDate] = useState(null);
  35. const [receiptToDate, setReceiptToDate] = useState(null);
  36. const [selectedRows, setSelectedRows] = useState([]);
  37. const rows = [
  38. {
  39. id: 1,
  40. clientCode: "CUST-001",
  41. clientName: "Client A",
  42. clientSubsidiaryCode: "N/A",
  43. clientSubsidiaryName: "N/A",
  44. noOfProjects: "5",
  45. },
  46. {
  47. id: 2,
  48. clientCode: "CUST-001",
  49. clientName: "Client A",
  50. clientSubsidiaryCode: "SUBS-001",
  51. clientSubsidiaryName: "Subsidiary A",
  52. noOfProjects: "5",
  53. },
  54. {
  55. id: 3,
  56. clientCode: "CUST-001",
  57. clientName: "Client A",
  58. clientSubsidiaryCode: "SUBS-002",
  59. clientSubsidiaryName: "Subsidiary B",
  60. noOfProjects: "3",
  61. },
  62. {
  63. id: 4,
  64. clientCode: "CUST-001",
  65. clientName: "Client A",
  66. clientSubsidiaryCode: "SUBS-003",
  67. clientSubsidiaryName: "Subsidiary C",
  68. noOfProjects: "1",
  69. },
  70. ];
  71. const rows2 = [
  72. {
  73. id: 1,
  74. project: "Consultancy Project 123",
  75. team: "XXX",
  76. teamLeader: "XXX",
  77. currentStage: "Contract Documentation",
  78. budgetedManhour: "200.00",
  79. spentManhour: "120.00",
  80. remainedManhour: "80.00",
  81. comingPaymentMilestone: "31/03/2024",
  82. alert: false,
  83. },
  84. {
  85. id: 2,
  86. project: "Consultancy Project 456",
  87. team: "XXX",
  88. teamLeader: "XXX",
  89. currentStage: "Report Preparation",
  90. budgetedManhour: "400.00",
  91. spentManhour: "200.00",
  92. remainedManhour: "200.00",
  93. comingPaymentMilestone: "20/02/2024",
  94. alert: false,
  95. },
  96. {
  97. id: 3,
  98. project: "Construction Project A",
  99. team: "YYY",
  100. teamLeader: "YYY",
  101. currentStage: "Construction",
  102. budgetedManhour: "187.50",
  103. spentManhour: "200.00",
  104. remainedManhour: "12.50",
  105. comingPaymentMilestone: "13/12/2023",
  106. alert: true,
  107. },
  108. {
  109. id: 4,
  110. project: "Construction Project B",
  111. team: "XXX",
  112. teamLeader: "XXX",
  113. currentStage: "Post Construction",
  114. budgetedManhour: "100.00",
  115. spentManhour: "40.00",
  116. remainedManhour: "60.00",
  117. comingPaymentMilestone: "05/01/2024",
  118. alert: false,
  119. },
  120. {
  121. id: 5,
  122. project: "Construction Project C",
  123. team: "YYY",
  124. teamLeader: "YYY",
  125. currentStage: "Construction",
  126. budgetedManhour: "300.00",
  127. spentManhour: "150.00",
  128. remainedManhour: "150.00",
  129. comingPaymentMilestone: "31/03/2024",
  130. alert: false,
  131. },
  132. ];
  133. const columns = [
  134. {
  135. id: "clientCode",
  136. field: "clientCode",
  137. headerName: "Client Code",
  138. flex: 1,
  139. },
  140. {
  141. id: "clientName",
  142. field: "clientName",
  143. headerName: "Client Name",
  144. flex: 1,
  145. },
  146. {
  147. id: "clientSubsidiaryCode",
  148. field: "clientSubsidiaryCode",
  149. headerName: "Client Subsidiary Code",
  150. flex: 1,
  151. },
  152. {
  153. id: "noOfProjects",
  154. field: "noOfProjects",
  155. headerName: "No. of Projects",
  156. flex: 1,
  157. },
  158. ];
  159. const columns2 = [
  160. {
  161. id: "project",
  162. field: "project",
  163. headerName: "Project",
  164. flex: 1,
  165. },
  166. {
  167. id: "team",
  168. field: "team",
  169. headerName: "Team",
  170. flex: 1,
  171. },
  172. {
  173. id: "teamLeader",
  174. field: "teamLeader",
  175. headerName: "Team Leader",
  176. flex: 1,
  177. },
  178. {
  179. id: "currentStage",
  180. field: "currentStage",
  181. headerName: "Current Stage",
  182. flex: 1,
  183. },
  184. {
  185. id: "budgetedManhour",
  186. field: "budgetedManhour",
  187. headerName: "Budgeted Manhour",
  188. flex: 1,
  189. },
  190. {
  191. id: "spentManhour",
  192. field: "spentManhour",
  193. headerName: "Spent Manhour",
  194. renderCell: (params: any) => {
  195. if (params.row.budgetedManhour - params.row.spentManhour <= 0) {
  196. return (
  197. <span className="text-red-300">{params.row.spentManhour}</span>
  198. );
  199. } else {
  200. return <span>{params.row.spentManhour}</span>;
  201. }
  202. },
  203. flex: 1,
  204. },
  205. {
  206. id: "remainedManhour",
  207. field: "remainedManhour",
  208. headerName: "Remained Manhour",
  209. renderCell: (params: any) => {
  210. if (params.row.budgetedManhour - params.row.spentManhour <= 0) {
  211. return (
  212. <span className="text-red-300">({params.row.remainedManhour})</span>
  213. );
  214. } else {
  215. return <span>{params.row.remainedManhour}</span>;
  216. }
  217. },
  218. flex: 1,
  219. },
  220. {
  221. id: "comingPaymentMilestone",
  222. field: "comingPaymentMilestone",
  223. headerName: "Coming Payment Milestone",
  224. flex: 1,
  225. },
  226. {
  227. id: "alert",
  228. field: "alert",
  229. headerName: "Alert",
  230. renderCell: (params: any) => {
  231. if (params.row.alert === true) {
  232. return (
  233. <span className="text-red-300 text-center">
  234. <ReportProblemIcon />
  235. </span>
  236. );
  237. } else {
  238. return <span></span>;
  239. }
  240. },
  241. flex: 1,
  242. },
  243. ];
  244. const InputFields = [
  245. {
  246. id: "clientCode",
  247. label: "Client Code",
  248. type: "text",
  249. value: clientCode,
  250. setValue: setClientCode,
  251. },
  252. {
  253. id: "clientName",
  254. label: "Client Name",
  255. type: "text",
  256. value: clientName,
  257. setValue: setClientName,
  258. },
  259. {
  260. id: "subsidiaryClientCode",
  261. label: "Subsidiary Client Code",
  262. type: "text",
  263. value: subsidiaryClientCode,
  264. setValue: setSubsidiaryClientCode,
  265. },
  266. {
  267. id: "subsidiaryClientName",
  268. label: "Subsidiary Client Name",
  269. type: "text",
  270. value: subsidiaryClientName,
  271. setValue: setSubsidiaryClientName,
  272. },
  273. // { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo },
  274. // { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo },
  275. // { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo },
  276. // { id: ['receiptFromDate','receiptToDate'], label: ["收貨日期","收貨日期"], value: [receiptFromDate ? receiptFromDate : null, receiptToDate ? receiptToDate : null],
  277. // setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' },
  278. ];
  279. const stageDeadline = [
  280. "31/03/2024",
  281. "20/02/2024",
  282. "01/12/2023",
  283. "05/01/2024",
  284. "31/03/2023",
  285. ];
  286. const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [
  287. {
  288. data: [17.1, 28.6, 5.7, 48.6],
  289. },
  290. ];
  291. const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [
  292. {
  293. name: "Project Resource Consumption Percentage",
  294. data: [80, 55, 40, 65, 70],
  295. },
  296. ];
  297. const options2: ApexOptions = {
  298. chart: {
  299. type: "donut",
  300. },
  301. plotOptions: {
  302. pie: {
  303. donut: {
  304. labels: {
  305. show: false,
  306. },
  307. },
  308. },
  309. },
  310. labels: [projectArray],
  311. legend: {
  312. show: false,
  313. },
  314. responsive: [
  315. {
  316. breakpoint: 480,
  317. options: {
  318. chart: {
  319. width: 200,
  320. },
  321. legend: {
  322. position: "bottom",
  323. show: false,
  324. },
  325. },
  326. },
  327. ],
  328. };
  329. const options: ApexOptions = {
  330. chart: {
  331. type: "bar",
  332. height: 350,
  333. },
  334. colors: ["#FF4560", "#00E396", "#008FFB", "#775DD0", "#FEB019"],
  335. plotOptions: {
  336. bar: {
  337. horizontal: true,
  338. distributed: true,
  339. },
  340. },
  341. dataLabels: {
  342. enabled: false,
  343. },
  344. xaxis: {
  345. categories: [
  346. "Consultancy Project 123",
  347. "Consultancy Project 456",
  348. "Construction Project A",
  349. "Construction Project B",
  350. "Construction Project C",
  351. ],
  352. },
  353. yaxis: {
  354. title: {
  355. text: "Projects",
  356. },
  357. labels: {
  358. maxWidth: 200,
  359. style: {
  360. cssClass: "apexcharts-yaxis-label",
  361. },
  362. },
  363. },
  364. title: {
  365. text: "Project Resource Consumption Percentage",
  366. align: "center",
  367. },
  368. grid: {
  369. borderColor: "#f1f1f1",
  370. },
  371. annotations: {},
  372. };
  373. const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => {
  374. const selectedRowsData = rows2.filter((row) =>
  375. newSelectionModel.includes(row.id),
  376. );
  377. console.log(selectedRowsData);
  378. const projectArray: any[] = [];
  379. let otherPercentage = 100;
  380. let totalBudgetManhour = 0;
  381. const percentageArray = [];
  382. for (let i = 0; i <= selectedRowsData.length; i++) {
  383. if (i === selectedRowsData.length) {
  384. projectArray.push("Other");
  385. } else {
  386. projectArray.push(selectedRowsData[i].project);
  387. totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour);
  388. }
  389. }
  390. for (let i = 0; i <= selectedRowsData.length; i++) {
  391. if (i === selectedRowsData.length) {
  392. percentageArray.push(otherPercentage);
  393. } else {
  394. const percentage = (
  395. (Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) *
  396. 100
  397. ).toFixed(1);
  398. percentageArray.push(Number(percentage));
  399. otherPercentage -= Number(percentage);
  400. }
  401. }
  402. setSelectionModel(newSelectionModel);
  403. setProjectArray(projectArray);
  404. setPercentageArray(percentageArray);
  405. };
  406. const applySearch = (data: any) => {
  407. console.log(data);
  408. setSearchCriteria(data);
  409. };
  410. return (
  411. <Grid item sm>
  412. {/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */}
  413. {/* <CustomDatagrid rows={rows} columns={columns} columnWidth={200} dataGridHeight={300}/> */}
  414. <div style={{ display: "inline-block", width: "70%" }}>
  415. <Grid item xs={12} md={12} lg={12}>
  416. <Card>
  417. <CardHeader className="text-slate-500" title="Project Resource Consumption" />
  418. <div style={{ display: "inline-block", width: "99%" }}>
  419. <ReactApexChart
  420. options={options}
  421. series={series}
  422. type="bar"
  423. height={350}
  424. />
  425. </div>
  426. {/* <div style={{display:"inline-block",width:"20%",verticalAlign:"top",textAlign:"center"}}>
  427. <p><strong><u>Stage Deadline</u></strong></p>
  428. {stageDeadline.map((date, index) => {
  429. const marginTop = index === 0 ? 25 : 20;
  430. return (
  431. <p style={{marginTop:marginTop}} key={index}>{date}</p>
  432. );
  433. })}
  434. </div> */}
  435. <CardHeader
  436. className="text-slate-500"
  437. title="Current Stage Due Date"
  438. />
  439. <div
  440. style={{ display: "inline-block", width: "99%", marginLeft: 10 }}
  441. >
  442. <CustomDatagrid
  443. rows={rows2}
  444. columns={columns2}
  445. columnWidth={200}
  446. dataGridHeight={300}
  447. checkboxSelection={true}
  448. onRowSelectionModelChange={handleSelectionChange}
  449. selectionModel={selectionModel}
  450. />
  451. </div>
  452. </Card>
  453. </Grid>
  454. </div>
  455. <div
  456. style={{
  457. display: "inline-block",
  458. width: "30%",
  459. verticalAlign: "top",
  460. marginLeft: 0,
  461. }}
  462. >
  463. <Grid item xs={12} md={12} lg={12}>
  464. <Card style={{ marginLeft: 15, marginRight: 20 }}>
  465. <CardHeader
  466. className="text-slate-500"
  467. title="Overall Progress per Project"
  468. />
  469. <ReactApexChart
  470. options={options2}
  471. series={percentageArray}
  472. type="donut"
  473. />
  474. </Card>
  475. </Grid>
  476. </div>
  477. </Grid>
  478. );
  479. };
  480. export default ProgressByClient;