FPSMS-frontend
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 

311 рядки
8.9 KiB

  1. "use client";
  2. import { PurchaseQcResult, PurchaseQCInput } from "@/app/api/po/actions";
  3. import {
  4. Box,
  5. Card,
  6. CardContent,
  7. Grid,
  8. Stack,
  9. TextField,
  10. Tooltip,
  11. Typography,
  12. } from "@mui/material";
  13. import { useFormContext } from "react-hook-form";
  14. import { useTranslation } from "react-i18next";
  15. import StyledDataGrid from "../StyledDataGrid";
  16. import { useCallback, useEffect, useMemo, useState } from "react";
  17. import {
  18. GridColDef,
  19. GridRowIdGetter,
  20. GridRowModel,
  21. useGridApiContext,
  22. GridRenderCellParams,
  23. GridRenderEditCellParams,
  24. useGridApiRef,
  25. } from "@mui/x-data-grid";
  26. import InputDataGrid from "../InputDataGrid";
  27. import { TableRow } from "../InputDataGrid/InputDataGrid";
  28. import TwoLineCell from "./TwoLineCell";
  29. import QcSelect from "./QcSelect";
  30. import { GridEditInputCell } from "@mui/x-data-grid";
  31. import { StockInLine } from "@/app/api/po";
  32. import { stockInLineStatusMap } from "@/app/utils/formatUtil";
  33. import { fetchQcItemCheck, fetchQcResult } from "@/app/api/qc/actions";
  34. import { QcItemWithChecks } from "@/app/api/qc";
  35. import axios from "@/app/(main)/axios/axiosInstance";
  36. import { NEXT_PUBLIC_API_URL } from "@/config/api";
  37. import axiosInstance from "@/app/(main)/axios/axiosInstance";
  38. interface Props {
  39. itemDetail: StockInLine;
  40. qc: QcItemWithChecks[];
  41. }
  42. type EntryError =
  43. | {
  44. [field in keyof PurchaseQcResult]?: string;
  45. }
  46. | undefined;
  47. type PoQcRow = TableRow<Partial<PurchaseQcResult>, EntryError>;
  48. // fetchQcItemCheck
  49. const QcForm: React.FC<Props> = ({ qc, itemDetail }) => {
  50. const { t } = useTranslation();
  51. const apiRef = useGridApiRef();
  52. const {
  53. register,
  54. formState: { errors, defaultValues, touchedFields },
  55. watch,
  56. control,
  57. setValue,
  58. getValues,
  59. reset,
  60. resetField,
  61. setError,
  62. clearErrors,
  63. } = useFormContext<PurchaseQCInput>();
  64. console.log(itemDetail);
  65. console.log(defaultValues);
  66. //// validate form
  67. const accQty = watch("acceptedQty");
  68. const validateForm = useCallback(() => {
  69. console.log(accQty);
  70. if (accQty > itemDetail.acceptedQty) {
  71. setError("acceptedQty", {
  72. message: `acceptedQty must not greater than ${itemDetail.acceptedQty}`,
  73. type: "required",
  74. });
  75. }
  76. if (accQty < 1) {
  77. setError("acceptedQty", {
  78. message: `minimal value is 1`,
  79. type: "required",
  80. });
  81. }
  82. if (isNaN(accQty)) {
  83. setError("acceptedQty", {
  84. message: `value must be a number`,
  85. type: "required",
  86. });
  87. }
  88. }, [accQty]);
  89. useEffect(() => {
  90. clearErrors();
  91. validateForm();
  92. }, [validateForm]);
  93. // const [recordQty, setRecordQty] = useState(0);
  94. const columns = useMemo<GridColDef[]>(
  95. () => [
  96. {
  97. field: "qcItemId",
  98. headerName: "qc Check",
  99. flex: 1,
  100. editable: true,
  101. valueFormatter(params) {
  102. const row = params.id ? params.api.getRow<PoQcRow>(params.id) : null;
  103. if (!row) {
  104. return null;
  105. }
  106. const Qc = qc.find((q) => q.id === row.qcItemId);
  107. return Qc ? `${Qc.code} - ${Qc.name}` : t("Please select QC");
  108. },
  109. renderCell(params: GridRenderCellParams<PoQcRow, number>) {
  110. console.log(params.value);
  111. return <TwoLineCell>{params.formattedValue}</TwoLineCell>;
  112. },
  113. renderEditCell(params: GridRenderEditCellParams<PoQcRow, number>) {
  114. const errorMessage =
  115. params.row._error?.[params.field as keyof PurchaseQcResult];
  116. console.log(errorMessage);
  117. const content = (
  118. <QcSelect
  119. allQcs={qc}
  120. value={params.row.qcItemId}
  121. onQcSelect={async (qcItemId) => {
  122. await params.api.setEditCellValue({
  123. id: params.id,
  124. field: "qcItemId",
  125. value: qcItemId,
  126. });
  127. // await params.api.setEditCellValue({
  128. // id: params.id,
  129. // field: "type",
  130. // value: "determine1",
  131. // });
  132. }}
  133. />
  134. );
  135. return errorMessage ? (
  136. <Tooltip title={t(errorMessage)}>
  137. <Box width="100%">{content}</Box>
  138. </Tooltip>
  139. ) : (
  140. content
  141. );
  142. },
  143. },
  144. {
  145. field: "failQty",
  146. headerName: "failQty",
  147. flex: 1,
  148. editable: true,
  149. type: "number",
  150. renderEditCell(params: GridRenderEditCellParams<PoQcRow>) {
  151. // const recordQty = params.row.qty
  152. // if (recordQty !== undefined) {
  153. // setUnrecordQty((prev) => prev - recordQty)
  154. // }
  155. const errorMessage =
  156. params.row._error?.[params.field as keyof PurchaseQcResult];
  157. const content = <GridEditInputCell {...params} />;
  158. return errorMessage ? (
  159. <Tooltip title={t(errorMessage)}>
  160. <Box width="100%">{content}</Box>
  161. </Tooltip>
  162. ) : (
  163. content
  164. );
  165. },
  166. },
  167. ],
  168. [qc]
  169. );
  170. /// validate datagrid
  171. const validation = useCallback(
  172. (newRow: GridRowModel<PoQcRow>): EntryError => {
  173. const error: EntryError = {};
  174. const { qcItemId, failQty } = newRow;
  175. if (!qcItemId || qcItemId <= 0) {
  176. error["qcItemId"] = "select qc";
  177. }
  178. if (!failQty || failQty <= 0) {
  179. error["failQty"] = "enter a failQty";
  180. }
  181. if (failQty && failQty > itemDetail.acceptedQty) {
  182. error["failQty"] = "qty too big";
  183. }
  184. return Object.keys(error).length > 0 ? error : undefined;
  185. },
  186. []
  187. );
  188. useEffect(() => {
  189. console.log(itemDetail);
  190. var status = "receiving";
  191. // switch (itemDetail.status) {
  192. // case 'pending':
  193. // status = "receiving"
  194. // break;
  195. // }
  196. setValue("status", status);
  197. }, [itemDetail]);
  198. return (
  199. <Grid container justifyContent="flex-start" alignItems="flex-start">
  200. <Grid item xs={12}>
  201. <Typography variant="h6" display="block" marginBlockEnd={1}>
  202. {t("Qc Detail")}
  203. </Typography>
  204. </Grid>
  205. <Grid
  206. container
  207. justifyContent="flex-start"
  208. alignItems="flex-start"
  209. spacing={2}
  210. sx={{ mt: 0.5 }}
  211. >
  212. <Grid item xs={12} lg={12}>
  213. <TextField
  214. label={t("accepted Qty")}
  215. fullWidth
  216. // value={itemDetail.acceptedQty}
  217. {...register("acceptedQty", {
  218. required: "acceptedQty required!",
  219. valueAsNumber: true,
  220. max: itemDetail.acceptedQty,
  221. })}
  222. // disabled
  223. error={Boolean(errors.acceptedQty)}
  224. helperText={errors.acceptedQty?.message}
  225. />
  226. </Grid>
  227. {/* <Grid item xs={12} lg={6}>
  228. <TextField
  229. label={t("Total record qty")}
  230. fullWidth
  231. value={recordQty}
  232. disabled
  233. // {...register("sampleRate", {
  234. // required: "sampleRate required!",
  235. // })}
  236. // error={Boolean(errors.sampleRate)}
  237. // helperText={errors.sampleRate?.message}
  238. />
  239. </Grid> */}
  240. <Grid item xs={12} lg={6}>
  241. <TextField
  242. label={t("sampleRate")}
  243. fullWidth
  244. defaultValue={1}
  245. {...register("sampleRate", {
  246. required: "sampleRate required!",
  247. valueAsNumber: true,
  248. })}
  249. error={Boolean(errors.sampleRate)}
  250. helperText={errors.sampleRate?.message}
  251. />
  252. </Grid>
  253. <Grid item xs={12} lg={6}>
  254. <TextField
  255. label={t("sampleWeight")}
  256. fullWidth
  257. defaultValue={1}
  258. {...register("sampleWeight", {
  259. required: "sampleWeight required!",
  260. valueAsNumber: true,
  261. })}
  262. error={Boolean(errors.sampleWeight)}
  263. helperText={errors.sampleWeight?.message}
  264. />
  265. </Grid>
  266. <Grid item xs={12} lg={6}>
  267. <TextField
  268. label={t("totalWeight")}
  269. fullWidth
  270. defaultValue={1}
  271. {...register("totalWeight", {
  272. required: "totalWeight required!",
  273. valueAsNumber: true,
  274. })}
  275. error={Boolean(errors.totalWeight)}
  276. helperText={errors.totalWeight?.message}
  277. />
  278. </Grid>
  279. </Grid>
  280. <Grid
  281. container
  282. justifyContent="flex-start"
  283. alignItems="flex-start"
  284. spacing={2}
  285. sx={{ mt: 0.5 }}
  286. >
  287. <Grid item xs={12}>
  288. <InputDataGrid<PurchaseQCInput, PurchaseQcResult, EntryError>
  289. apiRef={apiRef}
  290. checkboxSelection={false}
  291. _formKey={"qcResult"}
  292. columns={columns}
  293. validateRow={validation}
  294. needAdd={
  295. itemDetail.status === "qc" || itemDetail.status === "pending"
  296. }
  297. />
  298. </Grid>
  299. </Grid>
  300. </Grid>
  301. );
  302. };
  303. export default QcForm;