FPSMS-frontend
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 

645 wiersze
24 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. GridRowIdGetter,
  14. GridRowModel,
  15. useGridApiContext,
  16. GridRenderCellParams,
  17. GridRenderEditCellParams,
  18. useGridApiRef,
  19. GridRowSelectionModel,
  20. } from "@mui/x-data-grid";
  21. import InputDataGrid from "../InputDataGrid";
  22. import { TableRow } from "../InputDataGrid/InputDataGrid";
  23. import TwoLineCell from "../PoDetail/TwoLineCell";
  24. import QcSelect from "../PoDetail/QcSelect";
  25. import { GridEditInputCell } from "@mui/x-data-grid";
  26. import { ModalFormInput, StockInLine } from "@/app/api/stockIn";
  27. import { fetchQcCategory, fetchQcResult } from "@/app/api/qc/actions";
  28. import { QcCategory, QcData, QcInput, QcFormInput, QcResult } from "@/app/api/qc";
  29. import axios from "@/app/(main)/axios/axiosInstance";
  30. import { NEXT_PUBLIC_API_URL } from "@/config/api";
  31. import axiosInstance from "@/app/(main)/axios/axiosInstance";
  32. import EscalationComponent from "../PoDetail/EscalationComponent";
  33. import QcDataGrid from "../PoDetail/QCDatagrid";
  34. import { dummyEscalationHistory,
  35. dummyQcData_A1, dummyQcData_E1, dummyQcData_E2,
  36. dummyQcHeader_A1, dummyQcHeader_E1, dummyQcHeader_E2 } from "./dummyQcTemplate";
  37. import { escape, isNull, min, template } from "lodash";
  38. import { PanoramaSharp } from "@mui/icons-material";
  39. import EscalationLogTable from "../DashboardPage/escalation/EscalationLogTable";
  40. import { EscalationResult } from "@/app/api/escalation";
  41. import { EscalationCombo } from "@/app/api/user";
  42. import { fetchEscalationLogsByStockInLines } from "@/app/api/escalation/actions";
  43. import CollapsibleCard from "../CollapsibleCard/CollapsibleCard";
  44. import LoadingComponent from "../General/LoadingComponent";
  45. import QcForm from "./QcForm";
  46. interface Props {
  47. itemDetail: QcInput;
  48. // itemDetail: StockInLine & { qcResult?: PurchaseQcResult[] } & { escResult?: EscalationResult[] };
  49. // qc: QcItemWithChecks[];
  50. disabled: boolean;
  51. // qcItems: QcData[]
  52. // setQcItems: Dispatch<SetStateAction<QcData[]>>
  53. }
  54. type EntryError =
  55. | {
  56. [field in keyof QcData]?: string;
  57. }
  58. | undefined;
  59. type QcRow = TableRow<Partial<QcResult>, EntryError>;
  60. // fetchQcItemCheck
  61. const QcComponent: React.FC<Props> = ({ itemDetail, disabled = false }) => {
  62. const { t } = useTranslation("purchaseOrder");
  63. const apiRef = useGridApiRef();
  64. const {
  65. register,
  66. formState: { errors, defaultValues, touchedFields },
  67. watch,
  68. control,
  69. setValue,
  70. getValues,
  71. reset,
  72. resetField,
  73. setError,
  74. clearErrors,
  75. } = useFormContext<QcFormInput>();
  76. const [tabIndex, setTabIndex] = useState(0);
  77. const [rowSelectionModel, setRowSelectionModel] = useState<GridRowSelectionModel>();
  78. const [escalationHistory, setEscalationHistory] = useState(dummyEscalationHistory);
  79. const qcAccept = watch("qcAccept");
  80. const qcDecision = watch("qcDecision"); //WIP
  81. // const qcResult = useMemo(() => [...watch("qcResult")], [watch("qcResult")]);
  82. const [qcCategory, setQcCategory] = useState<QcCategory>();
  83. const qcRecord = useMemo(() => { // Need testing
  84. const value = watch('qcResult'); //console.log("%c QC update!", "color:green", value);
  85. return Array.isArray(value) ? [...value] : [];
  86. }, [watch('qcResult')]);
  87. const [qcHistory, setQcHistory] = useState<QcResult[]>([]);
  88. const [qcResult, setQcResult] = useState<QcResult[]>([]);
  89. const [escResult, setEscResult] = useState<EscalationResult[]>([]);
  90. // const [qcAccept, setQcAccept] = useState(true);
  91. // const [qcItems, setQcItems] = useState(dummyQCData)
  92. const qcDisabled = (row : QcResult) => {
  93. return disabled || isExist(row.escalationLogId);
  94. };
  95. const isExist = (data : string | number | undefined) => {
  96. return (data !== null && data !== undefined);
  97. }
  98. const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>(
  99. (_e, newValue) => {
  100. setTabIndex(newValue);
  101. },
  102. [],
  103. );
  104. const qcType = useMemo(() => {
  105. if (itemDetail) {
  106. const d = itemDetail;
  107. if (isExist(d.jobOrderId)) {
  108. return "EPQC";
  109. }
  110. }
  111. return "IQC"; // Default
  112. }, [itemDetail]);
  113. const detailMode = useMemo(() => {
  114. const isDetailMode = itemDetail.status == "escalated" || isExist(itemDetail.jobOrderId);
  115. return isDetailMode;
  116. }, [itemDetail]);
  117. // W I P //
  118. const validateFieldFail = (field : FieldPath<QcFormInput>, condition: boolean, message: string) : boolean => {
  119. // console.log("Checking if " + message)
  120. if (condition) { setError(field, { message: message}); return false; }
  121. else { clearErrors(field); return true; }
  122. }
  123. //// validate form
  124. const accQty = watch("acceptQty");
  125. const validateForm = useCallback(() => {
  126. if (qcDecision == 1) {
  127. if (isNaN(accQty) || accQty === undefined || accQty === null || typeof(accQty) != "number") {
  128. setError("acceptQty", { message: t("value must be a number") });
  129. } else
  130. if (!Number.isInteger(accQty)) {
  131. setError("acceptQty", { message: t("value must be integer") });
  132. }
  133. if (accQty > itemDetail.acceptedQty) {
  134. setError("acceptQty", { message: `${t("acceptQty must not greater than")} ${
  135. itemDetail.acceptedQty}` });
  136. } else
  137. if (accQty < 1) {
  138. setError("acceptQty", { message: t("minimal value is 1") });
  139. } else
  140. console.log("%c Validated accQty:", "color:yellow", accQty);
  141. }
  142. },[setError, qcDecision, accQty, itemDetail])
  143. useEffect(() => { // W I P // -----
  144. if (qcDecision == 1) {
  145. if (validateFieldFail("acceptQty", accQty > itemDetail.acceptedQty, `${t("acceptQty must not greater than")} ${
  146. itemDetail.acceptedQty}`)) return;
  147. if (validateFieldFail("acceptQty", accQty < 1, t("minimal value is 1"))) return;
  148. if (validateFieldFail("acceptQty", isNaN(accQty), t("value must be a number"))) return;
  149. }
  150. const qcResultItems = qcResult; //console.log("Validating:", qcResultItems);
  151. // Check if failed items have failed quantity
  152. const failedItemsWithoutQty = qcResultItems.filter(item =>
  153. item.qcPassed === false && (!item.failQty || item.failQty <= 0)
  154. );
  155. if (validateFieldFail("qcResult", failedItemsWithoutQty.length > 0, `${t("Failed items must have failed quantity")}`)) return;
  156. // Check if all QC items have results
  157. const itemsWithoutResult = qcResultItems.filter(item => item.qcPassed === undefined);
  158. if (validateFieldFail("qcDecision", (itemsWithoutResult.length > 0 && itemDetail.status != "escalated"),
  159. `${t("QC items without result")}`)) return;
  160. if (validateFieldFail("qcDecision", (!qcResultItems.every((qc) => qc.qcPassed) && qcDecision == 1 && itemDetail.status != "escalated"),
  161. "有不合格檢查項目,無法收貨!")) return; // TODO: Fix it please
  162. // submitDialogWithWarning(() => postStockInLineWithQc(qcData), t, {title:"有不合格檢查項目,確認接受收貨?",
  163. // confirmButtonText: t("confirm putaway"), html: ""});
  164. // return;
  165. // console.log("Validated without errors");
  166. }, [accQty, qcDecision, watch("qcResult")]);
  167. useEffect(() => {
  168. clearErrors();
  169. validateForm();
  170. }, [clearErrors, validateForm]);
  171. /// validate datagrid
  172. const validation = useCallback(
  173. (newRow: GridRowModel<QcRow>): EntryError => {
  174. const error: EntryError = {};
  175. // const { qcItemId, failQty } = newRow;
  176. return Object.keys(error).length > 0 ? error : undefined;
  177. },
  178. [],
  179. );
  180. // Set initial value for acceptQty
  181. useEffect(() => {
  182. if (itemDetail?.demandQty > 0) { //!== undefined) {
  183. setValue("acceptQty", itemDetail.demandQty); // TODO: THIS NEED TO UPDATE TO NOT USE DEMAND QTY
  184. } else {
  185. setValue("acceptQty", itemDetail?.acceptedQty);
  186. }
  187. }, [itemDetail?.demandQty, itemDetail?.acceptedQty, setValue]);
  188. // Fetch Qc Data
  189. useEffect(() => {
  190. // console.log("%c QC ItemDetail updated:", "color: gold", itemDetail);
  191. if (itemDetail) {
  192. const d = itemDetail;
  193. fetchNewQcData(d);
  194. if (d.status == "pending") {
  195. //
  196. } else {
  197. fetchQcResultData(d);
  198. }
  199. }
  200. }, [itemDetail]);
  201. const fetchNewQcData = useCallback(
  202. async (input: QcInput) => {
  203. try {
  204. const res = await fetchQcCategory(input.itemId, qcType);
  205. if (res.qcItems.length > 0) {
  206. console.log("%c Fetched Qc Template: ", "color:orange", res);
  207. setQcCategory(res);
  208. // setQcResult(res.qcItems);
  209. // setValue("qcResult", res.qcItems);
  210. } else throw("Result is undefined");
  211. } catch (e) {
  212. console.log("%c Error when fetching Qc Template: ", "color:red", e);
  213. alert(t("Missing QC Template, please contact administrator"));
  214. // closeHandler({}, "backdropClick");
  215. }
  216. },[fetchQcCategory, setValue]
  217. );
  218. const fetchQcResultData = useCallback(
  219. async (input: QcInput) => {
  220. try {
  221. const res = await fetchQcResult(input.id); // StockInLineId for now
  222. if (res.length > 0) {
  223. console.log("%c Fetched Qc Result: ", "color:orange", res);
  224. setValue("qcResult", res);
  225. fetchEscalationLogData(input.id);
  226. // } else {setStockInLineInfo((prev) => ({...prev, qcResult: []} as StockInLine));}
  227. } else throw("Result is undefined");
  228. } catch (e) {
  229. console.log("%c Error when fetching Qc Result: ", "color:red", e);
  230. // alert("Something went wrong, please retry");
  231. // closeHandler({}, "backdropClick");
  232. }
  233. },[fetchQcResult, setValue]
  234. );
  235. const fetchEscalationLogData = useCallback(
  236. async (stockInLineId: number) => {
  237. try {
  238. const res = await fetchEscalationLogsByStockInLines([stockInLineId]);
  239. if (res.length > 0) {
  240. console.log("%c Fetched Escalation Log: ", "color:orange", res[0]);
  241. setEscResult(res);
  242. // formProps.setValue("escalationLog", res[0]);
  243. }// else throw("Result is undefined");
  244. } catch (e) {
  245. console.log("%c Error when fetching EscalationLog: ", "color:red", e);
  246. // alert("Something went wrong, please retry");
  247. // closeHandler({}, "backdropClick");
  248. }
  249. },[fetchEscalationLogsByStockInLines]
  250. );
  251. // Set QC Data
  252. useEffect(() => {
  253. if (itemDetail) {
  254. const d = itemDetail;
  255. if (qcRecord.length < 1) { // No QC Data
  256. if (d.status == "pending") { // New QC
  257. if (qcCategory) {
  258. if (qcCategory.qcItems.length > 0) {
  259. const filledQcItems = fillQcResult(qcCategory.qcItems);
  260. setValue("qcResult", filledQcItems);
  261. console.log("%c New QC Record applied:", "color:green", filledQcItems);
  262. }
  263. }
  264. } else {
  265. console.log("%c No QC Record loaded:", "color:green");
  266. //
  267. }
  268. } else { // QC Result fetched
  269. if (qcRecord.some(qc => qc.order !== undefined)) { // If QC Result is filled with order
  270. if (d.status == "escalated") { // Copy the previous QC data for editing
  271. // If no editable Qc Data
  272. if (!qcRecord.some((qc) => !isExist(qc.escalationLogId))) {
  273. const mutableQcData = qcRecord.map(qc => ({ ...qc, escalationLogId: undefined }));
  274. const copiedQcData = [...mutableQcData, ...qcRecord];
  275. setValue("qcResult", copiedQcData);
  276. console.log("%c QC Record copied:", "color:green", copiedQcData);
  277. return;
  278. }
  279. }
  280. // Set QC Result
  281. // const filteredQcResult = qcRecord;
  282. const filteredQcResult = qcRecord.filter((qc) => !isExist(qc.escalationLogId));
  283. console.log("%c QC Result loaded:", "color:green", filteredQcResult);
  284. setQcResult(filteredQcResult);
  285. // Set QC History
  286. if (filteredQcResult.length < qcRecord.length) { // If there are Qc History
  287. if (qcHistory.length < 1) {
  288. const filteredQcHistory = qcRecord.filter((qc) => isExist(qc.escalationLogId));
  289. console.log("%c QC History loaded:", "color:green", filteredQcHistory);
  290. setQcHistory(filteredQcHistory);
  291. }
  292. }
  293. } else {
  294. if (qcCategory) {
  295. const filledQcData = fillQcResult(qcRecord, qcCategory?.qcItems);
  296. console.log("%c QC Result filled:", "color:green", filledQcData);
  297. setValue("qcResult", filledQcData);
  298. }
  299. }
  300. }
  301. }
  302. }, [qcRecord, qcCategory, setValue, itemDetail])
  303. const fillQcResult = (qcResults: QcResult[], qcItems: QcData[] = []) => {
  304. let result = [] as QcResult[];
  305. qcResults.forEach((r, index) => {
  306. const target = qcItems.find((t) => t.qcItemId === r.qcItemId);
  307. const n = { ...target, ...r }; //, id: index };
  308. result.push(n);
  309. });
  310. result.sort((a,b) => a.order! - b.order!);
  311. return result;
  312. };
  313. // const [openCollapse, setOpenCollapse] = useState(false)
  314. const [isCollapsed, setIsCollapsed] = useState<boolean>(true);
  315. const onFailedOpenCollapse = useCallback((qcItems: QcResult[]) => {
  316. const isFailed = qcItems.some((qc) => !qc.qcPassed)
  317. // console.log(isFailed)
  318. if (isFailed) {
  319. setIsCollapsed(true)
  320. } else {
  321. setIsCollapsed(false)
  322. }
  323. }, [])
  324. // const handleRadioChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
  325. // const value = event.target.value === 'true';
  326. // setValue("qcAccept", value);
  327. // }, [setValue]);
  328. const setDefaultQcDecision = (status : string | undefined) => {
  329. const param = status?.toLowerCase();
  330. if (param !== undefined && param !== null) {
  331. if (param == "received" || param == "completed" || param == "partially_completed") {
  332. return 1;
  333. } else if (param == "rejected") {
  334. return 2;
  335. } else if (param == "escalated") {
  336. return 1; // For new flow
  337. // return 3;
  338. } else { return undefined; }
  339. } else {
  340. return undefined;
  341. }
  342. }
  343. // }, [watch("qcResult")]);
  344. // useEffect(() => {
  345. // // onFailedOpenCollapse(qcItems)
  346. // }, [qcItems]);
  347. const getRowId = (row :any) => {
  348. return qcRecord.findIndex(qc => qc == row);
  349. // return row.id || `${row.name}-${Math.random().toString(36).substr(2, 9)}`;
  350. };
  351. const getRowHeight = (row :any) => { // Not used?
  352. console.log("row", row);
  353. if (!row.model.name) {
  354. return (row.model.name.length ?? 10) * 1.2 + 30;
  355. } else { return 60}
  356. };
  357. const formattedDesc = (content: string = "") => {
  358. return (
  359. <>
  360. {content.split("\\n").map((line, index) => (
  361. <span key={index}> {line} <br/></span>
  362. ))}
  363. </>
  364. );
  365. }
  366. const QcHeader = useMemo(() => () => {
  367. if (qcCategory === undefined || qcCategory === null) {
  368. return (
  369. <Typography variant="h5" component="h2" sx={{ fontWeight: 'bold', color: '#333' }}>
  370. N/A
  371. </Typography>
  372. );
  373. } else
  374. return (
  375. <>
  376. <Box sx={{ mb: 2, p: 2, backgroundColor: '#f5f5f5', borderRadius: 1 }}>
  377. <Typography variant="h5" component="h2" sx={{ fontWeight: 'bold', color: '#333' }}>
  378. {qcCategory?.name} ({qcCategory?.code})
  379. </Typography>
  380. <Typography variant="subtitle1" sx={{ color: '#666' }}>
  381. <b>品檢類型</b>:{qcType}
  382. </Typography>
  383. <Typography variant="subtitle2" sx={{ color: '#666' }}>
  384. {formattedDesc(qcCategory?.description)}
  385. </Typography>
  386. </Box>
  387. </>
  388. );
  389. }, [qcType, qcCategory]);
  390. return (
  391. <>
  392. <Grid container justifyContent="flex-start" alignItems="flex-start">
  393. {(qcRecord.length > 0) ? (
  394. // {(qcRecord.length > 0 && qcCategory) ? (
  395. <Grid
  396. container
  397. justifyContent="flex-start"
  398. alignItems="flex-start"
  399. spacing={2}
  400. sx={{ mt: 0.5 }}
  401. >
  402. <Grid item xs={12}>
  403. <Tabs
  404. value={tabIndex}
  405. onChange={handleTabChange}
  406. variant="scrollable"
  407. >
  408. <Tab label={t("QC Info")} iconPosition="end" />
  409. {(escResult && escResult?.length > 0) &&
  410. (<Tab label={t("Escalation History")} iconPosition="end" />)}
  411. </Tabs>
  412. </Grid>
  413. {tabIndex == 0 && (
  414. <>
  415. <Grid item xs={12}>
  416. <QcHeader/>
  417. {/* <QcDataGrid<ModalFormInput, QcData, EntryError>
  418. apiRef={apiRef}
  419. columns={qcColumns}
  420. _formKey="qcResult"
  421. validateRow={validation}
  422. /> */}
  423. <QcForm
  424. rows={qcResult}
  425. disabled={disabled}
  426. />
  427. </Grid>
  428. </>
  429. )}
  430. {tabIndex == 1 && (
  431. <>
  432. {/* <Grid item xs={12}>
  433. <StockInFormVer2
  434. itemDetail={itemDetail}
  435. disabled={false}
  436. />
  437. </Grid> */}
  438. {/* <Grid item xs={12}>
  439. <Typography variant="h6" display="block" marginBlockEnd={1}>
  440. {t("Escalation Info")}
  441. </Typography>
  442. </Grid> */}
  443. <Grid item xs={12}>
  444. <EscalationLogTable type="qc" items={escResult || []}/>
  445. <CollapsibleCard title={t("QC Record")}>
  446. <QcHeader/>
  447. <QcForm
  448. disabled={disabled}
  449. rows={qcHistory}
  450. />
  451. </CollapsibleCard>
  452. </Grid>
  453. </>
  454. )}
  455. <Grid item xs={12}>
  456. <Card sx={{p:2}}>
  457. <Typography variant="h6" display="block" marginBlockEnd={1}>
  458. {t("Qc Decision")}
  459. </Typography>
  460. <FormControl>
  461. <Controller
  462. name="qcDecision"
  463. // name="qcAccept"
  464. control={control}
  465. defaultValue={setDefaultQcDecision(itemDetail?.status)}
  466. // defaultValue={true}
  467. render={({ field }) => (
  468. <>
  469. {/* <Typography sx={{color:"red"}}>
  470. {errors.qcDecision?.message}
  471. </Typography> */}
  472. <RadioGroup
  473. row
  474. aria-labelledby="demo-radio-buttons-group-label"
  475. {...field}
  476. value={field.value}
  477. // value={field.value?.toString() || "true"}
  478. onChange={(e) => {
  479. const value = e.target.value.toString();// === 'true';
  480. const input = document.getElementById('accQty') as HTMLInputElement; //TODO improve
  481. // console.log("%c AccQty Error", "color:red", errors.acceptQty);
  482. if (input) { // Selected Reject in new flow with Error
  483. if (value == "1") { // Selected Accept
  484. input.value = Number(accQty).toString();
  485. } else {
  486. if (Boolean(errors.acceptQty)) {
  487. setValue("acceptQty", 0);
  488. }
  489. input.value = '0';
  490. }
  491. }
  492. // setValue("acceptQty", itemDetail.acceptedQty ?? 0);
  493. // clearErrors("acceptQty");
  494. // }
  495. field.onChange(value);
  496. }}
  497. >
  498. <FormControlLabel disabled={disabled}
  499. value="1" control={<Radio />} label="接受來貨" />
  500. {(detailMode || (disabled && accQty != itemDetail.acceptedQty && qcDecision == 1)) && ( //TODO Improve
  501. <Box sx={{mr:2}}>
  502. <TextField
  503. // type="number"
  504. id="accQty"
  505. label={t("acceptQty")}
  506. sx={{ width: '150px' }}
  507. // value={Number(accQty)}
  508. defaultValue={Number(accQty)}
  509. // defaultValue={(qcDecision == 1)? Number(accQty) : 0}
  510. // value={(qcDecision == 1)? Number(accQty) : undefined }
  511. // value={qcAccept? accQty : 0 }
  512. disabled={qcDecision != 1 || disabled}
  513. // disabled={!qcAccept || disabled}
  514. onBlur={(e) => {
  515. const value = e.target.value;
  516. const input = document.getElementById('accQty') as HTMLInputElement;
  517. input.value = Number(value).toString()
  518. setValue(`acceptQty`, Number(value));
  519. }}
  520. onInput={(e: React.ChangeEvent<HTMLInputElement>) => {
  521. const input = e.target.value;
  522. const numReg = /^[0-9]+$/
  523. let r = '';
  524. if (!numReg.test(input)) {
  525. const result = input.replace(/\D/g, "");
  526. r = (result === '' ? result : Number(result)).toString();
  527. } else {
  528. r = Number(input).toString()
  529. }
  530. e.target.value = r;
  531. }}
  532. inputProps={{ min: 1, max:itemDetail.acceptedQty }}
  533. // onChange={(e) => {
  534. // const inputValue = e.target.value;
  535. // if (inputValue === '' || /^[0-9]*$/.test(inputValue)) {
  536. // setValue("acceptQty", Number(inputValue === '' ? null : parseInt(inputValue, 10)));
  537. // }
  538. // }}
  539. // {...register("acceptQty", {
  540. // required: "acceptQty required!",
  541. // })}
  542. error={Boolean(errors.acceptQty)}
  543. helperText={errors.acceptQty?.message}
  544. />
  545. <TextField
  546. type="number"
  547. label={t("rejectQty")}
  548. sx={{ width: '150px' }}
  549. value={
  550. (!Boolean(errors.acceptQty) && qcDecision !== undefined) ?
  551. (qcDecision == 1 ? itemDetail.acceptedQty - accQty : itemDetail.acceptedQty)
  552. : ""
  553. }
  554. error={Boolean(errors.acceptQty)}
  555. disabled={true}
  556. />
  557. </Box>)}
  558. <FormControlLabel disabled={disabled}
  559. value="2" control={<Radio />}
  560. sx={{"& .Mui-checked": {color: "red"}}}
  561. label= {detailMode ? "全部拒絕並退貨" : "不接受並需要退貨"} />
  562. {(itemDetail.status == "pending" || disabled) && (<>
  563. <FormControlLabel disabled={disabled}
  564. value="3" control={<Radio />}
  565. sx={{"& .Mui-checked": {color: "blue"}}}
  566. label="暫時存放到置物區,並等待品檢結果" />
  567. </>)}
  568. </RadioGroup>
  569. </>
  570. )}
  571. />
  572. </FormControl>
  573. </Card>
  574. </Grid>
  575. {qcDecision == 3 && (
  576. // {!qcAccept && (
  577. <Grid item xs={12}>
  578. <EscalationComponent
  579. forSupervisor={false}
  580. isCollapsed={isCollapsed}
  581. setIsCollapsed={setIsCollapsed}
  582. />
  583. </Grid>)}
  584. </Grid>
  585. ) : <LoadingComponent/>}
  586. </Grid>
  587. </>
  588. );
  589. };
  590. export default QcComponent;