FPSMS-frontend
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

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