import { InventoryLotLineResult, InventoryResult } from "@/app/api/inventory"; import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Column } from "../SearchResults"; import SearchResults, { defaultPagingController, defaultSetPagingController } from "../SearchResults/SearchResults"; import { arrayToDateString } from "@/app/utils/formatUtil"; import { Box, Card, Grid, IconButton, Modal, TextField, Typography, Button } from "@mui/material"; import useUploadContext from "../UploadProvider/useUploadContext"; import { downloadFile } from "@/app/utils/commonUtil"; import { fetchQrCodeByLotLineId, LotLineToQrcode } from "@/app/api/pdf/actions"; import QrCodeIcon from "@mui/icons-material/QrCode"; import PrintIcon from "@mui/icons-material/Print"; import SwapHoriz from "@mui/icons-material/SwapHoriz"; import CloseIcon from "@mui/icons-material/Close"; import { Autocomplete } from "@mui/material"; import { WarehouseResult } from "@/app/api/warehouse"; import { fetchWarehouseListClient } from "@/app/api/warehouse/client"; import { updateInventoryLotLineQuantities } from "@/app/api/inventory/actions"; interface Props { inventoryLotLines: InventoryLotLineResult[] | null; setPagingController: defaultSetPagingController; pagingController: typeof defaultPagingController; totalCount: number; inventory: InventoryResult | null; } const InventoryLotLineTable: React.FC = ({ inventoryLotLines, pagingController, setPagingController, totalCount, inventory }) => { const { t } = useTranslation(["inventory"]); const { setIsUploading } = useUploadContext(); const [stockTransferModalOpen, setStockTransferModalOpen] = useState(false); const [selectedLotLine, setSelectedLotLine] = useState(null); const [startLocation, setStartLocation] = useState(""); const [targetLocation, setTargetLocation] = useState(""); const [targetLocationInput, setTargetLocationInput] = useState(""); const [qtyToBeTransferred, setQtyToBeTransferred] = useState(0); const [warehouses, setWarehouses] = useState([]); useEffect(() => { if (stockTransferModalOpen) { fetchWarehouseListClient() .then(setWarehouses) .catch(console.error); } }, [stockTransferModalOpen]); const originalQty = selectedLotLine?.availableQty || 0; const remainingQty = originalQty - qtyToBeTransferred; const downloadQrCode = useCallback(async (lotLineId: number) => { setIsUploading(true); // const postData = { stockInLineIds: [42,43,44] }; const postData: LotLineToQrcode = { inventoryLotLineId: lotLineId } const response = await fetchQrCodeByLotLineId(postData); if (response) { downloadFile(new Uint8Array(response.blobValue), response.filename!); } setIsUploading(false); }, [setIsUploading]); const handleStockTransfer = useCallback( (lotLine: InventoryLotLineResult) => { setSelectedLotLine(lotLine); setStockTransferModalOpen(true); setStartLocation(lotLine.warehouse.code || ""); setTargetLocation(""); setTargetLocationInput(""); setQtyToBeTransferred(0); }, [], ); const onDetailClick = useCallback( (lotLine: InventoryLotLineResult) => { downloadQrCode(lotLine.id) // lot line id to find stock in line }, [downloadQrCode], ); const columns = useMemo[]>( () => [ // { // name: "item", // label: t("Code"), // renderCell: (params) => { // return params.item.code; // }, // }, // { // name: "item", // label: t("Name"), // renderCell: (params) => { // return params.item.name; // }, // }, { name: "lotNo", label: t("Lot No"), }, // { // name: "item", // label: t("Type"), // renderCell: (params) => { // return t(params.item.type); // }, // }, { name: "availableQty", label: t("Available Qty"), align: "right", headerAlign: "right", type: "integer", }, { name: "uom", label: t("Stock UoM"), align: "left", headerAlign: "left", }, // { // name: "qtyPerSmallestUnit", // label: t("Available Qty Per Smallest Unit"), // align: "right", // headerAlign: "right", // type: "integer", // }, // { // name: "baseUom", // label: t("Base UoM"), // align: "left", // headerAlign: "left", // }, { name: "expiryDate", label: t("Expiry Date"), renderCell: (params) => { return arrayToDateString(params.expiryDate) }, }, { name: "warehouse", label: t("Warehouse"), renderCell: (params) => { return `${params.warehouse.code}` }, }, { name: "id", label: t("Download QR Code"), onClick: onDetailClick, buttonIcon: , align: "center", headerAlign: "center", }, { name: "id", label: t("Print QR Code"), onClick: () => {}, buttonIcon: , align: "center", headerAlign: "center", }, { name: "id", label: t("Stock Transfer"), onClick: handleStockTransfer, buttonIcon: , align: "center", headerAlign: "center", }, // { // name: "status", // label: t("Status"), // type: "icon", // icons: { // available: , // unavailable: , // }, // colors: { // available: "success", // unavailable: "error", // } // }, ], [t, onDetailClick, downloadQrCode, handleStockTransfer], ); const handleCloseStockTransferModal = useCallback(() => { setStockTransferModalOpen(false); setSelectedLotLine(null); setStartLocation(""); setTargetLocation(""); setTargetLocationInput(""); setQtyToBeTransferred(0); }, []); const handleSubmitStockTransfer = useCallback(async () => { try { setIsUploading(true); // Decrease the inQty (availableQty) in the source inventory lot line // TODO: Add logic to increase qty in target location warehouse alert(t("Stock transfer successful")); handleCloseStockTransferModal(); // TODO: Refresh the inventory lot lines list } catch (error: any) { console.error("Error transferring stock:", error); alert(error?.message || t("Failed to transfer stock. Please try again.")); } finally { setIsUploading(false); } }, [selectedLotLine, targetLocation, qtyToBeTransferred, originalQty, handleCloseStockTransferModal, setIsUploading, t]); return <> {inventory ? `${t("Item selected")}: ${inventory.itemCode} | ${inventory.itemName} (${t(inventory.itemType)})` : t("No items are selected yet.")} items={inventoryLotLines ?? []} columns={columns} pagingController={pagingController} setPagingController={setPagingController} totalCount={totalCount} /> {inventory && selectedLotLine ? `${inventory.itemCode} ${inventory.itemName} (${selectedLotLine.lotNo})` : t("Stock Transfer") } {t("to")} w.code !== startLocation)} getOptionLabel={(option) => option.code || ""} value={targetLocation ? warehouses.find(w => w.code === targetLocation) || null : null} inputValue={targetLocationInput} onInputChange={(event, newInputValue) => { setTargetLocationInput(newInputValue); if (targetLocation && newInputValue !== targetLocation) { setTargetLocation(""); } }} onChange={(event, newValue) => { if (newValue) { setTargetLocation(newValue.code); setTargetLocationInput(newValue.code); } else { setTargetLocation(""); setTargetLocationInput(""); } }} filterOptions={(options, { inputValue }) => { if (!inputValue || inputValue.trim() === "") return options; const searchTerm = inputValue.toLowerCase().trim(); return options.filter((option) => (option.code || "").toLowerCase().includes(searchTerm) || (option.name || "").toLowerCase().includes(searchTerm) || (option.description || "").toLowerCase().includes(searchTerm) ); }} isOptionEqualToValue={(option, value) => option.code === value.code} autoHighlight={false} autoSelect={false} clearOnBlur={false} renderOption={(props, option) => (
  • {option.code}
  • )} renderInput={(params) => ( )} />
    - { const value = parseInt(e.target.value) || 0; const maxValue = Math.max(0, originalQty); setQtyToBeTransferred(Math.min(Math.max(0, value), maxValue)); }} inputProps={{ min: 0, max: originalQty, step: 1 }} InputLabelProps={{ shrink: true, sx: { fontSize: "0.9375rem" }, }} /> =
    } export default InventoryLotLineTable;