Merge branch 'master' of http://128.199.30.231/possibillion/cheminova-admin-web
This commit is contained in:
commit
1fc0e1a596
@ -146,6 +146,8 @@ import SingleInventory from "./views/Inventory/SingleInventory";
|
|||||||
import ViewProductManual from "./views/ProductManual/SingleProductManual";
|
import ViewProductManual from "./views/ProductManual/SingleProductManual";
|
||||||
import ViewSalesCoOrdinatorTM from "./views/TerritoryManager/ViewSalesCoOrdinatorTM";
|
import ViewSalesCoOrdinatorTM from "./views/TerritoryManager/ViewSalesCoOrdinatorTM";
|
||||||
import ViewPrincipalDistributorTM from "./views/TerritoryManager/ViewPrincipalDistributorTM";
|
import ViewPrincipalDistributorTM from "./views/TerritoryManager/ViewPrincipalDistributorTM";
|
||||||
|
import ViewRetailDistributorTM from "./views/TerritoryManager/ViewRetailDistributor";
|
||||||
|
import AddRetailDistributor from "./views/RetailDistributors/addRetailDistributor";
|
||||||
const routes = [
|
const routes = [
|
||||||
//dashboard
|
//dashboard
|
||||||
|
|
||||||
@ -268,6 +270,12 @@ const routes = [
|
|||||||
element: ViewPrincipalDistributorTM,
|
element: ViewPrincipalDistributorTM,
|
||||||
navName: "TerritoryManagers",
|
navName: "TerritoryManagers",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/view/retaildistributor/:id",
|
||||||
|
name: "View Retail Distributor",
|
||||||
|
element: ViewRetailDistributorTM,
|
||||||
|
navName: "TerritoryManagers",
|
||||||
|
},
|
||||||
// Attendence
|
// Attendence
|
||||||
{
|
{
|
||||||
path: "/attendance/today",
|
path: "/attendance/today",
|
||||||
@ -331,6 +339,12 @@ const routes = [
|
|||||||
element: SingleRetailDistributor,
|
element: SingleRetailDistributor,
|
||||||
navName: "RetailDistributor",
|
navName: "RetailDistributor",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "/retaildistributor/add",
|
||||||
|
name: "Add Retail Distributor",
|
||||||
|
element: AddRetailDistributor,
|
||||||
|
navName: "RetailDistributor",
|
||||||
|
},
|
||||||
//----------------------- End Product Management Routes------------------------------------------------
|
//----------------------- End Product Management Routes------------------------------------------------
|
||||||
|
|
||||||
//Departure
|
//Departure
|
||||||
|
@ -1,54 +1,45 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useRef, useCallback } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { isAutheticated } from "src/auth";
|
import { isAutheticated } from "src/auth";
|
||||||
import swal from "sweetalert";
|
import swal from "sweetalert";
|
||||||
import {
|
|
||||||
Box,
|
|
||||||
FormControl,
|
|
||||||
IconButton,
|
|
||||||
InputLabel,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import SearchIcon from "@mui/icons-material/Search";
|
|
||||||
import Fuse from "fuse.js";
|
|
||||||
import { Typography } from "@material-ui/core";
|
|
||||||
import OrderDetails from "./orderDetails";
|
import OrderDetails from "./orderDetails";
|
||||||
|
import debounce from "lodash.debounce";
|
||||||
const principalDistributor = () => {
|
const principalDistributor = () => {
|
||||||
const token = isAutheticated();
|
const token = isAutheticated();
|
||||||
const [query, setQuery] = useState("");
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [loading1, setLoading1] = useState(true);
|
const [loading1, setLoading1] = useState(true);
|
||||||
const [success, setSuccess] = useState(true);
|
const [success, setSuccess] = useState(true);
|
||||||
const [users, setUsers] = useState([]);
|
const [users, setUsers] = useState([]);
|
||||||
|
const [totalPages, setTotalPages] = useState(1);
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [itemPerPage, setItemPerPage] = useState(10);
|
const [itemPerPage, setItemPerPage] = useState(10);
|
||||||
const [showData, setShowData] = useState(users);
|
const [totalData, setTotalData] = useState(0);
|
||||||
|
const nameRef = useRef();
|
||||||
const handleShowEntries = (e) => {
|
const SBURef = useRef();
|
||||||
setCurrentPage(1);
|
|
||||||
setItemPerPage(e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getUsers = async () => {
|
const getUsers = async () => {
|
||||||
axios
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await axios
|
||||||
.get(`/api/v1/admin/users`, {
|
.get(`/api/v1/admin/users`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
})
|
params: {
|
||||||
.then((res) => {
|
page: currentPage,
|
||||||
|
show: itemPerPage,
|
||||||
|
name: nameRef.current.value,
|
||||||
|
SBU: SBURef.current.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
// console.log(res.data);
|
// console.log(res.data);
|
||||||
setUsers(res.data.users);
|
setUsers(res.data.users);
|
||||||
setLoading(false);
|
setTotalData(res.data?.total_data);
|
||||||
})
|
setTotalPages(res.data?.total_pages);
|
||||||
.catch((error) => {
|
}catch(error) {
|
||||||
swal({
|
swal({
|
||||||
title: error,
|
title: error,
|
||||||
text: "please login to access the resource or refresh the page ",
|
text: "please login to access the resource or refresh the page ",
|
||||||
@ -56,23 +47,26 @@ const principalDistributor = () => {
|
|||||||
button: "Retry",
|
button: "Retry",
|
||||||
dangerMode: true,
|
dangerMode: true,
|
||||||
});
|
});
|
||||||
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getUsers();
|
getUsers();
|
||||||
}, [success]);
|
}, [itemPerPage, currentPage]);
|
||||||
// console.log(users);
|
|
||||||
|
|
||||||
useEffect(() => {
|
const debouncedSearch = useCallback(
|
||||||
const loadData = () => {
|
debounce(() => {
|
||||||
const indexOfLastPost = currentPage * itemPerPage;
|
setCurrentPage(1);
|
||||||
const indexOfFirstPost = indexOfLastPost - itemPerPage;
|
getUsers();
|
||||||
setShowData(users.slice(indexOfFirstPost, indexOfLastPost));
|
}, 500),
|
||||||
};
|
[]
|
||||||
loadData();
|
);
|
||||||
}, [currentPage, itemPerPage, users]);
|
|
||||||
|
const handleSearchChange = () => {
|
||||||
|
debouncedSearch();
|
||||||
|
};
|
||||||
// console.log(users);
|
// console.log(users);
|
||||||
|
|
||||||
// const handleDelete = (id) => {
|
// const handleDelete = (id) => {
|
||||||
@ -165,19 +159,17 @@ const principalDistributor = () => {
|
|||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-body">
|
<div className="card-body">
|
||||||
<div className="row ml-0 mr-0 mb-10 ">
|
<div className="row ml-0 mr-0 mb-10 ">
|
||||||
<div className="col-sm-12 col-md-12">
|
<div className="col-lg-1">
|
||||||
<div className="dataTables_length">
|
<div className="dataTables_length">
|
||||||
<label className="w-100">
|
<label className="w-100">
|
||||||
Show
|
Show
|
||||||
<select
|
<select
|
||||||
style={{ width: "10%" }}
|
onChange={(e) => {
|
||||||
name=""
|
setItemPerPage(Number(e.target.value));
|
||||||
onChange={(e) => handleShowEntries(e)}
|
setCurrentPage(1); // Reset to first page when changing items per page
|
||||||
className="
|
}}
|
||||||
select-w
|
className="form-control"
|
||||||
custom-select custom-select-sm
|
disabled={loading}
|
||||||
form-control form-control-sm
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<option value="10">10</option>
|
<option value="10">10</option>
|
||||||
<option value="25">25</option>
|
<option value="25">25</option>
|
||||||
@ -188,6 +180,30 @@ const principalDistributor = () => {
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="col-lg-3">
|
||||||
|
<label>Trade Name:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="searchTerm"
|
||||||
|
placeholder="Trade name"
|
||||||
|
className="form-control"
|
||||||
|
ref={nameRef}
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-3">
|
||||||
|
<label>SBU:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="searchTerm"
|
||||||
|
placeholder="SBU"
|
||||||
|
className="form-control"
|
||||||
|
ref={SBURef}
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="table-responsive table-shoot mt-3">
|
<div className="table-responsive table-shoot mt-3">
|
||||||
@ -213,55 +229,47 @@ const principalDistributor = () => {
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{!loading && showData.length === 0 && (
|
{loading ? (
|
||||||
<tr className="text-center">
|
<tr className="text-center">
|
||||||
<td colSpan="6">
|
<td colSpan="6">
|
||||||
<h5>No Data Available</h5>
|
<h5>Loading....</h5>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)}
|
) : users.length > 0 ? (
|
||||||
{loading ? (
|
users.map((user, i) => (
|
||||||
<tr>
|
<tr key={i}>
|
||||||
<td className="text-center" colSpan="6">
|
<td>{user.uniqueId}</td>
|
||||||
Loading...
|
<td>{user.SBU ? user.SBU : "N/A"}</td>
|
||||||
</td>
|
<td className="text-start">{user.name}</td>
|
||||||
</tr>
|
<td>{user.email}</td>
|
||||||
) : (
|
<td className="text-start">
|
||||||
showData.map((user, i) => {
|
{new Date(user.createdAt).toLocaleString(
|
||||||
return (
|
"en-IN",
|
||||||
<tr key={i}>
|
{
|
||||||
<td>{user.uniqueId}</td>
|
weekday: "short",
|
||||||
<td>{user.SBU?user.SBU:"N/A"}</td>
|
month: "short",
|
||||||
<td className="text-start">{user.name}</td>
|
day: "numeric",
|
||||||
<td>{user.email}</td>
|
year: "numeric",
|
||||||
<td className="text-start">
|
hour: "numeric",
|
||||||
{new Date(user.createdAt).toLocaleString(
|
minute: "numeric",
|
||||||
"en-IN",
|
hour12: true,
|
||||||
{
|
}
|
||||||
weekday: "short",
|
|
||||||
month: "short",
|
|
||||||
day: "numeric",
|
|
||||||
year: "numeric",
|
|
||||||
hour: "numeric",
|
|
||||||
minute: "numeric",
|
|
||||||
hour12: true,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
{loading1 && (
|
|
||||||
<>
|
|
||||||
<td className="text-start">loading...</td>
|
|
||||||
<td className="text-start">loading...</td>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
|
</td>
|
||||||
|
{loading1 && (
|
||||||
|
<>
|
||||||
|
<td className="text-start">loading...</td>
|
||||||
|
<td className="text-start">loading...</td>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
<OrderDetails
|
<OrderDetails
|
||||||
_id={user?._id}
|
_id={user?._id}
|
||||||
setLoading1={setLoading1}
|
setLoading1={setLoading1}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<td className="text-start">
|
<td className="text-start">
|
||||||
{/* <Link
|
{/* <Link
|
||||||
to={`/users-address/view/${userAddress._id}`}
|
to={`/users-address/view/${userAddress._id}`}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
@ -325,20 +333,25 @@ const principalDistributor = () => {
|
|||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
</Link> */}
|
</Link> */}
|
||||||
<Link
|
<Link
|
||||||
to={`/principal-distributor/${user?._id}`}
|
to={`/principal-distributor/${user?._id}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="mt-1 btn btn-info btn-sm waves-effect waves-light btn-table ml-2"
|
||||||
>
|
>
|
||||||
<button
|
View
|
||||||
type="button"
|
</button>
|
||||||
className="mt-1 btn btn-info btn-sm waves-effect waves-light btn-table ml-2"
|
</Link>
|
||||||
>
|
</td>
|
||||||
View
|
</tr>
|
||||||
</button>
|
))
|
||||||
</Link>
|
) : (
|
||||||
</td>
|
<tr>
|
||||||
</tr>
|
<td colSpan="6" className="text-center">
|
||||||
);
|
<h5>No Principal Distributor found!</h5>
|
||||||
})
|
</td>
|
||||||
|
</tr>
|
||||||
)}
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -352,88 +365,60 @@ const principalDistributor = () => {
|
|||||||
role="status"
|
role="status"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "}
|
Showing {users?.length} of {totalData} entries
|
||||||
{Math.min(currentPage * itemPerPage, users.length)} of{" "}
|
|
||||||
{users.length} entries
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-sm-12 col-md-6">
|
<div className="col-sm-12 col-md-6">
|
||||||
<div className="d-flex">
|
<div className="dataTables_paginate paging_simple_numbers">
|
||||||
<ul className="pagination ms-auto">
|
<ul className="pagination">
|
||||||
<li
|
<li
|
||||||
className={
|
className={`paginate_button page-item previous ${
|
||||||
currentPage === 1
|
currentPage === 1 ? "disabled" : ""
|
||||||
? "paginate_button page-item previous disabled"
|
}`}
|
||||||
: "paginate_button page-item previous"
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<span
|
<a
|
||||||
className="page-link"
|
className="page-link"
|
||||||
style={{ cursor: "pointer" }}
|
onClick={() =>
|
||||||
onClick={() => setCurrentPage((prev) => prev - 1)}
|
setCurrentPage((prev) => Math.max(prev - 1, 1))
|
||||||
|
}
|
||||||
|
aria-controls="datatable"
|
||||||
>
|
>
|
||||||
Previous
|
Previous
|
||||||
</span>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{Array.from({ length: totalPages }, (_, index) => (
|
||||||
{!(currentPage - 1 < 1) && (
|
<li
|
||||||
<li className="paginate_button page-item">
|
key={index}
|
||||||
<span
|
className={`paginate_button page-item ${
|
||||||
className="page-link"
|
currentPage === index + 1 ? "active" : ""
|
||||||
style={{ cursor: "pointer" }}
|
}`}
|
||||||
onClick={(e) =>
|
|
||||||
setCurrentPage((prev) => prev - 1)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{currentPage - 1}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<li className="paginate_button page-item active">
|
|
||||||
<span
|
|
||||||
className="page-link"
|
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
>
|
>
|
||||||
{currentPage}
|
<a
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
{!(
|
|
||||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
|
||||||
users.length - 1
|
|
||||||
) && (
|
|
||||||
<li className="paginate_button page-item ">
|
|
||||||
<span
|
|
||||||
className="page-link"
|
className="page-link"
|
||||||
style={{ cursor: "pointer" }}
|
onClick={() => setCurrentPage(index + 1)}
|
||||||
onClick={() => {
|
aria-controls="datatable"
|
||||||
setCurrentPage((prev) => prev + 1);
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{currentPage + 1}
|
{index + 1}
|
||||||
</span>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
)}
|
))}
|
||||||
|
|
||||||
<li
|
<li
|
||||||
className={
|
className={`paginate_button page-item next ${
|
||||||
!(
|
currentPage === totalPages ? "disabled" : ""
|
||||||
(currentPage + 1) * itemPerPage - itemPerPage >
|
}`}
|
||||||
users.length - 1
|
|
||||||
)
|
|
||||||
? "paginate_button page-item next"
|
|
||||||
: "paginate_button page-item next disabled"
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<span
|
<a
|
||||||
className="page-link"
|
className="page-link"
|
||||||
style={{ cursor: "pointer" }}
|
onClick={() =>
|
||||||
onClick={() => setCurrentPage((prev) => prev + 1)}
|
setCurrentPage((prev) =>
|
||||||
|
Math.min(prev + 1, totalPages)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
aria-controls="datatable"
|
||||||
>
|
>
|
||||||
Next
|
Next
|
||||||
</span>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect, useCallback, useRef } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import { isAutheticated } from "src/auth";
|
import { isAutheticated } from "src/auth";
|
||||||
@ -8,18 +9,17 @@ import debounce from "lodash.debounce";
|
|||||||
|
|
||||||
const RetailDistributor = () => {
|
const RetailDistributor = () => {
|
||||||
const token = isAutheticated();
|
const token = isAutheticated();
|
||||||
|
const Navigate = useNavigate();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [allRetailDistributorsData, setAllRetailDistributorsData] = useState(
|
const [allRetailDistributorsData, setAllRetailDistributorsData] = useState(
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
const [filteredRetailDistributorsData, setFilteredRetailDistributorsData] =
|
const nameRef = useRef();
|
||||||
useState([]);
|
const principalDistributorRef = useRef();
|
||||||
const [searchTerm, setSearchTerm] = useState("");
|
const [totalPages, setTotalPages] = useState(1);
|
||||||
const [searchPrincipalDistributor, setSearchPrincipalDistributor] =
|
|
||||||
useState("");
|
|
||||||
|
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const [itemPerPage, setItemPerPage] = useState(10);
|
const [itemPerPage, setItemPerPage] = useState(10);
|
||||||
|
const [totalData, setTotalData] = useState(0);
|
||||||
|
|
||||||
const getRetailDistributorsData = async () => {
|
const getRetailDistributorsData = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@ -28,9 +28,16 @@ const RetailDistributor = () => {
|
|||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
|
params: {
|
||||||
|
page: currentPage,
|
||||||
|
show: itemPerPage,
|
||||||
|
name: nameRef.current.value,
|
||||||
|
principaldistributor: principalDistributorRef.current.value,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
setAllRetailDistributorsData(res.data || []);
|
setAllRetailDistributorsData(res.data?.kycs);
|
||||||
setFilteredRetailDistributorsData(res.data || []); // Initialize filtered data
|
setTotalData(res.data?.total_data);
|
||||||
|
setTotalPages(res.data?.total_pages);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const msg = err?.response?.data?.message || "Something went wrong!";
|
const msg = err?.response?.data?.message || "Something went wrong!";
|
||||||
swal({
|
swal({
|
||||||
@ -47,65 +54,17 @@ const RetailDistributor = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getRetailDistributorsData();
|
getRetailDistributorsData();
|
||||||
}, []);
|
}, [ itemPerPage, currentPage]);
|
||||||
|
|
||||||
useEffect(() => {
|
const debouncedSearch = useCallback(debounce(() => {
|
||||||
filterData();
|
setCurrentPage(1);
|
||||||
}, [searchTerm, searchPrincipalDistributor, allRetailDistributorsData]);
|
getRetailDistributorsData();
|
||||||
|
}, 500), []);
|
||||||
|
|
||||||
const filterData = () => {
|
const handleSearchChange = () => {
|
||||||
let filteredData = allRetailDistributorsData;
|
|
||||||
|
|
||||||
if (searchTerm) {
|
|
||||||
filteredData = filteredData.filter((item) =>
|
|
||||||
item.trade_name.toLowerCase().includes(searchTerm.toLowerCase())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (searchPrincipalDistributor) {
|
|
||||||
filteredData = filteredData.filter((item) =>
|
|
||||||
item.principal_distributer?.name
|
|
||||||
?.toLowerCase()
|
|
||||||
.includes(searchPrincipalDistributor.toLowerCase())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
setFilteredRetailDistributorsData(filteredData);
|
|
||||||
setCurrentPage(1); // Reset to first page when filtering
|
|
||||||
};
|
|
||||||
|
|
||||||
const debouncedSearch = useCallback(
|
|
||||||
debounce(() => {
|
|
||||||
filterData();
|
|
||||||
}, 500),
|
|
||||||
[searchTerm, searchPrincipalDistributor]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleSearchChange = (e) => {
|
|
||||||
const { name, value } = e.target;
|
|
||||||
if (name === "searchTerm") {
|
|
||||||
setSearchTerm(value);
|
|
||||||
} else if (name === "searchPrincipalDistributor") {
|
|
||||||
setSearchPrincipalDistributor(value);
|
|
||||||
}
|
|
||||||
debouncedSearch();
|
debouncedSearch();
|
||||||
};
|
};
|
||||||
|
|
||||||
const totalPages = Math.ceil(
|
|
||||||
filteredRetailDistributorsData.length / itemPerPage
|
|
||||||
);
|
|
||||||
const paginatedData = filteredRetailDistributorsData.slice(
|
|
||||||
(currentPage - 1) * itemPerPage,
|
|
||||||
currentPage * itemPerPage
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleResetSearch = () => {
|
|
||||||
setSearchTerm("");
|
|
||||||
setSearchPrincipalDistributor("");
|
|
||||||
setFilteredRetailDistributorsData(allRetailDistributorsData); // Reset filtered data
|
|
||||||
setCurrentPage(1); // Reset to first page
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="main-content">
|
<div className="main-content">
|
||||||
<div className="page-content">
|
<div className="page-content">
|
||||||
@ -116,6 +75,18 @@ const RetailDistributor = () => {
|
|||||||
<div style={{ fontSize: "22px" }} className="fw-bold">
|
<div style={{ fontSize: "22px" }} className="fw-bold">
|
||||||
Retail Distributors
|
Retail Distributors
|
||||||
</div>
|
</div>
|
||||||
|
<div className="page-title-right">
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
className="font-bold mb-2 capitalize mr-2"
|
||||||
|
onClick={() => {
|
||||||
|
Navigate("/retaildistributor/add");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add Retail Distributor
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -153,9 +124,9 @@ const RetailDistributor = () => {
|
|||||||
name="searchTerm"
|
name="searchTerm"
|
||||||
placeholder="Trade name"
|
placeholder="Trade name"
|
||||||
className="form-control"
|
className="form-control"
|
||||||
|
ref={nameRef}
|
||||||
onChange={handleSearchChange}
|
onChange={handleSearchChange}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
value={searchTerm}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-lg-3">
|
<div className="col-lg-3">
|
||||||
@ -167,18 +138,9 @@ const RetailDistributor = () => {
|
|||||||
className="form-control"
|
className="form-control"
|
||||||
onChange={handleSearchChange}
|
onChange={handleSearchChange}
|
||||||
disabled={loading}
|
disabled={loading}
|
||||||
value={searchPrincipalDistributor}
|
ref={principalDistributorRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-lg-3">
|
|
||||||
<Button
|
|
||||||
variant="outlined"
|
|
||||||
color="primary"
|
|
||||||
onClick={handleResetSearch}
|
|
||||||
>
|
|
||||||
Reset Search
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="table-responsive table-shoot mt-3">
|
<div className="table-responsive table-shoot mt-3">
|
||||||
@ -205,8 +167,8 @@ const RetailDistributor = () => {
|
|||||||
Loading...
|
Loading...
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
) : paginatedData.length > 0 ? (
|
) : allRetailDistributorsData.length > 0 ? (
|
||||||
paginatedData.map((retailDistributor) => (
|
allRetailDistributorsData.map((retailDistributor) => (
|
||||||
<tr key={retailDistributor._id}>
|
<tr key={retailDistributor._id}>
|
||||||
<td className="text-start">
|
<td className="text-start">
|
||||||
{retailDistributor._id}
|
{retailDistributor._id}
|
||||||
@ -272,12 +234,7 @@ const RetailDistributor = () => {
|
|||||||
role="status"
|
role="status"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
>
|
>
|
||||||
Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "}
|
Showing {allRetailDistributorsData?.length} of {totalData} entries
|
||||||
{Math.min(
|
|
||||||
currentPage * itemPerPage,
|
|
||||||
filteredRetailDistributorsData.length
|
|
||||||
)}{" "}
|
|
||||||
of {filteredRetailDistributorsData.length} entries
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ const SingleRetailDistributor = () => {
|
|||||||
<strong>Mobile Number:</strong> {retailerDetails.mobile_number}
|
<strong>Mobile Number:</strong> {retailerDetails.mobile_number}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
<strong>Mapped Principal Distributor:</strong> {retailerDetails.principal_distributer.name}
|
<strong>Mapped Principal Distributor:</strong> {retailerDetails?.principal_distributer?.name || 'Not Mapped'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -181,13 +181,13 @@ const SingleRetailDistributor = () => {
|
|||||||
<Grid container spacing={2}>
|
<Grid container spacing={2}>
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
<Typography>
|
<Typography>
|
||||||
<strong>Designation:</strong> {retailerDetails.userType}
|
<strong>Designation:</strong> {retailerDetails?.userType|| 'Not Available'}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
<strong>Name:</strong> {retailerDetails.addedBy.name}
|
<strong>Name:</strong> {retailerDetails?.addedBy?.name || 'Not Available'}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
<strong>ID:</strong> {retailerDetails.addedBy.uniqueId}
|
<strong>ID:</strong> {retailerDetails?.addedBy?.uniqueId || 'Not Available'}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
524
src/views/RetailDistributors/addRetailDistributor.js
Normal file
524
src/views/RetailDistributors/addRetailDistributor.js
Normal file
@ -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 (
|
||||||
|
<div>
|
||||||
|
<Card
|
||||||
|
sx={{ padding: "1rem", marginBottom: "1rem", position: "relative" }}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="secondary"
|
||||||
|
onClick={handleCancel}
|
||||||
|
sx={{ position: "absolute", top: "10px", right: "10px" }}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Typography variant="h5" sx={{ mb: 3 }}>
|
||||||
|
Add Retail Distributor
|
||||||
|
</Typography>
|
||||||
|
<form onSubmit={handleFormSubmit}>
|
||||||
|
<Typography variant="h5" sx={{ mb: 2 }}>
|
||||||
|
Basic Information
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={2} sx={{ mb: 2 }}>
|
||||||
|
{/* Name */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="name"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
Name*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="name"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="name"
|
||||||
|
value={user.name}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Trade Name */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="trade_name"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
Trade Name*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="trade_name"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="trade_name"
|
||||||
|
value={user.trade_name}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Address */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="address"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
Address*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="address"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="address"
|
||||||
|
value={user.address}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Mobile Number */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="mobile_number"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
Mobile Number*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="mobile_number"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="mobile_number"
|
||||||
|
value={user.mobile_number}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* PAN Number */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="pan_number"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
PAN Number*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="pan_number"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="pan_number"
|
||||||
|
value={user.pan_number}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Aadhar Number */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="aadhar_number"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
Aadhar Number*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="aadhar_number"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="aadhar_number"
|
||||||
|
value={user.aadhar_number}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* GST Number */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="gst_number"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
GST Number*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="gst_number"
|
||||||
|
required
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="gst_number"
|
||||||
|
value={user.gst_number}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* State */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="state"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
State*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<Autocomplete
|
||||||
|
options={stateOptions}
|
||||||
|
value={selectedState}
|
||||||
|
onChange={handleStateChange}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
id="state"
|
||||||
|
required
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* City */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="city"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
City*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<Autocomplete
|
||||||
|
options={cityOptions}
|
||||||
|
value={selectedCity}
|
||||||
|
onChange={handleCityChange}
|
||||||
|
renderInput={(params) => (
|
||||||
|
<TextField
|
||||||
|
{...params}
|
||||||
|
id="city"
|
||||||
|
required
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* District */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="district"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
District*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="district"
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="district"
|
||||||
|
value={user.district}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* Pincode */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor="pincode"
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
Pincode*
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<TextField
|
||||||
|
id="pincode"
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
name="pincode"
|
||||||
|
value={user.pincode}
|
||||||
|
variant="outlined"
|
||||||
|
onChange={handleInputChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{/* File Uploads */}
|
||||||
|
{[
|
||||||
|
{ label: "Selfie Entrance Image*", name: "selfieEntranceImg" },
|
||||||
|
{ label: "PAN Image*", name: "panImg" },
|
||||||
|
{ label: "Aadhar Image*", name: "aadharImg" },
|
||||||
|
{ label: "GST Image*", name: "gstImg" },
|
||||||
|
{ label: "Pesticide License Image*", name: "pesticideLicenseImg" },
|
||||||
|
{ label: "Fertilizer License Image*", name: "fertilizerLicenseImg" },
|
||||||
|
].map(({ label, name }) => (
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center" key={name}>
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Typography
|
||||||
|
variant="body1"
|
||||||
|
htmlFor={name}
|
||||||
|
className="form-label"
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id={name}
|
||||||
|
name={name}
|
||||||
|
onChange={handleFileChange}
|
||||||
|
accept=".png,.jpg,.jpeg"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Submit Button */}
|
||||||
|
<Grid item xs={12} className="d-flex align-items-center">
|
||||||
|
<Grid item xs={2}></Grid>
|
||||||
|
<Grid item xs={10}>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<CircularProgress size={24} />
|
||||||
|
) : (
|
||||||
|
"Submit"
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</form>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddRetailDistributor;
|
@ -302,6 +302,20 @@ const TerritoryManager = () => {
|
|||||||
PD
|
PD
|
||||||
</button>
|
</button>
|
||||||
</Link>
|
</Link>
|
||||||
|
<Link
|
||||||
|
to={`/view/retaildistributor/${territorymanager._id}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
marginRight: "1rem",
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary btn-sm waves-effect waves-light btn-table ml-2"
|
||||||
|
>
|
||||||
|
RD
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
to={`/territorymanager/edit/${territorymanager._id}`}
|
to={`/territorymanager/edit/${territorymanager._id}`}
|
||||||
>
|
>
|
||||||
|
554
src/views/TerritoryManager/ViewRetailDistributor.js
Normal file
554
src/views/TerritoryManager/ViewRetailDistributor.js
Normal file
@ -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 (
|
||||||
|
<div className="main-content">
|
||||||
|
<div className="page-content">
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="page-title-box d-flex mb-1 align-items-center justify-content-between">
|
||||||
|
{/* Left Side with Information in Separate Columns */}
|
||||||
|
<div className="d-flex flex-column">
|
||||||
|
<div style={{ fontSize: "18px" }} className="fw-bold">
|
||||||
|
Unique ID: {data?.uniqueId}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: "18px" }} className="fw-bold">
|
||||||
|
Name: {data?.name}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: "18px" }} className="fw-bold">
|
||||||
|
Mobile Number: {data?.mobileNumber}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: "18px" }} className="fw-bold">
|
||||||
|
Mail: {data?.email}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Right Side with the Button */}
|
||||||
|
<div className="page-title-right">
|
||||||
|
{/* <Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: "1rem",
|
||||||
|
textTransform: "capitalize",
|
||||||
|
}}
|
||||||
|
onClick={handleOpenModal}
|
||||||
|
>
|
||||||
|
Add Retail Distributor
|
||||||
|
</Button> */}
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="secondary"
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: "1rem",
|
||||||
|
marginLeft: "1rem",
|
||||||
|
textTransform: "capitalize",
|
||||||
|
backgroundColor: "#d32f2f", // Red color for danger
|
||||||
|
color: "#fff",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#b71c1c", // Darker red on hover
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={() => navigate("/territorymanagers")}
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* <Dialog
|
||||||
|
open={openModal}
|
||||||
|
onClose={handleCloseModal}
|
||||||
|
maxWidth="md"
|
||||||
|
fullWidth
|
||||||
|
>
|
||||||
|
<DialogTitle>Search and Add Retail Distributor</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<div style={{ display: "flex", gap: "16px", marginBottom:"2rem",marginTop:"-1rem" }}>
|
||||||
|
<TextField
|
||||||
|
label="Retail Distributor Trade Name"
|
||||||
|
placeholder="Retail Distributor Trade name"
|
||||||
|
inputRef={rdnameRef}
|
||||||
|
onChange={handlemodalSearchChange}
|
||||||
|
disabled={loading}
|
||||||
|
style={{ flex: 1, marginRight: "16px" }}
|
||||||
|
/>
|
||||||
|
<TextField
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
label="Mobile Number"
|
||||||
|
placeholder="Mobile Number"
|
||||||
|
inputRef={rdmobileRef}
|
||||||
|
onChange={handlemodalSearchChange}
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="table-responsive table-shoot mt-3">
|
||||||
|
<table className="table table-centered table-nowrap">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Trade Name</th>
|
||||||
|
<th>Mobile</th>
|
||||||
|
<th>Approved PD</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{modalRetailDistributors.length > 0 ? (
|
||||||
|
modalRetailDistributors.map((RD) => (
|
||||||
|
<tr key={RD._id}>
|
||||||
|
<td>{RD.trade_name}</td>
|
||||||
|
<td>{RD.mobile_number}</td>
|
||||||
|
<td>{RD.principal_distributer?.name}</td>
|
||||||
|
<td>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={() =>
|
||||||
|
handleAddRetailDistributor(RD._id)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td colSpan="6" className="text-center">
|
||||||
|
No Retail Distributor found!
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
Showing {modalRetailDistributors?.length} of{" "}
|
||||||
|
{modalTotalData} entries
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={handlePreviousPage}
|
||||||
|
disabled={modalcurrentPage === 1 || loading}
|
||||||
|
className="btn btn-primary"
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleNextPage}
|
||||||
|
disabled={
|
||||||
|
modalRetailDistributors?.length <
|
||||||
|
modalitemPerPage || loading
|
||||||
|
}
|
||||||
|
className="btn btn-primary ml-2"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleCloseModal} color="secondary">
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog> */}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-lg-12">
|
||||||
|
<div className="card">
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="row ml-0 mr-0 mb-10">
|
||||||
|
<div className="col-lg-1">
|
||||||
|
<div className="dataTables_length">
|
||||||
|
<label className="w-100">
|
||||||
|
Show
|
||||||
|
<select
|
||||||
|
onChange={(e) => {
|
||||||
|
setItemPerPage(e.target.value);
|
||||||
|
setCurrentPage(1);
|
||||||
|
}}
|
||||||
|
className="form-control"
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="25">25</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
<option value="100">100</option>
|
||||||
|
</select>
|
||||||
|
entries
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-lg-3">
|
||||||
|
<label>Trade Name:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Retail Distributor Trade name"
|
||||||
|
className="form-control"
|
||||||
|
ref={nameRef}
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* <div className="col-lg-3">
|
||||||
|
<label>Mobile Number:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Mobile Number"
|
||||||
|
className="form-control"
|
||||||
|
ref={mobileRef}
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
disabled={loading}
|
||||||
|
/>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="table-responsive table-shoot mt-3">
|
||||||
|
<table className="table table-centered table-nowrap">
|
||||||
|
<thead
|
||||||
|
className="thead-light"
|
||||||
|
style={{ background: "#ecdddd" }}
|
||||||
|
>
|
||||||
|
<tr>
|
||||||
|
<th className="text-start">ID</th>
|
||||||
|
<th className="text-start">Trade Name</th>
|
||||||
|
<th className="text-start">Approved PD</th>
|
||||||
|
<th className="text-start">Mobile</th>
|
||||||
|
<th className="text-start">Created On</th>
|
||||||
|
{/* <th className="text-start">Action</th> */}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{loading ? (
|
||||||
|
<tr>
|
||||||
|
<td className="text-center" colSpan="6">
|
||||||
|
Loading...
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : retaildistributorData?.length > 0 ? (
|
||||||
|
retaildistributorData?.map((RD, i) => {
|
||||||
|
return (
|
||||||
|
<tr key={i}>
|
||||||
|
<td className="text-start">{RD?._id}</td>
|
||||||
|
<td className="text-start">{RD?.trade_name}</td>
|
||||||
|
<td className="text-start">{RD?.principal_distributer?.name}</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{RD?.mobile_number ? (
|
||||||
|
RD?.mobile_number
|
||||||
|
) : (
|
||||||
|
<small className="m-0 text-secondary">
|
||||||
|
No Phone Added!
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-start"> {new Date(
|
||||||
|
RD.updatedAt
|
||||||
|
).toLocaleString("en-IN", {
|
||||||
|
weekday: "short",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
year: "numeric",
|
||||||
|
hour: "numeric",
|
||||||
|
minute: "numeric",
|
||||||
|
hour12: true,
|
||||||
|
})}</td>
|
||||||
|
{/* <td className="text-start">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
style={{ color: "white" }}
|
||||||
|
className="btn btn-danger btn-sm waves-effect waves-light btn-table ml-2"
|
||||||
|
onClick={() => handleDelete(RD._id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</td> */}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td className="text-center" colSpan="6">
|
||||||
|
No Retail Distributor found!
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
Showing {retaildistributorData?.length} of {totalData}{" "}
|
||||||
|
entries
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
onClick={() => setCurrentPage(currentPage - 1)}
|
||||||
|
disabled={currentPage === 1 || loading}
|
||||||
|
className="btn btn-primary"
|
||||||
|
>
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setCurrentPage(currentPage + 1)}
|
||||||
|
disabled={
|
||||||
|
retaildistributorData?.length < itemPerPage ||
|
||||||
|
loading
|
||||||
|
}
|
||||||
|
className="btn btn-primary ml-2"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ViewRetailDistributorTM;
|
Loading…
Reference in New Issue
Block a user