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.
 
 

444 rivejä
12 KiB

  1. "use client";
  2. import { PurchaseQcResult, PutawayInput } from "@/app/api/po/actions";
  3. import {
  4. Autocomplete,
  5. Box,
  6. Button,
  7. Card,
  8. CardContent,
  9. FormControl,
  10. Grid,
  11. Modal,
  12. ModalProps,
  13. Stack,
  14. TextField,
  15. Tooltip,
  16. Typography,
  17. } from "@mui/material";
  18. import { Controller, useFormContext } from "react-hook-form";
  19. import { useTranslation } from "react-i18next";
  20. import StyledDataGrid from "../StyledDataGrid";
  21. import { useCallback, useEffect, useMemo, useState } from "react";
  22. import {
  23. GridColDef,
  24. GridRowIdGetter,
  25. GridRowModel,
  26. useGridApiContext,
  27. GridRenderCellParams,
  28. GridRenderEditCellParams,
  29. useGridApiRef,
  30. } from "@mui/x-data-grid";
  31. import InputDataGrid from "../InputDataGrid";
  32. import { TableRow } from "../InputDataGrid/InputDataGrid";
  33. import TwoLineCell from "./TwoLineCell";
  34. import QcSelect from "./QcSelect";
  35. import { QcItemWithChecks } from "@/app/api/qc";
  36. import { GridEditInputCell } from "@mui/x-data-grid";
  37. import { StockInLine } from "@/app/api/po";
  38. import { WarehouseResult } from "@/app/api/warehouse";
  39. import { stockInLineStatusMap } from "@/app/utils/formatUtil";
  40. import { QRCodeSVG } from "qrcode.react";
  41. import { QrCode } from "../QrCode";
  42. import ReactQrCodeScanner, {
  43. ScannerConfig,
  44. } from "../ReactQrCodeScanner/ReactQrCodeScanner";
  45. import { QrCodeInfo } from "@/app/api/qrcode";
  46. import { useQcCodeScanner } from "../QrCodeScannerProvider/QrCodeScannerProvider";
  47. interface Props {
  48. itemDetail: StockInLine;
  49. warehouse: WarehouseResult[];
  50. disabled: boolean
  51. // qc: QcItemWithChecks[];
  52. }
  53. type EntryError =
  54. | {
  55. [field in keyof PurchaseQcResult]?: string;
  56. }
  57. | undefined;
  58. // type PoQcRow = TableRow<Partial<PurchaseQcResult>, EntryError>;
  59. const style = {
  60. position: "absolute",
  61. top: "50%",
  62. left: "50%",
  63. transform: "translate(-50%, -50%)",
  64. bgcolor: "background.paper",
  65. pt: 5,
  66. px: 5,
  67. pb: 10,
  68. width: "auto",
  69. };
  70. const PutawayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled }) => {
  71. const { t } = useTranslation("purchaseOrder");
  72. const apiRef = useGridApiRef();
  73. const {
  74. register,
  75. formState: { errors, defaultValues, touchedFields },
  76. watch,
  77. control,
  78. setValue,
  79. getValues,
  80. reset,
  81. resetField,
  82. setError,
  83. clearErrors,
  84. } = useFormContext<PutawayInput>();
  85. console.log(itemDetail);
  86. // const [recordQty, setRecordQty] = useState(0);
  87. const [warehouseId, setWarehouseId] = useState(itemDetail.defaultWarehouseId);
  88. const filteredWarehouse = useMemo(() => {
  89. // do filtering here if any
  90. return warehouse;
  91. }, []);
  92. const defaultOption = {
  93. value: 0, // think think sin
  94. label: t("Select warehouse"),
  95. group: "default",
  96. }
  97. const options = useMemo(() => {
  98. return [
  99. // {
  100. // value: 0, // think think sin
  101. // label: t("Select warehouse"),
  102. // group: "default",
  103. // },
  104. ...filteredWarehouse.map((w) => ({
  105. value: w.id,
  106. label: `${w.code} - ${w.name}`,
  107. group: "existing",
  108. })),
  109. ];
  110. }, [filteredWarehouse]);
  111. const currentValue =
  112. warehouseId > 0
  113. ? options.find((o) => o.value === warehouseId)
  114. : options.find((o) => o.value === getValues("warehouseId")) || defaultOption;
  115. const onChange = useCallback(
  116. (
  117. event: React.SyntheticEvent,
  118. newValue: { value: number; group: string } | { value: number }[]
  119. ) => {
  120. const singleNewVal = newValue as {
  121. value: number;
  122. group: string;
  123. };
  124. console.log(singleNewVal);
  125. console.log("onChange");
  126. // setValue("warehouseId", singleNewVal.value);
  127. setWarehouseId(singleNewVal.value);
  128. },
  129. []
  130. );
  131. // const accQty = watch("acceptedQty");
  132. // const validateForm = useCallback(() => {
  133. // console.log(accQty);
  134. // if (accQty > itemDetail.acceptedQty) {
  135. // setError("acceptedQty", {
  136. // message: `acceptedQty must not greater than ${itemDetail.acceptedQty}`,
  137. // type: "required",
  138. // });
  139. // }
  140. // if (accQty < 1) {
  141. // setError("acceptedQty", {
  142. // message: `minimal value is 1`,
  143. // type: "required",
  144. // });
  145. // }
  146. // if (isNaN(accQty)) {
  147. // setError("acceptedQty", {
  148. // message: `value must be a number`,
  149. // type: "required",
  150. // });
  151. // }
  152. // }, [accQty]);
  153. // useEffect(() => {
  154. // clearErrors();
  155. // validateForm();
  156. // }, [validateForm]);
  157. const qrContent = useMemo(
  158. () => ({
  159. stockInLineId: itemDetail.id,
  160. itemId: itemDetail.itemId,
  161. lotNo: itemDetail.lotNo,
  162. // warehouseId: 2 // for testing
  163. // expiryDate: itemDetail.expiryDate,
  164. // productionDate: itemDetail.productionDate,
  165. // supplier: itemDetail.supplier,
  166. // poCode: itemDetail.poCode,
  167. }),
  168. [itemDetail]
  169. );
  170. const [isOpenScanner, setOpenScanner] = useState(false);
  171. const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
  172. (...args) => {
  173. setOpenScanner(false);
  174. },
  175. []
  176. );
  177. const onOpenScanner = useCallback(() => {
  178. setOpenScanner(true);
  179. }, []);
  180. const onCloseScanner = useCallback(() => {
  181. setOpenScanner(false);
  182. }, []);
  183. const scannerConfig = useMemo<ScannerConfig>(
  184. () => ({
  185. onUpdate: (err, result) => {
  186. console.log(result);
  187. console.log(Boolean(result));
  188. if (result) {
  189. const data: QrCodeInfo = JSON.parse(result.getText());
  190. console.log(data);
  191. if (data.warehouseId) {
  192. console.log(data.warehouseId);
  193. setWarehouseId(data.warehouseId);
  194. onCloseScanner();
  195. }
  196. } else return;
  197. },
  198. }),
  199. [onCloseScanner]
  200. );
  201. // QR Code Scanner
  202. const scanner = useQcCodeScanner()
  203. useEffect(() => {
  204. if (isOpenScanner) {
  205. scanner.startScan()
  206. } else if (!isOpenScanner) {
  207. scanner.stopScan()
  208. }
  209. }, [isOpenScanner])
  210. useEffect(() => {
  211. if (scanner.values.length > 0) {
  212. console.log(scanner.values[0])
  213. const data: QrCodeInfo = JSON.parse(scanner.values[0]);
  214. console.log(data);
  215. if (data.warehouseId) {
  216. console.log(data.warehouseId);
  217. setWarehouseId(data.warehouseId);
  218. onCloseScanner();
  219. }
  220. scanner.resetScan()
  221. }
  222. }, [scanner.values])
  223. useEffect(() => {
  224. setValue("status", "completed");
  225. }, []);
  226. useEffect(() => {
  227. if (warehouseId > 0) {
  228. setValue("warehouseId", warehouseId);
  229. clearErrors("warehouseId")
  230. }
  231. }, [warehouseId]);
  232. return (
  233. <Grid container justifyContent="flex-start" alignItems="flex-start">
  234. <Grid item xs={12}>
  235. <Typography variant="h6" display="block" marginBlockEnd={1}>
  236. {t("Putaway Detail")}
  237. </Typography>
  238. </Grid>
  239. <Grid
  240. container
  241. justifyContent="flex-start"
  242. alignItems="flex-start"
  243. spacing={2}
  244. sx={{ mt: 0.5 }}
  245. >
  246. <Grid item xs={12}>
  247. <TextField
  248. label={t("LotNo")}
  249. fullWidth
  250. value={itemDetail.lotNo}
  251. disabled
  252. />
  253. </Grid>
  254. <Grid item xs={6}>
  255. <TextField
  256. label={t("Supplier")}
  257. fullWidth
  258. value={itemDetail.supplier}
  259. disabled
  260. />
  261. </Grid>
  262. <Grid item xs={6}>
  263. <TextField
  264. label={t("Po Code")}
  265. fullWidth
  266. value={itemDetail.poCode}
  267. disabled
  268. />
  269. </Grid>
  270. <Grid item xs={6}>
  271. <TextField
  272. label={t("itemName")}
  273. fullWidth
  274. value={itemDetail.itemName}
  275. disabled
  276. />
  277. </Grid>
  278. <Grid item xs={6}>
  279. <TextField
  280. label={t("itemNo")}
  281. fullWidth
  282. value={itemDetail.itemNo}
  283. disabled
  284. />
  285. </Grid>
  286. <Grid item xs={6}>
  287. <TextField
  288. label={t("qty")}
  289. fullWidth
  290. value={itemDetail.acceptedQty}
  291. disabled
  292. />
  293. </Grid>
  294. <Grid item xs={6}>
  295. <TextField
  296. label={t("productionDate")}
  297. fullWidth
  298. value={itemDetail.productionDate}
  299. disabled
  300. />
  301. </Grid>
  302. <Grid item xs={6}>
  303. <TextField
  304. label={t("expiryDate")}
  305. fullWidth
  306. value={itemDetail.expiryDate}
  307. disabled
  308. />
  309. </Grid>
  310. <Grid item xs={6}>
  311. <FormControl fullWidth>
  312. <Autocomplete
  313. noOptionsText={t("No Warehouse")}
  314. disableClearable
  315. disabled
  316. fullWidth
  317. defaultValue={options.find((o) => o.value === 1)} /// modify this later
  318. // onChange={onChange}
  319. getOptionLabel={(option) => option.label}
  320. options={options}
  321. renderInput={(params) => (
  322. <TextField {...params} label="Default Warehouse" />
  323. )}
  324. />
  325. </FormControl>
  326. </Grid>
  327. <Grid item xs={5.5}>
  328. <TextField
  329. label={t("acceptedQty")}
  330. fullWidth
  331. {...register("acceptedQty", {
  332. required: "acceptedQty required!",
  333. min: 1,
  334. max: itemDetail.acceptedQty,
  335. valueAsNumber: true,
  336. })}
  337. // defaultValue={itemDetail.acceptedQty}
  338. disabled={disabled}
  339. error={Boolean(errors.acceptedQty)}
  340. helperText={errors.acceptedQty?.message}
  341. />
  342. </Grid>
  343. <Grid item xs={1}>
  344. <Button disabled={disabled} onClick={onOpenScanner}>bind</Button>
  345. </Grid>
  346. <Grid item xs={5.5}>
  347. {/* <Controller
  348. control={control}
  349. name="warehouseId"
  350. render={({ field }) => {
  351. console.log(field);
  352. return (
  353. <Autocomplete
  354. noOptionsText={t("No Warehouse")}
  355. disableClearable
  356. fullWidth
  357. value={options.find((o) => o.value == field.value)}
  358. onChange={onChange}
  359. getOptionLabel={(option) => option.label}
  360. options={options}
  361. renderInput={(params) => (
  362. <TextField
  363. {...params}
  364. label={"Select warehouse"}
  365. error={Boolean(errors.warehouseId?.message)}
  366. helperText={warehouseHelperText}
  367. // helperText={errors.warehouseId?.message}
  368. />
  369. )}
  370. />
  371. );
  372. }}
  373. /> */}
  374. <FormControl fullWidth>
  375. <Autocomplete
  376. noOptionsText={t("No Warehouse")}
  377. disableClearable
  378. fullWidth
  379. // value={warehouseId > 0
  380. // ? options.find((o) => o.value === warehouseId)
  381. // : undefined}
  382. value={currentValue}
  383. onChange={onChange}
  384. getOptionLabel={(option) => option.label}
  385. options={options}
  386. renderInput={(params) => (
  387. <TextField
  388. {...params}
  389. // label={"Select warehouse"}
  390. disabled={disabled}
  391. error={Boolean(errors.warehouseId?.message)}
  392. helperText={errors.warehouseId?.message}
  393. // helperText={warehouseHelperText}
  394. />
  395. )}
  396. />
  397. </FormControl>
  398. </Grid>
  399. <Grid
  400. item
  401. xs={12}
  402. style={{ display: "flex", justifyContent: "center" }}
  403. >
  404. <QrCode content={qrContent} sx={{ width: 200, height: 200 }} />
  405. </Grid>
  406. </Grid>
  407. {/* <Grid
  408. container
  409. justifyContent="flex-start"
  410. alignItems="flex-start"
  411. spacing={2}
  412. sx={{ mt: 0.5 }}
  413. >
  414. <Button onClick={onOpenScanner}>bind</Button>
  415. </Grid> */}
  416. <Modal open={isOpenScanner} onClose={closeHandler}>
  417. <Box sx={style}>
  418. <Typography variant="h4">{t("Please scan warehouse qr code.")}</Typography>
  419. {/* <ReactQrCodeScanner scannerConfig={scannerConfig} /> */}
  420. </Box>
  421. </Modal>
  422. </Grid>
  423. );
  424. };
  425. export default PutawayForm;