diff --git a/src/components/LoadStock/loadStock.jsx b/src/components/LoadStock/loadStock.jsx new file mode 100644 index 0000000..286c0ac --- /dev/null +++ b/src/components/LoadStock/loadStock.jsx @@ -0,0 +1,279 @@ +import { Add16, Subtract16 } from "@carbon/icons-react"; +import { + Button, + Column, + ComboBox, + DataTable, + DatePicker, + DatePickerInput, + Modal, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableHeader, + TableRow, + TextInput, +} from "carbon-components-react"; +import React, { useEffect, useState } from "react"; +import { useCookies } from "react-cookie"; +import useSWR from "swr"; +import { failureMessage, locationCookieName, successMessage } from "../../../constants"; +import "../../../index.scss"; +import { getLoadStockObj } from "../../inventory/aushada/eaushadha-response-mapper"; +import saveStockInitial from "../../service/save-initial"; +import { fetcher, invItemURL, inventoryItemURL, stockRoomURL } from "../../utils/api-utils"; +import { getDatePattern } from "../../utils/date-utils"; +import { ResponseNotification } from "../notifications/response-notification"; +import styles from "./loadStock.module.scss"; + +export const LoadStock = (props) => { + const [addDrugItems, setAddDrugItems] = useState([]); + const [showModal, setShowModal] = useState(false); + const [isSaveButtonDisabled, setSaveButtonDisabled] = useState(true); + const [rows, setRows] = useState([{ id: 1, drugName: "", batchNo: "", expiryDate: "", quantity: 0, totalQuantity: 0 }]); + const [onSuccessful, setOnSuccessful] = useState(false); + const [onFailure, setOnFailure] = useState(false); + const [cookies] = useCookies(); + const { setReloadData } = props; + let dropdownItems = []; + + const { data: inventoryItems, error: inventoryItemsError } = useSWR(inventoryItemURL(), fetcher); + let totalInventoryItems = inventoryItems?.length; + const { data: stockRoom, error: stockRoomError } = useSWR(stockRoomURL(cookies[locationCookieName]?.name.trim()), fetcher); + const { data: invItems, error: inventoryItemError } = useSWR(totalInventoryItems !== undefined ? invItemURL(totalInventoryItems) : "", fetcher); + + if (invItems?.results?.length > 0) { + for (let index = 0; index < invItems.results.length; index++) { + dropdownItems.push(invItems.results[index].name); + } + } + + useEffect(() => { + if (onSuccessful) { + setAddDrugItems([]); + setReloadData(false); + } + }, [onSuccessful]); + + useEffect(() => { + if (!showModal) { + setAddDrugItems([]); + setRows([ + { + id: 1, + drugName: "", + batchNo: "", + expiryDate: "", + quantity: 0, + totalQuantity: 0, + invalid: false, + }, + ]); + } + }, [showModal]); + + useEffect(() => { + const hasEmptyOrNegativeFields = rows.some((row) => !row.drugName || !row.batchNo || !row.expiryDate || !row.totalQuantity || row.totalQuantity <= 0); + setSaveButtonDisabled(hasEmptyOrNegativeFields); + }, [rows]); + + useEffect(() => { + const saveData = async () => { + try { + const response = await saveStockInitial(addDrugItems, "", stockRoom.results[0]?.uuid); + if (response && response.ok) { + setReloadData(true); + setOnSuccessful(true); + } else { + setOnFailure(true); + } + } catch (error) { + console.error("An error occurred during save:", error); + } + }; + + if (addDrugItems.length > 0) { + saveData(); + } + }, [addDrugItems]); + + const setOnSuccessAndFailure = (status) => { + setOnSuccessful(status); + setOnFailure(status); + }; + + const handleSaveDrugButtonClick = async () => { + try { + setAddDrugItems(getLoadStockObj(rows)); + setShowModal(false); + } catch (error) { + console.error("An error occurred:", error); + return; + } + }; + + const handleAddRow = () => { + setRows((prevRows) => [ + ...prevRows, + { + id: prevRows.length + 1, + drugName: "", + batchNo: "", + expiryDate: "", + totalQuantity: 0, + invalid: false, + }, + ]); + }; + + const handleDeleteRow = (id) => { + setRows((prevRows) => prevRows.filter((row) => row.id !== id)); + }; + + const handleComboBoxChange = (rowId, selectedValue) => { + setRows((prevRows) => + prevRows.map((row) => { + if (row.id === rowId) { + return { ...row, drugName: selectedValue }; + } + return row; + }) + ); + }; + + const isInvalid = (id) => { + const row = rows.find((row) => row.id === id); + return row ? row.invalid : false; + }; + + const handleInputChange = (id, field, value) => { + if (field === "totalQuantity") { + setRows((prevRows) => prevRows.map((row) => (row.id === id ? { ...row, totalQuantity: value, invalid: value <= 0 } : row))); + } else if (field === "expiryDate") { + setRows((prevRows) => prevRows.map((row) => (row.id === id ? { ...row, expiryDate: value } : row))); + } else { + setRows((prevRows) => prevRows.map((row) => (row.id === id ? { ...row, [field]: value } : row))); + } + }; + + const handleCloseModal = () => { + setShowModal(false); + }; + + const filterItems = (menu) => menu?.item?.toLowerCase().includes(menu?.inputValue?.toLowerCase()); + + return ( + + + {onSuccessful && ResponseNotification("success", "Success", successMessage, setOnSuccessAndFailure)} + {onFailure && ResponseNotification("error", "Error", failureMessage, setOnSuccessAndFailure)} + + + {showModal && ( + + ( + + + + + {headers.map((header, index) => ( + + {header} + + ))} + + + + {rows.map((row) => ( + <> + + {row.id} + + handleComboBoxChange(row.id, selectedItem)} + style={{ width: "270px" }} + /> + + + handleInputChange(row.id, "batchNo", e.target.value)} + /> + + + handleInputChange(row.id, "expiryDate", date[0])} + > + handleInputChange(row.id, "expiryDate", e.target.value)} pattern={getDatePattern} /> + + + + handleInputChange(row.id, "totalQuantity", e.target.valueAsNumber)} + /> + + +
+
- - - {showModal && ( - - ( - - - - - {headers.map((header, index) => ( - - {header} - - ))} - - - - {rows.map((row) => ( - <> - - {row.id} - - - handleComboBoxChange(row.id, selectedItem) - } - style={{ width: '270px' }} - /> - - - - handleInputChange(row.id, 'batchNo', e.target.value) - } - /> - - - - handleInputChange(row.id, 'expiryDate', date[0]) - } - > - - handleInputChange(row.id, 'expiryDate', e.target.value) - } - pattern={getDatePattern} - /> - - - - - handleInputChange( - row.id, - 'totalQuantity', - e.target.valueAsNumber, - ) - } - /> - - -
- - )} - - + + )} + +
{headers.map((header) => ( @@ -160,7 +165,7 @@ const InventoryLandingPage = () => { title={`Stock Details for ${selectedProductName}`} /> )} - + ); }; diff --git a/src/inventory/inventory-menu.jsx b/src/inventory/inventory-menu.jsx index 20e05f2..be46f00 100644 --- a/src/inventory/inventory-menu.jsx +++ b/src/inventory/inventory-menu.jsx @@ -5,7 +5,7 @@ import useSWR, { mutate } from 'swr'; import InventoryLandingPage from './inventory-landing-page'; import { getLocationName, inventoryMenu, locationCookieName } from '../../constants'; import DispensePage from './dispense/dispense-page'; -import StockReceipt from './stock-receipt/stock-receipt'; +import Aushada from './aushada/aushada'; import { fetcher, invItemURLByStockroom, stockRoomURL } from '../utils/api-utils'; import { useItemStockContext, useStockRoomContext } from '../context/item-stock-context'; import { ResponseNotification } from '../components/notifications/response-notification'; @@ -73,10 +73,10 @@ const InventoryMenu = () => {

{getLocationName(cookies[locationCookieName]?.name)}

- + - - + + diff --git a/src/inventory/inventory.module.scss b/src/inventory/inventory.module.scss index ad75d00..869a0cc 100644 --- a/src/inventory/inventory.module.scss +++ b/src/inventory/inventory.module.scss @@ -17,14 +17,11 @@ left: 0; z-index: 2; } -.tableToolbarContent { - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; -} .inventoryContainer { @media all and (min-width: 768px) { width: 50%; } -} + display: flex; + flex-direction: column; + align-items: flex-end; +} \ No newline at end of file diff --git a/src/utils/api-utils.js b/src/utils/api-utils.js index cd34f67..e63462d 100644 --- a/src/utils/api-utils.js +++ b/src/utils/api-utils.js @@ -4,13 +4,13 @@ export const inventoryItemURL=()=>`/openmrs/ws/rest/v2/inventory/item?limit=1&v= export const invItemURL=(limit)=>`/openmrs/ws/rest/v2/inventory/item?limit=${limit}&v=full`; export const activePatientWithDrugOrders = (locationUuid) => `/openmrs/ws/rest/v1/bahmnicore/sql?location_uuid=${locationUuid}&q=emrapi.sqlSearch.activePatientsWithDrugOrders&v=full`; -export const fetcher = (url) => - fetch(url).then((response) => { - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - return response.json(); - }); +export const fetcher = async (url) => { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); +}; const controller = new AbortController(); const timeout = 150000;