FPSMS-frontend
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

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