Retail distributor

This commit is contained in:
Sibunnayak 2024-08-05 19:05:28 +05:30
parent 059ddd0fa1
commit 99a358a567
4 changed files with 217 additions and 165 deletions

View File

@ -89,13 +89,13 @@ const _nav = [
to: "/territorymanagers",
group: "TerritoryManager",
},
// {
// component: CNavItem,
// name: "retail Distributor",
// icon: <CIcon icon={cilCompress} customClassName="nav-icon" />,
// to: "/retail-distributor",
// group: "RetailDistributor",
// },
{
component: CNavItem,
name: "retail Distributor",
icon: <CIcon icon={cilCompress} customClassName="nav-icon" />,
to: "/retail-distributor",
group: "RetailDistributor",
},
{
component: CNavItem,
name: "Attendance",

View File

@ -304,7 +304,7 @@ const routes = [
navName: "RetailDistributor",
},
{
path: "/single/retail-distributor",
path: "/retaildistributor/view/:id",
name: "Single Retail Distributor",
element: SingleRetailDistributor,
navName: "RetailDistributor",

View File

@ -1,44 +1,36 @@
import React, { useState, useEffect, useRef, useCallback } from "react";
import React, { useState, useEffect, useCallback } from "react";
import { Link } 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 debounce from "lodash.debounce";
const RetailDistributor = () => {
const token = isAutheticated();
const navigate = useNavigate();
const [loading, setLoading] = useState(false);
const [success, setSuccess] = useState(true);
const [retailDistributorsData, setRetailDistributorsData] = useState([]);
const nameRef = useRef();
const mobileRef = useRef();
const VerifyRetailDistributorRef = useRef();
const [allRetailDistributorsData, setAllRetailDistributorsData] = useState(
[]
);
const [filteredRetailDistributorsData, setFilteredRetailDistributorsData] =
useState([]);
const [searchTerm, setSearchTerm] = useState("");
const [searchPrincipalDistributor, setSearchPrincipalDistributor] =
useState("");
const [currentPage, setCurrentPage] = useState(1);
const [itemPerPage, setItemPerPage] = useState(10);
const [totalData, setTotalData] = useState(0);
const getRetailDistributorsData = async () => {
setLoading(true);
try {
const res = await axios.get(`/api/retaildistributor/getAll/`, {
const res = await axios.get(`/api/kyc/getAllapproved/`, {
headers: {
Authorization: `Bearer ${token}`,
},
params: {
page: currentPage,
show: itemPerPage,
name: nameRef.current.value,
mobileNumber: mobileRef.current.value,
isVerified: VerifyRetailDistributorRef.current.value,
},
});
setRetailDistributorsData(res.data?.retailDistributors);
setTotalData(res.data?.total_data);
setAllRetailDistributorsData(res.data || []);
setFilteredRetailDistributorsData(res.data || []); // Initialize filtered data
} catch (err) {
const msg = err?.response?.data?.message || "Something went wrong!";
swal({
@ -55,18 +47,64 @@ const RetailDistributor = () => {
useEffect(() => {
getRetailDistributorsData();
}, [success, itemPerPage, currentPage]);
}, []);
const debouncedSearch = useCallback(debounce(() => {
setCurrentPage(1);
getRetailDistributorsData();
}, 500), []);
useEffect(() => {
filterData();
}, [searchTerm, searchPrincipalDistributor, allRetailDistributorsData]);
const handleSearchChange = () => {
const filterData = () => {
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();
};
const totalPages = Math.ceil(totalData / itemPerPage);
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 (
<div className="main-content">
@ -93,8 +131,8 @@ const RetailDistributor = () => {
Show
<select
onChange={(e) => {
setItemPerPage(e.target.value);
setCurrentPage(1);
setItemPerPage(Number(e.target.value));
setCurrentPage(1); // Reset to first page when changing items per page
}}
className="form-control"
disabled={loading}
@ -109,39 +147,37 @@ const RetailDistributor = () => {
</div>
</div>
<div className="col-lg-3">
<label>Retail Distributor Name:</label>
<label>Trade Name:</label>
<input
type="text"
placeholder="Retail Distributor name"
name="searchTerm"
placeholder="Trade name"
className="form-control"
ref={nameRef}
onChange={handleSearchChange}
disabled={loading}
value={searchTerm}
/>
</div>
<div className="col-lg-3">
<label>Mobile Number:</label>
<label>Principal Distributor Name:</label>
<input
type="text"
placeholder="Mobile Number"
name="searchPrincipalDistributor"
placeholder="Principal Distributor name"
className="form-control"
ref={mobileRef}
onChange={handleSearchChange}
disabled={loading}
value={searchPrincipalDistributor}
/>
</div>
<div className="col-lg-3">
<label>Verify Retail Distributor:</label>
<select
className="form-control"
ref={VerifyRetailDistributorRef}
onChange={handleSearchChange}
disabled={loading}
<Button
variant="outlined"
color="primary"
onClick={handleResetSearch}
>
<option value="">----Select----</option>
<option value="true">YES</option>
<option value="false">NO</option>
</select>
Reset Search
</Button>
</div>
</div>
@ -155,9 +191,9 @@ const RetailDistributor = () => {
<th>ID</th>
<th className="text-start">Trade Name</th>
<th className="text-start">Created On</th>
<th className="text-start">PrincipleDistributor</th>
<th className="text-start">TerritoryManager</th>
<th className="text-start">SalesCoOrdinator</th>
<th className="text-start">Principal Distributor</th>
<th className="text-start">Territory Manager</th>
<th className="text-start">Sales Coordinator</th>
<th className="text-start">Action</th>
</tr>
</thead>
@ -165,61 +201,62 @@ const RetailDistributor = () => {
<tbody>
{loading ? (
<tr>
<td className="text-center" colSpan="5">
<td className="text-center" colSpan="7">
Loading...
</td>
</tr>
) : retailDistributorsData?.length > 0 ? (
retailDistributorsData?.map((retailDistributor, i) => {
return (
<tr key={i}>
<td className="text-start">
{retailDistributor?.id}
</td>
<td className="text-start">
{retailDistributor?.tradeName}
</td>
<td className="text-start">
{new Date(
retailDistributor.createdAt
).toLocaleString("en-IN", {
weekday: "short",
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "numeric",
hour12: true,
})}
</td>
<td className="text-start">
<div>
<div>Principal Distributor: {retailDistributor.principalDistributor || 'N/A'}</div>
<div>Territory Manager: {retailDistributor.territoryManager || 'N/A'}</div>
<div>Sales Coordinator: {retailDistributor.salesCoordinator || 'N/A'}</div>
</div>
</td>
<td className="text-start">
<Link
to={`/retaildistributor/view/${retailDistributor._id}`}
>
<button
style={{
color: "white",
}}
type="button"
className="btn btn-info btn-sm waves-effect waves-light btn-table ml-2"
>
View
</button>
</Link>
</td>
</tr>
);
})
) : paginatedData.length > 0 ? (
paginatedData.map((retailDistributor) => (
<tr key={retailDistributor._id}>
<td className="text-start">
{retailDistributor._id}
</td>
<td className="text-start">
{retailDistributor.trade_name}
</td>
<td className="text-start">
{new Date(
retailDistributor.updatedAt
).toLocaleString("en-IN", {
weekday: "short",
month: "short",
day: "numeric",
year: "numeric",
hour: "numeric",
minute: "numeric",
hour12: true,
})}
</td>
<td className="text-start">
{retailDistributor.principal_distributer
?.name || "N/A"}
</td>
<td className="text-start">
{retailDistributor.userType ===
"TerritoryManager"
? retailDistributor.addedBy?.name || "N/A"
: "N/A"}
</td>
<td className="text-start">
{retailDistributor.userType ===
"SalesCoOrdinator"
? retailDistributor.addedBy?.name || "N/A"
: "N/A"}
</td>
<td className="text-start">
<Link
to={`/retaildistributor/view/${retailDistributor._id}`}
>
<Button variant="contained" color="primary">
View
</Button>
</Link>
</td>
</tr>
))
) : (
<tr>
<td className="text-center" colSpan="5">
<td className="text-center" colSpan="7">
No Retail Distributor found!
</td>
</tr>
@ -236,49 +273,64 @@ const RetailDistributor = () => {
aria-live="polite"
>
Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "}
{Math.min(currentPage * itemPerPage, totalData)} of{" "}
{totalData} entries
{Math.min(
currentPage * itemPerPage,
filteredRetailDistributorsData.length
)}{" "}
of {filteredRetailDistributorsData.length} entries
</div>
</div>
<div className="col-sm-12 col-md-6">
<div className="d-flex">
<ul className="pagination ms-auto">
<div className="dataTables_paginate paging_simple_numbers">
<ul className="pagination">
<li
className={
currentPage === 1
? "paginate_button page-item previous disabled"
: "paginate_button page-item previous"
}
className={`paginate_button page-item previous ${
currentPage === 1 ? "disabled" : ""
}`}
>
<span
<a
className="page-link"
onClick={() =>
setCurrentPage((prev) =>
prev > 1 ? prev - 1 : prev
)
setCurrentPage((prev) => Math.max(prev - 1, 1))
}
aria-controls="datatable"
>
Previous
</span>
</a>
</li>
{Array.from({ length: totalPages }, (_, index) => (
<li
key={index}
className={`paginate_button page-item ${
currentPage === index + 1 ? "active" : ""
}`}
>
<a
className="page-link"
onClick={() => setCurrentPage(index + 1)}
aria-controls="datatable"
>
{index + 1}
</a>
</li>
))}
<li
className={
currentPage === totalPages
? "paginate_button page-item next disabled"
: "paginate_button page-item next"
}
className={`paginate_button page-item next ${
currentPage === totalPages ? "disabled" : ""
}`}
>
<span
<a
className="page-link"
onClick={() =>
setCurrentPage((prev) =>
prev < totalPages ? prev + 1 : prev
Math.min(prev + 1, totalPages)
)
}
aria-controls="datatable"
>
Next
</span>
</a>
</li>
</ul>
</div>

View File

@ -18,43 +18,43 @@ const SingleRetailDistributor = () => {
const fetchData = async () => {
try {
// Commented out the API call and using dummy data
// const response = await axios.get(`/api/kyc/get-single-kyc/${id}`, {
// headers: {
// 'Access-Control-Allow-Origin': '*',
// Authorization: `Bearer ${token}`,
// 'Content-Type': 'multipart/form-data',
// },
// });
// setRetailerDetails(response.data);
const response = await axios.get(`api/kyc/get-single-kyc/${id}`, {
headers: {
'Access-Control-Allow-Origin': '*',
Authorization: `Bearer ${token}`,
'Content-Type': 'multipart/form-data',
},
});
setRetailerDetails(response.data);
// Dummy data
const dummyData = {
_id: '66a8bb8392d90216331b1f73',
name: 'roshan garg',
trade_name: 'abc',
address: 'abc btm',
state: 'KA',
city: 'Bengaluru',
district: 'benga',
pincode: '124515',
mobile_number: '8516913819',
principal_distributer: { name: 'Distributor Name' },
pan_number: '123456454',
pan_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334072/KYC/pan/u3a08xjvrpovfzruedeq.png' },
aadhar_number: '123123123123',
aadhar_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334074/KYC/aadhar/ep64tuufileifysol4dx.png' },
gst_number: '121212',
gst_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334076/KYC/gst/jqy8uqa6ejntwhc7mq86.png' },
pesticide_license_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334077/KYC/pesticide_license/iyznci3iibp50pug8e8p.png' },
fertilizer_license_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334080/KYC/fertilizer_license/jnj1r8rzwsbkclarbbch.png' },
selfie_entrance_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334082/KYC/selfie_entrance/weri7zhyioi7lqwv3dvg.png' },
status: 'new',
addedBy: { name: 'Added By', uniqueId: 'E123' },
notes: [],
createdAt: '2024-01-01T00:00:00Z',
updatedAt: '2024-01-01T00:00:00Z',
};
setRetailerDetails(dummyData);
// // Dummy data
// const dummyData = {
// _id: '66a8bb8392d90216331b1f73',
// name: 'roshan garg',
// trade_name: 'abc',
// address: 'abc btm',
// state: 'KA',
// city: 'Bengaluru',
// district: 'benga',
// pincode: '124515',
// mobile_number: '8516913819',
// principal_distributer: { name: 'Distributor Name' },
// pan_number: '123456454',
// pan_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334072/KYC/pan/u3a08xjvrpovfzruedeq.png' },
// aadhar_number: '123123123123',
// aadhar_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334074/KYC/aadhar/ep64tuufileifysol4dx.png' },
// gst_number: '121212',
// gst_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334076/KYC/gst/jqy8uqa6ejntwhc7mq86.png' },
// pesticide_license_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334077/KYC/pesticide_license/iyznci3iibp50pug8e8p.png' },
// fertilizer_license_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334080/KYC/fertilizer_license/jnj1r8rzwsbkclarbbch.png' },
// selfie_entrance_img: { url: 'https://res.cloudinary.com/dslvetard/image/upload/v1722334082/KYC/selfie_entrance/weri7zhyioi7lqwv3dvg.png' },
// status: 'new',
// addedBy: { name: 'Added By', uniqueId: 'E123' },
// notes: [],
// createdAt: '2024-01-01T00:00:00Z',
// updatedAt: '2024-01-01T00:00:00Z',
// };
// setRetailerDetails(dummyData);
} catch (error) {
console.error('Error fetching data: ', error);
}