FPSMS-frontend
Não pode escolher mais do que 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.
 
 

260 linhas
8.4 KiB

  1. "use client";
  2. import {
  3. Box, Card, CardContent, Checkbox, Collapse, FormControl,
  4. FormControlLabel, Grid, Radio, RadioGroup, Stack, Tab,
  5. Tabs, TabsProps, TextField, Tooltip, Typography,
  6. } from "@mui/material";
  7. import { useFormContext, Controller, FieldPath } from "react-hook-form";
  8. import { useTranslation } from "react-i18next";
  9. import StyledDataGrid from "../StyledDataGrid";
  10. import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from "react";
  11. import {
  12. GridColDef,
  13. useGridApiContext,
  14. GridRenderEditCellParams,
  15. useGridApiRef,
  16. } from "@mui/x-data-grid";
  17. import { QcFormInput, QcResult } from "@/app/api/qc";
  18. interface Props {
  19. rows: QcResult[];
  20. disabled?: boolean;
  21. /** When true, use smaller typography and inputs to match 來貨詳情 (e.g. in QcStockInModal). */
  22. compactLayout?: boolean;
  23. }
  24. const QcForm: React.FC<Props> = ({ rows, disabled = false, compactLayout = false }) => {
  25. const { t } = useTranslation("purchaseOrder");
  26. const apiRef = useGridApiRef();
  27. const {
  28. register,
  29. formState: { errors, defaultValues, touchedFields },
  30. watch,
  31. control,
  32. setValue,
  33. getValues,
  34. reset,
  35. resetField,
  36. setError,
  37. clearErrors,
  38. } = useFormContext<QcFormInput>();
  39. const qcDisabled = (row : QcResult) => {
  40. return disabled || isExist(row.escalationLogId);
  41. };
  42. const isExist = (data : string | number | undefined) => {
  43. return (data !== null && data !== undefined);
  44. }
  45. function BooleanEditCell(params: GridRenderEditCellParams) {
  46. const apiRef = useGridApiContext();
  47. const { id, field, value } = params;
  48. const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
  49. apiRef.current.setEditCellValue({ id, field, value: e.target.checked });
  50. apiRef.current.stopCellEditMode({ id, field }); // commit immediately
  51. };
  52. return <Checkbox checked={!!value} onChange={handleChange} sx={{ p: 0 }} />;
  53. }
  54. const qcColumns: GridColDef[] = useMemo(() => [
  55. {
  56. field: "name",
  57. headerName: t("qcItem"),
  58. wrapText: true,
  59. flex: 2.5,
  60. renderCell: (params) => {
  61. const index = getRowIndex(params);//params.api.getRowIndexRelativeToVisibleRows(params.id);
  62. return (
  63. <Box
  64. sx={{
  65. lineHeight: 1.5,
  66. padding: "4px",
  67. fontSize: compactLayout ? 14 : 18,
  68. }}
  69. >
  70. <b>{`${params.row.order ?? "N/A"}. ${params.value}`}</b><br/>
  71. {params.row.description}
  72. </Box>
  73. )},
  74. },
  75. {
  76. field: 'qcResult',
  77. headerName: t("qcResult"),
  78. flex: 1,
  79. renderCell: (params) => {
  80. const rowValue = params.row;
  81. const index = getRowIndex(params);//params.api.getRowIndexRelativeToVisibleRows(params.row.id);
  82. // const index = Number(params.id);
  83. // const index = Number(params.row.order - 1);
  84. // console.log(rowValue.row);
  85. return (
  86. <FormControl>
  87. <RadioGroup
  88. row
  89. aria-labelledby="demo-radio-buttons-group-label"
  90. // defaultValue={""}
  91. value={rowValue.qcPassed === undefined ? "" : (rowValue.qcPassed ? "true" : "false")}
  92. onChange={(e) => {
  93. const value = (e.target.value === "true");
  94. // setQcItems((prev) =>
  95. // prev.map((r): QcData => (r.id === params.id ? { ...r, qcPassed: value === "true" } : r))
  96. // );
  97. setValue(`qcResult.${index}.qcPassed`, value);
  98. }}
  99. name={`qcPassed-${params.id}`}
  100. >
  101. <FormControlLabel
  102. value="true"
  103. control={<Radio />}
  104. label="合格"
  105. disabled={qcDisabled(rowValue)}
  106. sx={{
  107. color: rowValue.qcPassed === true ? "green" : "inherit",
  108. "& .Mui-checked": {color: "green"}
  109. }}
  110. />
  111. <FormControlLabel
  112. value="false"
  113. control={<Radio />}
  114. label="不合格"
  115. disabled={qcDisabled(rowValue)}
  116. sx={{
  117. color: rowValue.qcPassed === false ? "red" : "inherit",
  118. "& .Mui-checked": {color: "red"}
  119. }}
  120. />
  121. </RadioGroup>
  122. </FormControl>
  123. );
  124. },
  125. },
  126. {
  127. field: "failQty",
  128. headerName: t("failedQty"),
  129. flex: 0.8,
  130. // editable: true,
  131. renderCell: (params) => {
  132. const index = getRowIndex(params);//params.api.getRowIndexRelativeToVisibleRows(params.id);
  133. // const index = Number(params.id);
  134. return (
  135. <TextField
  136. type="number"
  137. value={!params.row.qcPassed? params.value : '0'}
  138. disabled={params.row.qcPassed || qcDisabled(params.row)}
  139. /* TODO improve */
  140. /* Reference: https://grok.com/share/c2hhcmQtNA%3D%3D_10787069-3eec-40af-a7cc-bacbdb86bf05 */
  141. onChange={(e) => {
  142. const v = e.target.value;
  143. const next = v === '' ? undefined : Number(v);
  144. if (Number.isNaN(next)) return;
  145. setValue(`qcResult.${index}.failQty`, next);
  146. }}
  147. // onBlur={(e) => {
  148. // const v = e.target.value;
  149. // const next = v === '' ? undefined : Number(v);
  150. // if (Number.isNaN(next)) return;
  151. // setValue(`qcResult.${index}.failQty`, next);
  152. // }}
  153. onClick={(e) => e.stopPropagation()}
  154. onMouseDown={(e) => e.stopPropagation()}
  155. onKeyDown={(e) => e.stopPropagation()}
  156. inputProps={{ min: 0 }}
  157. size={compactLayout ? "small" : "medium"}
  158. sx={{ width: '100%',
  159. "& .MuiInputBase-input": compactLayout ? undefined : {
  160. padding: "0.75rem",
  161. fontSize: 24,
  162. },
  163. }}
  164. />
  165. );
  166. },
  167. },
  168. {
  169. field: "remarks",
  170. headerName: t("remarks"),
  171. flex: 1.7,
  172. renderCell: (params) => {
  173. // const index = Number(params.id);//params.api.getRowIndexRelativeToVisibleRows(params.id);
  174. const index = getRowIndex(params);//params.api.getRowIndexRelativeToVisibleRows(params.id);
  175. return (
  176. <TextField
  177. size="small"
  178. defaultValue={params.value}
  179. disabled={qcDisabled(params.row)}
  180. onBlur={(e) => {
  181. const value = e.target.value;
  182. setValue(`qcResult.${index}.remarks`, value);
  183. }}
  184. // onChange={(e) => {
  185. // const remarks = e.target.value;
  186. // // const next = v === '' ? undefined : Number(v);
  187. // // if (Number.isNaN(next)) return;
  188. // // setQcItems((prev) =>
  189. // // prev.map((r) => (r.id === params.id ? { ...r, remarks: remarks } : r))
  190. // // );
  191. // }}
  192. // {...register(`qcResult.${index}.remarks`, {
  193. // required: "remarks required!",
  194. // })}
  195. onClick={(e) => e.stopPropagation()}
  196. onMouseDown={(e) => e.stopPropagation()}
  197. onKeyDown={(e) => e.stopPropagation()}
  198. sx={{ width: '100%',
  199. "& .MuiInputBase-input": compactLayout ? undefined : {
  200. padding: "0.75rem",
  201. fontSize: 24,
  202. },
  203. }}
  204. />
  205. );
  206. },
  207. },
  208. ], [compactLayout, t, setValue, qcDisabled])
  209. // const getRowId = (row :any) => {
  210. // return qcRecord.findIndex(qc => qc == row);
  211. // // return row.id || `${row.name}-${Math.random().toString(36).substr(2, 9)}`;
  212. // };
  213. const getRowHeight = (row :any) => { // Not used?
  214. console.log("row", row);
  215. if (!row.model.name) {
  216. return (row.model.name.length ?? 10) * 1.2 + 30;
  217. } else { return 60}
  218. };
  219. const getRowIndex = (params: any) => {
  220. return params.api.getRowIndexRelativeToVisibleRows(params.id);
  221. // return params.row.id;
  222. }
  223. return (
  224. <>
  225. <StyledDataGrid
  226. columns={qcColumns}
  227. rows={rows}
  228. sortModel={[]}
  229. getRowHeight={() => 'auto'}
  230. initialState={{
  231. pagination: { paginationModel: { page: 0, pageSize: 100 } },
  232. }}
  233. pageSizeOptions={[100]}
  234. slotProps={{
  235. pagination: {
  236. sx: {
  237. display: "none",
  238. },
  239. },
  240. }}
  241. />
  242. </>
  243. );
  244. };
  245. export default QcForm;