| @@ -55,6 +55,8 @@ import { downloadFile } from "@/app/utils/commonUtil"; | |||
| import { fetchPoQrcode } from "@/app/api/pdf/actions"; | |||
| import { fetchQcResult } from "@/app/api/qc/actions"; | |||
| import PoQcStockInModal from "./PoQcStockInModal"; | |||
| import { notifyActionSuccess } from "../Toast/Toast"; | |||
| import DoDisturbIcon from "@mui/icons-material/DoDisturb"; | |||
| interface ResultWithId { | |||
| id: number; | |||
| @@ -124,6 +126,7 @@ function PoInputGrid({ | |||
| const [escalOpen, setEscalOpen] = useState(false); | |||
| const [stockInOpen, setStockInOpen] = useState(false); | |||
| const [putAwayOpen, setPutAwayOpen] = useState(false); | |||
| const [rejectOpen, setRejectOpen] = useState(false); | |||
| const [btnIsLoading, setBtnIsLoading] = useState(false); | |||
| const [currQty, setCurrQty] = useState(() => { | |||
| const total = entries.reduce( | |||
| @@ -178,6 +181,7 @@ function PoInputGrid({ | |||
| ) as StockInLine[] | |||
| ); | |||
| setBtnIsLoading(false); | |||
| notifyActionSuccess(); | |||
| // do post directly to test | |||
| // openStartModal(); | |||
| }, 200); | |||
| @@ -229,6 +233,27 @@ function PoInputGrid({ | |||
| }, | |||
| [] | |||
| ); | |||
| const handleReject = useCallback( | |||
| (id: GridRowId, params: any) => () => { | |||
| setRowModesModel((prev) => ({ | |||
| ...prev, | |||
| [id]: { mode: GridRowModes.View }, | |||
| })); | |||
| setModalInfo(params.row); | |||
| setTimeout(() => { | |||
| // open stock in modal | |||
| // openPutAwayModal(); | |||
| // return the record with its status as pending | |||
| // update layout | |||
| console.log("delayed"); | |||
| openRejectModal(); | |||
| // printQrcode(params.row); | |||
| }, 200); | |||
| }, | |||
| [] | |||
| ); | |||
| const handleStockIn = useCallback( | |||
| (id: GridRowId, params: any) => () => { | |||
| // setBtnIsLoading(true); | |||
| @@ -332,6 +357,13 @@ function PoInputGrid({ | |||
| setEscalOpen(true); | |||
| }, []); | |||
| const closeRejectModal = useCallback(() => { | |||
| setRejectOpen(false); | |||
| }, []); | |||
| const openRejectModal = useCallback(() => { | |||
| setRejectOpen(true); | |||
| }, []); | |||
| const columns = useMemo<GridColDef[]>( | |||
| () => [ | |||
| { | |||
| @@ -393,7 +425,7 @@ function PoInputGrid({ | |||
| color: "primary.main", | |||
| // marginRight: 1, | |||
| }} | |||
| disabled={btnIsLoading || !(stockInLineStatusMap[status] === 0)} | |||
| disabled={!(stockInLineStatusMap[status] === 0)} | |||
| // set _isNew to false after posting | |||
| // or check status | |||
| onClick={handleStart(params.row.id, params)} | |||
| @@ -407,7 +439,10 @@ function PoInputGrid({ | |||
| color: "primary.main", | |||
| // marginRight: 1, | |||
| }} | |||
| disabled={btnIsLoading || stockInLineStatusMap[status] < 1} | |||
| disabled={ | |||
| // stockInLineStatusMap[status] === 9 || | |||
| stockInLineStatusMap[status] < 1 | |||
| } | |||
| // set _isNew to false after posting | |||
| // or check status | |||
| onClick={handleQC(params.row.id, params)} | |||
| @@ -422,7 +457,7 @@ function PoInputGrid({ | |||
| // marginRight: 1, | |||
| }} | |||
| disabled={ | |||
| btnIsLoading || | |||
| stockInLineStatusMap[status] === 9 || | |||
| stockInLineStatusMap[status] <= 0 || | |||
| stockInLineStatusMap[status] >= 5 | |||
| } | |||
| @@ -440,7 +475,7 @@ function PoInputGrid({ | |||
| // marginRight: 1, | |||
| }} | |||
| disabled={ | |||
| btnIsLoading || | |||
| stockInLineStatusMap[status] === 9 || | |||
| stockInLineStatusMap[status] <= 2 || | |||
| stockInLineStatusMap[status] >= 7 | |||
| } | |||
| @@ -457,7 +492,7 @@ function PoInputGrid({ | |||
| color: "primary.main", | |||
| // marginRight: 1, | |||
| }} | |||
| disabled={btnIsLoading || stockInLineStatusMap[status] < 7} | |||
| disabled={stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] < 7} | |||
| // set _isNew to false after posting | |||
| // or check status | |||
| onClick={handlePutAway(params.row.id, params)} | |||
| @@ -471,7 +506,7 @@ function PoInputGrid({ | |||
| color: "primary.main", | |||
| // marginRight: 1, | |||
| }} | |||
| disabled={btnIsLoading || stockInLineStatusMap[status] !== 8} | |||
| disabled={stockInLineStatusMap[status] === 9 || stockInLineStatusMap[status] !== 8} | |||
| // set _isNew to false after posting | |||
| // or check status | |||
| onClick={handleQrCode(params.row.id, params)} | |||
| @@ -479,14 +514,26 @@ function PoInputGrid({ | |||
| key="edit" | |||
| />, | |||
| <GridActionsCellItem | |||
| icon={<DeleteIcon />} | |||
| icon={ | |||
| stockInLineStatusMap[status] >= 1 ? ( | |||
| <DoDisturbIcon /> | |||
| ) : ( | |||
| <DeleteIcon /> | |||
| ) | |||
| } | |||
| label="Delete" | |||
| sx={{ | |||
| color: "error.main", | |||
| }} | |||
| disabled={btnIsLoading || stockInLineStatusMap[status] !== 0} | |||
| // disabled={Boolean(params.row.status)} | |||
| onClick={handleDelete(params.row.id)} | |||
| disabled={ | |||
| stockInLineStatusMap[status] >= 7 && | |||
| stockInLineStatusMap[status] <= 9 | |||
| } | |||
| onClick={ | |||
| stockInLineStatusMap[status] === 0 | |||
| ? handleDelete(params.row.id) | |||
| : handleReject(params.row.id, params) | |||
| } | |||
| color="inherit" | |||
| key="edit" | |||
| />, | |||
| @@ -494,7 +541,7 @@ function PoInputGrid({ | |||
| }, | |||
| }, | |||
| ], | |||
| [btnIsLoading] | |||
| [stockInLineStatusMap, btnIsLoading, handleQrCode, handleReject] | |||
| ); | |||
| const addRow = useCallback(() => { | |||
| @@ -671,6 +718,21 @@ function PoInputGrid({ | |||
| /> | |||
| </> | |||
| )} | |||
| {modalInfo !== undefined && ( | |||
| <> | |||
| <PoQcStockInModal | |||
| type={"reject"} | |||
| // setRows={setRows} | |||
| setEntries={setEntries} | |||
| setStockInLine={setStockInLine} | |||
| setItemDetail={setModalInfo} | |||
| // qc={qc} | |||
| open={rejectOpen} | |||
| onClose={closeRejectModal} | |||
| itemDetail={modalInfo} | |||
| /> | |||
| </> | |||
| )} | |||
| {modalInfo !== undefined && ( | |||
| <> | |||
| <PoQcStockInModal | |||
| @@ -39,6 +39,7 @@ import { downloadFile } from "@/app/utils/commonUtil"; | |||
| import { fetchPoQrcode } from "@/app/api/pdf/actions"; | |||
| import UploadContext from "../UploadProvider/UploadProvider"; | |||
| import useUploadContext from "../UploadProvider/useUploadContext"; | |||
| import RejectForm from "./RejectForm"; | |||
| dayjs.extend(arraySupport); | |||
| interface CommonProps extends Omit<ModalProps, "children"> { | |||
| @@ -56,7 +57,7 @@ interface CommonProps extends Omit<ModalProps, "children"> { | |||
| >; | |||
| qc?: QcItemWithChecks[]; | |||
| warehouse?: any[]; | |||
| type: "qc" | "stockIn" | "escalation" | "putaway"; | |||
| type: "qc" | "stockIn" | "escalation" | "putaway" | "reject"; | |||
| } | |||
| interface QcProps extends CommonProps { | |||
| qc: QcItemWithChecks[]; | |||
| @@ -74,8 +75,17 @@ interface EscalationProps extends CommonProps { | |||
| // naming | |||
| type: "escalation"; | |||
| } | |||
| interface RejectProps extends CommonProps { | |||
| // naming | |||
| type: "reject"; | |||
| } | |||
| type Props = QcProps | StockInProps | PutawayProps | EscalationProps; | |||
| type Props = | |||
| | QcProps | |||
| | StockInProps | |||
| | PutawayProps | |||
| | EscalationProps | |||
| | RejectProps; | |||
| const style = { | |||
| position: "absolute", | |||
| top: "50%", | |||
| @@ -194,7 +204,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| const onSubmit = useCallback<SubmitHandler<ModalFormInput & {}>>( | |||
| async (data, event) => { | |||
| setBtnIsLoading(true); | |||
| setIsUploading(true) | |||
| setIsUploading(true); | |||
| formProps.clearErrors(); | |||
| let hasErrors = false; | |||
| console.log(errors); | |||
| @@ -204,12 +214,12 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| try { | |||
| // add checking | |||
| if (type === "stockIn") { | |||
| hasErrors = checkStockIn(data) | |||
| console.log(hasErrors) | |||
| hasErrors = checkStockIn(data); | |||
| console.log(hasErrors); | |||
| } | |||
| if (type === "putaway") { | |||
| hasErrors = checkPutaway(data); | |||
| console.log(hasErrors) | |||
| console.log(hasErrors); | |||
| } | |||
| //////////////////////// modify this mess later ////////////////////// | |||
| var productionDate = null; | |||
| @@ -246,7 +256,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| console.log(args); | |||
| setServerError(t("An error has occurred. Please try again later.")); | |||
| setBtnIsLoading(false); | |||
| setIsUploading(false) | |||
| setIsUploading(false); | |||
| return; | |||
| } | |||
| console.log(args); | |||
| @@ -294,7 +304,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| } | |||
| // add loading | |||
| setBtnIsLoading(false); | |||
| setIsUploading(false) | |||
| setIsUploading(false); | |||
| setItemDetail(undefined); | |||
| closeHandler({}, "backdropClick"); | |||
| } | |||
| @@ -303,7 +313,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| } catch (e) { | |||
| // server error | |||
| setBtnIsLoading(false); | |||
| setIsUploading(false) | |||
| setIsUploading(false); | |||
| setServerError(t("An error has occurred. Please try again later.")); | |||
| console.log(e); | |||
| } | |||
| @@ -313,7 +323,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| const printQrcode = useCallback(async () => { | |||
| setBtnIsLoading(true); | |||
| setIsUploading(true) | |||
| setIsUploading(true); | |||
| const postData = { stockInLineIds: [itemDetail.id] }; | |||
| // const postData = { stockInLineIds: [42,43,44] }; | |||
| const response = await fetchPoQrcode(postData); | |||
| @@ -322,7 +332,7 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| downloadFile(new Uint8Array(response.blobValue), response.filename!!); | |||
| } | |||
| setBtnIsLoading(false); | |||
| setIsUploading(false) | |||
| setIsUploading(false); | |||
| }, [itemDetail, fetchPoQrcode, downloadFile]); | |||
| const renderSubmitButton = useMemo((): boolean => { | |||
| @@ -348,6 +358,11 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| ); | |||
| case "putaway": | |||
| return stockInLineStatusMap[status] === 7; | |||
| case "reject": | |||
| return ( | |||
| stockInLineStatusMap[status] >= 1 && | |||
| stockInLineStatusMap[status] <= 6 | |||
| ); | |||
| default: | |||
| return false; // Handle unexpected type | |||
| } | |||
| @@ -366,16 +381,36 @@ const PoQcStockInModal: React.FC<Props> = ({ | |||
| onSubmit={formProps.handleSubmit(onSubmit)} | |||
| > | |||
| {itemDetail !== undefined && type === "qc" && ( | |||
| <QcForm qc={qc!!} itemDetail={itemDetail} disabled={renderSubmitButton}/> | |||
| <QcForm | |||
| qc={qc!!} | |||
| itemDetail={itemDetail} | |||
| disabled={!renderSubmitButton} | |||
| /> | |||
| )} | |||
| {itemDetail !== undefined && type === "stockIn" && ( | |||
| <StockInForm itemDetail={itemDetail} disabled={renderSubmitButton}/> | |||
| <StockInForm | |||
| itemDetail={itemDetail} | |||
| disabled={!renderSubmitButton} | |||
| /> | |||
| )} | |||
| {itemDetail !== undefined && type === "escalation" && ( | |||
| <EscalationForm itemDetail={itemDetail} disabled={renderSubmitButton}/> | |||
| <EscalationForm | |||
| itemDetail={itemDetail} | |||
| disabled={!renderSubmitButton} | |||
| /> | |||
| )} | |||
| {itemDetail !== undefined && type === "putaway" && ( | |||
| <PutawayForm itemDetail={itemDetail} warehouse={warehouse!!} disabled={renderSubmitButton}/> | |||
| <PutawayForm | |||
| itemDetail={itemDetail} | |||
| warehouse={warehouse!!} | |||
| disabled={!renderSubmitButton} | |||
| /> | |||
| )} | |||
| {itemDetail !== undefined && type === "reject" && ( | |||
| <RejectForm | |||
| itemDetail={itemDetail} | |||
| disabled={!renderSubmitButton} | |||
| /> | |||
| )} | |||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | |||
| {renderSubmitButton ? ( | |||
| @@ -249,7 +249,7 @@ const QcForm: React.FC<Props> = ({ qc, itemDetail, disabled }) => { | |||
| <TextField | |||
| label={t("sampleRate")} | |||
| fullWidth | |||
| defaultValue={1} | |||
| // defaultValue={1} | |||
| {...register("sampleRate", { | |||
| required: "sampleRate required!", | |||
| valueAsNumber: true, | |||
| @@ -263,7 +263,7 @@ const QcForm: React.FC<Props> = ({ qc, itemDetail, disabled }) => { | |||
| <TextField | |||
| label={t("sampleWeight")} | |||
| fullWidth | |||
| defaultValue={1} | |||
| // defaultValue={1} | |||
| {...register("sampleWeight", { | |||
| required: "sampleWeight required!", | |||
| valueAsNumber: true, | |||
| @@ -277,7 +277,7 @@ const QcForm: React.FC<Props> = ({ qc, itemDetail, disabled }) => { | |||
| <TextField | |||
| label={t("totalWeight")} | |||
| fullWidth | |||
| defaultValue={1} | |||
| // defaultValue={1} | |||
| {...register("totalWeight", { | |||
| required: "totalWeight required!", | |||
| valueAsNumber: true, | |||
| @@ -0,0 +1,125 @@ | |||
| "use client"; | |||
| import { StockInLineEntry, EscalationInput } from "@/app/api/po/actions"; | |||
| import { | |||
| Box, | |||
| Card, | |||
| CardContent, | |||
| Grid, | |||
| Stack, | |||
| TextField, | |||
| Tooltip, | |||
| Typography, | |||
| } from "@mui/material"; | |||
| import { useFormContext } from "react-hook-form"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import StyledDataGrid from "../StyledDataGrid"; | |||
| import { useCallback, useEffect, useMemo } from "react"; | |||
| import { | |||
| GridColDef, | |||
| GridRowIdGetter, | |||
| GridRowModel, | |||
| useGridApiContext, | |||
| GridRenderCellParams, | |||
| GridRenderEditCellParams, | |||
| useGridApiRef, | |||
| } from "@mui/x-data-grid"; | |||
| import InputDataGrid from "../InputDataGrid"; | |||
| import { TableRow } from "../InputDataGrid/InputDataGrid"; | |||
| import TwoLineCell from "./TwoLineCell"; | |||
| import QcSelect from "./QcSelect"; | |||
| import { QcItemWithChecks } from "@/app/api/qc"; | |||
| import { GridEditInputCell } from "@mui/x-data-grid"; | |||
| import { StockInLine } from "@/app/api/po"; | |||
| import { stockInLineStatusMap } from "@/app/utils/formatUtil"; | |||
| interface Props { | |||
| itemDetail: StockInLine; | |||
| // qc: QcItemWithChecks[]; | |||
| disabled: boolean | |||
| } | |||
| type EntryError = | |||
| | { | |||
| [field in keyof StockInLineEntry]?: string; | |||
| } | |||
| | undefined; | |||
| const RejectForm: React.FC<Props> = ({ | |||
| // qc, | |||
| itemDetail, | |||
| disabled | |||
| }) => { | |||
| const { t } = useTranslation(); | |||
| const apiRef = useGridApiRef(); | |||
| const { | |||
| register, | |||
| formState: { errors, defaultValues, touchedFields }, | |||
| watch, | |||
| control, | |||
| setValue, | |||
| getValues, | |||
| reset, | |||
| resetField, | |||
| setError, | |||
| clearErrors, | |||
| } = useFormContext<EscalationInput>(); | |||
| console.log(itemDetail) | |||
| // const status = "rejected" | |||
| const acceptedQty = watch("acceptedQty") || 0 | |||
| console.log(disabled) | |||
| useEffect(() => { | |||
| console.log("triggered") | |||
| setValue("status", "rejected") | |||
| }, []) | |||
| return ( | |||
| <Grid container justifyContent="flex-start" alignItems="flex-start"> | |||
| <Grid item xs={12}> | |||
| <Typography variant="h6" display="block" marginBlockEnd={1}> | |||
| {t(`Reject`)} | |||
| </Typography> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Typography variant="h6" display="block" marginBlockEnd={1}> | |||
| {t(`to be processed`)}: {itemDetail.acceptedQty - acceptedQty} | |||
| </Typography> | |||
| </Grid> | |||
| <Grid | |||
| container | |||
| justifyContent="flex-start" | |||
| alignItems="flex-start" | |||
| spacing={2} | |||
| sx={{ mt: 0.5 }} | |||
| > | |||
| <Grid item xs={6}> | |||
| <TextField | |||
| label={t("acceptedQty")} | |||
| fullWidth | |||
| {...register("acceptedQty", { | |||
| required: "acceptedQty required!", | |||
| min: 0, | |||
| valueAsNumber: true, | |||
| max: itemDetail.acceptedQty | |||
| })} | |||
| disabled={disabled} | |||
| defaultValue={itemDetail.acceptedQty} | |||
| error={Boolean(errors.acceptedQty)} | |||
| helperText={errors.acceptedQty?.message} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid | |||
| container | |||
| justifyContent="flex-start" | |||
| alignItems="flex-start" | |||
| spacing={2} | |||
| sx={{ mt: 0.5 }} | |||
| > | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default RejectForm; | |||