From f9a73384802e17a7f8a26c8889dda3cd079b3851 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Tue, 30 Jul 2024 13:40:47 +0530 Subject: [PATCH] territory manager added --- package.json | 1 + src/App.js | 213 +++++++--- src/_nav.js | 7 + src/components/ProtectedRoute.js | 65 ++- src/routes.js | 25 +- src/views/Attendance/TodayAttendance.js | 9 + .../SalesCoOrdinators/AddSalesCoOrdinator.js | 3 +- .../SalesCoOrdinators/EditSalesCoOrdinator.js | 1 + .../TerritoryManager/AddTerritoryManager.js | 198 +++++++++ .../TerritoryManager/EditTerritoryManager.js | 396 ++++++++++++++++++ .../TerritoryManager/TerritoryManager.js | 345 +++++++++++++++ 11 files changed, 1182 insertions(+), 81 deletions(-) create mode 100644 src/views/TerritoryManager/AddTerritoryManager.js create mode 100644 src/views/TerritoryManager/EditTerritoryManager.js create mode 100644 src/views/TerritoryManager/TerritoryManager.js diff --git a/package.json b/package.json index bbf9af3..0d6de74 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "draft-js-export-html": "^1.4.1", "draft-js-import-html": "^1.4.1", "file-saver": "^2.0.5", + "jwt-decode": "^4.0.0", "md5": "^2.3.0", "moment": "^2.30.1", "prop-types": "^15.7.2", diff --git a/src/App.js b/src/App.js index ba18c6d..475cd7a 100644 --- a/src/App.js +++ b/src/App.js @@ -111,82 +111,159 @@ // }; // export default App; +// import React, { Suspense, useEffect, useState } from "react"; +// import axios from "axios"; +// import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; +// import { Toaster } from "react-hot-toast"; +// import "./scss/style.scss"; +// import ForgotPassword from "./views/pages/register/ForgotPassword"; +// import NewRegister from "./views/pages/register/NewRegister"; +// import ProtectedRoute from './components/ProtectedRoute'; +// import { isAutheticated } from "./auth"; +// import InternetConnectionPopUp from "./views/InternetConnectionPopUp"; + +// const loading = ( +//
+//
+//
+// ); + +// const DefaultLayout = React.lazy(() => import("./layout/DefaultLayout")); +// const Login = React.lazy(() => import("./views/pages/login/Login")); +// const Page404 = React.lazy(() => import("./views/pages/register/page404/Page404")); +// const Page500 = React.lazy(() => import("./views/pages/page500/Page500")); + +// const App = () => { +// const [userdata, setUserData] = useState(null); +// const token = isAutheticated(); + +// useEffect(() => { +// const getUser = async () => { +// let existanceData = localStorage.getItem("authToken"); +// if (!existanceData) { +// setUserData(false); +// } else { +// try { +// let response = await axios.get(`/api/v1/user/details`, { +// headers: { +// Authorization: `Bearer ${token}`, +// }, +// }); +// const data = response?.data; +// if (data?.success && (data?.user?.role === "admin" || data?.user?.role === "Employee")) { +// setUserData(data?.user); +// } else { +// setUserData(false); +// } +// } catch (err) { +// setUserData(false); +// console.log(err); +// } +// } +// }; +// getUser(); +// }, [token]); + +// return ( +// +// +// +// } /> +// } /> +// } /> +// } /> +// } /> + +// } +// /> + +// {/* Redirect all other routes to 404 */} +// } /> +// +// +// +// +// +// ); +// }; + +// export default App; + import React, { Suspense, useEffect, useState } from "react"; -import axios from "axios"; -import { HashRouter, Routes, Route, Navigate } from "react-router-dom"; -import { Toaster } from "react-hot-toast"; -import "./scss/style.scss"; -import ForgotPassword from "./views/pages/register/ForgotPassword"; -import NewRegister from "./views/pages/register/NewRegister"; -import ProtectedRoute from './components/ProtectedRoute'; +import { HashRouter, Route, Routes } from "react-router-dom"; +import { useSelector } from "react-redux"; import { isAutheticated } from "./auth"; -import InternetConnectionPopUp from "./views/InternetConnectionPopUp"; - -const loading = ( -
-
-
-); - +import "./scss/style.scss"; +import ProtectedRoute from "./components/ProtectedRoute"; +import axios from "axios"; +// Containers const DefaultLayout = React.lazy(() => import("./layout/DefaultLayout")); + +// Pages const Login = React.lazy(() => import("./views/pages/login/Login")); -const Page404 = React.lazy(() => import("./views/pages/register/page404/Page404")); +const Page404 = React.lazy(() => + import("./views/pages/register/page404/Page404") +); const Page500 = React.lazy(() => import("./views/pages/page500/Page500")); const App = () => { - const [userdata, setUserData] = useState(null); - const token = isAutheticated(); + const [userdata, setUserData] = useState(null); + const token = isAutheticated(); - useEffect(() => { - const getUser = async () => { - let existanceData = localStorage.getItem("authToken"); - if (!existanceData) { - setUserData(false); - } else { - try { - let response = await axios.get(`/api/v1/user/details`, { - headers: { - Authorization: `Bearer ${token}`, - }, - }); - const data = response?.data; - if (data?.success && (data?.user?.role === "admin" || data?.user?.role === "Employee")) { - setUserData(data?.user); - } else { - setUserData(false); - } - } catch (err) { - setUserData(false); - console.log(err); - } - } - }; - getUser(); - }, [token]); - - return ( - - - - } /> - } /> - } /> - } /> - } /> - - } - /> - - {/* Redirect all other routes to 404 */} - } /> - - - - - - ); + useEffect(() => { + const getUser = async () => { + let existanceData = localStorage.getItem("authToken"); + if (!existanceData) { + setUserData(false); + } else { + try { + let response = await axios.get(`/api/v1/user/details`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + const data = response?.data; + if ( + data?.success && + (data?.user?.role === "admin" || data?.user?.role === "Employee") + ) { + setUserData(data?.user); + } else { + setUserData(false); + } + } catch (err) { + setUserData(false); + console.log(err); + } + } + }; + getUser(); + }, [token]); + return ( + + +
+ + } + > + + {/* } /> */} + } /> + } /> + } /> + } + /> + } /> + +
+
+ ); }; export default App; diff --git a/src/_nav.js b/src/_nav.js index 6d2d62c..f2b1fee 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -83,6 +83,13 @@ const _nav = [ to: "/salescoordinators", group: "SalesCoOrdinator", }, + { + component: CNavItem, + name: "Territory Managers", + icon: , + to: "/territorymanagers", + group: "TerritoryManager", + }, { component: CNavItem, name: "Attendance", diff --git a/src/components/ProtectedRoute.js b/src/components/ProtectedRoute.js index bb65726..421c151 100644 --- a/src/components/ProtectedRoute.js +++ b/src/components/ProtectedRoute.js @@ -16,20 +16,63 @@ // } // export default ProtectedRoute -import React, { useEffect } from "react"; -import { useNavigate } from "react-router-dom"; -const ProtectedRoute = ({ element: Element }) => { - const navigate = useNavigate(); +// import React, { useEffect } from "react"; +// import { useNavigate } from "react-router-dom"; - useEffect(() => { - if (!localStorage.getItem('authToken')) { - navigate('/'); - } - }, [navigate]); +// const ProtectedRoute = ({ element: Element }) => { +// const navigate = useNavigate(); - return ; +// useEffect(() => { +// if (!localStorage.getItem('authToken')) { +// navigate('/'); +// } +// }, [navigate]); + +// return ; +// } + +// export default ProtectedRoute; + +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable react/prop-types */ +import { useEffect } from 'react' +import { useNavigate } from 'react-router-dom' +import { jwtDecode } from 'jwt-decode' + +const isTokenExpired = (token) => { + try { + const decodedToken = jwtDecode(token) + // console.log('Decoded Token:', decodedToken) // Debugging + const currentTime = Date.now() / 1000 + // console.log('Current Time:', currentTime) // Debugging + // console.log('Token Expiration Time:', decodedToken.exp) // Debugging + return decodedToken.exp < currentTime + } catch (error) { + console.error('Error decoding token:', error) // Debugging + return true // If there's an error decoding the token, consider it expired + } } -export default ProtectedRoute; +const ProtectedRoute = ({ element: Element }) => { + const navigate = useNavigate() + useEffect(() => { + const checkToken = () => { + const token = localStorage.getItem('authToken') + // console.log('Token:', token) // Debugging + if (!token || isTokenExpired(token)) { + // console.log('Token is expired or not present, redirecting to login') + navigate('/') + } else { + // console.log('Token is valid') + } + } + + checkToken() + }, [navigate]) + + return +} + +export default ProtectedRoute \ No newline at end of file diff --git a/src/routes.js b/src/routes.js index ec2ed38..c9b7907 100644 --- a/src/routes.js +++ b/src/routes.js @@ -133,6 +133,10 @@ import SingleAttendanceSalesCoOrdinator from "./views/Attendance/SingleAttendanc import TodayLeave from "./views/Leaves/TodayLeaves"; import LeaveSalesCoordinator from "./views/Leaves/LeaveSalesCoordinator"; import SingleLeaveSalesCoOrdinator from "./views/Leaves/SingleLeaveSalesCoordinator"; +//TerritoryManagers +import EditTerritoryManager from "./views/TerritoryManager/EditTerritoryManager"; +import TerritoryManager from "./views/TerritoryManager/TerritoryManager"; +import AddTerritoryManager from "./views/TerritoryManager/AddTerritoryManager"; const routes = [ //dashboard @@ -181,7 +185,7 @@ const routes = [ element: Categories, navName: "Product Management", }, - +//SalesCoOrdinator { path: "/salescoordinator/edit/:id", name: "Edit SalesCoOrdinator", @@ -200,6 +204,25 @@ const routes = [ element: AddSalesCoOrdinator, navName: "SalesCoOrdinators", }, + //TerritoryManager + { + path: "/territorymanager/edit/:id", + name: "Edit TerritoryManager", + element: EditTerritoryManager, + navName: "TerritoryManagers", + }, + { + path: "/territorymanagers", + name: "TerritoryManagers", + element: TerritoryManager, + navName: "TerritoryManagers", + }, + { + path: "/territorymanager/add", + name: "Add TerritoryManagers", + element: AddTerritoryManager, + navName: "TerritoryManagers", + }, // Attendence { path: "/attendance/today", diff --git a/src/views/Attendance/TodayAttendance.js b/src/views/Attendance/TodayAttendance.js index ebcccdf..3ad3cee 100644 --- a/src/views/Attendance/TodayAttendance.js +++ b/src/views/Attendance/TodayAttendance.js @@ -27,6 +27,7 @@ const TodayAttendance = () => { show: itemPerPage, }, }); + // console.log(res.data); setSalesCoOrdinatorsData(res.data?.attendance); setTotalData(res.data?.total_data); } catch (err) { @@ -135,6 +136,7 @@ const TodayAttendance = () => { Email Position Time + Location Note @@ -179,6 +181,13 @@ const TodayAttendance = () => { )} + + {attendance?.location || ( + + No Location Added! + + )} + {attendance?.notes ? ( attendance?.notes diff --git a/src/views/SalesCoOrdinators/AddSalesCoOrdinator.js b/src/views/SalesCoOrdinators/AddSalesCoOrdinator.js index a1556ab..ecfd62d 100644 --- a/src/views/SalesCoOrdinators/AddSalesCoOrdinator.js +++ b/src/views/SalesCoOrdinators/AddSalesCoOrdinator.js @@ -14,7 +14,7 @@ const AddSalesCoOrdinator = () => { const [formData, setFormData] = useState({ name: "", email: "", - countryCode: "", + countryCode: "+91", mobileNumber: "", otp: "", }); @@ -137,6 +137,7 @@ const AddSalesCoOrdinator = () => { value={formData.countryCode} onChange={handleChange} required + disabled />
diff --git a/src/views/SalesCoOrdinators/EditSalesCoOrdinator.js b/src/views/SalesCoOrdinators/EditSalesCoOrdinator.js index bce8323..a7bc450 100644 --- a/src/views/SalesCoOrdinators/EditSalesCoOrdinator.js +++ b/src/views/SalesCoOrdinators/EditSalesCoOrdinator.js @@ -262,6 +262,7 @@ const EditSalesCoOrdinator = () => { value={formData.countryCode} onChange={handleChange} required + disabled />
diff --git a/src/views/TerritoryManager/AddTerritoryManager.js b/src/views/TerritoryManager/AddTerritoryManager.js new file mode 100644 index 0000000..a5b8d96 --- /dev/null +++ b/src/views/TerritoryManager/AddTerritoryManager.js @@ -0,0 +1,198 @@ +import React, { useState } from "react"; +import axios from "axios"; +import { useNavigate } from "react-router-dom"; +import { isAutheticated } from "src/auth"; +import Modal from "react-bootstrap/Modal"; +import Button from "react-bootstrap/Button"; +import Form from "react-bootstrap/Form"; +import swal from "sweetalert"; + +const AddTerritoryManager = () => { + const navigate = useNavigate(); + const token = isAutheticated(); + + const [formData, setFormData] = useState({ + name: "", + email: "", + countryCode: "+91", + mobileNumber: "", + otp: "", + }); + + const [showModal, setShowModal] = useState(false); + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleRegister = async (e) => { + e.preventDefault(); + try { + await axios.post("/api/territorymanager/register", formData, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + + setShowModal(true); // Show OTP modal after registration + } catch (error) { + console.error(error); + let msg = + error?.response?.data?.message || + "Failed to register TerritoryManager. Please try again."; + swal({ + title: "Warning", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + } + }; + + const handleVerifyOTP = async () => { + try { + await axios.post("/api/territorymanager/verify-otp", { + otp: formData.otp, + fullMobileNumber: `${formData.countryCode}${formData.mobileNumber}`, + }); + + setShowModal(false); // Close OTP modal after verification + swal({ + title: "Success", + text: "OTP verified successfully!", + icon: "success", + button: "OK", + }).then(() => { + navigate("/territorymanagers"); // Navigate to success page or desired route + }); + } catch (error) { + console.error(error); + let msg = + error?.response?.data?.message || + "OTP verification failed. Please try again."; + swal({ + title: "Warning", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + } + }; + + // Function to handle cancel button click + const handleCancel = () => { + navigate("/territorymanagers"); // Navigate to '/territorymanagers' + }; + + return ( +
+
+
+
+
+
+

Add Sales Coordinator

+ +
+
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
+ + {/* OTP Modal */} + setShowModal(false)}> + + Enter OTP + + + + OTP + + setFormData({ ...formData, otp: e.target.value }) + } + required + /> + + + + + + + +
+ ); +}; + +export default AddTerritoryManager; diff --git a/src/views/TerritoryManager/EditTerritoryManager.js b/src/views/TerritoryManager/EditTerritoryManager.js new file mode 100644 index 0000000..7e69130 --- /dev/null +++ b/src/views/TerritoryManager/EditTerritoryManager.js @@ -0,0 +1,396 @@ +import React, { useState, useEffect } from "react"; +import axios from "axios"; +import { useNavigate, useParams } from "react-router-dom"; +import { isAutheticated } from "src/auth"; +import Modal from "react-bootstrap/Modal"; +import Button from "react-bootstrap/Button"; +import Form from "react-bootstrap/Form"; +import swal from "sweetalert"; + +const EditTerritoryManager = () => { + const navigate = useNavigate(); + const token = isAutheticated(); + const { id } = useParams(); + + const [formData, setFormData] = useState({ + name: "", + email: "", + countryCode: "", + mobileNumber: "", + currentPassword: "", + newPassword: "", + confirmPassword: "", + otp: "", + }); + + const [showVerifyModal, setShowVerifyModal] = useState(false); + const [showPasswordModal, setShowPasswordModal] = useState(false); + + useEffect(() => { + getTerritoryManagerData(); + }, []); + + const getTerritoryManagerData = async () => { + try { + const response = await axios.get(`/api/territorymanager/getOne/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + }); + const { data } = response.data; + + // Assuming country code always starts with + and is followed by 1-3 digits + const fullMobileNumber = data?.mobileNumber || ""; + const countryCodeMatch = fullMobileNumber.match(/^\+\d{1,2}/); + const countryCode = countryCodeMatch ? countryCodeMatch[0] : ""; + const mobileNumber = fullMobileNumber.replace(countryCode, ""); + + setFormData({ + name: data?.name || "", + email: data?.email || "", + countryCode: countryCode, + mobileNumber: mobileNumber, + currentPassword: "", + newPassword: "", + confirmPassword: "", + otp: "", + }); + } catch (error) { + console.error("Error fetching sales coordinator data: ", error); + } + }; + + const handleChange = (e) => { + setFormData({ ...formData, [e.target.name]: e.target.value }); + }; + + const handleUpdateBasicInfo = () => { + axios + .patch( + `/api/territorymanager/profile/update/${id}`, + { + name: formData.name, + email: formData.email, + }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ) + .then((response) => { + swal({ + title: "Success", + text: "Sales coordinator information updated successfully!", + icon: "success", + button: "OK", + }); + }) + .catch((error) => { + let msg = error?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Warning", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + const handleVerifyMobile = () => { + axios + .post( + `/api/territorymanager/update-mobile-number/${id}`, + { + newCountryCode: formData.countryCode, + newMobileNumber: formData.mobileNumber, + }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ) + .then(() => { + setShowVerifyModal(true); + }) + .catch((error) => { + let msg = error?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Warning", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + const handleVerifyOTP = () => { + axios + .post( + "/api/territorymanager/verify-updated-mobile-otp", + { + otp: formData.otp, + newMobileNumber: `${formData.countryCode}${formData.mobileNumber}`, + }, + { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + } + ) + .then(() => { + setShowVerifyModal(false); + // Handle success, if needed + }) + .catch((error) => { + let msg = error?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Warning", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + const handleChangePassword = () => { + axios + .put( + `/api/territorymanager/password/update/${id}`, + { + oldPassword: formData.currentPassword, + newPassword: formData.newPassword, + confirmPassword: formData.confirmPassword, + }, + { + headers: { + Authorization: `Bearer ${token}`, + }, + } + ) + .then(() => { + setShowPasswordModal(false); + swal({ + title: "Success", + text: "Password updated successfully!", + icon: "success", + button: "OK", + }); + }) + .catch((error) => { + let msg = error?.response?.data?.message || "Something went wrong!"; + swal({ + title: "Warning", + text: msg, + icon: "error", + button: "Retry", + dangerMode: true, + }); + }); + }; + + const onCancel = () => { + navigate("/territorymanagers"); + }; + + return ( +
+
+
+
+
+
+

Edit Sales Coordinator

+ +
+
+
+ +
+
+
+
+
+ + +
+
+ + +
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+
+ + {/* OTP Verification Modal */} + setShowVerifyModal(false)} + > + + Verify Mobile + + + + Enter OTP + + + + + + + + + + {/* Change Password Modal */} + setShowPasswordModal(false)} + > + + Change Password + + + + Current Password + + + + New Password + + + + Confirm New Password + + + + + + + + +
+
+
+ ); +}; + +export default EditTerritoryManager; diff --git a/src/views/TerritoryManager/TerritoryManager.js b/src/views/TerritoryManager/TerritoryManager.js new file mode 100644 index 0000000..286f2f4 --- /dev/null +++ b/src/views/TerritoryManager/TerritoryManager.js @@ -0,0 +1,345 @@ +import React, { useState, useEffect, useRef, 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'; + +const TerritoryManager = () => { + const token = isAutheticated(); + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [success, setSuccess] = useState(true); + const [territorymanagersData, setTerritoryManagersData] = useState([]); + + const nameRef = useRef(); + const mobileRef = useRef(); + const VerifyTerritoryManagerRef = useRef(); + + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [totalData, setTotalData] = useState(0); + + const getTerritoryManagersData = async () => { + setLoading(true); + try { + const res = await axios.get(`/api/territorymanager/getAll/`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: currentPage, + show: itemPerPage, + name: nameRef.current.value, + mobileNumber: mobileRef.current.value, + isVerified: VerifyTerritoryManagerRef.current.value, + }, + }); + setTerritoryManagersData(res.data?.salesCoOrinators); + 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(() => { + getTerritoryManagersData(); + }, [success, itemPerPage, currentPage]); + + const debouncedSearch = useCallback(debounce(() => { + setCurrentPage(1); + getTerritoryManagersData(); + }, 500), []); + + const handleSearchChange = () => { + debouncedSearch(); + }; + + const handleDelete = (id) => { + swal({ + title: "Are you sure?", + icon: "error", + buttons: { + Yes: { text: "Yes", value: true }, + Cancel: { text: "Cancel", value: "cancel" }, + }, + }).then((value) => { + if (value === true) { + axios + .delete(`/api/territorymanager/delete/${id}`, { + headers: { + "Access-Control-Allow-Origin": "*", + Authorization: `Bearer ${token}`, + }, + }) + .then((res) => { + swal({ + title: "Deleted", + text: "TerritoryManager Deleted 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, + }); + }); + } + }); + }; + + return ( +
+
+
+
+
+
+
+ TerritoryManagers +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + + + + + + + + + + + + + + {loading ? ( + + + + ) : territorymanagersData?.length > 0 ? ( + territorymanagersData?.map((territorymanager, i) => { + return ( + + + + + + + + + + ); + }) + ) : ( + + + + )} + +
Unique Id NameMobile No.EmailVerifyRegister OnAction
+ Loading... +
+ {territorymanager?.uniqueId} + + {territorymanager?.name} + + {territorymanager?.mobileNumber} + + {territorymanager?.email ? ( + territorymanager?.email + ) : ( + + No Email Added! + + )} + + + {territorymanager?.isVerified + ? "YES" + : "NO"} + + + {new Date( + territorymanager.createdAt + ).toLocaleString("en-IN", { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + })} + + + + + + +
+ No TerritoryManager found! +
+
+
+
+ Showing {territorymanagersData?.length} of {totalData} entries +
+
+ + +
+
+
+
+
+
+
+
+
+ ); +}; + +export default TerritoryManager;