FPSMS-frontend
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.
 
 

914 lines
27 KiB

  1. "use client";
  2. import {
  3. FooterPropsOverrides,
  4. GridActionsCellItem,
  5. GridCellParams,
  6. GridRowId,
  7. GridRowIdGetter,
  8. GridRowModel,
  9. GridRowModes,
  10. GridRowModesModel,
  11. GridToolbarContainer,
  12. useGridApiRef,
  13. } from "@mui/x-data-grid";
  14. import {
  15. Dispatch,
  16. MutableRefObject,
  17. SetStateAction,
  18. useCallback,
  19. useEffect,
  20. useMemo,
  21. useState,
  22. } from "react";
  23. import StyledDataGrid from "../StyledDataGrid";
  24. import { GridColDef } from "@mui/x-data-grid";
  25. import { Box, Button, Grid, Typography } from "@mui/material";
  26. import { useTranslation } from "react-i18next";
  27. import { Add } from "@mui/icons-material";
  28. import SaveIcon from "@mui/icons-material/Save";
  29. import DeleteIcon from "@mui/icons-material/Delete";
  30. import CancelIcon from "@mui/icons-material/Cancel";
  31. import FactCheckIcon from "@mui/icons-material/FactCheck";
  32. import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
  33. import { QcItemWithChecks } from "src/app/api/qc";
  34. import PlayArrowIcon from "@mui/icons-material/PlayArrow";
  35. import { PurchaseOrderLine, StockInLine } from "@/app/api/po";
  36. import { createStockInLine, PurchaseQcResult } from "@/app/api/po/actions";
  37. import { useSearchParams } from "next/navigation";
  38. import {
  39. returnWeightUnit,
  40. calculateWeight,
  41. stockInLineStatusMap,
  42. } from "@/app/utils/formatUtil";
  43. // import PoQcStockInModal from "./PoQcStockInModal";
  44. import NotificationImportantIcon from "@mui/icons-material/NotificationImportant";
  45. import { WarehouseResult } from "@/app/api/warehouse";
  46. import LooksOneIcon from "@mui/icons-material/LooksOne";
  47. import LooksTwoIcon from "@mui/icons-material/LooksTwo";
  48. import Looks3Icon from "@mui/icons-material/Looks3";
  49. import axiosInstance from "@/app/(main)/axios/axiosInstance";
  50. // import axios, { AxiosRequestConfig } from "axios";
  51. import { BASE_API_URL, NEXT_PUBLIC_API_URL } from "@/config/api";
  52. import qs from "qs";
  53. import QrCodeIcon from "@mui/icons-material/QrCode";
  54. import { downloadFile } from "@/app/utils/commonUtil";
  55. import { fetchPoQrcode } from "@/app/api/pdf/actions";
  56. import { fetchQcResult } from "@/app/api/qc/actions";
  57. import PoQcStockInModal from "./PoQcStockInModal";
  58. import DoDisturbIcon from "@mui/icons-material/DoDisturb";
  59. import { useSession } from "next-auth/react";
  60. import PoQcStockInModalVer2 from "./QcStockInModalVer2";
  61. interface ResultWithId {
  62. id: number;
  63. }
  64. interface Props {
  65. qc: QcItemWithChecks[];
  66. setRows: Dispatch<SetStateAction<PurchaseOrderLine[]>>;
  67. setStockInLine: Dispatch<SetStateAction<StockInLine[]>>;
  68. setProcessedQty: Dispatch<SetStateAction<number>>;
  69. itemDetail: PurchaseOrderLine;
  70. stockInLine: StockInLine[];
  71. warehouse: WarehouseResult[];
  72. }
  73. export type StockInLineEntryError = {
  74. [field in keyof StockInLine]?: string;
  75. };
  76. export type StockInLineRow = Partial<
  77. StockInLine & {
  78. isActive: boolean | undefined;
  79. _isNew: boolean;
  80. _error: StockInLineEntryError;
  81. } & ResultWithId
  82. >;
  83. class ProcessRowUpdateError extends Error {
  84. public readonly row: StockInLineRow;
  85. public readonly errors: StockInLineEntryError | undefined;
  86. constructor(
  87. row: StockInLineRow,
  88. message?: string,
  89. errors?: StockInLineEntryError,
  90. ) {
  91. super(message);
  92. this.row = row;
  93. this.errors = errors;
  94. Object.setPrototypeOf(this, ProcessRowUpdateError.prototype);
  95. }
  96. }
  97. function PoInputGrid({
  98. qc,
  99. setRows,
  100. setStockInLine,
  101. setProcessedQty,
  102. itemDetail,
  103. stockInLine,
  104. warehouse,
  105. }: Props) {
  106. console.log(itemDetail);
  107. const { t } = useTranslation("purchaseOrder");
  108. const apiRef = useGridApiRef();
  109. const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
  110. const getRowId = useCallback<GridRowIdGetter<StockInLineRow>>(
  111. (row) => row.id as number,
  112. [],
  113. );
  114. console.log(stockInLine);
  115. const [entries, setEntries] = useState<StockInLineRow[]>(stockInLine || []);
  116. const [modalInfo, setModalInfo] = useState<
  117. StockInLine & { qcResult?: PurchaseQcResult[] }
  118. >();
  119. const [qcOpen, setQcOpen] = useState(false);
  120. const [escalOpen, setEscalOpen] = useState(false);
  121. const [stockInOpen, setStockInOpen] = useState(false);
  122. const [putAwayOpen, setPutAwayOpen] = useState(false);
  123. const [rejectOpen, setRejectOpen] = useState(false);
  124. const [btnIsLoading, setBtnIsLoading] = useState(false);
  125. const [currQty, setCurrQty] = useState(() => {
  126. const total = entries.reduce(
  127. (acc, curr) => acc + (curr.acceptedQty || 0),
  128. 0,
  129. );
  130. return total;
  131. });
  132. const { data: session } = useSession();
  133. useEffect(() => {
  134. const completedList = entries.filter(
  135. (e) => stockInLineStatusMap[e.status!] >= 8,
  136. );
  137. const processedQty = completedList.reduce(
  138. (acc, curr) => acc + (curr.acceptedQty || 0),
  139. 0,
  140. );
  141. setProcessedQty(processedQty);
  142. }, [entries, setProcessedQty]);
  143. const handleDelete = useCallback(
  144. (id: GridRowId) => () => {
  145. setEntries((es) => es.filter((e) => getRowId(e) !== id));
  146. },
  147. [getRowId],
  148. );
  149. const closeQcModal = useCallback(() => {
  150. setQcOpen(false);
  151. }, []);
  152. const openQcModal = useCallback(() => {
  153. setQcOpen(true);
  154. }, []);
  155. const closeStockInModal = useCallback(() => {
  156. setStockInOpen(false);
  157. }, []);
  158. const openStockInModal = useCallback(() => {
  159. setStockInOpen(true);
  160. }, []);
  161. const closePutAwayModal = useCallback(() => {
  162. setPutAwayOpen(false);
  163. }, []);
  164. const openPutAwayModal = useCallback(() => {
  165. setPutAwayOpen(true);
  166. }, []);
  167. const closeEscalationModal = useCallback(() => {
  168. setEscalOpen(false);
  169. }, []);
  170. const openEscalationModal = useCallback(() => {
  171. setEscalOpen(true);
  172. }, []);
  173. const closeRejectModal = useCallback(() => {
  174. setRejectOpen(false);
  175. }, []);
  176. const openRejectModal = useCallback(() => {
  177. setRejectOpen(true);
  178. }, []);
  179. const handleStart = useCallback(
  180. (id: GridRowId, params: any) => () => {
  181. setBtnIsLoading(true);
  182. setRowModesModel((prev) => ({
  183. ...prev,
  184. [id]: { mode: GridRowModes.View },
  185. }));
  186. setTimeout(async () => {
  187. // post stock in line
  188. const oldId = params.row.id;
  189. const postData = {
  190. itemId: params.row.itemId,
  191. itemNo: params.row.itemNo,
  192. itemName: params.row.itemName,
  193. purchaseOrderId: params.row.purchaseOrderId,
  194. purchaseOrderLineId: params.row.purchaseOrderLineId,
  195. acceptedQty: params.row.acceptedQty,
  196. };
  197. const res = await createStockInLine(postData);
  198. console.log(res);
  199. setEntries((prev) =>
  200. prev.map((p) => (p.id === oldId ? (res.entity as StockInLine) : p)),
  201. );
  202. setStockInLine(
  203. (prev) =>
  204. prev.map((p) =>
  205. p.id === oldId ? (res.entity as StockInLine) : p,
  206. ) as StockInLine[],
  207. );
  208. setBtnIsLoading(false);
  209. // do post directly to test
  210. // openStartModal();
  211. }, 200);
  212. },
  213. [setStockInLine],
  214. );
  215. const fetchQcDefaultValue = useCallback(async (stockInLineId: GridRowId) => {
  216. return await fetchQcResult(stockInLineId as number);
  217. }, []);
  218. const handleQC = useCallback(
  219. (id: GridRowId, params: any) => async () => {
  220. setBtnIsLoading(true);
  221. setRowModesModel((prev) => ({
  222. ...prev,
  223. [id]: { mode: GridRowModes.View },
  224. }));
  225. const qcResult = await fetchQcDefaultValue(id);
  226. console.log(params.row);
  227. console.log(qcResult);
  228. setModalInfo({
  229. ...params.row,
  230. qcResult: qcResult,
  231. });
  232. // set default values
  233. setTimeout(() => {
  234. // open qc modal
  235. console.log("delayed");
  236. openQcModal();
  237. setBtnIsLoading(false);
  238. }, 200);
  239. },
  240. [fetchQcDefaultValue, openQcModal],
  241. );
  242. const [newOpen, setNewOpen] = useState(false);
  243. const closeNewModal = useCallback(() => {
  244. setNewOpen(false);
  245. }, []);
  246. const openNewModal = useCallback(() => {
  247. setNewOpen(true);
  248. }, []);
  249. const handleNewQC = useCallback(
  250. (id: GridRowId, params: any) => async () => {
  251. setBtnIsLoading(true);
  252. setRowModesModel((prev) => ({
  253. ...prev,
  254. [id]: { mode: GridRowModes.View },
  255. }));
  256. const qcResult = await fetchQcDefaultValue(id);
  257. console.log(params.row);
  258. console.log(qcResult);
  259. setModalInfo({
  260. ...params.row,
  261. qcResult: qcResult,
  262. });
  263. // set default values
  264. setTimeout(() => {
  265. // open qc modal
  266. console.log("delayed");
  267. openNewModal();
  268. setBtnIsLoading(false);
  269. }, 200);
  270. },
  271. [fetchQcDefaultValue, openNewModal],
  272. );
  273. const handleEscalation = useCallback(
  274. (id: GridRowId, params: any) => () => {
  275. // setBtnIsLoading(true);
  276. setRowModesModel((prev) => ({
  277. ...prev,
  278. [id]: { mode: GridRowModes.View },
  279. }));
  280. setModalInfo(params.row);
  281. setTimeout(() => {
  282. // open qc modal
  283. console.log("delayed");
  284. openEscalationModal();
  285. // setBtnIsLoading(false);
  286. }, 200);
  287. },
  288. [openEscalationModal],
  289. );
  290. const handleReject = useCallback(
  291. (id: GridRowId, params: any) => () => {
  292. setRowModesModel((prev) => ({
  293. ...prev,
  294. [id]: { mode: GridRowModes.View },
  295. }));
  296. setModalInfo(params.row);
  297. setTimeout(() => {
  298. // open stock in modal
  299. // openPutAwayModal();
  300. // return the record with its status as pending
  301. // update layout
  302. console.log("delayed");
  303. openRejectModal();
  304. // printQrcode(params.row);
  305. }, 200);
  306. },
  307. [openRejectModal],
  308. );
  309. const handleStockIn = useCallback(
  310. (id: GridRowId, params: any) => () => {
  311. // setBtnIsLoading(true);
  312. setRowModesModel((prev) => ({
  313. ...prev,
  314. [id]: { mode: GridRowModes.View },
  315. }));
  316. setModalInfo(params.row);
  317. setTimeout(() => {
  318. // open stock in modal
  319. openStockInModal();
  320. // return the record with its status as pending
  321. // update layout
  322. console.log("delayed");
  323. // setBtnIsLoading(false);
  324. }, 200);
  325. },
  326. [openStockInModal],
  327. );
  328. const handlePutAway = useCallback(
  329. (id: GridRowId, params: any) => () => {
  330. // setBtnIsLoading(true);
  331. setRowModesModel((prev) => ({
  332. ...prev,
  333. [id]: { mode: GridRowModes.View },
  334. }));
  335. setModalInfo(params.row);
  336. setTimeout(() => {
  337. // open stock in modal
  338. openPutAwayModal();
  339. // return the record with its status as pending
  340. // update layout
  341. console.log("delayed");
  342. // setBtnIsLoading(false);
  343. }, 200);
  344. },
  345. [openPutAwayModal],
  346. );
  347. const printQrcode = useCallback(
  348. async (row: any) => {
  349. setBtnIsLoading(true);
  350. console.log(row.id);
  351. const postData = { stockInLineIds: [row.id] };
  352. // const postData = { stockInLineIds: [42,43,44] };
  353. const response = await fetchPoQrcode(postData);
  354. if (response) {
  355. console.log(response);
  356. downloadFile(new Uint8Array(response.blobValue), response.filename!);
  357. }
  358. setBtnIsLoading(false);
  359. },
  360. [],
  361. );
  362. // const handleQrCode = useCallback(
  363. // (id: GridRowId, params: any) => () => {
  364. // setRowModesModel((prev) => ({
  365. // ...prev,
  366. // [id]: { mode: GridRowModes.View },
  367. // }));
  368. // setModalInfo(params.row);
  369. // setTimeout(() => {
  370. // // open stock in modal
  371. // // openPutAwayModal();
  372. // // return the record with its status as pending
  373. // // update layout
  374. // console.log("delayed");
  375. // printQrcode(params.row);
  376. // }, 200);
  377. // },
  378. // [printQrcode],
  379. // );
  380. const columns = useMemo<GridColDef[]>(
  381. () => [
  382. {
  383. field: "itemNo",
  384. headerName: t("itemNo"),
  385. width: 100,
  386. // flex: 0.4,
  387. },
  388. {
  389. field: "dnNo",
  390. headerName: t("dnNo"),
  391. width: 100,
  392. renderCell: () => {
  393. return <>DN0000001</>
  394. }
  395. // flex: 0.4,
  396. },
  397. {
  398. field: "dnDate",
  399. headerName: t("dnDate"),
  400. width: 100,
  401. renderCell: () => {
  402. return <>07/08/2025</>
  403. }
  404. // flex: 0.4,
  405. },
  406. {
  407. field: "itemName",
  408. headerName: t("itemName"),
  409. width: 100,
  410. // flex: 0.6,
  411. },
  412. {
  413. field: "acceptedQty",
  414. headerName: t("acceptedQty"),
  415. // flex: 0.5,
  416. width: 100,
  417. type: "number",
  418. // editable: true,
  419. // replace with tooltip + content
  420. },
  421. {
  422. field: "uom",
  423. headerName: t("uom"),
  424. width: 120,
  425. // flex: 0.5,
  426. renderCell: (params) => {
  427. return params.row.uom.code;
  428. },
  429. },
  430. {
  431. field: "weight",
  432. headerName: t("weight"),
  433. width: 120,
  434. // flex: 0.5,
  435. renderCell: (params) => {
  436. const weight = calculateWeight(
  437. params.row.acceptedQty,
  438. params.row.uom,
  439. );
  440. const weightUnit = returnWeightUnit(params.row.uom);
  441. return `${weight} ${weightUnit}`;
  442. },
  443. },
  444. {
  445. field: "status",
  446. headerName: t("status"),
  447. width: 70,
  448. // flex: 0.5,
  449. renderCell: (params) => {
  450. return t(`${params.row.status}`);
  451. },
  452. },
  453. {
  454. field: "actions",
  455. type: "actions",
  456. // headerName: `${t("start")} | ${t("qc")} | ${t("escalation")} | ${t(
  457. // "stock in",
  458. // )} | ${t("putaway")} | ${t("delete")}`,
  459. headerName: "動作",
  460. // headerName: "start | qc | escalation | stock in | putaway | delete",
  461. width: 300,
  462. // flex: 2,
  463. cellClassName: "actions",
  464. getActions: (params) => {
  465. // console.log(params.row.status);
  466. const status = params.row.status.toLowerCase();
  467. // console.log(stockInLineStatusMap[status]);
  468. // console.log(session?.user?.abilities?.includes("APPROVAL"));
  469. return [
  470. <GridActionsCellItem
  471. icon={<Button variant="contained">{t("qc processing")}</Button>}
  472. label="start"
  473. sx={{
  474. color: "primary.main",
  475. // marginRight: 1,
  476. }}
  477. // disabled={!(stockInLineStatusMap[status] === 0)}
  478. // set _isNew to false after posting
  479. // or check status
  480. onClick={handleNewQC(params.row.id, params)}
  481. color="inherit"
  482. key="edit"
  483. />,
  484. <GridActionsCellItem
  485. icon={<Button variant="contained">{t("putawayBtn")}</Button>}
  486. label="start"
  487. sx={{
  488. color: "primary.main",
  489. // marginRight: 1,
  490. }}
  491. // disabled={!(stockInLineStatusMap[status] === 0)}
  492. // set _isNew to false after posting
  493. // or check status
  494. onClick={handleStart(params.row.id, params)}
  495. color="inherit"
  496. key="edit"
  497. />,
  498. // <GridActionsCellItem
  499. // icon={<Button variant="contained">{t("qc processing")}</Button>}
  500. // label="start"
  501. // sx={{
  502. // color: "primary.main",
  503. // // marginRight: 1,
  504. // }}
  505. // disabled={!(stockInLineStatusMap[status] === 0)}
  506. // // set _isNew to false after posting
  507. // // or check status
  508. // onClick={handleStart(params.row.id, params)}
  509. // color="inherit"
  510. // key="edit"
  511. // />,
  512. // <GridActionsCellItem
  513. // icon={<FactCheckIcon />}
  514. // label="qc"
  515. // sx={{
  516. // color: "primary.main",
  517. // // marginRight: 1,
  518. // }}
  519. // disabled={
  520. // // stockInLineStatusMap[status] === 9 ||
  521. // stockInLineStatusMap[status] < 1
  522. // }
  523. // // set _isNew to false after posting
  524. // // or check status
  525. // onClick={handleQC(params.row.id, params)}
  526. // color="inherit"
  527. // key="edit"
  528. // />,
  529. // <GridActionsCellItem
  530. // icon={<NotificationImportantIcon />}
  531. // label="escalation"
  532. // sx={{
  533. // color: "primary.main",
  534. // // marginRight: 1,
  535. // }}
  536. // disabled={
  537. // stockInLineStatusMap[status] === 9 ||
  538. // stockInLineStatusMap[status] <= 0 ||
  539. // stockInLineStatusMap[status] >= 5
  540. // }
  541. // // set _isNew to false after posting
  542. // // or check status
  543. // onClick={handleEscalation(params.row.id, params)}
  544. // color="inherit"
  545. // key="edit"
  546. // />,
  547. // <GridActionsCellItem
  548. // icon={<ShoppingCartIcon />}
  549. // label="stockin"
  550. // sx={{
  551. // color: "primary.main",
  552. // // marginRight: 1,
  553. // }}
  554. // disabled={
  555. // stockInLineStatusMap[status] === 9 ||
  556. // stockInLineStatusMap[status] <= 2 ||
  557. // stockInLineStatusMap[status] >= 7 ||
  558. // (stockInLineStatusMap[status] >= 3 &&
  559. // stockInLineStatusMap[status] <= 5 &&
  560. // !session?.user?.abilities?.includes("APPROVAL"))
  561. // }
  562. // // set _isNew to false after posting
  563. // // or check status
  564. // onClick={handleStockIn(params.row.id, params)}
  565. // color="inherit"
  566. // key="edit"
  567. // />,
  568. // <GridActionsCellItem
  569. // icon={<ShoppingCartIcon />}
  570. // label="putaway"
  571. // sx={{
  572. // color: "primary.main",
  573. // // marginRight: 1,
  574. // }}
  575. // disabled={
  576. // stockInLineStatusMap[status] === 9 ||
  577. // stockInLineStatusMap[status] < 7
  578. // }
  579. // // set _isNew to false after posting
  580. // // or check status
  581. // onClick={handlePutAway(params.row.id, params)}
  582. // color="inherit"
  583. // key="edit"
  584. // />,
  585. // // <GridActionsCellItem
  586. // // icon={<QrCodeIcon />}
  587. // // label="putaway"
  588. // // sx={{
  589. // // color: "primary.main",
  590. // // // marginRight: 1,
  591. // // }}
  592. // // disabled={stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] !== 8}
  593. // // // set _isNew to false after posting
  594. // // // or check status
  595. // // onClick={handleQrCode(params.row.id, params)}
  596. // // color="inherit"
  597. // // key="edit"
  598. // // />,
  599. // <GridActionsCellItem
  600. // icon={
  601. // stockInLineStatusMap[status] >= 1 ? (
  602. // <DoDisturbIcon />
  603. // ) : (
  604. // <DeleteIcon />
  605. // )
  606. // }
  607. // label="Delete"
  608. // sx={{
  609. // color: "error.main",
  610. // }}
  611. // disabled={
  612. // stockInLineStatusMap[status] >= 7 &&
  613. // stockInLineStatusMap[status] <= 9
  614. // }
  615. // onClick={
  616. // stockInLineStatusMap[status] === 0
  617. // ? handleDelete(params.row.id)
  618. // : handleReject(params.row.id, params)
  619. // }
  620. // color="inherit"
  621. // key="edit"
  622. // />,
  623. ];
  624. },
  625. },
  626. ],
  627. [t, handleStart, handleQC, handleEscalation, session?.user?.abilities, handleStockIn, handlePutAway, handleDelete, handleReject],
  628. );
  629. const addRow = useCallback(() => {
  630. console.log(itemDetail);
  631. const newEntry = {
  632. id: Date.now(),
  633. _isNew: true,
  634. itemId: itemDetail.itemId,
  635. purchaseOrderId: itemDetail.purchaseOrderId,
  636. purchaseOrderLineId: itemDetail.id,
  637. itemNo: itemDetail.itemNo,
  638. itemName: itemDetail.itemName,
  639. acceptedQty: itemDetail.qty - currQty, // this bug
  640. uom: itemDetail.uom,
  641. status: "draft",
  642. };
  643. setEntries((e) => [...e, newEntry]);
  644. setRowModesModel((model) => ({
  645. ...model,
  646. [getRowId(newEntry)]: {
  647. mode: GridRowModes.Edit,
  648. // fieldToFocus: "projectId",
  649. },
  650. }));
  651. }, [currQty, getRowId, itemDetail]);
  652. const validation = useCallback(
  653. (
  654. newRow: GridRowModel<StockInLineRow>,
  655. // rowModel: GridRowSelectionModel
  656. ): StockInLineEntryError | undefined => {
  657. const error: StockInLineEntryError = {};
  658. console.log(newRow);
  659. console.log(currQty);
  660. if (newRow.acceptedQty && newRow.acceptedQty > itemDetail.qty) {
  661. error["acceptedQty"] = t("qty cannot be greater than remaining qty");
  662. }
  663. return Object.keys(error).length > 0 ? error : undefined;
  664. },
  665. [currQty, itemDetail.qty, t],
  666. );
  667. const processRowUpdate = useCallback(
  668. (
  669. newRow: GridRowModel<StockInLineRow>,
  670. originalRow: GridRowModel<StockInLineRow>,
  671. ) => {
  672. const errors = validation(newRow); // change to validation
  673. if (errors) {
  674. throw new ProcessRowUpdateError(
  675. originalRow,
  676. "validation error",
  677. errors,
  678. );
  679. }
  680. const { _isNew, _error, ...updatedRow } = newRow;
  681. const rowToSave = {
  682. ...updatedRow,
  683. } satisfies StockInLineRow;
  684. const newEntries = entries.map((e) =>
  685. getRowId(e) === getRowId(originalRow) ? rowToSave : e,
  686. );
  687. setStockInLine(newEntries as StockInLine[]);
  688. console.log("triggered");
  689. setEntries(newEntries);
  690. //update remaining qty
  691. const total = newEntries.reduce(
  692. (acc, curr) => acc + (curr.acceptedQty || 0),
  693. 0,
  694. );
  695. setCurrQty(total);
  696. return rowToSave;
  697. },
  698. [validation, entries, setStockInLine, getRowId],
  699. );
  700. const onProcessRowUpdateError = useCallback(
  701. (updateError: ProcessRowUpdateError) => {
  702. const errors = updateError.errors;
  703. const oldRow = updateError.row;
  704. apiRef.current.updateRows([{ ...oldRow, _error: errors }]);
  705. },
  706. [apiRef],
  707. );
  708. const footer = (
  709. <>
  710. {/* <Box display="flex" gap={2} alignItems="center">
  711. <Button
  712. disableRipple
  713. variant="outlined"
  714. startIcon={<Add />}
  715. disabled={itemDetail.qty - currQty <= 0}
  716. onClick={addRow}
  717. size="small"
  718. >
  719. {t("Record pol")}
  720. </Button>
  721. </Box> */}
  722. </>
  723. );
  724. return (
  725. <>
  726. <StyledDataGrid
  727. getRowId={getRowId}
  728. apiRef={apiRef}
  729. autoHeight
  730. sx={{
  731. "--DataGrid-overlayHeight": "100px",
  732. ".MuiDataGrid-row .MuiDataGrid-cell.hasError": {
  733. border: "1px solid",
  734. borderColor: "error.main",
  735. },
  736. ".MuiDataGrid-row .MuiDataGrid-cell.hasWarning": {
  737. border: "1px solid",
  738. borderColor: "warning.main",
  739. },
  740. }}
  741. disableColumnMenu
  742. editMode="row"
  743. rows={entries}
  744. rowModesModel={rowModesModel}
  745. onRowModesModelChange={setRowModesModel}
  746. processRowUpdate={processRowUpdate}
  747. onProcessRowUpdateError={onProcessRowUpdateError}
  748. columns={columns}
  749. isCellEditable={(params) => {
  750. const status = params.row.status.toLowerCase();
  751. return (
  752. stockInLineStatusMap[status] >= 0 ||
  753. stockInLineStatusMap[status] <= 1
  754. );
  755. }}
  756. getCellClassName={(params: GridCellParams<StockInLineRow>) => {
  757. let classname = "";
  758. if (params.row._error) {
  759. classname = "hasError";
  760. }
  761. return classname;
  762. }}
  763. slots={{
  764. footer: FooterToolbar,
  765. noRowsOverlay: NoRowsOverlay,
  766. }}
  767. slotProps={{
  768. footer: { child: footer },
  769. }}
  770. />
  771. {modalInfo !== undefined && (
  772. <>
  773. <PoQcStockInModalVer2
  774. // setRows={setRows}
  775. setEntries={setEntries}
  776. setStockInLine={setStockInLine}
  777. setItemDetail={setModalInfo}
  778. qc={qc}
  779. open={newOpen}
  780. onClose={closeNewModal}
  781. itemDetail={modalInfo}
  782. />
  783. </>
  784. )
  785. }
  786. {modalInfo !== undefined && (
  787. <>
  788. <PoQcStockInModal
  789. type={"qc"}
  790. // setRows={setRows}
  791. setEntries={setEntries}
  792. setStockInLine={setStockInLine}
  793. setItemDetail={setModalInfo}
  794. qc={qc}
  795. open={qcOpen}
  796. onClose={closeQcModal}
  797. itemDetail={modalInfo}
  798. />
  799. </>
  800. )}
  801. {modalInfo !== undefined && (
  802. <>
  803. <PoQcStockInModal
  804. type={"escalation"}
  805. // setRows={setRows}
  806. setEntries={setEntries}
  807. setStockInLine={setStockInLine}
  808. setItemDetail={setModalInfo}
  809. // qc={qc}
  810. open={escalOpen}
  811. onClose={closeEscalationModal}
  812. itemDetail={modalInfo}
  813. />
  814. </>
  815. )}
  816. {modalInfo !== undefined && (
  817. <>
  818. <PoQcStockInModal
  819. type={"reject"}
  820. // setRows={setRows}
  821. setEntries={setEntries}
  822. setStockInLine={setStockInLine}
  823. setItemDetail={setModalInfo}
  824. // qc={qc}
  825. open={rejectOpen}
  826. onClose={closeRejectModal}
  827. itemDetail={modalInfo}
  828. />
  829. </>
  830. )}
  831. {modalInfo !== undefined && (
  832. <>
  833. <PoQcStockInModal
  834. type={"stockIn"}
  835. // setRows={setRows}
  836. setEntries={setEntries}
  837. setStockInLine={setStockInLine}
  838. // qc={qc}
  839. setItemDetail={setModalInfo}
  840. open={stockInOpen}
  841. onClose={closeStockInModal}
  842. itemDetail={modalInfo}
  843. />
  844. </>
  845. )}
  846. {modalInfo !== undefined && (
  847. <>
  848. <PoQcStockInModal
  849. type={"putaway"}
  850. // setRows={setRows}
  851. setEntries={setEntries}
  852. setStockInLine={setStockInLine}
  853. setItemDetail={setModalInfo}
  854. open={putAwayOpen}
  855. warehouse={warehouse}
  856. onClose={closePutAwayModal}
  857. itemDetail={modalInfo}
  858. />
  859. </>
  860. )}
  861. </>
  862. );
  863. }
  864. const NoRowsOverlay: React.FC = () => {
  865. const { t } = useTranslation("home");
  866. return (
  867. <Box
  868. display="flex"
  869. justifyContent="center"
  870. alignItems="center"
  871. height="100%"
  872. >
  873. <Typography variant="caption">{t("Add some entries!")}</Typography>
  874. </Box>
  875. );
  876. };
  877. const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => {
  878. return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>;
  879. };
  880. export default PoInputGrid;