RD and Tm added multiple by spreadsheet

This commit is contained in:
Sibunnayak 2024-10-08 17:07:25 +05:30
parent 90cb27e69b
commit efdbe2377c
8 changed files with 821 additions and 62 deletions

View File

@ -156,6 +156,9 @@ import PendingOrders from "./views/orders/pendingOrders";
import ViewInvoices from "./views/orders/viewInoices"; import ViewInvoices from "./views/orders/viewInoices";
import SingleDistributorOrder from "./views/RetailDistributors/DistributorOrders"; import SingleDistributorOrder from "./views/RetailDistributors/DistributorOrders";
import DistributorStocks from "./views/RetailDistributors/DistributorStock"; import DistributorStocks from "./views/RetailDistributors/DistributorStock";
import AddMultiplerd from "./views/RetailDistributors/AddMultipleRD";
import AddMultipletm from "./views/TerritoryManager/AddMultipleTM";
import AddMultiplesc from "./views/SalesCoOrdinators/AddMultipleSC";
const routes = [ const routes = [
//dashboard //dashboard
@ -259,6 +262,12 @@ const routes = [
element: ViewRetailDistributorSC, element: ViewRetailDistributorSC,
navName: "SalesCoOrdinators", navName: "SalesCoOrdinators",
}, },
{
path: "/add-sales-coordinator/multiple",
name: "Add Sales Coordinators",
element: AddMultiplesc,
navName: "SalesCoOrdinators",
},
//TerritoryManager //TerritoryManager
{ {
path: "/territorymanager/edit/:id", path: "/territorymanager/edit/:id",
@ -296,6 +305,12 @@ const routes = [
element: ViewRetailDistributorTM, element: ViewRetailDistributorTM,
navName: "TerritoryManagers", navName: "TerritoryManagers",
}, },
{
path: "/add-territory-manager/multiple",
name: "Add Territory Managers",
element: AddMultipletm,
navName: "TerritoryManagers",
},
// Attendence // Attendence
{ {
path: "/attendance/today", path: "/attendance/today",
@ -365,6 +380,12 @@ const routes = [
element: AddRetailDistributor, element: AddRetailDistributor,
navName: "RetailDistributor", navName: "RetailDistributor",
}, },
{
path: "/add-retail-distributor/multiple",
name: "Add Retail Distributor",
element: AddMultiplerd,
navName: "RetailDistributor",
},
{ {
path: "/retaildistributor/mapping/:id", path: "/retaildistributor/mapping/:id",
name: "Mapping Retail Distributor with PD SC TM", name: "Mapping Retail Distributor with PD SC TM",

View File

@ -0,0 +1,237 @@
import React, { useState } from "react";
import axios from "axios";
import swal from "sweetalert";
import { isAutheticated } from "src/auth";
import { useNavigate } from "react-router-dom";
import { toast } from "react-hot-toast";
const AddMultiplerd = () => {
const [file, setFile] = useState(null);
const [loading, setLoading] = useState(false);
const [errors, setErrors] = useState([]);
const [newlyCreated, setNewlyCreated] = useState([]);
const [updatedDistributors, setUpdatedDistributors] = useState([]);
const navigate = useNavigate();
const token = isAutheticated();
const handleFileChange = (e) => {
const selectedFile = e.target.files[0];
if (
selectedFile &&
selectedFile.type ===
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
) {
setFile(selectedFile);
} else {
swal("Error", "Please upload a valid Excel file", "error");
setFile(null);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!file) {
toast.error("Please select a file to upload");
return;
}
// console.log(file);
// console.log(token);
setLoading(true);
setErrors([]);
setNewlyCreated([]);
setUpdatedDistributors([]);
try {
const formData = new FormData();
formData.append("file", file);
const { data } = await axios.post(
"/api/retaildistributor/upload",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
}
);
// console.log(data);
if (data.errors && data.errors.length > 0) {
setErrors(data.errors);
}
if (data.newlyCreated && data.newlyCreated.length > 0) {
setNewlyCreated(data.newlyCreated);
// console.log(data.newlyCreated);
}
if (data.updatedDistributors && data.updatedDistributors.length > 0) {
setUpdatedDistributors(data.updatedDistributors);
// console.log(data.updatedDistributors);
}
// Redirect or display success message
if (data.errors && data.errors.length > 0) {
setErrors(data.errors);
swal({
title: "SpreadSheet Upload Successful",
text: "A few Retail Distributor have errors. Please fix them and upload again.",
icon: "warning",
button: "OK",
});
} else if (
data.newlyCreated > 0 ||
data.updatedDistributors > 0
) {
swal({
title: "SpreadSheet Upload Successful",
text: "Retail Distributors added successfully.",
icon: "success",
buttons: "OK",
});
} else {
toast.success("File processed successfully with no new entries.");
navigate("/retail-distributor");
}
setFile(null); // Clear the file input
document.querySelector('input[type="file"]').value = "";
} catch (error) {
console.error("Upload error:", error);
swal(
"Error",
`Failed to upload Retail Distributor: ${
error.response?.data?.message || "An unexpected error occurred"
}`,
"error"
);
} finally {
setLoading(false);
}
};
return (
<div className="container mt-4">
<div className="mb-6">
<button
onClick={() => navigate("/retail-distributor")}
className="btn btn-secondary"
>
Back
</button>
</div>
<h5 className="mb-6 mt-4">Add Multiple Retail Distributor</h5>
<div className="my-3">
<div className="row">
<div className="col-lg-9">
<input
type="file"
name="file"
className="form-control"
accept=".xlsx"
onChange={handleFileChange}
/>
</div>
<div className="col-lg-3">
<button
className="btn btn-primary"
onClick={handleSubmit}
disabled={loading}
>
{loading ? "Uploading..." : "Upload"}
</button>
</div>
</div>
<p className="pt-1 pl-2 text-secondary">Upload only .xlsx files*</p>
</div>
{errors.length > 0 && (
<div className="my-4">
<h6>Finding errors while adding the Retail Distributor.</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Retail Distributor Name</th>
<th>Email</th>
<th>Phone</th>
<th>PAN</th>
<th>GST</th>
<th>AAdhar</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{errors.map((error, index) => (
<tr key={index}>
<td>{error.name || "N/A"}</td>
<td>{error.email || "N/A"}</td>
<td>{error.phone || "N/A"}</td>
<td>{error.panNumber || "N/A"}</td>
<td>{error.gstNumber || "N/A"}</td>
<td>{error.AadharNumber || "N/A"}</td>
<td>{error.message}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
{updatedDistributors.length > 0 && (
<div className="my-4">
<h6>Updated Retail Distributors</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Retail Distributor Name</th>
<th>Email</th>
<th>Phone</th>
<th>PAN</th>
<th>GST</th>
<th>Aadhar</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{updatedDistributors.map((distributor, index) => (
<tr key={index}>
<td>{distributor.name || "N/A"}</td>
<td>{distributor.email || "N/A"}</td>
<td>{distributor.mobile_number || "N/A"}</td>
<td>{distributor.pan_number || "N/A"}</td>
<td>{distributor.gst_number || "N/A"}</td>
<td>{distributor.aadhar_number || "N/A"}</td>
<td>{distributor.updatedFields}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
{newlyCreated.length > 0 && (
<div className="my-4">
<h6>Newly Created Retail Distributors:</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Retail Distributor Name</th>
<th>Email</th>
<th>Phone</th>
<th>PAN</th>
<th>GST</th>
<th>Aadhar</th>
</tr>
</thead>
<tbody>
{newlyCreated.map((distributor, index) => (
<tr key={index}>
<td>{distributor?.Kyc?.name || "N/A"}</td>
<td>{distributor?.Kyc?.email || "N/A"}</td>
<td>{distributor?.Kyc?.mobile_number || "N/A"}</td>
<td>{distributor?.Kyc?.pan_number || "N/A"}</td>
<td>{distributor?.Kyc?.gst_number || "N/A"}</td>
<td>{distributor?.Kyc?.aadhar_number || "N/A"}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
);
};
export default AddMultiplerd;

View File

@ -90,6 +90,18 @@ const RetailDistributor = () => {
> >
Add Retail Distributor Add Retail Distributor
</Button> </Button>
<Button
variant="contained"
color="primary"
className="font-bold mb-2 capitalize"
onClick={() =>
Navigate("/add-retail-distributor/multiple", {
replace: true,
})
}
>
Upload Spreadsheet
</Button>
</div> </div>
</div> </div>
</div> </div>
@ -251,7 +263,9 @@ const RetailDistributor = () => {
View View
</button> </button>
</Link> </Link>
<Link to={`/retailerdistributor/stocks/${retailDistributor?._id}`}> <Link
to={`/retailerdistributor/stocks/${retailDistributor?._id}`}
>
<button <button
style={{ style={{
color: "white", color: "white",

View File

@ -24,7 +24,6 @@ const SingleRetailDistributor = () => {
const token = isAutheticated(); const token = isAutheticated();
const navigate = useNavigate(); const navigate = useNavigate();
const getUserDetails = useCallback(async () => { const getUserDetails = useCallback(async () => {
try { try {
// Commented out the API call and using dummy data // Commented out the API call and using dummy data
@ -136,57 +135,79 @@ useEffect(() => {
<Typography> <Typography>
<strong>PAN Number:</strong> {retailerDetails.kyc.pan_number} <strong>PAN Number:</strong> {retailerDetails.kyc.pan_number}
</Typography> </Typography>
{retailerDetails?.kyc?.pan_img ? (
<Avatar <Avatar
variant="square" variant="square"
src={retailerDetails.kyc.pan_img.url} src={retailerDetails?.kyc?.pan_img?.url}
sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }} sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }}
onClick={() => handleOpenPopup(retailerDetails.kyc.pan_img.url)} onClick={() =>
handleOpenPopup(retailerDetails?.kyc?.pan_img?.url)
}
/> />
) : (
<Typography>Img not available</Typography>
)}
<Typography> <Typography>
<strong>Aadhar Number:</strong>{" "} <strong>Aadhar Number:</strong>{" "}
{retailerDetails.kyc.aadhar_number} {retailerDetails.kyc.aadhar_number}
</Typography> </Typography>
{retailerDetails?.kyc?.aadhar_img ? (
<Avatar <Avatar
variant="square" variant="square"
src={retailerDetails.kyc.aadhar_img.url} src={retailerDetails?.kyc?.aadhar_img?.url}
sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }} sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }}
onClick={() => onClick={() =>
handleOpenPopup(retailerDetails.kyc.aadhar_img.url) handleOpenPopup(retailerDetails?.kyc?.aadhar_img?.url)
} }
/> />
) : (
<Typography>Img not available</Typography>
)}
<Typography> <Typography>
<strong>GST Number:</strong> {retailerDetails.kyc.gst_number} <strong>GST Number:</strong> {retailerDetails.kyc.gst_number}
</Typography> </Typography>
{retailerDetails?.kyc?.gst_img ? (
<Avatar <Avatar
variant="square" variant="square"
src={retailerDetails.kyc.gst_img.url} src={retailerDetails?.kyc?.gst_img?.url}
sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }} sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }}
onClick={() => handleOpenPopup(retailerDetails.kyc.gst_img.url)} onClick={() =>
handleOpenPopup(retailerDetails?.kyc?.gst_img?.url)
}
/> />
) : (
<Typography>Img not available</Typography>
)}
</Grid> </Grid>
<Grid item xs={6}> <Grid item xs={6}>
<Typography> <Typography>
<strong>Pesticide License:</strong> <strong>Pesticide License:</strong>
</Typography> </Typography>
{retailerDetails?.kyc?.pesticide_license_img ? (
<Avatar <Avatar
variant="square" variant="square"
src={retailerDetails.kyc.pesticide_license_img.url} src={retailerDetails?.kyc?.pesticide_license_img?.url}
sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }}
onClick={() =>
handleOpenPopup(retailerDetails.kyc.pesticide_license_img.url)
}
/>
<Typography>
<strong>Fertilizer License (optional):</strong>
</Typography>
{retailerDetails.kyc.fertilizer_license_img ? (
<Avatar
variant="square"
src={retailerDetails.kyc.fertilizer_license_img.url}
sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }} sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }}
onClick={() => onClick={() =>
handleOpenPopup( handleOpenPopup(
retailerDetails.kyc.fertilizer_license_img.url retailerDetails?.kyc?.pesticide_license_img?.url
)
}
/>
) : (
<Typography>Img not available</Typography>
)}
<Typography>
<strong>Fertilizer License (optional):</strong>
</Typography>
{retailerDetails?.kyc?.fertilizer_license_img ? (
<Avatar
variant="square"
src={retailerDetails?.kyc?.fertilizer_license_img?.url}
sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }}
onClick={() =>
handleOpenPopup(
retailerDetails?.kyc?.fertilizer_license_img?.url
) )
} }
/> />
@ -196,14 +217,20 @@ useEffect(() => {
<Typography> <Typography>
<strong>Selfie of Entrance Board:</strong> <strong>Selfie of Entrance Board:</strong>
</Typography> </Typography>
{retailerDetails?.kyc?.selfie_entrance_img ? (
<Avatar <Avatar
variant="square" variant="square"
src={retailerDetails.kyc.selfie_entrance_img.url} src={retailerDetails?.kyc?.selfie_entrance_img?.url}
sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }} sx={{ width: 100, height: 100, mb: 2, cursor: "pointer" }}
onClick={() => onClick={() =>
handleOpenPopup(retailerDetails.kyc.selfie_entrance_img.url) handleOpenPopup(
retailerDetails?.kyc?.selfie_entrance_img?.url
)
} }
/> />
) : (
<Typography>Img not available</Typography>
)}
</Grid> </Grid>
</Grid> </Grid>
</Paper> </Paper>

View File

@ -0,0 +1,218 @@
import React, { useState } from "react";
import axios from "axios";
import swal from "sweetalert";
import { isAutheticated } from "src/auth";
import { useNavigate } from "react-router-dom";
import { toast } from "react-hot-toast";
const AddMultiplesc = () => {
const [file, setFile] = useState(null);
const [loading, setLoading] = useState(false);
const [errors, setErrors] = useState([]);
const [newlyCreated, setNewlyCreated] = useState([]);
const [updatedsalesCoordinators, setupdatedsalesCoordinators] = useState([]);
const navigate = useNavigate();
const token = isAutheticated();
const handleFileChange = (e) => {
const selectedFile = e.target.files[0];
if (
selectedFile &&
selectedFile.type ===
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
) {
setFile(selectedFile);
} else {
swal("Error", "Please upload a valid Excel file", "error");
setFile(null);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!file) {
toast.error("Please select a file to upload");
return;
}
// console.log(file);
// console.log(token);
setLoading(true);
setErrors([]);
setNewlyCreated([]);
setupdatedsalesCoordinators([]);
try {
const formData = new FormData();
formData.append("file", file);
const { data } = await axios.post(
"/api/salescoordinator/upload",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
}
);
// console.log(data);
if (data.errors && data.errors.length > 0) {
setErrors(data.errors);
}
if (data.newlyCreated && data.newlyCreated.length > 0) {
setNewlyCreated(data.newlyCreated);
// console.log(data.newlyCreated);
}
if (data.updatedsalesCoordinators && data.updatedsalesCoordinators.length > 0) {
setupdatedsalesCoordinators(data.updatedsalesCoordinators);
// console.log(data.updatedsalesCoordinators);
}
// Redirect or display success message
if (data.errors && data.errors.length > 0) {
setErrors(data.errors);
swal({
title: "SpreadSheet Upload Successful",
text: "A few Sales Coordinator have errors. Please fix them and upload again.",
icon: "warning",
button: "OK",
});
} else if (
data.newlyCreated > 0 ||
data.updatedsalesCoordinators > 0
) {
swal({
title: "SpreadSheet Upload Successful",
text: "Sales Coordinators added successfully.",
icon: "success",
buttons: "OK",
});
} else {
toast.success("File processed successfully with no new entries.");
navigate("/salescoordinators");
}
setFile(null); // Clear the file input
document.querySelector('input[type="file"]').value = "";
} catch (error) {
console.error("Upload error:", error);
swal(
"Error",
`Failed to upload Sales Coordinators: ${
error.response?.data?.message || "An unexpected error occurred"
}`,
"error"
);
} finally {
setLoading(false);
}
};
return (
<div className="container mt-4">
<div className="mb-6">
<button
onClick={() => navigate("/salescoordinators")}
className="btn btn-secondary"
>
Back
</button>
</div>
<h5 className="mb-6 mt-4">Add Multiple Sales Coordinators</h5>
<div className="my-3">
<div className="row">
<div className="col-lg-9">
<input
type="file"
name="file"
className="form-control"
accept=".xlsx"
onChange={handleFileChange}
/>
</div>
<div className="col-lg-3">
<button
className="btn btn-primary"
onClick={handleSubmit}
disabled={loading}
>
{loading ? "Uploading..." : "Upload"}
</button>
</div>
</div>
<p className="pt-1 pl-2 text-secondary">Upload only .xlsx files*</p>
</div>
{errors.length > 0 && (
<div className="my-4">
<h6>Finding errors while adding the Sales Coordinators.</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Sales Coordinator Name</th>
<th>Email</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{errors.map((error, index) => (
<tr key={index}>
<td>{error.name || "N/A"}</td>
<td>{error.email || "N/A"}</td>
<td>{error.phone || "N/A"}</td>
<td>{error.message}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
{updatedsalesCoordinators.length > 0 && (
<div className="my-4">
<h6>Updated Sales Coordinators</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Sales Coordinator Name</th>
<th>Email</th>
<th>Phone</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{updatedsalesCoordinators.map((SC, index) => (
<tr key={index}>
<td>{SC.name || "N/A"}</td>
<td>{SC.email || "N/A"}</td>
<td>{SC.mobileNumber || "N/A"}</td>
<td>{SC.updatedFields}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
{newlyCreated.length > 0 && (
<div className="my-4">
<h6>Newly Created Sales Coordinators:</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Sales Coordinator Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{newlyCreated.map((SC, index) => (
<tr key={index}>
<td>{SC?.salesCoordinator?.name || "N/A"}</td>
<td>{SC?.salesCoordinator?.email || "N/A"}</td>
<td>{SC?.salesCoordinator?.mobileNumber || "N/A"}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
);
};
export default AddMultiplesc;

View File

@ -122,17 +122,25 @@ const SalesCoOrdinator = () => {
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
style={{ className="font-bold mb-2 capitalize mr-2"
fontWeight: "bold",
marginBottom: "1rem",
textTransform: "capitalize",
}}
onClick={() => { onClick={() => {
navigate("/salescoordinator/add", { replace: true }); navigate("/salescoordinator/add", { replace: true });
}} }}
> >
Add Sales Coordinator Add Sales Coordinator
</Button> </Button>
{/* <Button
variant="contained"
color="primary"
className="font-bold mb-2 capitalize"
onClick={() =>
navigate("/add-sales-coordinator/multiple", {
replace: true,
})
}
>
Upload Spreadsheet
</Button> */}
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,218 @@
import React, { useState } from "react";
import axios from "axios";
import swal from "sweetalert";
import { isAutheticated } from "src/auth";
import { useNavigate } from "react-router-dom";
import { toast } from "react-hot-toast";
const AddMultipletm = () => {
const [file, setFile] = useState(null);
const [loading, setLoading] = useState(false);
const [errors, setErrors] = useState([]);
const [newlyCreated, setNewlyCreated] = useState([]);
const [updatedtrritoryManagers, setupdatedtrritoryManagers] = useState([]);
const navigate = useNavigate();
const token = isAutheticated();
const handleFileChange = (e) => {
const selectedFile = e.target.files[0];
if (
selectedFile &&
selectedFile.type ===
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
) {
setFile(selectedFile);
} else {
swal("Error", "Please upload a valid Excel file", "error");
setFile(null);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!file) {
toast.error("Please select a file to upload");
return;
}
// console.log(file);
// console.log(token);
setLoading(true);
setErrors([]);
setNewlyCreated([]);
setupdatedtrritoryManagers([]);
try {
const formData = new FormData();
formData.append("file", file);
const { data } = await axios.post(
"/api/territorymanager/upload",
formData,
{
headers: {
"Content-Type": "multipart/form-data",
Authorization: `Bearer ${token}`,
},
}
);
// console.log(data);
if (data.errors && data.errors.length > 0) {
setErrors(data.errors);
}
if (data.newlyCreated && data.newlyCreated.length > 0) {
setNewlyCreated(data.newlyCreated);
// console.log(data.newlyCreated);
}
if (data.updatedtrritoryManagers && data.updatedtrritoryManagers.length > 0) {
setupdatedtrritoryManagers(data.updatedtrritoryManagers);
// console.log(data.updatedtrritoryManagers);
}
// Redirect or display success message
if (data.errors && data.errors.length > 0) {
setErrors(data.errors);
swal({
title: "SpreadSheet Upload Successful",
text: "A few Territory Manager have errors. Please fix them and upload again.",
icon: "warning",
button: "OK",
});
} else if (
data.newlyCreated > 0 ||
data.updatedtrritoryManagers > 0
) {
swal({
title: "SpreadSheet Upload Successful",
text: "Territory Managers added successfully.",
icon: "success",
buttons: "OK",
});
} else {
toast.success("File processed successfully with no new entries.");
navigate("/territorymanagers");
}
setFile(null); // Clear the file input
document.querySelector('input[type="file"]').value = "";
} catch (error) {
console.error("Upload error:", error);
swal(
"Error",
`Failed to upload Territory Managers: ${
error.response?.data?.message || "An unexpected error occurred"
}`,
"error"
);
} finally {
setLoading(false);
}
};
return (
<div className="container mt-4">
<div className="mb-6">
<button
onClick={() => navigate("/territorymanagers")}
className="btn btn-secondary"
>
Back
</button>
</div>
<h5 className="mb-6 mt-4">Add Multiple Territory Managers</h5>
<div className="my-3">
<div className="row">
<div className="col-lg-9">
<input
type="file"
name="file"
className="form-control"
accept=".xlsx"
onChange={handleFileChange}
/>
</div>
<div className="col-lg-3">
<button
className="btn btn-primary"
onClick={handleSubmit}
disabled={loading}
>
{loading ? "Uploading..." : "Upload"}
</button>
</div>
</div>
<p className="pt-1 pl-2 text-secondary">Upload only .xlsx files*</p>
</div>
{errors.length > 0 && (
<div className="my-4">
<h6>Finding errors while adding the Territory Manager.</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Territory Manager Name</th>
<th>Email</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{errors.map((error, index) => (
<tr key={index}>
<td>{error.name || "N/A"}</td>
<td>{error.email || "N/A"}</td>
<td>{error.phone || "N/A"}</td>
<td>{error.message}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
{updatedtrritoryManagers.length > 0 && (
<div className="my-4">
<h6>Updated Territory Managers</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Territory Manager Name</th>
<th>Email</th>
<th>Phone</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{updatedtrritoryManagers.map((TM, index) => (
<tr key={index}>
<td>{TM.name || "N/A"}</td>
<td>{TM.email || "N/A"}</td>
<td>{TM.mobileNumber || "N/A"}</td>
<td>{TM.updatedFields}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
{newlyCreated.length > 0 && (
<div className="my-4">
<h6>Newly Created Territory Managers:</h6>
<table className="table table-bordered">
<thead>
<tr>
<th>Territory Manager Name</th>
<th>Email</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
{newlyCreated.map((TM, index) => (
<tr key={index}>
<td>{TM?.territoryManager?.name || "N/A"}</td>
<td>{TM?.territoryManager?.email || "N/A"}</td>
<td>{TM?.territoryManager?.mobileNumber || "N/A"}</td>
</tr>
))}
</tbody>
</table>
</div>
)}
</div>
);
};
export default AddMultipletm;

View File

@ -5,7 +5,7 @@ import Button from "@material-ui/core/Button";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { isAutheticated } from "src/auth"; import { isAutheticated } from "src/auth";
import swal from "sweetalert"; import swal from "sweetalert";
import debounce from 'lodash.debounce'; import debounce from "lodash.debounce";
const TerritoryManager = () => { const TerritoryManager = () => {
const token = isAutheticated(); const token = isAutheticated();
@ -57,10 +57,13 @@ const TerritoryManager = () => {
getTerritoryManagersData(); getTerritoryManagersData();
}, [success, itemPerPage, currentPage]); }, [success, itemPerPage, currentPage]);
const debouncedSearch = useCallback(debounce(() => { const debouncedSearch = useCallback(
debounce(() => {
setCurrentPage(1); setCurrentPage(1);
getTerritoryManagersData(); getTerritoryManagersData();
}, 500), []); }, 500),
[]
);
const handleSearchChange = () => { const handleSearchChange = () => {
debouncedSearch(); debouncedSearch();
@ -122,17 +125,25 @@ const TerritoryManager = () => {
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
style={{ className="font-bold mb-2 capitalize mr-2"
fontWeight: "bold",
marginBottom: "1rem",
textTransform: "capitalize",
}}
onClick={() => { onClick={() => {
navigate("/territorymanager/add", { replace: true }); navigate("/territorymanager/add", { replace: true });
}} }}
> >
Add Territory Manager Add Territory Manager
</Button> </Button>
<Button
variant="contained"
color="primary"
className="font-bold mb-2 capitalize"
onClick={() =>
navigate("/add-territory-manager/multiple", {
replace: true,
})
}
>
Upload Spreadsheet
</Button>
</div> </div>
</div> </div>
</div> </div>
@ -338,7 +349,9 @@ const TerritoryManager = () => {
type="button" type="button"
style={{ color: "white" }} style={{ color: "white" }}
className="btn btn-danger btn-sm waves-effect waves-light btn-table ml-2" className="btn btn-danger btn-sm waves-effect waves-light btn-table ml-2"
onClick={() => handleDelete(territorymanager._id)} onClick={() =>
handleDelete(territorymanager._id)
}
> >
Delete Delete
</button> </button>
@ -358,7 +371,8 @@ const TerritoryManager = () => {
</div> </div>
<div className="d-flex justify-content-between"> <div className="d-flex justify-content-between">
<div> <div>
Showing {territorymanagersData?.length} of {totalData} entries Showing {territorymanagersData?.length} of {totalData}{" "}
entries
</div> </div>
<div> <div>
<button <button
@ -370,7 +384,9 @@ const TerritoryManager = () => {
</button> </button>
<button <button
onClick={() => setCurrentPage(currentPage + 1)} onClick={() => setCurrentPage(currentPage + 1)}
disabled={territorymanagersData?.length < itemPerPage || loading} disabled={
territorymanagersData?.length < itemPerPage || loading
}
className="btn btn-primary ml-2" className="btn btn-primary ml-2"
> >
Next Next