"use client"; import { FooterPropsOverrides, GridActionsCellItem, GridCellParams, GridRowId, GridRowIdGetter, GridRowModel, GridRowModes, GridRowModesModel, GridToolbarContainer, useGridApiRef, } from "@mui/x-data-grid"; import { Dispatch, MutableRefObject, SetStateAction, useCallback, useEffect, useMemo, useState, } from "react"; import StyledDataGrid from "../StyledDataGrid"; import { GridColDef } from "@mui/x-data-grid"; import { Box, Button, Grid, Icon, Typography } from "@mui/material"; import { useTranslation } from "react-i18next"; import { Add } from "@mui/icons-material"; import SaveIcon from "@mui/icons-material/Save"; import DeleteIcon from "@mui/icons-material/Delete"; import CancelIcon from "@mui/icons-material/Cancel"; import FactCheckIcon from "@mui/icons-material/FactCheck"; import ShoppingCartIcon from "@mui/icons-material/ShoppingCart"; // import PoQcModal from "./PoQcModal"; import PlayArrowIcon from "@mui/icons-material/PlayArrow"; import { useSearchParams } from "next/navigation"; import { decimalFormatter } from "@/app/utils/formatUtil"; import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'; import HighlightOffIcon from '@mui/icons-material/HighlightOff'; import { ProdScheduleLineBomMaterialResult, ScheduleType } from "@/app/api/scheduling"; interface ResultWithId { id: number; } interface Props { bomMaterial: ProdScheduleLineBomMaterialResult[]; type: ScheduleType } export type BomMaterialEntryError = { [field in keyof any]?: string; }; export type BomMaterialRow = Partial< any & { isActive: boolean | undefined; _isNew: boolean; _error: BomMaterialEntryError; } & ResultWithId >; class ProcessRowUpdateError extends Error { public readonly row: BomMaterialRow; public readonly errors: BomMaterialEntryError | undefined; constructor(row: BomMaterialRow, message?: string, errors?: BomMaterialEntryError) { super(message); this.row = row; this.errors = errors; Object.setPrototypeOf(this, ProcessRowUpdateError.prototype); } } function BomMaterialTable({ bomMaterial }: Props) { const { t } = useTranslation("schedule"); const apiRef = useGridApiRef(); const [rowModesModel, setRowModesModel] = useState({}); const getRowId = useCallback>( (row) => row.id as number, [] ); const [entries, setEntries] = useState(bomMaterial || []); const columns = useMemo( () => [ { field: "code", headerName: t("Code"), flex: 1, }, { field: "name", headerName: t("Name"), flex: 1, }, { field: "type", headerName: t("type"), flex: 1, renderCell: (row) => { return t(row.value) } }, { field: "availableQty", headerName: t("Available Qty"), flex: 0.5, type: "number", editable: true, align: "right", headerAlign: "right", renderCell: (row) => { return decimalFormatter.format(row.value) } // replace with tooltip + content }, { field: "demandQty", headerName: t("Demand Qty"), flex: 0.5, editable: true, align: "right", headerAlign: "right", renderCell: (row) => { return decimalFormatter.format(row.value) } }, { field: "status", headerName: t("status"), flex: 0.5, editable: true, align: "center", headerAlign: "center", renderCell: (params) => { return params.row.availableQty - params.row.demandQty >= 0 ? : } }, ], [] ); const validation = useCallback( ( newRow: GridRowModel ): BomMaterialEntryError | undefined => { const error: BomMaterialEntryError = {}; console.log(newRow); return Object.keys(error).length > 0 ? error : undefined; }, [] ); const processRowUpdate = useCallback( (newRow: GridRowModel, originalRow: GridRowModel) => { const errors = validation(newRow); // change to validation if (errors) { throw new ProcessRowUpdateError( originalRow, "validation error", errors ); } const { _isNew, _error, ...updatedRow } = newRow; const rowToSave = { ...updatedRow, } satisfies BomMaterialRow; const newEntries = entries.map((e) => getRowId(e) === getRowId(originalRow) ? rowToSave : e ); setEntries(newEntries); //update remaining qty const total = newEntries.reduce((acc, curr) => acc + (curr.acceptedQty || 0), 0); return rowToSave; }, [getRowId, entries] ); const onProcessRowUpdateError = useCallback( (updateError: ProcessRowUpdateError) => { const errors = updateError.errors; const oldRow = updateError.row; apiRef.current.updateRows([{ ...oldRow, _error: errors }]); }, [apiRef] ); return ( <> ) => { let classname = ""; if (params.row._error) { classname = "hasError"; } return classname; }} // slots={{ // footer: FooterToolbar, // noRowsOverlay: NoRowsOverlay, // }} // slotProps={{ // footer: { child: footer }, // }} /> ); } const NoRowsOverlay: React.FC = () => { const { t } = useTranslation("home"); return ( {t("Add some entries!")} ); }; const FooterToolbar: React.FC = ({ child }) => { return {child}; }; export default BomMaterialTable;