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.
 
 

181 lines
6.6 KiB

  1. "use client"
  2. import { JoDetail } from "@/app/api/jo"
  3. import { useRouter } from "next/navigation";
  4. import { useTranslation } from "react-i18next";
  5. import useUploadContext from "../UploadProvider/useUploadContext";
  6. import { FormProvider, SubmitErrorHandler, SubmitHandler, useForm } from "react-hook-form";
  7. import React, { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react";
  8. import { Button, Stack, Typography } from "@mui/material";
  9. import StartIcon from "@mui/icons-material/Start";
  10. import ArrowBackIcon from '@mui/icons-material/ArrowBack';
  11. import { releaseJo } from "@/app/api/jo/actions";
  12. import InfoCard from "./InfoCard";
  13. import PickTable from "./PickTable";
  14. import ActionButtons from "./ActionButtons";
  15. import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider";
  16. import { fetchStockInLineInfo } from "@/app/api/po/actions";
  17. type Props = {
  18. id?: number;
  19. defaultValues: Partial<JoDetail> | undefined;
  20. }
  21. const JoSave: React.FC<Props> = ({
  22. defaultValues,
  23. id,
  24. }) => {
  25. const { t } = useTranslation("jo")
  26. const router = useRouter();
  27. const { setIsUploading } = useUploadContext();
  28. const scanner = useQrCodeScannerContext()
  29. const [serverError, setServerError] = useState("");
  30. const finalDefaultValues = useMemo(() => {
  31. const values = {
  32. ...defaultValues,
  33. pickLines: defaultValues?.pickLines?.map(line => ({
  34. ...line,
  35. pickedLotNo: Array.isArray(line.pickedLotNo)
  36. ? line.pickedLotNo.map(lot => ({
  37. ...lot,
  38. isScanned: false
  39. }))
  40. : line.pickedLotNo
  41. }))
  42. }
  43. return values;
  44. }, [defaultValues])
  45. const formProps = useForm<JoDetail>({
  46. defaultValues: finalDefaultValues
  47. })
  48. const pickLines = useMemo(() => {
  49. return formProps.watch("pickLines")
  50. }, [formProps.watch("pickLines")])
  51. // --------------------------------------------- Qr Code Scan --------------------------------------------- //
  52. const needScan = useMemo(() => {
  53. return pickLines.some((line) => line.status === "pending")
  54. }, [pickLines.some((line) => line.status === "pending")])
  55. useLayoutEffect(() => {
  56. if (needScan && !scanner.isScanning) {
  57. scanner.startScan();
  58. } else if (!needScan) {
  59. scanner.stopScan();
  60. }
  61. }, [needScan])
  62. const checkScannedId = useCallback(async (stockInLineId: number | undefined) => {
  63. try {
  64. setIsUploading(true)
  65. if (stockInLineId) {
  66. const response = await fetchStockInLineInfo(stockInLineId);
  67. // const pickLines = formProps.watch("pickLines")
  68. const pickedLotNoIndex = pickLines.findIndex((line) => line.pickedLotNo?.some((pln) => pln.lotNo === response?.lotNo))
  69. if (pickedLotNoIndex >= 0) {
  70. const updatedPickLines = [...pickLines]
  71. const matchedLotNoIndex = updatedPickLines[pickedLotNoIndex].pickedLotNo?.findIndex((line) => line?.lotNo === response?.lotNo && Boolean(line?.isScanned) === false)
  72. if (matchedLotNoIndex !== null && matchedLotNoIndex !== undefined && matchedLotNoIndex >= 0) {
  73. const updatedPickedLotNo = [...(updatedPickLines[pickedLotNoIndex].pickedLotNo || [])]
  74. updatedPickedLotNo[matchedLotNoIndex] = {
  75. ...updatedPickedLotNo[matchedLotNoIndex],
  76. isScanned: true,
  77. }
  78. updatedPickLines[pickedLotNoIndex] = {
  79. ...updatedPickLines[pickedLotNoIndex],
  80. pickedLotNo: updatedPickedLotNo,
  81. };
  82. formProps.setValue("pickLines", updatedPickLines, {
  83. shouldValidate: true,
  84. shouldDirty: true,
  85. });
  86. }
  87. }
  88. }
  89. } finally {
  90. scanner.resetScan()
  91. setIsUploading(false)
  92. }
  93. }, [])
  94. useEffect(() => {
  95. const result = scanner.result
  96. console.log(scanner.result)
  97. if (result?.value) {
  98. if (!isNaN(Number(result.value))) { checkScannedId(Number(result?.value)); }
  99. } else if (result?.stockInLineId) {
  100. checkScannedId(result?.stockInLineId)
  101. }
  102. }, [scanner.result])
  103. // --------------------------------------------- Button Actions --------------------------------------------- //
  104. const handleBack = useCallback(() => {
  105. router.replace(`/jo`)
  106. }, [])
  107. const handleRelease = useCallback(async () => {
  108. try {
  109. setIsUploading(true)
  110. if (id) {
  111. const response = await releaseJo({ id: id })
  112. if (response) {
  113. formProps.setValue("status", response.entity.status)
  114. }
  115. }
  116. } catch (e) {
  117. // backend error
  118. setServerError(t("An error has occurred. Please try again later."));
  119. console.log(e);
  120. } finally {
  121. setIsUploading(false)
  122. }
  123. }, [])
  124. const handleStart = useCallback(async () => {
  125. console.log("first")
  126. }, [])
  127. // --------------------------------------------- Form Submit --------------------------------------------- //
  128. const onSubmit = useCallback<SubmitHandler<JoDetail>>(async (data, event) => {
  129. console.log(data)
  130. }, [t])
  131. const onSubmitError = useCallback<SubmitErrorHandler<JoDetail>>((errors) => {
  132. console.log(errors)
  133. }, [t])
  134. return <>
  135. <FormProvider {...formProps}>
  136. <Stack
  137. spacing={2}
  138. component="form"
  139. onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
  140. >
  141. {serverError && (
  142. <Typography variant="body2" color="error" alignSelf="flex-end">
  143. {serverError}
  144. </Typography>
  145. )}
  146. <ActionButtons handleRelease={handleRelease} handleStart={handleStart}/>
  147. <InfoCard />
  148. <PickTable />
  149. <Stack direction="row" justifyContent="flex-end" gap={1}>
  150. <Button
  151. variant="outlined"
  152. startIcon={<ArrowBackIcon />}
  153. onClick={handleBack}
  154. >
  155. {t("Back")}
  156. </Button>
  157. </Stack>
  158. </Stack>
  159. </FormProvider>
  160. </>
  161. }
  162. export default JoSave;