From c478471124625dabf5a1f91ad1b6075a5827fe05 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Thu, 24 Oct 2024 11:06:19 +0530 Subject: [PATCH] opening inventory in PD --- src/_nav.js | 14 +- src/routes.js | 9 +- .../PrincipalDistributors/OpeningInventory.js | 525 ++++++++++++++++++ .../principalDistributor.js | 18 +- .../RetailDistributors/DistributorStock.js | 7 +- 5 files changed, 559 insertions(+), 14 deletions(-) create mode 100644 src/views/PrincipalDistributors/OpeningInventory.js diff --git a/src/_nav.js b/src/_nav.js index 5ae6421..bb31db6 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -104,13 +104,13 @@ const _nav = [ to: "/retail-distributor", group: "RetailDistributor", }, - { - component: CNavItem, - name: "Opening Inventory", - icon: , - to: "/opening-inventory", - group: "OpeningInventory", - }, + // { + // component: CNavItem, + // name: "Opening Inventory", + // icon: , + // to: "/opening-inventory", + // group: "OpeningInventory", + // }, { component: CNavItem, name: "Attendance", diff --git a/src/routes.js b/src/routes.js index 0cbbe0d..0abaa22 100644 --- a/src/routes.js +++ b/src/routes.js @@ -166,6 +166,7 @@ import Sales from "./views/Sales/Sales"; import SingleSales from "./views/Sales/SingleSale"; import MobileApp from "./views/configuration/MobileApp"; import PDOpeningInventory from "./views/OpeningInventory/PDOpeningInventory"; +import DistributorOpeningInventory from "./views/PrincipalDistributors/OpeningInventory"; const routes = [ //dashboard @@ -413,11 +414,17 @@ const routes = [ navName: "Distributor", }, { - path: "/:distributortype/:stocks/:id", + path: "/:distributortype/stocks/:id", name: " Distributor Stocks", element: DistributorStocks, navName: "Distributor", }, + { + path: "/:distributortype/opening-inventory/:id", + name: " Distributor Opening Inventory", + element: DistributorOpeningInventory, + navName: "Distributor", + }, //----------------------- End Product Management Routes------------------------------------------------ //Departure diff --git a/src/views/PrincipalDistributors/OpeningInventory.js b/src/views/PrincipalDistributors/OpeningInventory.js new file mode 100644 index 0000000..f85f2f2 --- /dev/null +++ b/src/views/PrincipalDistributors/OpeningInventory.js @@ -0,0 +1,525 @@ +import React, { useState, useEffect, useRef, useCallback } from "react"; +import { Link, useParams } from "react-router-dom"; +import axios from "axios"; +import Button from "@material-ui/core/Button"; +import { useNavigate } from "react-router-dom"; +import { isAutheticated } from "src/auth"; +import swal from "sweetalert"; +import debounce from "lodash.debounce"; +import { Typography, Paper } from "@mui/material"; + +const DistributorOpeningInventory = () => { + const token = isAutheticated(); + const navigate = useNavigate(); + const { id, distributortype } = useParams(); + + const [loading, setLoading] = useState(false); + const [productsData, setProductsData] = useState([]); + const [categories, setCategories] = useState([]); + const [brands, setBrands] = useState([]); + const [user, setUser] = useState(null); + const [updatedStocks, setUpdatedStocks] = useState({}); + const [currencyDetails, setCurrencyDetails] = useState(null); + + const nameRef = useRef(); + const categoryRef = useRef(); + const brandRef = useRef(); + + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [totalData, setTotalData] = useState(0); + + // Fetch User Details + const getUserDetails = useCallback(async () => { + try { + const response = await axios.get( + distributortype === "principaldistributor" + ? `/api/v1/admin/user/${id}` + : `/api/getRD/${id}`, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + setUser( + distributortype === "principaldistributor" + ? response.data.user + : response.data + ); + } catch (error) { + swal({ + title: "Warning", + text: error.message, + icon: "error", + button: "Close", + dangerMode: true, + }); + } + }, [id, token]); + + // Fetch Products Data + const getProductsData = async () => { + setLoading(true); + try { + const response = await axios.get( + distributortype === "principaldistributor" + ? `/api/pd/stock/${id}` + : `/api/rd/stock/${id}`, + { + headers: { Authorization: `Bearer ${token}` }, + params: { + page: currentPage, + show: itemPerPage, + name: nameRef.current?.value || "", + category: categoryRef.current?.value || "", + brand: brandRef.current?.value || "", + }, + } + ); + setProductsData(response.data?.products || []); + setTotalData(response.data?.totalProducts || 0); + } catch (err) { + swal({ + title: "Error", + text: "Something went wrong!", + icon: "error", + button: "Retry", + dangerMode: true, + }); + } finally { + setLoading(false); + } + }; + // Call getUserDetails on component mount + useEffect(() => { + getUserDetails(); + }, [getUserDetails]); + useEffect(() => { + getProductsData(); + }, [currentPage, itemPerPage]); + const getCatagories = () => { + axios + .get(`/api/category/getCategories`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + // console.log(res?.data?.categories); + setCategories(res?.data?.categories); + }); + }; + const getBrands = () => { + axios + .get(`/api/brand/getBrands`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + // console.log(res?.data?.brands); + setBrands(res?.data?.brands); + }); + }; + const getCurrency = async () => { + try { + const response = await axios.get("/api/currency/getall", { + // headers: { + // Authorization: `Bearer ${token}`, + // }, + }); + + if (response.status === 200) { + setCurrencyDetails(response?.data?.currency[0]); + } + } catch (error) { + console.log(error); + } + }; + useEffect(() => { + getCatagories(); + getCurrency(); + getBrands(); + }, []); + const handleSearchChange = useCallback( + debounce(() => { + setCurrentPage(1); + getProductsData(); + }, 500), + [] + ); + + const handleStockChange = (sku, newStock) => { + setUpdatedStocks((prevStocks) => ({ + ...prevStocks, + [sku]: newStock, // Update stock for specific product (identified by SKU) + })); + }; + + const handleSubmitStocks = async () => { + try { + const updatedProducts = productsData.map((product) => ({ + ...product, + stock: updatedStocks[product.SKU] || product.stock, + })); + await axios.post( + distributortype === "principaldistributor" + ? `/api/pd/updateStocks/${id}` + : `/api/rd/updateStocks/${id}`, + { updatedProducts }, + { headers: { Authorization: `Bearer ${token}` } } + ); + swal("Success", "Stocks updated successfully!", "success"); + } catch (error) { + swal("Error", "Failed to update stocks!", "error"); + } + }; + + const handleCancel = () => { + navigate( + distributortype === "principaldistributor" + ? "/principal-distributor" + : "/retail-distributor" + ); + }; + + return ( +
+
+
+
+
+ +
+
+ + Name: {user?.name} + + + Mobile Number:{" "} + {distributortype === "principaldistributor" + ? user?.phone + : user?.mobile_number} + + + Email: {user?.email} + +
+ + {/* Back Button on the right */} +
+ +
+
+
+ {/* Section Heading: Product Stocks */} +
+
+
+ Product Stocks +
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + {loading ? ( + + + + ) : productsData?.length > 0 ? ( + productsData?.map((product, i) => { + return ( + + + + + + + + + + ); + }) + ) : ( + !loading && + productsData?.length === 0 && ( + + + + ) + )} + +
SKUProductCategory NameBrand NamePriceAdded OnOpening Inventory
+ Loading... +
{product.SKU}{product.name} + {product.category !== "" + ? product.category + : "Category Not selected "} + + {product.brand !== "" + ? product.brand + : "Brand Not selected "} + + {currencyDetails?.CurrencySymbol} + {product?.price} + + {new Date(product.createdAt).toLocaleString( + "en-IN", + { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + } + )} + + { + // Check if the input is a valid number or empty + const value = e.target.value; + if ( + value === "" || + /^[0-9]*$/.test(value) + ) { + // Allow only numbers or empty + handleStockChange(product.SKU, value); + } + }} + className="form-control" + /> +
+
No Product Available...
+
+
+ +
+
+
+ Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} + {Math.min(currentPage * itemPerPage, totalData)} of{" "} + {totalData} entries +
+
+ +
+
+
    +
  • + setCurrentPage((prev) => prev - 1)} + disabled={loading} + > + Previous + +
  • + + {!(currentPage - 1 < 1) && ( +
  • + + setCurrentPage((prev) => prev - 1) + } + disabled={loading} + > + {currentPage - 1} + +
  • + )} + +
  • + + {currentPage} + +
  • + + {!( + (currentPage + 1) * itemPerPage - itemPerPage > + totalData - 1 + ) && ( +
  • + { + setCurrentPage((prev) => prev + 1); + }} + disabled={loading} + > + {currentPage + 1} + +
  • + )} + +
  • + totalData - 1 + ) + ? "paginate_button page-item next" + : "paginate_button page-item next disabled" + } + > + setCurrentPage((prev) => prev + 1)} + disabled={loading} + > + Next + +
  • +
+
+
+
+
+
+
+
+
+
+
+ ); +}; + +export default DistributorOpeningInventory; diff --git a/src/views/PrincipalDistributors/principalDistributor.js b/src/views/PrincipalDistributors/principalDistributor.js index e72c559..0795109 100644 --- a/src/views/PrincipalDistributors/principalDistributor.js +++ b/src/views/PrincipalDistributors/principalDistributor.js @@ -220,14 +220,14 @@ const principalDistributor = () => { > Unique Id - SBU + SBU Name - Email + Email Date Registered Last Purchase Orders Mapping - + Action @@ -411,6 +411,18 @@ const principalDistributor = () => { Stock + + + )) diff --git a/src/views/RetailDistributors/DistributorStock.js b/src/views/RetailDistributors/DistributorStock.js index 278017d..d6c60fa 100644 --- a/src/views/RetailDistributors/DistributorStock.js +++ b/src/views/RetailDistributors/DistributorStock.js @@ -160,7 +160,8 @@ const DistributorStocks = () => { const handleCancel = () => { navigate( distributortype === "principaldistributor" - ? stocks==="stocks"?"/principal-distributor":"/opening-inventory" + // ? stocks==="stocks"?"/principal-distributor":"/opening-inventory" + ? "/principal-distributor" : "/retail-distributor" ); }; @@ -324,7 +325,7 @@ const DistributorStocks = () => { productsData?.map((product, i) => { return ( - + {product?.image && product?.image?.length !== 0 ? ( <> @@ -344,7 +345,7 @@ const DistributorStocks = () => {

uploaded!

)} - + {product.SKU} {product.name}