@@ -205,8 +167,8 @@ const RetailDistributor = () => {
Loading...
- ) : paginatedData.length > 0 ? (
- paginatedData.map((retailDistributor) => (
+ ) : allRetailDistributorsData.length > 0 ? (
+ allRetailDistributorsData.map((retailDistributor) => (
{retailDistributor._id}
@@ -272,12 +234,7 @@ const RetailDistributor = () => {
role="status"
aria-live="polite"
>
- Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "}
- {Math.min(
- currentPage * itemPerPage,
- filteredRetailDistributorsData.length
- )}{" "}
- of {filteredRetailDistributorsData.length} entries
+ Showing {allRetailDistributorsData?.length} of {totalData} entries
diff --git a/src/views/RetailDistributors/SingleRetailDistributor.js b/src/views/RetailDistributors/SingleRetailDistributor.js
index d2e13f4..4fd7ce9 100644
--- a/src/views/RetailDistributors/SingleRetailDistributor.js
+++ b/src/views/RetailDistributors/SingleRetailDistributor.js
@@ -98,7 +98,7 @@ const SingleRetailDistributor = () => {
Mobile Number: {retailerDetails.mobile_number}
- Mapped Principal Distributor: {retailerDetails.principal_distributer.name}
+ Mapped Principal Distributor: {retailerDetails?.principal_distributer?.name || 'Not Mapped'}
@@ -181,13 +181,13 @@ const SingleRetailDistributor = () => {
- Designation: {retailerDetails.userType}
+ Designation: {retailerDetails?.userType|| 'Not Available'}
- Name: {retailerDetails.addedBy.name}
+ Name: {retailerDetails?.addedBy?.name || 'Not Available'}
- ID: {retailerDetails.addedBy.uniqueId}
+ ID: {retailerDetails?.addedBy?.uniqueId || 'Not Available'}
diff --git a/src/views/RetailDistributors/addRetailDistributor.js b/src/views/RetailDistributors/addRetailDistributor.js
new file mode 100644
index 0000000..0750e51
--- /dev/null
+++ b/src/views/RetailDistributors/addRetailDistributor.js
@@ -0,0 +1,524 @@
+import React, { useState, useEffect } from "react";
+import {
+ TextField,
+ Button,
+ Card,
+ Grid,
+ Typography,
+ Autocomplete,
+ CircularProgress,
+} from "@mui/material";
+import { useNavigate } from "react-router-dom";
+import { toast } from "react-hot-toast";
+import axios from "axios";
+import { isAutheticated } from "src/auth";
+import { City, State } from "country-state-city";
+
+const AddRetailDistributor = () => {
+ const navigate = useNavigate();
+ const token = isAutheticated();
+
+ const [user, setUser] = useState({
+ name: "",
+ trade_name: "",
+ address: "",
+ state: "",
+ city: "",
+ district: "",
+ pincode: "",
+ mobile_number: "",
+ pan_number: "",
+ aadhar_number: "",
+ gst_number: "",
+ });
+
+ const [files, setFiles] = useState({
+ selfieEntranceImg: null,
+ panImg: null,
+ aadharImg: null,
+ gstImg: null,
+ pesticideLicenseImg: null,
+ fertilizerLicenseImg: null,
+ });
+
+ const [loading, setLoading] = useState(false);
+ const [stateOptions, setStateOptions] = useState([]);
+ const [cityOptions, setCityOptions] = useState([]);
+ const [selectedState, setSelectedState] = useState(null);
+ const [selectedCity, setSelectedCity] = useState(null);
+ const [errors, setErrors] = useState({});
+
+ useEffect(() => {
+ const fetchStates = async () => {
+ const states = State.getStatesOfCountry("IN").map((state) => ({
+ label: state.name,
+ value: state.isoCode,
+ }));
+ setStateOptions(states);
+ };
+ fetchStates();
+ }, []);
+
+ useEffect(() => {
+ const fetchCities = async () => {
+ if (selectedState) {
+ const cities = City.getCitiesOfState("IN", selectedState.value).map(
+ (city) => ({
+ label: city.name,
+ value: city.name,
+ })
+ );
+ setCityOptions(cities);
+ }
+ };
+ fetchCities();
+ }, [selectedState]);
+
+ const handleInputChange = (e) => {
+ setUser({ ...user, [e.target.name]: e.target.value });
+ };
+
+ const handleStateChange = (event, newValue) => {
+ setSelectedState(newValue);
+ };
+
+ const handleCityChange = (event, newValue) => {
+ setSelectedCity(newValue);
+ };
+
+ const handleFileChange = (e) => {
+ const { name, files } = e.target;
+ if (files.length > 0) {
+ const file = files[0];
+ if (["image/png", "image/jpeg", "image/jpg"].includes(file.type)) {
+ setFiles((prev) => ({ ...prev, [name]: file }));
+ } else {
+ toast.error("Only PNG, JPG, and JPEG files are allowed.");
+ }
+ }
+ };
+
+ const handleFormSubmit = async (e) => {
+ e.preventDefault();
+ try {
+ // Validate input fields
+ if (
+ !user.name ||
+ !user.trade_name ||
+ !user.address ||
+ !user.mobile_number ||
+ !user.pan_number ||
+ !user.aadhar_number ||
+ !user.gst_number ||
+ !selectedState ||
+ !selectedCity
+ ) {
+ setErrors({ message: "Fill all required fields!" });
+ return;
+ }
+
+ setLoading(true);
+
+ const formData = new FormData();
+ formData.append("name", user.name);
+ formData.append("trade_name", user.trade_name);
+ formData.append("address", user.address);
+ formData.append("state", selectedState.value);
+ formData.append("city", selectedCity.value);
+ formData.append("district", user.district);
+ formData.append("pincode", user.pincode);
+ formData.append("mobile_number", user.mobile_number);
+ formData.append("pan_number", user.pan_number);
+ formData.append("aadhar_number", user.aadhar_number);
+ formData.append("gst_number", user.gst_number);
+
+ // Ensure files are included only if they exist
+ Object.keys(files).forEach((key) => {
+ if (files[key]) {
+ formData.append(key, files[key]);
+ }
+ });
+
+ // Attempt to create distributor
+ const response = await axios.post("/api/kyc/create-admin/", formData, {
+ headers: {
+ "Content-Type": "multipart/form-data",
+ "Authorization": `Bearer ${token}`,
+ },
+ });
+
+ if (response.data.success) {
+ toast.success("Retail Distributor created successfully!");
+ navigate("/retail-distributor");
+ }
+ } catch (error) {
+ setLoading(false);
+ if (error.response && error.response.data) {
+ toast.error(error.response.data.message || "Something went wrong!");
+ } else {
+ toast.error("Something went wrong!");
+ }
+ }
+ };
+
+ const handleCancel = () => {
+ navigate("/retail-distributor");
+ };
+
+ return (
+
+
+
+
+ Add Retail Distributor
+
+
+
+
+ );
+};
+
+export default AddRetailDistributor;
diff --git a/src/views/TerritoryManager/TerritoryManager.js b/src/views/TerritoryManager/TerritoryManager.js
index 38ce033..f76faae 100644
--- a/src/views/TerritoryManager/TerritoryManager.js
+++ b/src/views/TerritoryManager/TerritoryManager.js
@@ -302,6 +302,20 @@ const TerritoryManager = () => {
PD
+
+
+
diff --git a/src/views/TerritoryManager/ViewRetailDistributor.js b/src/views/TerritoryManager/ViewRetailDistributor.js
new file mode 100644
index 0000000..c2f8253
--- /dev/null
+++ b/src/views/TerritoryManager/ViewRetailDistributor.js
@@ -0,0 +1,554 @@
+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 Dialog from "@material-ui/core/Dialog";
+import DialogActions from "@material-ui/core/DialogActions";
+import DialogContent from "@material-ui/core/DialogContent";
+import DialogTitle from "@material-ui/core/DialogTitle";
+import TextField from "@material-ui/core/TextField";
+
+const ViewRetailDistributorTM = () => {
+ const token = isAutheticated();
+ const { id } = useParams();
+ const navigate = useNavigate();
+ const [loading, setLoading] = useState(false);
+ const [success, setSuccess] = useState(true);
+ const [retaildistributorData, setretaildistributorData] = useState([]);
+ const [data, setData] = useState({});
+ const nameRef = useRef();
+ const mobileRef = useRef();
+ const rdnameRef = useRef();
+ const rdmobileRef = useRef();
+
+ const [currentPage, setCurrentPage] = useState(1);
+ const [itemPerPage, setItemPerPage] = useState(10);
+ const [modalcurrentPage, setmodalCurrentPage] = useState(1);
+ const modalitemPerPage = 10;
+ const [totalData, setTotalData] = useState(0);
+ const [openModal, setOpenModal] = useState(false);
+ const [modalRetailDistributors, setmodalRetailDistributors] = useState(
+ []
+ );
+ const [modalTotalData, setModalTotalData] = useState(0);
+
+ // Fetch territory manager data
+ useEffect(() => {
+ axios
+ .get(`/api/territorymanager/getOne/${id}`, {
+ headers: { Authorization: `Bearer ${token}` },
+ })
+ .then((response) => setData(response.data.data))
+ .catch((error) => console.error("Error fetching TM data:", error));
+ }, [id, token]);
+
+ // Fetch Retail Distributors data
+ const getTMsretaildistributorData = async () => {
+ setLoading(true);
+ axios
+ .get(`/api/kyc/getAllapprovedbytmid/${id}`, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ params: {
+ page: currentPage,
+ show: itemPerPage,
+ tradename: nameRef.current?.value,
+ },
+ })
+ .then((res) => {
+ // console.log(res.data);
+ setretaildistributorData(res.data?.retaildistributor);
+ setTotalData(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(() => {
+ getTMsretaildistributorData();
+ }, [success, itemPerPage, currentPage]);
+
+ // Debounced search for Retail Distributors
+ const debouncedSearch = useCallback(
+ debounce(() => {
+ setCurrentPage(1);
+ getTMsretaildistributorData();
+ }, 500),
+ [currentPage, itemPerPage]
+ );
+
+ const handleSearchChange = useCallback(() => {
+ debouncedSearch();
+ }, [debouncedSearch]);
+ // Fetch Retail Distributors data for modal
+ const getretaildistributorData = async () => {
+ setLoading(true);
+ try {
+ const res = await axios.get(`/api/v1/admin/users`, {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ params: {
+ page: modalcurrentPage,
+ show: modalitemPerPage,
+ name: rdnameRef.current?.value,
+ mobileNumber: rdmobileRef.current?.value,
+ },
+ });
+ setmodalRetailDistributors(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 (openModal) {
+ getretaildistributorData();
+ }
+ }, [openModal, modalcurrentPage]);
+
+ // Debounced search for Retail Distributors in modal
+ const debouncedmodalSearch = useCallback(
+ debounce(() => {
+ setmodalCurrentPage(1);
+ getretaildistributorData();
+ }, 500),
+ [modalcurrentPage]
+ );
+
+ const handlemodalSearchChange = useCallback(() => {
+ debouncedmodalSearch();
+ }, [debouncedmodalSearch]);
+
+ const handleOpenModal = () => {
+ setOpenModal(true);
+ };
+
+ const handleCloseModal = () => {
+ setOpenModal(false);
+ };
+ const handlePreviousPage = () => {
+ if (modalcurrentPage > 1) {
+ setmodalCurrentPage(modalcurrentPage - 1);
+ }
+ };
+
+ const handleNextPage = () => {
+ if (modalRetailDistributors.length === modalitemPerPage) {
+ setmodalCurrentPage(modalcurrentPage + 1);
+ }
+ };
+
+ const handleDelete = (id) => {
+ swal({
+ title: "Are you sure?",
+ icon: "warning",
+ buttons: {
+ Yes: { text: "Yes", value: true },
+ Cancel: { text: "Cancel", value: "cancel" },
+ },
+ }).then((value) => {
+ if (value === true) {
+ axios
+ .patch(`/api/v1/unmap/${id}`, {}, { // Changed to PATCH and sent an empty body
+ headers: {
+ "Access-Control-Allow-Origin": "*",
+ Authorization: `Bearer ${token}`,
+ },
+ })
+ .then((res) => {
+ swal({
+ title: "Deleted",
+ text: "Retail Distributor Unmapped successfully!",
+ icon: "success",
+ button: "ok",
+ });
+ setSuccess((prev) => !prev);
+ })
+ .catch((err) => {
+ let msg = err?.response?.data?.message
+ ? err?.response?.data?.message
+ : "Something went wrong!";
+ swal({
+ title: "Warning",
+ text: msg,
+ icon: "error",
+ button: "Retry",
+ dangerMode: true,
+ });
+ });
+ }
+ });
+ };
+ const handleAddRetailDistributor = async (rdid) => {
+ try {
+ await axios.put(
+ `/api/v1/mappedtm/${rdid}`,
+ { mappedby: id },
+ {
+ headers: {
+ Authorization: `Bearer ${token}`,
+ },
+ }
+ );
+ swal({
+ title: "Success",
+ text: "Retail Distributor added successfully!",
+ icon: "success",
+ button: "Ok",
+ });
+ setSuccess((prev) => !prev);
+ handleCloseModal(); // Close modal after adding
+ } catch (err) {
+ const msg = err?.response?.data?.message || "Something went wrong!";
+ swal({
+ title: "Error",
+ text: msg,
+ icon: "error",
+ button: "Retry",
+ dangerMode: true,
+ });
+ }
+ };
+
+ return (
+
+
+
+
+
+
+ {/* Left Side with Information in Separate Columns */}
+
+
+ Unique ID: {data?.uniqueId}
+
+
+ Name: {data?.name}
+
+
+ Mobile Number: {data?.mobileNumber}
+
+
+ Mail: {data?.email}
+
+
+
+ {/* Right Side with the Button */}
+
+ {/* */}
+
+
+
+ {/* */}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/*
+
+
+ */}
+
+
+
+
+
+
+ ID |
+ Trade Name |
+ Approved PD |
+ Mobile |
+ Created On |
+ {/* Action | */}
+
+
+
+
+ {loading ? (
+
+
+ Loading...
+ |
+
+ ) : retaildistributorData?.length > 0 ? (
+ retaildistributorData?.map((RD, i) => {
+ return (
+
+ {RD?._id} |
+ {RD?.trade_name} |
+ {RD?.principal_distributer?.name} |
+
+ {RD?.mobile_number ? (
+ RD?.mobile_number
+ ) : (
+
+ No Phone Added!
+
+ )}
+ |
+ {new Date(
+ RD.updatedAt
+ ).toLocaleString("en-IN", {
+ weekday: "short",
+ month: "short",
+ day: "numeric",
+ year: "numeric",
+ hour: "numeric",
+ minute: "numeric",
+ hour12: true,
+ })} |
+ {/*
+
+ | */}
+
+ );
+ })
+ ) : (
+
+
+ No Retail Distributor found!
+ |
+
+ )}
+
+
+
+
+
+ Showing {retaildistributorData?.length} of {totalData}{" "}
+ entries
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ViewRetailDistributorTM;
|