diff --git a/src/_nav.js b/src/_nav.js index ffdfe39..f9ab4c0 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -110,6 +110,13 @@ const _nav = [ to: "/leaves/today", group: "Leaves", }, + { + component: CNavItem, + name: "Inventory Data", + icon: , + to: "/inventory", + group: "Inventory", + }, // { // component: CNavGroup, // name: "Orders", diff --git a/src/routes.js b/src/routes.js index 6f56c0a..8d26eaf 100644 --- a/src/routes.js +++ b/src/routes.js @@ -143,6 +143,8 @@ import RetailDistributor from "./views/RetailDistributors/RetailDistributor"; import SingleRetailDistributor from "./views/RetailDistributors/SingleRetailDistributor"; import AddMultipleProduct from "./views/Products/AddMultipleProducts"; import AddMultiplePd from "./views/PrincipalDistributors/AddMultiplePD"; +import Inventory from "./views/Inventory/Inventory"; +import SingleInventory from "./views/Inventory/SingleInventory"; const routes = [ //dashboard @@ -367,6 +369,19 @@ const routes = [ element: AddMultiplePd, navName: "PrincipalDistributor", }, + //Inventory + { + path: "/inventory", + name: "Inventory", + element: Inventory, + navName: "Inventory", + }, + { + path: "/inventory/view/:id", + name: "Inventory", + element: SingleInventory, + navName: "Inventory", + }, //------------------ End customers Route------------------------- // { diff --git a/src/views/Inventory/Inventory.js b/src/views/Inventory/Inventory.js new file mode 100644 index 0000000..d32d0b8 --- /dev/null +++ b/src/views/Inventory/Inventory.js @@ -0,0 +1,370 @@ +import React, { useState, useEffect, useRef, useCallback } from "react"; +import { Link } from "react-router-dom"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; +import swal from "sweetalert"; +import debounce from "lodash.debounce"; + +const Inventory = () => { + const token = isAutheticated(); + const [loading, setLoading] = useState(false); + const [inventoryData, setInventoryData] = useState([]); + const [filteredData, setFilteredData] = useState([]); + + const nameRef = useRef(); + const startDateRef = useRef(); + const endDateRef = useRef(); + + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [totalData, setTotalData] = useState(0); + + const getInventoryData = async () => { + setLoading(true); + try { + const response = await axios.get(`api/inventory/all`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: currentPage, + show: itemPerPage, + startDate: startDateRef.current?.value || "", + endDate: endDateRef.current?.value || "", + }, + }); + + const transformedData = + response.data?.inventories?.map((entry) => ({ + id: entry._id, + tradeName: + entry.addedForData?.shippingAddress?.tradeName || + entry.addedForData?.trade_name || + "N/A", + designation: entry.addedFor === "PrincipalDistributor" ? "PD" : "RD", + products: entry.products.map((product) => ({ + SKU: product.SKU, + ProductName: product.ProductName, + Sale: product.Sale, + Inventory: product.Inventory, + })), + createdAt: entry.createdAt, + updatedAt: entry.updatedAt, + })) || []; + + setInventoryData(transformedData); + setTotalData(response.data?.total_data || 0); + + // Apply the filter after data is fetched + filterData(transformedData); + + } catch (err) { + const msg = err?.response?.data?.msg || "Something went wrong!"; + swal({ + title: "Error", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + } finally { + setLoading(false); + } + }; + + const filterData = (data) => { + const tradeName = nameRef.current?.value || ""; + const filtered = data.filter((entry) => + entry.tradeName.toLowerCase().includes(tradeName.toLowerCase()) + ); + setFilteredData(filtered); + }; + + const debouncedSearch = useCallback( + debounce(() => { + setCurrentPage(1); + getInventoryData(); + }, 500), + [] + ); + + const handleSearchChange = () => { + debouncedSearch(); + }; + + useEffect(() => { + getInventoryData(); + }, [itemPerPage, currentPage]); + + return ( +
+
+
+
+
+
+
+ Inventory List +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + {loading ? ( + + + + ) : filteredData.length > 0 ? ( + filteredData.map((entry, i) => + entry.products.map((product, j) => ( + + + + + + + + + + + + + )) + ) + ) : ( + !loading && + filteredData.length === 0 && ( + + + + ) + )} + +
IDDateTimeTrade NamePD/RDProduct SKUProduct NameSaleInventoryActions
+ Loading... +
{entry.id} + {new Date(entry.createdAt).toLocaleString( + "en-IN", + { + month: "short", + day: "numeric", + year: "numeric", + } + )} + + {new Date(entry.createdAt).toLocaleString( + "en-IN", + { + hour: "numeric", + minute: "numeric", + hour12: true, + } + )} + + {entry.tradeName} + + {entry.designation} + {product.SKU} + {product.ProductName} + {product.Sale} + {product.Inventory} + + + + +
+
No Data Available...
+
+
+ +
+
+
+ Showing {Math.min(itemPerPage * currentPage, totalData)} of {totalData} entries +
+
+ +
+
+
+
+
+
+
+
+ ); +}; + +export default Inventory; diff --git a/src/views/Inventory/SingleInventory.js b/src/views/Inventory/SingleInventory.js new file mode 100644 index 0000000..f62f98c --- /dev/null +++ b/src/views/Inventory/SingleInventory.js @@ -0,0 +1,178 @@ +import React, { useState, useEffect } from "react"; +import axios from "axios"; +import { + Box, + Typography, + Grid, + Paper, + IconButton, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Paper as MuiPaper, +} from "@mui/material"; +import { useParams, useNavigate } from "react-router-dom"; +import { isAutheticated } from "../../auth"; +import CancelIcon from "@mui/icons-material/Cancel"; // Add this import + +const SingleInventory = () => { + const { id } = useParams(); + const [inventoryDetails, setInventoryDetails] = useState(null); + const token = isAutheticated(); + const navigate = useNavigate(); + + useEffect(() => { + const fetchData = async () => { + try { + const response = await axios.get(`api/inventory/${id}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + setInventoryDetails(response.data); + // console.log("Inventory Details: ", response.data); + } catch (error) { + console.error("Error fetching data: ", error); + } + }; + + fetchData(); + }, [id]); + + const handleCancel = () => { + navigate("/inventory"); + }; + + if (!inventoryDetails) { + return Loading...; + } + + return ( + + + Inventory Details + + + + + + + + Inventory Data + + + + + Timestamp:{" "} + {new Date(inventoryDetails.createdAt).toLocaleString("en-IN", { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + })} + + + + + + + + Product Details + + + + + + Product Name + SKU + Sale + Inventory + + + + {inventoryDetails.products.map((product, index) => ( + + {product.ProductName} + {product.SKU} + {product.Sale} + {product.Inventory} + + ))} + +
+
+
+ + + + Data Added For + + + + + PD or RD:{" "} + {inventoryDetails.addedFor} + + + Name: {inventoryDetails.addedForData.name} + + + Mobile Number:{" "} + {inventoryDetails.addedForData.phone || inventoryDetails.addedForData.mobile_number} + + + Email: {inventoryDetails.addedForData.email||'N/A'} + + + Trade Name:{" "} + {inventoryDetails.addedForData.shippingAddress?.tradeName||inventoryDetails.addedForData.trade_name} + + + + + + + + Data Entered By + + + + + Designation: {inventoryDetails.userType} + + + Name: {inventoryDetails.user?.name} + + + ID: {inventoryDetails.user?.uniqueId} + + + Email: {inventoryDetails.user?.email} + + + Mobile Number:{" "} + {inventoryDetails.user?.mobileNumber} + + + + +
+ ); +}; + +export default SingleInventory; diff --git a/src/views/PrincipalDistributors/addPrincipalDistributor.js b/src/views/PrincipalDistributors/addPrincipalDistributor.js index c8dd404..cec2350 100644 --- a/src/views/PrincipalDistributors/addPrincipalDistributor.js +++ b/src/views/PrincipalDistributors/addPrincipalDistributor.js @@ -20,6 +20,7 @@ const AddPrincipalDistributor = () => { const token = isAutheticated(); const [user, setUser] = useState({ + PD_ID: "", name: "", email: "", phone: "", @@ -89,6 +90,7 @@ const AddPrincipalDistributor = () => { try { // Validate input fields if ( + !user.PD_ID || !user.name || !user.email || !user.phone || @@ -167,7 +169,20 @@ const AddPrincipalDistributor = () => { Basic Information - + + + + { onChange={handleInputChange} /> - + { onChange={handleInputChange} /> - + { { { const [loading, setLoading] = useState(false); const [data, setData] = useState({ + SKU:"", name: "", category: "", description: "", diff --git a/src/views/Products/Productcomponents/ProductDetails.js b/src/views/Products/Productcomponents/ProductDetails.js index 4f01907..d3a1509 100644 --- a/src/views/Products/Productcomponents/ProductDetails.js +++ b/src/views/Products/Productcomponents/ProductDetails.js @@ -89,6 +89,19 @@ const ProductDetails = (props) => { {loading ? "Loading" : "Save Details"} +
+ + handleChange(e)} + /> +
)} + {product.SKU} {product.name} {product.category?.categoryName !== "" diff --git a/src/views/Products/ViewProduct.js b/src/views/Products/ViewProduct.js index f22f01d..600a382 100644 --- a/src/views/Products/ViewProduct.js +++ b/src/views/Products/ViewProduct.js @@ -66,6 +66,10 @@ const ViewProduct = () => {
+ + + + diff --git a/src/views/RetailDistributors/SingleRetailDistributor.js b/src/views/RetailDistributors/SingleRetailDistributor.js index 2396306..d2e13f4 100644 --- a/src/views/RetailDistributors/SingleRetailDistributor.js +++ b/src/views/RetailDistributors/SingleRetailDistributor.js @@ -26,35 +26,7 @@ const SingleRetailDistributor = () => { }, }); setRetailerDetails(response.data); - - // // Dummy data - // const dummyData = { - // _id: '66a8bb8392d90216331b1f73', - // name: 'roshan garg', - // trade_name: 'abc', - // address: 'abc btm', - // state: 'KA', - // city: 'Bengaluru', - // district: 'benga', - // pincode: '124515', - // mobile_number: '8516913819', - // principal_distributer: { name: 'Distributor Name' }, - // pan_number: '123456454', - // pan_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334072/KYC/pan/u3a08xjvrpovfzruedeq.png' }, - // aadhar_number: '123123123123', - // aadhar_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334074/KYC/aadhar/ep64tuufileifysol4dx.png' }, - // gst_number: '121212', - // gst_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334076/KYC/gst/jqy8uqa6ejntwhc7mq86.png' }, - // pesticide_license_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334077/KYC/pesticide_license/iyznci3iibp50pug8e8p.png' }, - // fertilizer_license_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334080/KYC/fertilizer_license/jnj1r8rzwsbkclarbbch.png' }, - // selfie_entrance_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334082/KYC/selfie_entrance/weri7zhyioi7lqwv3dvg.png' }, - // status: 'new', - // addedBy: { name: 'Added By', uniqueId: 'E123' }, - // notes: [], - // createdAt: '2024-01-01T00:00:00Z', - // updatedAt: '2024-01-01T00:00:00Z', - // }; - // setRetailerDetails(dummyData); + // console.log('Retailer Details: ', response.data); } catch (error) { console.error('Error fetching data: ', error); } @@ -209,7 +181,10 @@ const SingleRetailDistributor = () => { - Designation: {retailerDetails.addedBy.name} + Designation: {retailerDetails.userType} + + + Name: {retailerDetails.addedBy.name} ID: {retailerDetails.addedBy.uniqueId}
SKU{productData?.SKU}
Name {productData?.name}