FPSMS-frontend
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 

536 rader
16 KiB

  1. "use client";
  2. import {
  3. StockInInput,
  4. } from "@/app/api/stockIn/actions";
  5. import {
  6. Box,
  7. Card,
  8. CardContent,
  9. Grid,
  10. Stack,
  11. TextField,
  12. Tooltip,
  13. Typography,
  14. Button,
  15. } from "@mui/material";
  16. import { Controller, useFormContext } from "react-hook-form";
  17. import { useTranslation } from "react-i18next";
  18. import StyledDataGrid from "../StyledDataGrid";
  19. import { useCallback, useEffect, useMemo, useState } from "react";
  20. import {
  21. GridColDef,
  22. GridRowIdGetter,
  23. GridRowModel,
  24. useGridApiContext,
  25. GridRenderCellParams,
  26. GridRenderEditCellParams,
  27. useGridApiRef,
  28. } from "@mui/x-data-grid";
  29. import InputDataGrid from "../InputDataGrid";
  30. import { TableRow } from "../InputDataGrid/InputDataGrid";
  31. import { QcItemWithChecks } from "@/app/api/qc";
  32. import { GridEditInputCell } from "@mui/x-data-grid";
  33. import { StockInLine } from "@/app/api/stockIn";
  34. import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
  35. import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
  36. import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
  37. import dayjs from "dayjs";
  38. import CalculateExpiryDateModal from "./CalculateExpiryDateModal";
  39. import { InputAdornment } from "@mui/material";
  40. import { dayjsToDateString } from "@/app/utils/formatUtil";
  41. // change PurchaseQcResult to stock in entry props
  42. interface Props {
  43. itemDetail: StockInLine;
  44. // qc: QcItemWithChecks[];
  45. disabled: boolean;
  46. putawayMode?: boolean;
  47. }
  48. type EntryError =
  49. | {
  50. [field in keyof StockInInput]?: string;
  51. }
  52. | undefined;
  53. // type PoQcRow = TableRow<Partial<PurchaseQcResult>, EntryError>;
  54. const textfieldSx = {
  55. width: "100%",
  56. "& .MuiInputBase-root": {
  57. // height: "120", // Scales with root font size
  58. height: "5rem", // Scales with root font size
  59. },
  60. "& .MuiInputBase-input": {
  61. height: "100%",
  62. boxSizing: "border-box",
  63. padding: "0.75rem",
  64. fontSize: 30,
  65. },
  66. "& .MuiInputLabel-root": {
  67. fontSize: 30,
  68. transform: "translate(14px, 1.2rem) scale(1)",
  69. "&.MuiInputLabel-shrink": {
  70. fontSize: 24,
  71. transform: "translate(14px, -0.5rem) scale(1)",
  72. },
  73. // [theme.breakpoints.down("sm")]: {
  74. // fontSize: "1rem",
  75. // transform: "translate(14px, 1.5rem) scale(1)",
  76. // "&.MuiInputLabel-shrink": {
  77. // fontSize: "0.875rem",
  78. // },
  79. // },
  80. },
  81. };
  82. const FgStockInForm: React.FC<Props> = ({
  83. // qc,
  84. itemDetail,
  85. disabled,
  86. putawayMode = false,
  87. }) => {
  88. const {
  89. t,
  90. i18n: { language },
  91. } = useTranslation("purchaseOrder");
  92. const apiRef = useGridApiRef();
  93. const {
  94. register,
  95. formState: { errors, defaultValues, touchedFields },
  96. watch,
  97. control,
  98. setValue,
  99. getValues,
  100. reset,
  101. resetField,
  102. setError,
  103. clearErrors,
  104. } = useFormContext<StockInInput>();
  105. // console.log(itemDetail);
  106. useEffect(() => {
  107. // console.log("triggered");
  108. // // receiptDate default tdy
  109. // setValue("receiptDate", dayjs().add(0, "month").format(INPUT_DATE_FORMAT));
  110. // setValue("status", "received");
  111. }, [setValue]);
  112. useEffect(() => {
  113. console.log(errors);
  114. }, [errors]);
  115. const [openModal, setOpenModal] = useState<boolean>(false);
  116. const [openExpDatePicker, setOpenExpDatePicker] = useState<boolean>(false);
  117. const productionDate = watch("productionDate");
  118. const expiryDate = watch("expiryDate");
  119. const uom = watch("uom");
  120. //// TODO : Add Checking ////
  121. // Check if dates are input
  122. // if (data.productionDate === undefined || data.productionDate == null) {
  123. // validationErrors.push("請輸入生產日期!");
  124. // }
  125. // if (data.expiryDate === undefined || data.expiryDate == null) {
  126. // validationErrors.push("請輸入到期日!");
  127. // }
  128. useEffect(() => {
  129. // console.log(uom);
  130. // console.log(productionDate);
  131. // console.log(expiryDate);
  132. if (expiryDate) clearErrors();
  133. if (productionDate) clearErrors();
  134. }, [productionDate, expiryDate, clearErrors]);
  135. useEffect(() => {
  136. console.log("%c StockInForm itemDetail update: ", "color: brown", itemDetail);
  137. }, [itemDetail]);
  138. const handleOpenModal = useCallback(() => {
  139. setOpenModal(true);
  140. }, []);
  141. const handleOnModalClose = useCallback(() => {
  142. setOpenExpDatePicker(false);
  143. setOpenModal(false);
  144. }, []);
  145. const handleReturnExpiryDate = useCallback((result: dayjs.Dayjs) => {
  146. if (result) {
  147. setValue("expiryDate", dayjsToDateString(result));
  148. }
  149. }, [setValue]);
  150. return (
  151. <>
  152. <Grid container justifyContent="flex-start" alignItems="flex-start">
  153. {/* <Grid item xs={12}>
  154. <Typography variant="h6" display="block" marginBlockEnd={1}>
  155. {t("Stock In Detail")}
  156. </Typography>
  157. </Grid> */}
  158. <Grid
  159. container
  160. justifyContent="flex-start"
  161. alignItems="flex-start"
  162. spacing={2}
  163. sx={{ mt: 0.5 }}
  164. >
  165. {putawayMode && (
  166. <Grid item xs={6}>
  167. <TextField
  168. label={t("joCode")}
  169. fullWidth
  170. {...register("productLotNo", {
  171. // required: "productLotNo required!",
  172. })}
  173. sx={textfieldSx}
  174. disabled={true}
  175. />
  176. </Grid>
  177. )
  178. }
  179. <Grid item xs={6}>
  180. <TextField
  181. label={t("itemName")}
  182. fullWidth
  183. {...register("itemName", {
  184. // required: "productLotNo required!",
  185. })}
  186. sx={textfieldSx}
  187. disabled={true}
  188. // error={Boolean(errors.productLotNo)}
  189. // helperText={errors.productLotNo?.message}
  190. />
  191. </Grid>
  192. {putawayMode || (
  193. <>
  194. <Grid item xs={6}>
  195. <Controller
  196. control={control}
  197. name="receiptDate"
  198. rules={{ required: true }}
  199. render={({ field }) => {
  200. return (
  201. <LocalizationProvider
  202. dateAdapter={AdapterDayjs}
  203. adapterLocale={`${language}-hk`}
  204. >
  205. <DatePicker
  206. {...field}
  207. sx={textfieldSx}
  208. label={t("receiptDate")}
  209. value={dayjs(watch("receiptDate"))}
  210. format={OUTPUT_DATE_FORMAT}
  211. disabled={true}
  212. onChange={(date) => {
  213. if (!date) return;
  214. // setValue("receiptDate", date.format(INPUT_DATE_FORMAT));
  215. field.onChange(date);
  216. }}
  217. inputRef={field.ref}
  218. slotProps={{
  219. textField: {
  220. // required: true,
  221. error: Boolean(errors.receiptDate?.message),
  222. helperText: errors.receiptDate?.message,
  223. },
  224. }}
  225. />
  226. </LocalizationProvider>
  227. );
  228. }}
  229. />
  230. </Grid>
  231. </>
  232. )}
  233. <Grid item xs={6}>
  234. {putawayMode ? (
  235. <TextField
  236. label={t("stockLotNo")}
  237. fullWidth
  238. {...register("lotNo", {
  239. // required: "productLotNo required!",
  240. })}
  241. sx={textfieldSx}
  242. disabled={true}
  243. error={Boolean(errors.productLotNo)}
  244. helperText={errors.productLotNo?.message}
  245. />) : (
  246. <TextField
  247. label={t("stockLotNo")}
  248. fullWidth
  249. {...register("productLotNo", {
  250. // required: "productLotNo required!",
  251. })}
  252. sx={textfieldSx}
  253. disabled={true}
  254. error={Boolean(errors.productLotNo)}
  255. helperText={errors.productLotNo?.message}
  256. />)
  257. }
  258. </Grid>
  259. <Grid item xs={6}>
  260. <Controller
  261. control={control}
  262. name="productionDate"
  263. render={({ field }) => {
  264. return (
  265. <LocalizationProvider
  266. dateAdapter={AdapterDayjs}
  267. adapterLocale={`${language}-hk`}
  268. >
  269. <DatePicker
  270. {...field}
  271. sx={textfieldSx}
  272. label={t("productionDate")}
  273. value={productionDate ? dayjs(productionDate) : undefined}
  274. format={OUTPUT_DATE_FORMAT}
  275. disabled={disabled}
  276. onChange={(date) => {
  277. if (!date) return;
  278. setValue(
  279. "productionDate",
  280. date.format(INPUT_DATE_FORMAT),
  281. );
  282. }}
  283. inputRef={field.ref}
  284. slotProps={{
  285. textField: {
  286. error: Boolean(errors.productionDate?.message),
  287. helperText: errors.productionDate?.message,
  288. },
  289. }}
  290. />
  291. </LocalizationProvider>
  292. );
  293. }}
  294. />
  295. </Grid>
  296. {/* {putawayMode || (<>
  297. {/* {putawayMode || (<>
  298. <Grid item xs={6}>
  299. <Controller
  300. control={control}
  301. name="productionDate"
  302. // rules={{ required: !Boolean(expiryDate) }}
  303. render={({ field }) => {
  304. return (
  305. <LocalizationProvider
  306. dateAdapter={AdapterDayjs}
  307. adapterLocale={`${language}-hk`}
  308. >
  309. <DatePicker
  310. {...field}
  311. sx={textfieldSx}
  312. label={t("productionDate")}
  313. value={productionDate ? dayjs(productionDate) : undefined}
  314. disabled={disabled}
  315. onChange={(date) => {
  316. if (!date) return;
  317. setValue(
  318. "productionDate",
  319. date.format(INPUT_DATE_FORMAT),
  320. );
  321. // field.onChange(date);
  322. }}
  323. inputRef={field.ref}
  324. slotProps={{
  325. textField: {
  326. // required: true,
  327. error: Boolean(errors.productionDate?.message),
  328. helperText: errors.productionDate?.message,
  329. },
  330. }}
  331. />
  332. </LocalizationProvider>
  333. );
  334. }}
  335. />
  336. </Grid>
  337. <Grid item xs={6}>
  338. <TextField
  339. label={t("qty")}
  340. fullWidth
  341. {...register("qty", {
  342. required: "qty required!",
  343. })}
  344. sx={textfieldSx}
  345. disabled={true}
  346. />
  347. </Grid></>
  348. )} */}
  349. <Grid item xs={6}>
  350. <Controller
  351. control={control}
  352. name="expiryDate"
  353. // rules={{ required: !Boolean(productionDate) }}
  354. render={({ field }) => {
  355. return (
  356. <LocalizationProvider
  357. dateAdapter={AdapterDayjs}
  358. adapterLocale={`${language}-hk`}
  359. >
  360. <DatePicker
  361. {...field}
  362. sx={textfieldSx}
  363. label={t("expiryDate")}
  364. value={expiryDate ? dayjs(expiryDate) : undefined}
  365. format={OUTPUT_DATE_FORMAT}
  366. disabled={disabled}
  367. onChange={(date) => {
  368. if (!date) return;
  369. console.log(date.format(INPUT_DATE_FORMAT));
  370. setValue("expiryDate", date.format(INPUT_DATE_FORMAT));
  371. }}
  372. inputRef={field.ref}
  373. open={openExpDatePicker && !openModal}
  374. onOpen={() => setOpenExpDatePicker(true)}
  375. onClose={() => setOpenExpDatePicker(false)}
  376. slotProps={{
  377. textField: {
  378. InputProps: {
  379. ...(!disabled && {
  380. endAdornment: (
  381. <InputAdornment position='end'>
  382. <Button
  383. type="button"
  384. variant="contained"
  385. color="primary"
  386. sx={{ fontSize: '24px' }}
  387. onClick={handleOpenModal}
  388. >
  389. {t("Calculate Expiry Date")}
  390. </Button>
  391. </InputAdornment>
  392. ),
  393. })
  394. },
  395. error: Boolean(errors.expiryDate?.message),
  396. helperText: errors.expiryDate?.message,
  397. onClick: () => setOpenExpDatePicker(true),
  398. },
  399. }}
  400. />
  401. </LocalizationProvider>
  402. );
  403. }}
  404. />
  405. </Grid>
  406. {/* <Grid item xs={6}>
  407. {putawayMode ? (
  408. <TextField
  409. label={t("acceptedQty")}
  410. fullWidth
  411. sx={textfieldSx}
  412. disabled={true}
  413. value={itemDetail.acceptedQty}
  414. // disabled={true}
  415. // disabled={disabled}
  416. // error={Boolean(errors.acceptedQty)}
  417. // helperText={errors.acceptedQty?.message}
  418. />
  419. ) : (
  420. <TextField
  421. label={t("receivedQty")}
  422. fullWidth
  423. {...register("receivedQty", {
  424. required: "receivedQty required!",
  425. })}
  426. sx={textfieldSx}
  427. disabled={true}
  428. />
  429. )}
  430. </Grid> */}
  431. <Grid item xs={6}>
  432. <TextField
  433. label={t("salesUnit")}
  434. fullWidth
  435. {...register("uom.udfudesc", {
  436. required: "uom required!",
  437. })}
  438. // value={uom?.code}
  439. sx={textfieldSx}
  440. disabled={true}
  441. />
  442. </Grid>
  443. {putawayMode ? (<>
  444. <Grid item xs={3}>
  445. <TextField
  446. label={t("processedQty")}
  447. fullWidth
  448. sx={textfieldSx}
  449. disabled={true}
  450. value={itemDetail.putAwayLines?.reduce((sum, p) => sum + p.qty, 0) ?? 0}
  451. />
  452. </Grid>
  453. <Grid item xs={3}>
  454. <TextField
  455. label={t("acceptedQty")}
  456. fullWidth
  457. sx={textfieldSx}
  458. disabled={true}
  459. {...register("acceptedQty", {
  460. required: "acceptedQty required!",
  461. })}
  462. />
  463. </Grid></>
  464. ) : (
  465. <Grid item xs={6}>
  466. <TextField
  467. label={t("acceptedQty")}
  468. fullWidth
  469. sx={textfieldSx}
  470. disabled={true}
  471. {...register("acceptedQty", {
  472. required: "acceptedQty required!",
  473. })}
  474. />
  475. </Grid>
  476. )}
  477. {/* <Grid item xs={4}>
  478. <TextField
  479. label={t("acceptedWeight")}
  480. fullWidth
  481. // {...register("acceptedWeight", {
  482. // required: "acceptedWeight required!",
  483. // })}
  484. disabled={disabled}
  485. error={Boolean(errors.acceptedWeight)}
  486. helperText={errors.acceptedWeight?.message}
  487. />
  488. </Grid> */}
  489. </Grid>
  490. <Grid
  491. container
  492. justifyContent="flex-start"
  493. alignItems="flex-start"
  494. spacing={2}
  495. sx={{ mt: 0.5 }}
  496. >
  497. {/* <Grid item xs={12}>
  498. <InputDataGrid<PurchaseQCInput, PurchaseQcResult, EntryError>
  499. apiRef={apiRef}
  500. checkboxSelection={false}
  501. _formKey={"qcCheck"}
  502. columns={columns}
  503. validateRow={validationTest}
  504. />
  505. </Grid> */}
  506. </Grid>
  507. </Grid>
  508. <CalculateExpiryDateModal
  509. open={openModal}
  510. onClose={handleOnModalClose}
  511. onSubmit={handleReturnExpiryDate}
  512. textfieldSx={textfieldSx}
  513. />
  514. </>
  515. );
  516. };
  517. export default FgStockInForm;