| @@ -21,6 +21,7 @@ import { | |||
| GridRowModel, | |||
| GridRowModes, | |||
| GridRowModesModel, | |||
| GridRowParams, | |||
| GridRowSelectionModel, | |||
| GridToolbarContainer, | |||
| GridValidRowModel, | |||
| @@ -63,6 +64,7 @@ export type TableRow<V, E> = Partial< | |||
| isActive: boolean | undefined; | |||
| _isNew: boolean; | |||
| _error: E; | |||
| _disableDelete: boolean; | |||
| } & ResultWithId | |||
| >; | |||
| @@ -76,6 +78,7 @@ export interface InputDataGridProps<T, V, E> { | |||
| showRemoveBtn?: boolean; | |||
| addRowDefaultValue?: Partial<V>; | |||
| _setRowModesModel?: Dispatch<SetStateAction<GridRowModesModel>>; | |||
| _setRowSelectionModel?: Dispatch<SetStateAction<GridRowSelectionModel>>; | |||
| } | |||
| export interface SelectionInputDataGridProps<T, V, E> { | |||
| @@ -89,6 +92,7 @@ export interface SelectionInputDataGridProps<T, V, E> { | |||
| showRemoveBtn?: boolean; | |||
| addRowDefaultValue?: Partial<V>; | |||
| _setRowModesModel?: Dispatch<SetStateAction<GridRowModesModel>>; | |||
| _setRowSelectionModel?: Dispatch<SetStateAction<GridRowSelectionModel>>; | |||
| } | |||
| export type Props<T, V, E> = | |||
| @@ -118,6 +122,7 @@ function InputDataGrid<T, V, E>({ | |||
| showRemoveBtn = true, | |||
| addRowDefaultValue = {}, | |||
| _setRowModesModel = undefined, | |||
| _setRowSelectionModel = undefined, | |||
| }: Props<T, V, E>) { | |||
| const { | |||
| t, | |||
| @@ -157,9 +162,15 @@ function InputDataGrid<T, V, E>({ | |||
| `${formKey}_active`, | |||
| ) as GridRowSelectionModel; | |||
| // console.log(rowModel); | |||
| return rowModel; | |||
| return rowModel ?? []; | |||
| }); | |||
| useEffect(() => { | |||
| if (_setRowSelectionModel) { | |||
| _setRowSelectionModel(rowSelectionModel) | |||
| } | |||
| }, [rowSelectionModel]) | |||
| const handleSave = useCallback( | |||
| (id: GridRowId) => () => { | |||
| setRowModesModel((prevRowModesModel) => ({ | |||
| @@ -259,7 +270,9 @@ function InputDataGrid<T, V, E>({ | |||
| headerName: "", | |||
| flex: 0.5, | |||
| cellClassName: "actions", | |||
| getActions: ({ id }: { id: GridRowId }) => { | |||
| getActions: (params: GridRowParams<TableRow<V, E>>) => { | |||
| const id = params.id | |||
| const _disableDelete = Boolean(params.row._disableDelete) | |||
| const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; | |||
| if (isInEditMode) { | |||
| return [ | |||
| @@ -284,6 +297,7 @@ function InputDataGrid<T, V, E>({ | |||
| <GridActionsCellItem | |||
| icon={<DeleteIcon />} | |||
| label="Delete" | |||
| disabled={_disableDelete} | |||
| sx={{ | |||
| color: "error.main", | |||
| }} | |||
| @@ -349,7 +363,8 @@ function InputDataGrid<T, V, E>({ | |||
| rowSelectionModel={rowSelectionModel} | |||
| apiRef={apiRef} | |||
| rows={rows} | |||
| columns={!checkboxSelection ? _columns : columns} | |||
| // columns={!checkboxSelection ? _columns : columns} | |||
| columns={_columns} | |||
| editMode="row" | |||
| autoHeight | |||
| sx={{ | |||
| @@ -377,15 +392,17 @@ function InputDataGrid<T, V, E>({ | |||
| return classname; | |||
| }} | |||
| slots={ | |||
| !checkboxSelection | |||
| ? { | |||
| // !checkboxSelection | |||
| // ? | |||
| { | |||
| footer: FooterToolbar, | |||
| noRowsOverlay: NoRowsOverlay, | |||
| } | |||
| : undefined | |||
| // : undefined | |||
| } | |||
| slotProps={ | |||
| !checkboxSelection && Boolean(needAdd) | |||
| // !checkboxSelection && Boolean(needAdd) | |||
| Boolean(needAdd) | |||
| ? { | |||
| footer: { child: footer }, | |||
| } | |||
| @@ -28,6 +28,7 @@ import { | |||
| GridRenderCellParams, | |||
| GridRenderEditCellParams, | |||
| useGridApiRef, | |||
| GridRowSelectionModel, | |||
| } from "@mui/x-data-grid"; | |||
| import InputDataGrid from "../InputDataGrid"; | |||
| import { TableRow } from "../InputDataGrid/InputDataGrid"; | |||
| @@ -60,6 +61,7 @@ interface Props { | |||
| disabled: boolean; | |||
| // qc: QcItemWithChecks[]; | |||
| setRowModesModel: Dispatch<SetStateAction<GridRowModesModel>>; | |||
| setRowSelectionModel: Dispatch<SetStateAction<GridRowSelectionModel>>; | |||
| } | |||
| type EntryError = | |||
| | { | |||
| @@ -81,7 +83,7 @@ const style = { | |||
| width: "auto", | |||
| }; | |||
| const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowModesModel }) => { | |||
| const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowModesModel, setRowSelectionModel }) => { | |||
| const { t } = useTranslation("purchaseOrder"); | |||
| const apiRef = useGridApiRef(); | |||
| const { | |||
| @@ -534,7 +536,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM | |||
| {/* <QrCode content={qrContent} sx={{ width: 200, height: 200 }} /> */} | |||
| <InputDataGrid<PutAwayInput, PutAwayLine, EntryError> | |||
| apiRef={apiRef} | |||
| checkboxSelection={false} | |||
| checkboxSelection={true} | |||
| _formKey={"putAwayLines"} | |||
| columns={columns} | |||
| validateRow={validation} | |||
| @@ -542,6 +544,7 @@ const PutAwayForm: React.FC<Props> = ({ itemDetail, warehouse, disabled, setRowM | |||
| showRemoveBtn={false} | |||
| addRowDefaultValue={addRowDefaultValue} | |||
| _setRowModesModel={setRowModesModel} | |||
| _setRowSelectionModel={setRowSelectionModel} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| @@ -21,7 +21,7 @@ import StockInFormVer2 from "./StockInFormVer2"; | |||
| import QcComponent from "./QcComponent"; | |||
| import { dummyPutAwayLine, dummyQCData } from "./dummyQcTemplate"; | |||
| import PutAwayForm from "./PutAwayForm"; | |||
| import { GridRowModes, useGridApiRef } from "@mui/x-data-grid"; | |||
| import { GridRowModes, GridRowSelectionModel, useGridApiRef } from "@mui/x-data-grid"; | |||
| import {submitDialogWithWarning} from "../Swal/CustomAlerts"; | |||
| import { INPUT_DATE_FORMAT, arrayToDateString, dayjsToInputDateString } from "@/app/utils/formatUtil"; | |||
| import dayjs from "dayjs"; | |||
| @@ -33,6 +33,7 @@ import { SessionWithTokens } from "@/config/authConfig"; | |||
| import { GridRowModesModel } from "@mui/x-data-grid"; | |||
| import { isEmpty } from "lodash"; | |||
| import { EscalationCombo } from "@/app/api/user"; | |||
| import { truncateSync } from "fs"; | |||
| const style = { | |||
| @@ -103,7 +104,7 @@ const defaultNewValue = useMemo(() => { | |||
| dnDate: arrayToDateString(itemDetail.dnDate, "input")?? dayjsToInputDateString(dayjs()), | |||
| // putAwayLines: dummyPutAwayLine, | |||
| // putAwayLines: itemDetail.putAwayLines.map((line) => (return {...line, printQty: 1})) ?? [], | |||
| putAwayLines: itemDetail.putAwayLines?.map((line) => ({...line, printQty: 1, _isNew: false})) ?? [], | |||
| putAwayLines: itemDetail.putAwayLines?.map((line) => ({...line, printQty: 1, _isNew: false, _disableDelete: true})) ?? [], | |||
| // qcResult: (itemDetail.qcResult && itemDetail.qcResult?.length > 0) ? itemDetail.qcResult : [],//[...dummyQCData], | |||
| escResult: (itemDetail.escResult && itemDetail.escResult?.length > 0) ? itemDetail.escResult : [], | |||
| productionDate: itemDetail.productionDate ? arrayToDateString(itemDetail.productionDate, "input") : undefined, | |||
| @@ -366,6 +367,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||
| // Put away model | |||
| const [pafRowModesModel, setPafRowModesModel] = useState<GridRowModesModel>({}) | |||
| const [pafRowSelectionModel, setPafRowSelectionModel] = useState<GridRowSelectionModel>([]) | |||
| const pafSubmitDisable = useMemo(() => { | |||
| // console.log("%c mode: ", "background:#90EE90; color:red", Object.entries(pafRowModesModel)) | |||
| // console.log("%c mode: ", "background:pink; color:#87CEEB", Object.entries(pafRowModesModel)) | |||
| @@ -441,11 +443,14 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||
| alert("列印數量不正確!"); | |||
| return; | |||
| } | |||
| // console.log(pafRowSelectionModel) | |||
| const printList = formProps.watch("putAwayLines")?.filter((line) => ((pafRowSelectionModel ?? []).some((model) => model === line.id))) ?? [] | |||
| const printQty = printList.reduce((acc, cur) => acc + cur.printQty, 0) | |||
| // console.log(printQty) | |||
| const data: PrintQrCodeForSilRequest = { | |||
| stockInLineId: itemDetail.id, | |||
| printerId: selectedPrinter.id, | |||
| printQty: formProps.watch("putAwayLines")?.reduce((acc, cur) => acc + cur.printQty, 0) | |||
| printQty: printQty | |||
| } | |||
| const response = await printQrCodeForSil(data); | |||
| if (response) { | |||
| @@ -454,7 +459,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||
| } finally { | |||
| setIsPrinting(() => false) | |||
| } | |||
| }, [itemDetail.id]); | |||
| }, [itemDetail.id, pafRowSelectionModel]); | |||
| const acceptQty = formProps.watch("acceptedQty") | |||
| @@ -499,6 +504,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||
| warehouse={warehouse!} | |||
| disabled={viewOnly} | |||
| setRowModesModel={setPafRowModesModel} | |||
| setRowSelectionModel={setPafRowSelectionModel} | |||
| /> | |||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | |||
| <Autocomplete | |||
| @@ -524,7 +530,7 @@ const [qcItems, setQcItems] = useState(dummyQCData) | |||
| color="primary" | |||
| sx={{ mt: 1 }} | |||
| onClick={handlePrint} | |||
| disabled={isPrinting || printerCombo.length <= 0} | |||
| disabled={isPrinting || printerCombo.length <= 0 || pafSubmitDisable} | |||
| > | |||
| {isPrinting ? t("Printing") : t("print")} | |||
| </Button> | |||