FPSMS-frontend
選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

PoInputGrid.tsx 23 KiB

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