|
- "use client";
-
- import { PurchaseQcResult, PutAwayInput, PutAwayLine } from "@/app/api/po/actions";
- import {
- Autocomplete,
- Box,
- Button,
- Card,
- CardContent,
- FormControl,
- Grid,
- Modal,
- ModalProps,
- Stack,
- TextField,
- Tooltip,
- Typography,
- } from "@mui/material";
- import { Controller, useFormContext } from "react-hook-form";
- import { useTranslation } from "react-i18next";
- import StyledDataGrid from "../StyledDataGrid";
- import { useCallback, useEffect, useMemo, useState } 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 { WarehouseResult } from "@/app/api/warehouse";
- import {
- OUTPUT_DATE_FORMAT,
- stockInLineStatusMap,
- } from "@/app/utils/formatUtil";
- import { QRCodeSVG } from "qrcode.react";
- import { QrCode } from "../QrCode";
- import ReactQrCodeScanner, {
- ScannerConfig,
- } from "../ReactQrCodeScanner/ReactQrCodeScanner";
- import { QrCodeInfo } from "@/app/api/qrcode";
- import { useQrCodeScannerContext } from "../QrCodeScannerProvider/QrCodeScannerProvider";
- import dayjs from "dayjs";
- import arraySupport from "dayjs/plugin/arraySupport";
- import { dummyPutAwayLine } from "./dummyQcTemplate";
- import { PrinterCombo } from "@/app/api/settings/printer";
- dayjs.extend(arraySupport);
-
- interface Props {
- itemDetail: StockInLine;
- warehouse: WarehouseResult[];
- disabled: boolean;
- // qc: QcItemWithChecks[];
- printerCombo: PrinterCombo[];
- }
- type EntryError =
- | {
- [field in keyof PutAwayLine]?: string;
- }
- | undefined;
-
- type PutAwayRow = TableRow<Partial<PutAwayLine>, EntryError>;
-
- const style = {
- position: "absolute",
- top: "50%",
- left: "50%",
- transform: "translate(-50%, -50%)",
- bgcolor: "background.paper",
- pt: 5,
- px: 5,
- pb: 10,
- width: "auto",
- };
-
- const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, printerCombo }) => {
- const { t } = useTranslation("purchaseOrder");
- const apiRef = useGridApiRef();
- const {
- register,
- formState: { errors, defaultValues, touchedFields },
- watch,
- control,
- setValue,
- getValues,
- reset,
- resetField,
- setError,
- clearErrors,
- } = useFormContext<PutAwayInput>();
- console.log(itemDetail);
- // const [recordQty, setRecordQty] = useState(0);
- const [warehouseId, setWarehouseId] = useState(itemDetail.defaultWarehouseId);
- const filteredWarehouse = useMemo(() => {
- // do filtering here if any
- return warehouse;
- }, []);
-
- const defaultOption = {
- value: 0, // think think sin
- label: t("Select warehouse"),
- group: "default",
- };
- const options = useMemo(() => {
- return [
- // {
- // value: 0, // think think sin
- // label: t("Select warehouse"),
- // group: "default",
- // },
- ...filteredWarehouse.map((w) => ({
- value: w.id,
- label: `${w.code} - ${w.name}`,
- group: "existing",
- })),
- ];
- }, [filteredWarehouse]);
- const currentValue =
- warehouseId > 0
- ? options.find((o) => o.value === warehouseId)
- : options.find((o) => o.value === getValues("warehouseId")) ||
- defaultOption;
-
- const onChange = useCallback(
- (
- event: React.SyntheticEvent,
- newValue: { value: number; group: string } | { value: number }[],
- ) => {
- const singleNewVal = newValue as {
- value: number;
- group: string;
- };
- console.log(singleNewVal);
- console.log("onChange");
- // setValue("warehouseId", singleNewVal.value);
- setWarehouseId(singleNewVal.value);
- },
- [],
- );
- console.log(watch("putAwayLines"))
- // const accQty = watch("acceptedQty");
- // const validateForm = useCallback(() => {
- // console.log(accQty);
- // if (accQty > itemDetail.acceptedQty) {
- // setError("acceptedQty", {
- // message: `acceptedQty must not greater than ${itemDetail.acceptedQty}`,
- // type: "required",
- // });
- // }
- // if (accQty < 1) {
- // setError("acceptedQty", {
- // message: `minimal value is 1`,
- // type: "required",
- // });
- // }
- // if (isNaN(accQty)) {
- // setError("acceptedQty", {
- // message: `value must be a number`,
- // type: "required",
- // });
- // }
- // }, [accQty]);
-
- // useEffect(() => {
- // clearErrors();
- // validateForm();
- // }, [validateForm]);
-
- const qrContent = useMemo(
- () => ({
- stockInLineId: itemDetail.id,
- itemId: itemDetail.itemId,
- lotNo: itemDetail.lotNo,
- // warehouseId: 2 // for testing
- // expiryDate: itemDetail.expiryDate,
- // productionDate: itemDetail.productionDate,
- // supplier: itemDetail.supplier,
- // poCode: itemDetail.poCode,
- }),
- [itemDetail],
- );
- const [isOpenScanner, setOpenScanner] = useState(false);
-
- const closeHandler = useCallback<NonNullable<ModalProps["onClose"]>>(
- (...args) => {
- setOpenScanner(false);
- },
- [],
- );
-
- const onOpenScanner = useCallback(() => {
- setOpenScanner(true);
- }, []);
-
- const onCloseScanner = useCallback(() => {
- setOpenScanner(false);
- }, []);
- const scannerConfig = useMemo<ScannerConfig>(
- () => ({
- onUpdate: (err, result) => {
- console.log(result);
- console.log(Boolean(result));
- if (result) {
- const data: QrCodeInfo = JSON.parse(result.getText());
- console.log(data);
- if (data.warehouseId) {
- console.log(data.warehouseId);
- setWarehouseId(data.warehouseId);
- onCloseScanner();
- }
- } else return;
- },
- }),
- [onCloseScanner],
- );
-
- // QR Code Scanner
- const scanner = useQrCodeScannerContext();
- useEffect(() => {
- if (isOpenScanner) {
- scanner.startScan();
- } else if (!isOpenScanner) {
- scanner.stopScan();
- }
- }, [isOpenScanner]);
-
- useEffect(() => {
- if (scanner.values.length > 0) {
- console.log(scanner.values[0]);
- const data: QrCodeInfo = JSON.parse(scanner.values[0]);
- console.log(data);
- if (data.warehouseId) {
- console.log(data.warehouseId);
- setWarehouseId(data.warehouseId);
- onCloseScanner();
- }
- scanner.resetScan();
- }
- }, [scanner.values]);
-
- useEffect(() => {
- setValue("status", "received");
- // setValue("status", "completed");
- setValue("warehouseId", options[0].value); //TODO: save all warehouse entry?
- }, []);
-
- useEffect(() => {
- if (warehouseId > 0) {
- setValue("warehouseId", warehouseId);
- clearErrors("warehouseId");
- }
- }, [warehouseId]);
-
- const getWarningTextHardcode = useCallback((): string | undefined => {
- console.log(options)
- if (options.length === 0) return undefined
- const defaultWarehouseId = options[0].value;
- const currWarehouseId = watch("warehouseId");
- if (defaultWarehouseId !== currWarehouseId) {
- return t("not default warehosue");
- }
- return undefined;
- }, [options]);
-
- const columns = useMemo<GridColDef[]>(
- () => [
- {
- field: "qty",
- headerName: t("qty"),
- flex: 1,
- editable: true,
- // renderCell(params) {
- // return <>100</>
- // },
- },
- {
- field: "warehouse",
- headerName: t("warehouse"),
- flex: 1,
- editable: true,
- renderEditCell: (params) => {
- const index = params.api.getRowIndexRelativeToVisibleRows(params.row.id)
- // console.log(index)
- // console.log(watch(`putAwayLines.${index}.warehouse`))
- return <Autocomplete
- fullWidth
- disableClearable
- options={options}
- // defaultValue={options.find((o) => o.value === itemDetail.defaultWarehouseId)}
- // value={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))}
- defaultValue={options.find((o) => o.value === watch(`putAwayLines.${index}.warehouseId`))}
- onChange={(event, value) => {
- params.api.setEditCellValue({ id: params.id, field: params.field, value: options.find((o) => o.value === value.value)?.label ?? ""})
- params.api.setEditCellValue({ id: params.id, field: "warehouseId", value: value.value})
- // setValue(`putAwayLines.${index}.warehouseId`, value.value)
- // setValue(`putAwayLines.${index}.warehouse`, options.find((o) => o.value === value.value)?.label ?? "")
- }}
- renderInput={(params) => (
- <TextField
- {...params}
- variant="outlined"
- // label={t("Warehouse")}
- />
- )}
- />
- }
- // renderCell(params) {
- // return <>{filteredWarehouse[0].name}</>
- // },
- },
- {
- field: "printQty",
- headerName: t("printQty"),
- flex: 1,
- editable: true,
- // renderCell(params) {
- // return <>100</>
- // },
- },
- ], [])
-
- const validation = useCallback(
- (newRow: GridRowModel<PutAwayRow>): EntryError => {
- const error: EntryError = {};
- const { qty, warehouseId, printQty } = newRow;
-
- return Object.keys(error).length > 0 ? error : undefined;
- },
- [],
- );
-
- const addRowDefaultValue = useMemo(() => {
- const defaultMaxQty = watch("acceptedQty") - watch("putAwayLines").reduce((acc, cur) => acc + cur.qty, 0)
- const defaultWarehouseId = itemDetail.defaultWarehouseId ?? 1
- const defaultWarehouse = options.find((o) => o.value === defaultWarehouseId)?.label
- return {qty: defaultMaxQty, warehouseId: defaultWarehouseId, warehouse: defaultWarehouse, printQty: 1 } as Partial<PutAwayLine>
- }, [])
-
- return (
- <Grid container justifyContent="flex-start" alignItems="flex-start">
- <Grid item xs={12}>
- <Typography variant="h6" display="block" marginBlockEnd={1}>
- {t("Putaway Detail")}
- </Typography>
- </Grid>
- <Grid
- container
- justifyContent="flex-start"
- alignItems="flex-start"
- spacing={2}
- sx={{ mt: 0.5 }}
- >
- <Grid item xs={12}>
- <TextField
- label={t("LotNo")}
- fullWidth
- value={itemDetail.lotNo}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <TextField
- label={t("Supplier")}
- fullWidth
- value={itemDetail.supplier}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <TextField
- label={t("Po Code")}
- fullWidth
- value={itemDetail.poCode}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <TextField
- label={t("itemName")}
- fullWidth
- value={itemDetail.itemName}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <TextField
- label={t("itemNo")}
- fullWidth
- value={itemDetail.itemNo}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <TextField
- label={t("qty")}
- fullWidth
- value={itemDetail.acceptedQty}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <TextField
- label={t("productionDate")}
- fullWidth
- value={
- // dayjs(itemDetail.productionDate)
- dayjs()
- // .add(-1, "month")
- .format(OUTPUT_DATE_FORMAT)}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <TextField
- label={t("expiryDate")}
- fullWidth
- value={
- // dayjs(itemDetail.expiryDate)
- dayjs()
- .add(20, "day")
- .format(OUTPUT_DATE_FORMAT)}
- disabled
- />
- </Grid>
- <Grid item xs={6}>
- <FormControl fullWidth>
- <Autocomplete
- noOptionsText={t("No Warehouse")}
- disableClearable
- disabled
- fullWidth
- defaultValue={options[0]} /// modify this later
- // onChange={onChange}
- getOptionLabel={(option) => option.label}
- options={options}
- renderInput={(params) => (
- <TextField {...params} label={t("Default Warehouse")} />
- )}
- />
- </FormControl>
- </Grid>
- {/* <Grid item xs={5.5}>
- <TextField
- label={t("acceptedQty")}
- fullWidth
- {...register("acceptedQty", {
- required: "acceptedQty required!",
- min: 1,
- max: itemDetail.acceptedQty,
- valueAsNumber: true,
- })}
- // defaultValue={itemDetail.acceptedQty}
- disabled={disabled}
- error={Boolean(errors.acceptedQty)}
- helperText={errors.acceptedQty?.message}
- />
- </Grid>
- <Grid item xs={1}>
- <Button disabled={disabled} onClick={onOpenScanner}>
- {t("bind")}
- </Button>
- </Grid> */}
- {/* <Grid item xs={5.5}>
- <Controller
- control={control}
- name="warehouseId"
- render={({ field }) => {
- console.log(field);
- return (
- <Autocomplete
- noOptionsText={t("No Warehouse")}
- disableClearable
- fullWidth
- value={options.find((o) => o.value == field.value)}
- onChange={onChange}
- getOptionLabel={(option) => option.label}
- options={options}
- renderInput={(params) => (
- <TextField
- {...params}
- label={"Select warehouse"}
- error={Boolean(errors.warehouseId?.message)}
- helperText={warehouseHelperText}
- // helperText={errors.warehouseId?.message}
- />
- )}
- />
- );
- }}
- />
- <FormControl fullWidth>
- <Autocomplete
- noOptionsText={t("No Warehouse")}
- disableClearable
- fullWidth
- // value={warehouseId > 0
- // ? options.find((o) => o.value === warehouseId)
- // : undefined}
- defaultValue={options[0]}
- // defaultValue={options.find((o) => o.value === 1)}
- value={currentValue}
- onChange={onChange}
- getOptionLabel={(option) => option.label}
- options={options}
- renderInput={(params) => (
- <TextField
- {...params}
- // label={"Select warehouse"}
- disabled={disabled}
- error={Boolean(errors.warehouseId?.message)}
- helperText={
- errors.warehouseId?.message ?? getWarningTextHardcode()
- }
- // helperText={warehouseHelperText}
- />
- )}
- />
- </FormControl>
- </Grid> */}
- <Grid
- item
- xs={12}
- style={{ display: "flex", justifyContent: "center" }}
- >
- {/* <QrCode content={qrContent} sx={{ width: 200, height: 200 }} /> */}
- <InputDataGrid<PutAwayInput, PutAwayLine, EntryError>
- apiRef={apiRef}
- checkboxSelection={false}
- _formKey={"putAwayLines"}
- columns={columns}
- validateRow={validation}
- needAdd={true}
- showRemoveBtn={false}
- addRowDefaultValue={addRowDefaultValue}
- />
- </Grid>
- </Grid>
- {/* <Grid
- container
- justifyContent="flex-start"
- alignItems="flex-start"
- spacing={2}
- sx={{ mt: 0.5 }}
- >
- <Button onClick={onOpenScanner}>bind</Button>
- </Grid> */}
-
- <Modal open={isOpenScanner} onClose={closeHandler}>
- <Box sx={style}>
- <Typography variant="h4">
- {t("Please scan warehouse qr code.")}
- </Typography>
- {/* <ReactQrCodeScanner scannerConfig={scannerConfig} /> */}
- </Box>
- </Modal>
- </Grid>
- );
- };
- export default PutAwayForm;
|