diff --git a/src/_nav.js b/src/_nav.js index 6c76fd9..42636d6 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -132,6 +132,13 @@ const _nav = [ to: "/inventory", group: "Inventory", }, + { + component: CNavItem, + name: "Sales Data", + icon: , + to: "/sales", + group: "Sales", + }, { component: CNavGroup, name: "Orders", diff --git a/src/routes.js b/src/routes.js index 03ae19b..f4fd360 100644 --- a/src/routes.js +++ b/src/routes.js @@ -162,6 +162,9 @@ import AddMultiplesc from "./views/SalesCoOrdinators/AddMultipleSC"; import Announcements from "./views/Announcment/announcement"; import CreateAnnouncement from "./views/Announcment/createAnnouncement"; import TodayTask from "./views/Tasks/TodayTasks"; +import Sales from "./views/Sales/Sales"; +import SingleSales from "./views/Sales/SingleSale"; +import MobileApp from "./views/configuration/MobileApp"; const routes = [ //dashboard @@ -483,6 +486,19 @@ const routes = [ element: SingleInventory, navName: "Inventory", }, + //Sales + { + path: "/sales", + name: "Sales", + element: Sales, + navName: "Sales", + }, + { + path: "/sales/view/:id", + name: "Sales", + element: SingleSales, + navName: "Sales", + }, //------------------ End customers Route------------------------- // { @@ -775,6 +791,7 @@ const routes = [ navName: "Configuration", }, { path: "/logo", name: "Logo", element: Logo, navName: "Configuration" }, + { path: "/mobile-app", name: "MobileApp", element: MobileApp, navName: "Configuration" }, //----------------- End Configuration Routes----------------------------------- //-----------------Affiliate & Coupons Routes----------------------------------- diff --git a/src/views/Categories/categories.js b/src/views/Categories/categories.js index 8a997d5..ebdd031 100644 --- a/src/views/Categories/categories.js +++ b/src/views/Categories/categories.js @@ -442,7 +442,7 @@ const Categories = () => { {!loading && category.length === 0 && ( - +
No Data Available
diff --git a/src/views/RetailDistributors/MapRD.js b/src/views/RetailDistributors/MapRD.js index 97736e4..b1043d6 100644 --- a/src/views/RetailDistributors/MapRD.js +++ b/src/views/RetailDistributors/MapRD.js @@ -1,65 +1,27 @@ -import React, { useState, useEffect, useRef, useCallback } from "react"; +import React, { useState, useEffect } from "react"; import axios from "axios"; -import { - Box, - Typography, - Grid, - Paper, - Dialog, - DialogContent, - DialogTitle, -} from "@mui/material"; +import { Box, Typography, Grid, Paper } from "@mui/material"; import { useParams, useNavigate } from "react-router-dom"; import { isAutheticated } from "../../auth"; import Button from "@material-ui/core/Button"; import swal from "sweetalert"; -import debounce from "lodash.debounce"; -import TextField from "@mui/material/TextField"; -import DialogActions from "@mui/material/DialogActions"; +import PDmodal from "./ModalPD.js"; +import SCmodal from "./ModalSC.js"; +import TMmodal from "./ModalTM.js"; const MapRD = () => { const { id } = useParams(); const token = isAutheticated(); const navigate = useNavigate(); - - const [loading, setLoading] = useState(false); const [success, setSuccess] = useState(true); const [data, setData] = useState(null); - - const pdnameRef = useRef(); - const pdmobileRef = useRef(); - const scnameRef = useRef(); - const scmobileRef = useRef(); - const tmnameRef = useRef(); - const tmmobileRef = useRef(); - - const [modalcurrentPage, setmodalCurrentPage] = useState(1); - const modalitemPerPage = 10; const [openPDModal, setOpenPDModal] = useState(false); const [openSCModal, setOpenSCModal] = useState(false); const [openTMModal, setOpenTMModal] = useState(false); - // For opening each modal - const handleOpenPDModal = () => setOpenPDModal(true); - const handleOpenSCModal = () => setOpenSCModal(true); - const handleOpenTMModal = () => setOpenTMModal(true); - - // For closing each modal - const handleClosePDModal = () => setOpenPDModal(false); - const handleCloseSCModal = () => setOpenSCModal(false); - const handleCloseTMModal = () => setOpenTMModal(false); - - const [modalTotalData, setModalTotalData] = useState(0); - const [modalSalesCoordinators, setModalSalesCoordinators] = useState([]); - const [modalPrincipalDistributors, setmodalPrincipalDistributors] = useState( - [] - ); - const [modalterritorymanagers, setmodalterritorymanagers] = useState([]); - useEffect(() => { const fetchData = async () => { try { - // Commented out the API call and using dummy data const response = await axios.get(`/api/getRD/${id}`, { headers: { "Access-Control-Allow-Origin": "*", @@ -67,8 +29,7 @@ const MapRD = () => { "Content-Type": "multipart/form-data", }, }); - setData(response.data); - // console.log('Retailer Details: ', response.data); + setData(response?.data); } catch (error) { console.error("Error fetching data: ", error); } @@ -77,161 +38,6 @@ const MapRD = () => { fetchData(); }, [id, token, success]); - // SC - const getSalesCoOrdinatorsData = async () => { - setLoading(true); - try { - const res = await axios.get(`/api/salescoordinator/getAll`, { - headers: { - Authorization: `Bearer ${token}`, - }, - params: { - page: modalcurrentPage, - show: modalitemPerPage, - name: scnameRef.current?.value, - mobileNumber: scmobileRef.current?.value, - }, - }); - setModalSalesCoordinators(res.data?.salesCoOrinators); - setModalTotalData(res.data?.total_data); - } catch (err) { - const msg = err?.response?.data?.message || "Something went wrong!"; - swal({ - title: "Error", - text: msg, - icon: "error", - button: "Retry", - dangerMode: true, - }); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - if (openSCModal) { - getSalesCoOrdinatorsData(); - } - }, [openSCModal, modalcurrentPage]); - - // Debounced search for Sales Coordinators in modal - const debouncedmodalSearchforSC = useCallback( - debounce(() => { - setmodalCurrentPage(1); - getSalesCoOrdinatorsData(); - }, 500), - [modalcurrentPage] - ); - - const handlemodalSearchChangeinSC = useCallback(() => { - debouncedmodalSearchforSC(); - }, [debouncedmodalSearchforSC]); - - // PD - const getprincipaldistributorData = async () => { - setLoading(true); - try { - const res = await axios.get(`/api/v1/admin/users`, { - headers: { - Authorization: `Bearer ${token}`, - }, - params: { - page: modalcurrentPage, - show: modalitemPerPage, - name: pdnameRef.current?.value, - mobileNumber: pdmobileRef.current?.value, - }, - }); - setmodalPrincipalDistributors(res.data?.users); - setModalTotalData(res.data?.totalUsers); - } catch (err) { - const msg = err?.response?.data?.message || "Something went wrong!"; - swal({ - title: "Error", - text: msg, - icon: "error", - button: "Retry", - dangerMode: true, - }); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - if (openPDModal) { - getprincipaldistributorData(); - } - }, [openPDModal, modalcurrentPage]); - - // Debounced search for Principal Distributors in modal - const debouncedmodalSearchforPD = useCallback( - debounce(() => { - setmodalCurrentPage(1); - getprincipaldistributorData(); - }, 500), - [modalcurrentPage] - ); - - const handlemodalSearchChangeinPD = useCallback(() => { - debouncedmodalSearchforPD(); - }, [debouncedmodalSearchforPD]); - - // TM - const getTerritorymanagersData = async () => { - setLoading(true); - try { - const res = await axios.get(`/api/territorymanager/getAll`, { - headers: { - Authorization: `Bearer ${token}`, - }, - params: { - page: modalcurrentPage, - show: modalitemPerPage, - name: tmnameRef.current?.value, - mobileNumber: tmmobileRef.current?.value, - }, - }); - setmodalterritorymanagers(res.data?.territoryManager); - setModalTotalData(res.data?.total_data); - } catch (err) { - const msg = err?.response?.data?.message || "Something went wrong!"; - swal({ - title: "Error", - text: msg, - icon: "error", - button: "Retry", - dangerMode: true, - }); - } finally { - setLoading(false); - } - }; - - useEffect(() => { - if (openTMModal) { - getTerritorymanagersData(); - } - }, [openTMModal, modalcurrentPage]); - - // Debounced search for Territory manager in modal - const debouncedmodalSearchforTM = useCallback( - debounce(() => { - setmodalCurrentPage(1); - getTerritorymanagersData(); - }, 500), - [modalcurrentPage] - ); - - const handlemodalSearchChangeinTM = useCallback(() => { - debouncedmodalSearchforTM(); - }, [debouncedmodalSearchforTM]); - - const handlePreviousPage = () => { - if (modalcurrentPage > 1) { - setmodalCurrentPage(modalcurrentPage - 1); - } - }; const handleDelete = (designation) => { swal({ title: "Are you sure?", @@ -242,7 +48,6 @@ const MapRD = () => { }, }).then((value) => { if (value === true) { - // Create the data object based on designation let data = {}; if (designation === "TM") { data.mappedTM = true; @@ -251,19 +56,14 @@ const MapRD = () => { } else { data.principal_distributor = true; } - - // Make the PATCH request with the constructed data object + axios - .patch( - `/api/unmap/${id}`, - data, // Send the constructed data object - { - headers: { - "Access-Control-Allow-Origin": "*", - Authorization: `Bearer ${token}`, - }, - } - ) + .patch(`/api/unmap/${id}`, data, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) .then((res) => { swal({ title: "Deleted", @@ -286,59 +86,19 @@ const MapRD = () => { } }); }; - - const handleUpdateMapping = async (rdid, designation) => { - try { - // Create the data object based on designation - let data = {}; - if (designation === "TM") { - data.mappedTM = rdid; - } else if (designation === "SC") { - data.mappedSC = rdid; - } else { - data.principal_distributor = rdid; - } - - // Make the API request - await axios.put( - `/api/mapped/${id}`, - data, // Send the constructed data object - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); - - // Success alert - swal({ - title: "Success", - text: "Mapped successfully!", - icon: "success", - button: "Ok", - }); - - // Trigger success state change and close modals - setSuccess((prev) => !prev); - handleClosePDModal(); - handleCloseSCModal(); - handleCloseTMModal(); - } catch (err) { - // Handle error and show error message - const msg = err?.response?.data?.message || "Something went wrong!"; - swal({ - title: "Error", - text: msg, - icon: "error", - button: "Retry", - dangerMode: true, - }); - } - }; - if (!data) { - return Loading...; - } + const handleOpenPDModal = () => setOpenPDModal(true); + const handleClosePDModal = () => setOpenPDModal(false); + + const handleOpenSCModal = () => setOpenSCModal(true); + const handleCloseSCModal = () => setOpenSCModal(false); + + const handleOpenTMModal = () => setOpenTMModal(true); + const handleCloseTMModal = () => setOpenTMModal(false); + + const refreshData = () => { + setSuccess((prev) => !prev); + }; return ( @@ -374,28 +134,28 @@ const MapRD = () => { - Trade Name: {data.kyc.trade_name} + Trade Name: {data?.kyc.trade_name} - Name: {data.name} + Name: {data?.name} - Address: {data.kyc.address} + Address: {data?.kyc.address} - Town/City: {data.kyc.city} + Town/City: {data?.kyc.city} - District: {data.kyc.district} + District: {data?.kyc.district} - State: {data.kyc.state} + State: {data?.kyc.state} - Pincode: {data.kyc.pincode} + Pincode: {data?.kyc.pincode} - Mobile Number: {data.mobile_number} + Mobile Number: {data?.mobile_number} @@ -414,7 +174,6 @@ const MapRD = () => { - {/* Territory Managers */} { - Name: {data.mappedTM?.name || "Not Mapped"} + Name: {data?.mappedTM?.name || "Not Mapped"} Mobile Number:{" "} - {data.mappedTM?.mobileNumber || "Not Mapped"} + {data?.mappedTM?.mobileNumber || "Not Mapped"} - Email: {data.mappedTM?.email || "Not Mapped"} + Email: {data?.mappedTM?.email || "Not Mapped"} - {/* Sales Coordinators */} { - Name: {data.mappedSC?.name || "Not Mapped"} + Name: {data?.mappedSC?.name || "Not Mapped"} Mobile Number:{" "} - {data.mappedSC?.mobileNumber || "Not Mapped"} + {data?.mappedSC?.mobileNumber || "Not Mapped"} - Email: {data.mappedSC?.email || "Not Mapped"} + Email: {data?.mappedSC?.email || "Not Mapped"} - {/* Principal Distributor */} { - - - - - - - - - {/* Sales Coordinator */} - - Search and Add Sales Coordinator - -
- - -
-
- - - - - - - - - - - - {modalSalesCoordinators.map((coordinator) => ( - - - - - - - - ))} - -
IdNameMobileTMAction
{coordinator.uniqueId}{coordinator.name}{coordinator.mobileNumber}{coordinator.mappedby?.name || "N/A"} - -
-
-
-
- Showing {modalSalesCoordinators?.length} of {modalTotalData}{" "} - entries -
-
- - -
-
-
- - - -
- {/* Territory Manager */} - - Search and Add Territory Manager - -
- - -
-
- - - - - - - - - - - - {modalterritorymanagers.length > 0 ? ( - modalterritorymanagers.map((TM) => ( - - - - - - - - )) - ) : ( - - - - )} - -
IdNameMobileEmailAction
{TM.uniqueId}{TM.name}{TM.mobileNumber}{TM.email} - -
- No Territory Manager found! -
-
-
-
- Showing {modalterritorymanagers?.length} of {modalTotalData}{" "} - entries -
-
- - -
-
-
- - - -
+ + +
); }; diff --git a/src/views/RetailDistributors/ModalPD.js b/src/views/RetailDistributors/ModalPD.js new file mode 100644 index 0000000..93afe2d --- /dev/null +++ b/src/views/RetailDistributors/ModalPD.js @@ -0,0 +1,224 @@ +import React, { useState, useEffect, useRef, useCallback } from "react"; +import axios from "axios"; +import { + Box, + Typography, + Grid, + Paper, + Dialog, + DialogContent, + DialogTitle, + Button, + TextField, + DialogActions, +} from "@mui/material"; +import { isAutheticated } from "../../auth"; +import swal from "sweetalert"; +import debounce from "lodash.debounce"; + +const PDmodal = ({ openPDModal, handleClosePDModal, refreshData, rdid }) => { + const token = isAutheticated(); + const [modalPrincipalDistributors, setmodalPrincipalDistributors] = useState( + [] + ); + const [modalTotalData, setModalTotalData] = useState(0); + const [modalcurrentPage, setmodalCurrentPage] = useState(1); + const [modalitemPerPage, setmodalItemPerPage] = useState(10); + const [loading, setLoading] = useState(false); + const pdnameRef = useRef(); + const pdmobileRef = useRef(); + + const getprincipaldistributorData = async () => { + setLoading(true); + try { + const res = await axios.get(`/api/v1/admin/users`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: modalcurrentPage, + show: modalitemPerPage, + name: pdnameRef.current?.value, + mobileNumber: pdmobileRef.current?.value, + }, + }); + setmodalPrincipalDistributors(res.data?.users); + setModalTotalData(res.data?.totalUsers); + } catch (err) { + const msg = err?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Error", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + } finally { + setLoading(false); + } + }; + + const handlePDMap = (id) => { + const data = { + principal_distributor: id, + }; + axios + .put(`/api/mapped/${rdid}`, data, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + swal({ + title: "Success", + text: "Principal Distributor mapped successfully!", + icon: "success", + button: "Ok", + }); + refreshData(); // Call the refresh function + handleClosePDModal(); + }) + .catch((err) => { + const msg = err?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Error", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + useEffect(() => { + getprincipaldistributorData(); + }, [modalcurrentPage]); + + const handleInputChange = useCallback( + debounce(() => { + getprincipaldistributorData(); + }, 1000), + [] + ); + const handleNextPage = () => { + setmodalCurrentPage((prev) => prev + 1); + }; + const handlePreviousPage = () => { + setmodalCurrentPage((prev) => prev - 1); + }; + return ( + + Map Principal Distributor + Search and Add Principal Distributor + +
+ + +
+
+ + + + + + + + + + + + + + + {modalPrincipalDistributors.length > 0 ? ( + modalPrincipalDistributors.map((PD) => ( + + + + + + + + + + + )) + ) : ( + + + + )} + +
IdSBUNameMobileEmailSCTMAction
{PD.uniqueId}{PD.SBU}{PD.name}{PD.phone}{PD.email}{PD.mappedbySC?.name || "N/A"}{PD.mappedby?.name || "N/A"} + +
+ No Principal Distributor found! +
+
+
+
+ Showing {modalPrincipalDistributors.length} of {modalTotalData}{" "} + entries +
+
+ + +
+
+
+ + + +
+ ); +}; + +export default PDmodal; diff --git a/src/views/RetailDistributors/ModalSC.js b/src/views/RetailDistributors/ModalSC.js new file mode 100644 index 0000000..7369f19 --- /dev/null +++ b/src/views/RetailDistributors/ModalSC.js @@ -0,0 +1,206 @@ +import React, { useState, useEffect, useRef, useCallback } from "react"; +import axios from "axios"; +import { + Dialog, + DialogContent, + DialogTitle, + Button, + TextField, + DialogActions, +} from "@mui/material"; +import { isAutheticated } from "../../auth"; +import swal from "sweetalert"; +import debounce from "lodash.debounce"; + +const SCmodal = ({ openSCModal, handleCloseSCModal, refreshData, rdid }) => { + const token = isAutheticated(); + const [modalSalesCoordinators, setmodalSalesCoordinators] = useState( + [] + ); + const [modalTotalData, setModalTotalData] = useState(0); + const [modalcurrentPage, setmodalCurrentPage] = useState(1); + const [modalitemPerPage, setmodalItemPerPage] = useState(10); + const [loading, setLoading] = useState(false); + const scnameRef = useRef(); + const scmobileRef = useRef(); + + const getSalesCoOrdinatorsData = async () => { + setLoading(true); + try { + const res = await axios.get(`/api/salescoordinator/getAll`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: modalcurrentPage, + show: modalitemPerPage, + name: scnameRef.current?.value, + mobileNumber: scmobileRef.current?.value, + }, + }); + setmodalSalesCoordinators(res.data?.salesCoOrinators); + setModalTotalData(res.data?.total_data); + } catch (err) { + const msg = err?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Error", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + } finally { + setLoading(false); + } + }; + + const handleSCMap = (id) => { + const data = { + mappedSC: id, + }; + axios + .put(`/api/mapped/${rdid}`, data, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + swal({ + title: "Success", + text: "Principal Distributor mapped successfully!", + icon: "success", + button: "Ok", + }); + refreshData(); // Call the refresh function + handleCloseSCModal(); + }) + .catch((err) => { + const msg = err?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Error", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + useEffect(() => { + getSalesCoOrdinatorsData(); + }, [modalcurrentPage]); + + const handleInputChange = useCallback( + debounce(() => { + getSalesCoOrdinatorsData(); + }, 1000), + [] + ); + const handleNextPage = () => { + setmodalCurrentPage((prev) => prev + 1); + }; + const handlePreviousPage = () => { + setmodalCurrentPage((prev) => prev - 1); + }; + return ( + + Search and Add Sales Coordinator + +
+ + +
+ +
+ + + + + + + + + + + + {modalSalesCoordinators.map((coordinator) => ( + + + + + + + + ))} + +
IdNameMobileTMAction
{coordinator.uniqueId}{coordinator.name}{coordinator.mobileNumber}{coordinator.mappedby?.name || "N/A"} + +
+
+
+
+ Showing {modalSalesCoordinators?.length} of {modalTotalData}{" "} + entries +
+
+ + +
+
+
+ + + +
+ ); +}; + +export default SCmodal; diff --git a/src/views/RetailDistributors/ModalTM.js b/src/views/RetailDistributors/ModalTM.js new file mode 100644 index 0000000..e455c9d --- /dev/null +++ b/src/views/RetailDistributors/ModalTM.js @@ -0,0 +1,213 @@ +import React, { useState, useEffect, useRef, useCallback } from "react"; +import axios from "axios"; +import { + Dialog, + DialogContent, + DialogTitle, + Button, + TextField, + DialogActions, +} from "@mui/material"; +import { isAutheticated } from "../../auth"; +import swal from "sweetalert"; +import debounce from "lodash.debounce"; + +const TMmodal = ({ openTMModal, handleCloseTMModal, refreshData, rdid }) => { + const token = isAutheticated(); + const [modalTerritoryManagers, setmodalTerritoryManagers] = useState( + [] + ); + const [modalTotalData, setModalTotalData] = useState(0); + const [modalcurrentPage, setmodalCurrentPage] = useState(1); + const [modalitemPerPage, setmodalItemPerPage] = useState(10); + const [loading, setLoading] = useState(false); + const tmnameRef = useRef(); + const tmmobileRef = useRef(); + + const getTerritorymanagersData = async () => { + setLoading(true); + try { + const res = await axios.get(`/api/territorymanager/getAll`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: modalcurrentPage, + show: modalitemPerPage, + name: tmnameRef.current?.value, + mobileNumber: tmmobileRef.current?.value, + }, + }); + setmodalTerritoryManagers(res.data?.territoryManager); + setModalTotalData(res.data?.total_data); + } catch (err) { + const msg = err?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Error", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + } finally { + setLoading(false); + } + }; + + const handleTMMap = (id) => { + const data = { + mappedTM: id, + }; + axios + .put(`/api/mapped/${rdid}`, data, { + headers: { + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + swal({ + title: "Success", + text: "Principal Distributor mapped successfully!", + icon: "success", + button: "Ok", + }); + refreshData(); // Call the refresh function + handleCloseTMModal(); + }) + .catch((err) => { + const msg = err?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Error", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + useEffect(() => { + getTerritorymanagersData(); + }, [modalcurrentPage]); + + const handleInputChange = useCallback( + debounce(() => { + getTerritorymanagersData(); + }, 1000), + [] + ); + const handleNextPage = () => { + setmodalCurrentPage((prev) => prev + 1); + }; + const handlePreviousPage = () => { + setmodalCurrentPage((prev) => prev - 1); + }; + return ( + + Search and Add Territory Manager + +
+ + +
+
+ + + + + + + + + + + + {modalTerritoryManagers.length > 0 ? ( + modalTerritoryManagers.map((TM) => ( + + + + + + + + )) + ) : ( + + + + )} + +
IdNameMobileEmailAction
{TM.uniqueId}{TM.name}{TM.mobileNumber}{TM.email} + +
+ No Territory Manager found! +
+
+
+
+ Showing {modalTerritoryManagers?.length} of {modalTotalData}{" "} + entries +
+
+ + +
+
+
+ + + +
+ ); +}; + +export default TMmodal; diff --git a/src/views/Sales/Sales.js b/src/views/Sales/Sales.js new file mode 100644 index 0000000..a8474f5 --- /dev/null +++ b/src/views/Sales/Sales.js @@ -0,0 +1,481 @@ +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 Sales = () => { + const token = isAutheticated(); + const [loading, setLoading] = useState(false); + const [SalesData, setSalesData] = 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 getSalesData = async () => { + setLoading(true); + try { + const response = await axios.get(`/api/sales/all`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: currentPage, + show: itemPerPage, + startDate: startDateRef.current?.value || "", + endDate: endDateRef.current?.value || "", + name: nameRef.current?.value || "", + }, + }); + // console.log("response", response.data); + const transformedData = + response.data?.Sales?.map((entry) => ({ + id: entry._id, + uniqueId: entry.uniqueId, + tradeName: entry.tradeName || "N/A", + designation: entry.addedFor === "PrincipalDistributor" ? "PD" : "RD", + products: entry.products.map((product) => ({ + SKU: product.SKU, + ProductName: product.ProductName, + SalesAmount: product.SalesAmount, + QuantitySold: product.QuantitySold, + })), + createdAt: entry.createdAt, + updatedAt: entry.updatedAt, + })) || []; + + setSalesData(transformedData); + setTotalData(response.data?.total_data || 0); + } 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 debouncedSearch = useCallback( + debounce(() => { + setCurrentPage(1); + getSalesData(); + }, 500), + [] + ); + + const handleSearchChange = () => { + debouncedSearch(); + }; + + useEffect(() => { + getSalesData(); + }, [itemPerPage, currentPage]); + + return ( +
+
+
+
+
+
+
+ Sales List +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + + + + {loading ? ( + + + + ) : SalesData.length > 0 ? ( + SalesData.map((entry, i) => + entry.products.map((product, j) => ( + + {/* Only show ID, Date, Time, Trade Name, PD/RD, and Actions on the first row of each entry */} + {j === 0 && ( + <> + + + + + + + )} + {/* Product details */} + + + + + {/* Actions: only show on the first row of each entry */} + {j === 0 && ( + + )} + + )) + ) + ) : ( + + + + )} + +
+ ID + + Date + + Time + + Trade Name + + PD/RD + + Product SKU + + Product Name + + QuantitySold + + SalesAmount + + Actions +
+ Loading... +
+ {entry.uniqueId} + + {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.QuantitySold} + + {product.SalesAmount} + + + + +
+
No Data 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 Sales; diff --git a/src/views/Sales/SingleSale.js b/src/views/Sales/SingleSale.js new file mode 100644 index 0000000..6a8c79c --- /dev/null +++ b/src/views/Sales/SingleSale.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 SingleSales = () => { + const { id } = useParams(); + const [SalesDetails, setSalesDetails] = useState(null); + const token = isAutheticated(); + const navigate = useNavigate(); + + useEffect(() => { + const fetchData = async () => { + try { + const response = await axios.get(`/api/sales/${id}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + setSalesDetails(response.data); + // console.log("Inventory Details: ", response.data); + } catch (error) { + console.error("Error fetching data: ", error); + } + }; + + fetchData(); + }, [id]); + + const handleCancel = () => { + navigate("/inventory"); + }; + + if (!SalesDetails) { + return Loading...; + } + + return ( + + + Sales Details + + + + + + + + Sales Data + + + + + Timestamp:{" "} + {new Date(SalesDetails.createdAt).toLocaleString("en-IN", { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + })} + + + + + + + + Product Details + + + + + + Product Name + SKU + QuantitySold + SalesAmount + + + + {SalesDetails.products.map((product, index) => ( + + {product.ProductName} + {product.SKU} + {product.QuantitySold} + {product.SalesAmount} + + ))} + +
+
+
+ + + + Data Added For + + + + + PD or RD:{" "} + {SalesDetails.addedFor} + + + Name: {SalesDetails.addedForData.name} + + + Mobile Number:{" "} + {SalesDetails.addedForData.phone || SalesDetails.addedForData.mobile_number} + + + Email: {SalesDetails.addedForData.email||'N/A'} + + + Trade Name:{" "} + {SalesDetails.addedForData.shippingAddress?.tradeName||SalesDetails.addedForData.kyc.trade_name} + + + + + + + + Data Entered By + + + + + Designation: {SalesDetails.userType} + + + Name: {SalesDetails.user?.name} + + + ID: {SalesDetails.user?.uniqueId} + + + Email: {SalesDetails.user?.email} + + + Mobile Number:{" "} + {SalesDetails.user?.mobileNumber} + + + + +
+ ); +}; + +export default SingleSales; diff --git a/src/views/configuration/MobileApp.js b/src/views/configuration/MobileApp.js new file mode 100644 index 0000000..94af13e --- /dev/null +++ b/src/views/configuration/MobileApp.js @@ -0,0 +1,249 @@ +import React, { useEffect, useState } from "react"; +import swal from "sweetalert"; +import ClipLoader from "react-spinners/ClipLoader"; +import { Link } from "react-router-dom"; +import axios from "axios"; +import { isAutheticated } from "src/auth"; + +function MobileApp() { + const [loading, setLoading] = useState(false); + const [PDApp, setPDApp] = useState(""); + const [RDApp, setRDApp] = useState(""); + const [SCApp, setSCApp] = useState(""); + const [TMApp, setTMApp] = useState(""); + const [display, setDisplay] = useState(true); + const token = isAutheticated(); + + // urlcreated images + + const [PDAppUrl, setPDAppUrl] = useState(""); + const [RDAppUrl, setRDAppUrl] = useState(""); + const [SCAppUrl, setSCAppUrl] = useState(""); + const [TMAppUrl, setTMAppUrl] = useState(""); + + useEffect(() => { + async function getConfiguration() { + const configDetails = await axios.get(`/api/config`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + // console.log(configDetails.data.result[0]?.logo[0]); + const data = configDetails.data.result[0]?.logo[0]; + setPDApp(data?.PDApp); + setRDApp(data?.RDApp); + setSCApp(data?.SCApp); + setTMApp(data?.TMApp); + } + getConfiguration(); + }, []); + + async function handelSubmit() { + setLoading(true); + + const formdata = new FormData(); + formdata.append("PDApp", PDApp); + formdata.append("RDApp", RDApp); + formdata.append("SCApp", SCApp); + formdata.append("TMApp", TMApp); + + await axios + .post(`/api/config/logo`, formdata, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "multipart/formdata", + "Access-Control-Allow-Origin": "*", + }, + }) + .then((res) => { + setLoading(false); + swal("Success!", res.data.message, res.data.status); + }) + .catch((error) => { + setLoading(false); + }); + } + + return ( +
+
+
+
+
+
+
+
+
+
+

Mobile App

+ +
+
+
+
+ <> + +
+ { + setPDApp(e.target.files[0]); + if ( + e.target.files && + e.target.files[0] + ) { + setPDAppUrl({ + image: URL.createObjectURL( + e.target.files[0] + ), + }); + console.log(setPDAppUrl); + } + }} + className="form-control input-field mb-3 col-md-6 d-inline-block" + id="basicpill-phoneno-input" + /> + {display ? ( + + ) : ( + "" + )} +
+ +
+ { + setRDApp(e.target.files[0]); + + if (e.target.files && e.target.files[0]) { + setRDAppUrl({ + image: URL.createObjectURL( + e.target.files[0] + ), + }); + } + }} + className="form-control input-field mt-1 col-md-6 d-inline-block" + id="basicpill-phoneno-input" + />{" "} + {display ? ( + + ) : ( + "" + )} + + { + setSCApp(e.target.files[0]); + + if (e.target.files && e.target.files[0]) { + setSCAppUrl({ + image: URL.createObjectURL( + e.target.files[0] + ), + }); + } + }} + className="form-control input-field col-md-6 d-inline-block" + id="basicpill-phoneno-input" + />{" "} + {display ? ( + + ) : ( + "" + )} + +
+
+
+
+
+
+ +
+
+
+
+
+
+ + {/* */} +
+
+
+
+
+ {/* */} +
+ {/* */} +
+
+ ); +} + +export default MobileApp;