|
- import { JoDetail, JoDetailPickLine } from "@/app/api/jo";
- import { decimalFormatter } from "@/app/utils/formatUtil";
- import { GridColDef, GridRenderCellParams, GridValidRowModel } from "@mui/x-data-grid";
- import { isEmpty, pick, upperFirst } from "lodash";
- import { useCallback, useMemo } from "react";
- import { useFormContext } from "react-hook-form";
- import { useTranslation } from "react-i18next";
- import StyledDataGrid from "../StyledDataGrid/StyledDataGrid";
- import { Box, Grid, Icon, IconButton, Stack, Typography } from "@mui/material";
- import PendingOutlinedIcon from '@mui/icons-material/PendingOutlined';
- import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
- import HelpOutlineOutlinedIcon from '@mui/icons-material/HelpOutlineOutlined';
- import { fetchInventories } from "@/app/api/inventory/actions";
- import { InventoryResult } from "@/app/api/inventory";
- import { useEffect, useState } from "react";
- import DoDisturbAltRoundedIcon from '@mui/icons-material/DoDisturbAltRounded';
-
- type JoDetailPickLineWithCalculations = JoDetailPickLine & {
- stockAvailable: number;
- isStockSufficient: boolean;
- };
-
- type Props = {
-
- };
-
- const PickTable: React.FC<Props> = ({
-
- }) => {
- const { t } = useTranslation("jo")
- const {
- watch
- } = useFormContext<JoDetail>()
-
- const [inventoryData, setInventoryData] = useState<InventoryResult[]>([]);
- const pickLines = watch("pickLines");
- useEffect(() => {
- const fetchInventoryData = async () => {
- try {
- const inventoryResponse = await fetchInventories({
- code: "",
- name: "",
- type: "",
- pageNum: 0,
- pageSize: 1000
- });
- setInventoryData(inventoryResponse.records);
- } catch (error) {
- console.error("Error fetching inventory data:", error);
- }
- };
-
- fetchInventoryData();
- }, [pickLines]);
-
- const getStockAvailable = (pickLine: JoDetailPickLine) => {
- const inventory = inventoryData.find(inventory =>
- inventory.itemCode === pickLine.code || inventory.itemName === pickLine.name
- );
-
- if (inventory) {
- return inventory.availableQty || (inventory.onHandQty - inventory.onHoldQty - inventory.unavailableQty);
- }
-
- return 0;
- };
-
- const getUomShortDesc = (pickLine: JoDetailPickLine) => {
- const inventory = inventoryData.find(inventory =>
- inventory.itemCode === pickLine.code || inventory.itemName === pickLine.name
- );
-
- return inventory?.uomShortDesc; // || pickLine.uom;
- };
-
- const isStockSufficient = (pickLine: JoDetailPickLine) => {
- const stockAvailable = getStockAvailable(pickLine);
- return stockAvailable >= pickLine.reqQty;
- };
-
- const sufficientStockIcon = useMemo(() => {
- return <CheckCircleOutlineOutlinedIcon fontSize={"large"} color="success" />
- }, []);
-
- const insufficientStockIcon = useMemo(() => {
- return <DoDisturbAltRoundedIcon fontSize={"large"} color="error" />
- }, []);
-
- const rowsWithCalculatedFields = useMemo(() => {
- return pickLines.map((pickLine, index) => ({
- ...pickLine,
- id: pickLine.id || index,
- sequence: index + 1,
- stockAvailable: getStockAvailable(pickLine),
- isStockSufficient: isStockSufficient(pickLine),
- }));
- }, [pickLines, inventoryData]);
-
- const notPickedStatusColumn = useMemo(() => {
- return (<HelpOutlineOutlinedIcon fontSize={"large"} color={"error"} />)
- }, [])
-
- const scanStatusColumn = useCallback((status: boolean) => {
- return status ?
- <CheckCircleOutlineOutlinedIcon fontSize={"large"} sx={{ ml: "5px" }} color="success" />
- : <PendingOutlinedIcon fontSize={"large"} sx={{ ml: "5px" }} color="warning" />
- }, [])
-
- const columns = useMemo<GridColDef[]>(() => [
- {
- field: "sequence",
- headerName: t("Sequence"),
- flex: 0.2,
- align: "left",
- headerAlign: "left",
- type: "number",
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- return params.value;
- },
- },
- {
- field: "code",
- headerName: t("Item Code"),
- flex: 0.6,
- },
- {
- field: "name",
- headerName: t("Item Name"),
- flex: 1,
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- return `${params.value} (${params.row.uom})`;
- },
- },
- /*{
- field: "scanStatus",
- headerName: t("Scan Status"),
- flex: 0.4,
- align: "right",
- headerAlign: "right",
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- if (params.row.pickedLotNo === null || params.row.pickedLotNo === undefined) {
- return notPickedStatusColumn
- }
- const scanStatus = params.row.pickedLotNo.map((pln) => Boolean(pln.isScanned))
- return isEmpty(scanStatus) ? notPickedStatusColumn : <Stack direction={"column"}>{scanStatus.map((status) => scanStatusColumn(status))}</Stack>
- },
- },
- {
- field: "lotNo",
- headerName: t("Lot No."),
- flex: 1,
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- if (params.row.pickedLotNo === null || params.row.pickedLotNo === undefined) {
- return t("Pending for pick")
- }
- const lotNos = params.row.pickedLotNo.map((pln) => pln.lotNo)
- return isEmpty(lotNos) ? t("Pending for pick") : lotNos.map((lotNo) => (<>{lotNo}<br /></>))
- },
- },
- {
- field: "pickedQty",
- headerName: t("Picked Qty"),
- flex: 0.7,
- align: "right",
- headerAlign: "right",
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- if (params.row.pickedLotNo === null || params.row.pickedLotNo === undefined) {
- return t("Pending for pick")
- }
- const qtys = params.row.pickedLotNo.map((pln) => pln.qty)
- return isEmpty(qtys) ? t("Pending for pick") : qtys.map((qty) => <>{qty}<br /></>)
- },
- },*/
- {
- field: "reqQty",
- headerName: t("Req. Qty"),
- flex: 0.7,
- align: "right",
- headerAlign: "right",
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- const uomShortDesc = getUomShortDesc(params.row);
- return `${decimalFormatter.format(params.value)} ${uomShortDesc}`;
- },
- },
- {
- field: "stockAvailable",
- headerName: t("Stock Available"),
- flex: 0.7,
- align: "right",
- headerAlign: "right",
- type: "number",
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- const uomShortDesc = getUomShortDesc(params.row);
- return `${decimalFormatter.format(params.value)} ${uomShortDesc}`;
- },
- },
- {
- field: "stockStatus",
- headerName: t("Stock Status"),
- flex: 0.5,
- align: "right",
- headerAlign: "right",
- type: "boolean",
- renderCell: (params: GridRenderCellParams<JoDetailPickLineWithCalculations>) => {
- return params.row.isStockSufficient ? sufficientStockIcon : insufficientStockIcon;
- },
- }
-
- /*{
- field: "status",
- headerName: t("Status"),
- flex: 1,
- align: "right",
- headerAlign: "right",
- renderCell: (params: GridRenderCellParams<JoDetailPickLine>) => {
- return (
- <>
- {params.row.pickedLotNo?.every((lotNo) => Boolean(lotNo.isScanned)) ? t("Scanned") : t(upperFirst(params.value))}
- {scanStatusColumn(Boolean(params.row.pickedLotNo?.every((lotNo) => Boolean(lotNo.isScanned))))}
- </>
- )
- },
- },*/
-
- ], [t, inventoryData])
-
- return (
- <>
- <StyledDataGrid
- sx={{
- "--DataGrid-overlayHeight": "100px",
- ".MuiDataGrid-row .MuiDataGrid-cell.hasError": {
- border: "1px solid",
- borderColor: "error.main",
- },
- ".MuiDataGrid-row .MuiDataGrid-cell.hasWarning": {
- border: "1px solid",
- borderColor: "warning.main",
- },
- }}
- disableColumnMenu
- rows={rowsWithCalculatedFields}
- columns={columns}
- getRowHeight={() => 'auto'}
- />
- </>
- )
- }
-
- export default PickTable;
|