territory manager added
This commit is contained in:
parent
810d5770b5
commit
f9a7338480
@ -53,6 +53,7 @@
|
|||||||
"draft-js-export-html": "^1.4.1",
|
"draft-js-export-html": "^1.4.1",
|
||||||
"draft-js-import-html": "^1.4.1",
|
"draft-js-import-html": "^1.4.1",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
|
"jwt-decode": "^4.0.0",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
|
137
src/App.js
137
src/App.js
@ -111,26 +111,101 @@
|
|||||||
// };
|
// };
|
||||||
// export default App;
|
// 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 = (
|
||||||
|
// <div className="pt-3 text-center">
|
||||||
|
// <div className="sk-spinner sk-spinner-pulse"></div>
|
||||||
|
// </div>
|
||||||
|
// );
|
||||||
|
|
||||||
|
// 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 (
|
||||||
|
// <HashRouter>
|
||||||
|
// <Suspense fallback={loading}>
|
||||||
|
// <Routes>
|
||||||
|
// <Route path="/" element={<Login />} />
|
||||||
|
// <Route path="/register" element={<NewRegister />} />
|
||||||
|
// <Route path="/password/forgot" element={<ForgotPassword />} />
|
||||||
|
// <Route path="/404" element={<Page404 />} />
|
||||||
|
// <Route path="/500" element={<Page500 />} />
|
||||||
|
|
||||||
|
// <Route
|
||||||
|
// path="/*"
|
||||||
|
// element={<ProtectedRoute element={DefaultLayout} />}
|
||||||
|
// />
|
||||||
|
|
||||||
|
// {/* Redirect all other routes to 404 */}
|
||||||
|
// <Route path="*" element={<Navigate to="/404" />} />
|
||||||
|
// </Routes>
|
||||||
|
// <Toaster />
|
||||||
|
// </Suspense>
|
||||||
|
// <InternetConnectionPopUp />
|
||||||
|
// </HashRouter>
|
||||||
|
// );
|
||||||
|
// };
|
||||||
|
|
||||||
|
// export default App;
|
||||||
|
|
||||||
import React, { Suspense, useEffect, useState } from "react";
|
import React, { Suspense, useEffect, useState } from "react";
|
||||||
import axios from "axios";
|
import { HashRouter, Route, Routes } from "react-router-dom";
|
||||||
import { HashRouter, Routes, Route, Navigate } from "react-router-dom";
|
import { useSelector } from "react-redux";
|
||||||
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 { isAutheticated } from "./auth";
|
||||||
import InternetConnectionPopUp from "./views/InternetConnectionPopUp";
|
import "./scss/style.scss";
|
||||||
|
import ProtectedRoute from "./components/ProtectedRoute";
|
||||||
const loading = (
|
import axios from "axios";
|
||||||
<div className="pt-3 text-center">
|
// Containers
|
||||||
<div className="sk-spinner sk-spinner-pulse"></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const DefaultLayout = React.lazy(() => import("./layout/DefaultLayout"));
|
const DefaultLayout = React.lazy(() => import("./layout/DefaultLayout"));
|
||||||
|
|
||||||
|
// Pages
|
||||||
const Login = React.lazy(() => import("./views/pages/login/Login"));
|
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 Page500 = React.lazy(() => import("./views/pages/page500/Page500"));
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
@ -150,7 +225,10 @@ const App = () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
const data = response?.data;
|
const data = response?.data;
|
||||||
if (data?.success && (data?.user?.role === "admin" || data?.user?.role === "Employee")) {
|
if (
|
||||||
|
data?.success &&
|
||||||
|
(data?.user?.role === "admin" || data?.user?.role === "Employee")
|
||||||
|
) {
|
||||||
setUserData(data?.user);
|
setUserData(data?.user);
|
||||||
} else {
|
} else {
|
||||||
setUserData(false);
|
setUserData(false);
|
||||||
@ -163,28 +241,27 @@ const App = () => {
|
|||||||
};
|
};
|
||||||
getUser();
|
getUser();
|
||||||
}, [token]);
|
}, [token]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<Suspense fallback={loading}>
|
<Suspense
|
||||||
|
fallback={
|
||||||
|
<div className="pt-3 text-center">
|
||||||
|
<div className="sk-spinner sk-spinner-pulse"></div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Login />} />
|
{/* <Route exact path="/change-password" name="My profile" element={<ChangePassword />} /> */}
|
||||||
<Route path="/register" element={<NewRegister />} />
|
<Route exact path="/" name="Login Page" element={<Login />} />
|
||||||
<Route path="/password/forgot" element={<ForgotPassword />} />
|
<Route exact path="/404" name="Page 404" element={<Page404 />} />
|
||||||
<Route path="/404" element={<Page404 />} />
|
<Route exact path="/500" name="Page 500" element={<Page500 />} />
|
||||||
<Route path="/500" element={<Page500 />} />
|
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path="/*"
|
path="/*"
|
||||||
element={<ProtectedRoute element={DefaultLayout} />}
|
element={<ProtectedRoute element={DefaultLayout} />}
|
||||||
/>
|
/>
|
||||||
|
<Route path="*" name="Home" element={<DefaultLayout />} />
|
||||||
{/* Redirect all other routes to 404 */}
|
|
||||||
<Route path="*" element={<Navigate to="/404" />} />
|
|
||||||
</Routes>
|
</Routes>
|
||||||
<Toaster />
|
|
||||||
</Suspense>
|
</Suspense>
|
||||||
<InternetConnectionPopUp />
|
|
||||||
</HashRouter>
|
</HashRouter>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -83,6 +83,13 @@ const _nav = [
|
|||||||
to: "/salescoordinators",
|
to: "/salescoordinators",
|
||||||
group: "SalesCoOrdinator",
|
group: "SalesCoOrdinator",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
component: CNavItem,
|
||||||
|
name: "Territory Managers",
|
||||||
|
icon: <CIcon icon={cilUser} customClassName="nav-icon" />,
|
||||||
|
to: "/territorymanagers",
|
||||||
|
group: "TerritoryManager",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
component: CNavItem,
|
component: CNavItem,
|
||||||
name: "Attendance",
|
name: "Attendance",
|
||||||
|
@ -16,20 +16,63 @@
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// export default ProtectedRoute
|
// export default ProtectedRoute
|
||||||
import React, { useEffect } from "react";
|
|
||||||
import { useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
const ProtectedRoute = ({ element: Element }) => {
|
// import React, { useEffect } from "react";
|
||||||
const navigate = useNavigate();
|
// import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
useEffect(() => {
|
// const ProtectedRoute = ({ element: Element }) => {
|
||||||
if (!localStorage.getItem('authToken')) {
|
// const navigate = useNavigate();
|
||||||
navigate('/');
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// if (!localStorage.getItem('authToken')) {
|
||||||
|
// navigate('/');
|
||||||
|
// }
|
||||||
|
// }, [navigate]);
|
||||||
|
|
||||||
|
// return <Element />;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
}, [navigate]);
|
|
||||||
|
|
||||||
return <Element />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 <Element />
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ProtectedRoute
|
@ -133,6 +133,10 @@ import SingleAttendanceSalesCoOrdinator from "./views/Attendance/SingleAttendanc
|
|||||||
import TodayLeave from "./views/Leaves/TodayLeaves";
|
import TodayLeave from "./views/Leaves/TodayLeaves";
|
||||||
import LeaveSalesCoordinator from "./views/Leaves/LeaveSalesCoordinator";
|
import LeaveSalesCoordinator from "./views/Leaves/LeaveSalesCoordinator";
|
||||||
import SingleLeaveSalesCoOrdinator from "./views/Leaves/SingleLeaveSalesCoordinator";
|
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 = [
|
const routes = [
|
||||||
//dashboard
|
//dashboard
|
||||||
|
|
||||||
@ -181,7 +185,7 @@ const routes = [
|
|||||||
element: Categories,
|
element: Categories,
|
||||||
navName: "Product Management",
|
navName: "Product Management",
|
||||||
},
|
},
|
||||||
|
//SalesCoOrdinator
|
||||||
{
|
{
|
||||||
path: "/salescoordinator/edit/:id",
|
path: "/salescoordinator/edit/:id",
|
||||||
name: "Edit SalesCoOrdinator",
|
name: "Edit SalesCoOrdinator",
|
||||||
@ -200,6 +204,25 @@ const routes = [
|
|||||||
element: AddSalesCoOrdinator,
|
element: AddSalesCoOrdinator,
|
||||||
navName: "SalesCoOrdinators",
|
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
|
// Attendence
|
||||||
{
|
{
|
||||||
path: "/attendance/today",
|
path: "/attendance/today",
|
||||||
|
@ -27,6 +27,7 @@ const TodayAttendance = () => {
|
|||||||
show: itemPerPage,
|
show: itemPerPage,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// console.log(res.data);
|
||||||
setSalesCoOrdinatorsData(res.data?.attendance);
|
setSalesCoOrdinatorsData(res.data?.attendance);
|
||||||
setTotalData(res.data?.total_data);
|
setTotalData(res.data?.total_data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -135,6 +136,7 @@ const TodayAttendance = () => {
|
|||||||
<th className="text-start">Email</th>
|
<th className="text-start">Email</th>
|
||||||
<th className="text-start">Position</th>
|
<th className="text-start">Position</th>
|
||||||
<th className="text-start">Time</th>
|
<th className="text-start">Time</th>
|
||||||
|
<th className="text-start">Location</th>
|
||||||
<th className="text-start">Note</th>
|
<th className="text-start">Note</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -179,6 +181,13 @@ const TodayAttendance = () => {
|
|||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{attendance?.location || (
|
||||||
|
<small className="m-0 text-secondary">
|
||||||
|
No Location Added!
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
<td className="text-start">
|
<td className="text-start">
|
||||||
{attendance?.notes ? (
|
{attendance?.notes ? (
|
||||||
attendance?.notes
|
attendance?.notes
|
||||||
|
@ -14,7 +14,7 @@ const AddSalesCoOrdinator = () => {
|
|||||||
const [formData, setFormData] = useState({
|
const [formData, setFormData] = useState({
|
||||||
name: "",
|
name: "",
|
||||||
email: "",
|
email: "",
|
||||||
countryCode: "",
|
countryCode: "+91",
|
||||||
mobileNumber: "",
|
mobileNumber: "",
|
||||||
otp: "",
|
otp: "",
|
||||||
});
|
});
|
||||||
@ -137,6 +137,7 @@ const AddSalesCoOrdinator = () => {
|
|||||||
value={formData.countryCode}
|
value={formData.countryCode}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
required
|
required
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: 3 }}>
|
<div style={{ flex: 3 }}>
|
||||||
|
@ -262,6 +262,7 @@ const EditSalesCoOrdinator = () => {
|
|||||||
value={formData.countryCode}
|
value={formData.countryCode}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
required
|
required
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mr-2" style={{ flex: 3 }}>
|
<div className="mr-2" style={{ flex: 3 }}>
|
||||||
|
198
src/views/TerritoryManager/AddTerritoryManager.js
Normal file
198
src/views/TerritoryManager/AddTerritoryManager.js
Normal file
@ -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 (
|
||||||
|
<div className="main-content">
|
||||||
|
<div className="my-3 page-content">
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||||
|
<h4 className="mb-3">Add Sales Coordinator</h4>
|
||||||
|
<Button variant="danger" onClick={handleCancel}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-lg-12">
|
||||||
|
<div className="card">
|
||||||
|
<div className="card-body">
|
||||||
|
<form onSubmit={handleRegister}>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.name}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Email</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.email}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-group d-flex">
|
||||||
|
<div className="mr-2" style={{ flex: 1 }}>
|
||||||
|
<label>Country Code</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="countryCode"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.countryCode}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ flex: 3 }}>
|
||||||
|
<label>Mobile Number</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="mobileNumber"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.mobileNumber}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" className="btn btn-primary">
|
||||||
|
Register
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* OTP Modal */}
|
||||||
|
<Modal show={showModal} onHide={() => setShowModal(false)}>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>Enter OTP</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>OTP</Form.Label>
|
||||||
|
<Form.Control
|
||||||
|
type="text"
|
||||||
|
placeholder="Enter OTP"
|
||||||
|
value={formData.otp}
|
||||||
|
onChange={(e) =>
|
||||||
|
setFormData({ ...formData, otp: e.target.value })
|
||||||
|
}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button variant="secondary" onClick={() => setShowModal(false)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" onClick={handleVerifyOTP}>
|
||||||
|
Verify OTP
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddTerritoryManager;
|
396
src/views/TerritoryManager/EditTerritoryManager.js
Normal file
396
src/views/TerritoryManager/EditTerritoryManager.js
Normal file
@ -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 (
|
||||||
|
<div className="main-content">
|
||||||
|
<div className="my-3 page-content">
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<div className="page-title-box d-flex align-items-center justify-content-between">
|
||||||
|
<h4 className="mb-3">Edit Sales Coordinator</h4>
|
||||||
|
<button
|
||||||
|
onClick={onCancel}
|
||||||
|
type="button"
|
||||||
|
className="btn btn-warning btn-cancel waves-effect waves-light mr-3"
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-lg-12">
|
||||||
|
<div className="card">
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Name</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="name"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.name}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>Email</label>
|
||||||
|
<input
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.email}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 mb-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary mr-2"
|
||||||
|
onClick={handleUpdateBasicInfo}
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="form-group d-flex align-items-center">
|
||||||
|
<div className="mr-2" style={{ flex: 1 }}>
|
||||||
|
<label>Country Code</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="countryCode"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.countryCode}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mr-2" style={{ flex: 3 }}>
|
||||||
|
<label>Mobile Number</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
name="mobileNumber"
|
||||||
|
className="form-control"
|
||||||
|
value={formData.mobileNumber}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="mr-2" style={{ flex: 1 }}>
|
||||||
|
<label> </label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-success"
|
||||||
|
onClick={handleVerifyMobile}
|
||||||
|
style={{ display: "block" }}
|
||||||
|
>
|
||||||
|
Verify Mobile
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="mt-4 mb-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-danger"
|
||||||
|
onClick={() => setShowPasswordModal(true)}
|
||||||
|
>
|
||||||
|
Change Password
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* OTP Verification Modal */}
|
||||||
|
<Modal
|
||||||
|
show={showVerifyModal}
|
||||||
|
onHide={() => setShowVerifyModal(false)}
|
||||||
|
>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>Verify Mobile</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>Enter OTP</Form.Label>
|
||||||
|
<Form.Control
|
||||||
|
type="text"
|
||||||
|
placeholder="Enter OTP"
|
||||||
|
name="otp"
|
||||||
|
value={formData.otp}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => setShowVerifyModal(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary" onClick={handleVerifyOTP}>
|
||||||
|
Verify OTP
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
{/* Change Password Modal */}
|
||||||
|
<Modal
|
||||||
|
show={showPasswordModal}
|
||||||
|
onHide={() => setShowPasswordModal(false)}
|
||||||
|
>
|
||||||
|
<Modal.Header closeButton>
|
||||||
|
<Modal.Title>Change Password</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>Current Password</Form.Label>
|
||||||
|
<Form.Control
|
||||||
|
type="password"
|
||||||
|
placeholder="Enter current password"
|
||||||
|
name="currentPassword"
|
||||||
|
value={formData.currentPassword}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>New Password</Form.Label>
|
||||||
|
<Form.Control
|
||||||
|
type="password"
|
||||||
|
placeholder="Enter new password"
|
||||||
|
name="newPassword"
|
||||||
|
value={formData.newPassword}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
<Form.Group>
|
||||||
|
<Form.Label>Confirm New Password</Form.Label>
|
||||||
|
<Form.Control
|
||||||
|
type="password"
|
||||||
|
placeholder="Confirm new password"
|
||||||
|
name="confirmPassword"
|
||||||
|
value={formData.confirmPassword}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
|
</Modal.Body>
|
||||||
|
<Modal.Footer>
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
onClick={() => setShowPasswordModal(false)}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button variant="danger" onClick={handleChangePassword}>
|
||||||
|
Change Password
|
||||||
|
</Button>
|
||||||
|
</Modal.Footer>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditTerritoryManager;
|
345
src/views/TerritoryManager/TerritoryManager.js
Normal file
345
src/views/TerritoryManager/TerritoryManager.js
Normal file
@ -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 (
|
||||||
|
<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 align-items-center justify-content-between">
|
||||||
|
<div style={{ fontSize: "22px" }} className="fw-bold">
|
||||||
|
TerritoryManagers
|
||||||
|
</div>
|
||||||
|
<div className="page-title-right">
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginBottom: "1rem",
|
||||||
|
textTransform: "capitalize",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
navigate("/territorymanager/add", { replace: true });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add TerritoryManager
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</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>TerritoryManager Name:</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="TerritoryManager 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 className="col-lg-3">
|
||||||
|
<label>Verify TerritoryManager:</label>
|
||||||
|
<select
|
||||||
|
className="form-control"
|
||||||
|
ref={VerifyTerritoryManagerRef}
|
||||||
|
onChange={handleSearchChange}
|
||||||
|
disabled={loading}
|
||||||
|
>
|
||||||
|
<option value="">----Select----</option>
|
||||||
|
<option value="true">YES</option>
|
||||||
|
<option value="false">NO</option>
|
||||||
|
</select>
|
||||||
|
</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>Unique Id </th>
|
||||||
|
<th className="text-start">Name</th>
|
||||||
|
<th className="text-start">Mobile No.</th>
|
||||||
|
<th className="text-start">Email</th>
|
||||||
|
<th className="text-start">Verify</th>
|
||||||
|
<th className="text-start">Register On</th>
|
||||||
|
<th className="text-start">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{loading ? (
|
||||||
|
<tr>
|
||||||
|
<td className="text-center" colSpan="6">
|
||||||
|
Loading...
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
) : territorymanagersData?.length > 0 ? (
|
||||||
|
territorymanagersData?.map((territorymanager, i) => {
|
||||||
|
return (
|
||||||
|
<tr key={i}>
|
||||||
|
<td className="text-start">
|
||||||
|
{territorymanager?.uniqueId}
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{territorymanager?.name}
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{territorymanager?.mobileNumber}
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{territorymanager?.email ? (
|
||||||
|
territorymanager?.email
|
||||||
|
) : (
|
||||||
|
<small className="m-0 text-secondary">
|
||||||
|
No Email Added!
|
||||||
|
</small>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
<span
|
||||||
|
className={`badge text-white ${
|
||||||
|
territorymanager?.isVerified === true
|
||||||
|
? "text-bg-success"
|
||||||
|
: "text-bg-danger"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{territorymanager?.isVerified
|
||||||
|
? "YES"
|
||||||
|
: "NO"}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
{new Date(
|
||||||
|
territorymanager.createdAt
|
||||||
|
).toLocaleString("en-IN", {
|
||||||
|
weekday: "short",
|
||||||
|
month: "short",
|
||||||
|
day: "numeric",
|
||||||
|
year: "numeric",
|
||||||
|
hour: "numeric",
|
||||||
|
minute: "numeric",
|
||||||
|
hour12: true,
|
||||||
|
})}
|
||||||
|
</td>
|
||||||
|
<td className="text-start">
|
||||||
|
<Link
|
||||||
|
to={`/territorymanager/edit/${territorymanager._id}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
style={{
|
||||||
|
color: "white",
|
||||||
|
marginRight: "1rem",
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
className="btn btn-info btn-sm waves-effect waves-light btn-table ml-2"
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</button>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
style={{ color: "white" }}
|
||||||
|
className="btn btn-danger btn-sm waves-effect waves-light btn-table ml-2"
|
||||||
|
onClick={() => handleDelete(territorymanager._id)}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td className="text-center" colSpan="6">
|
||||||
|
No TerritoryManager found!
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div className="d-flex justify-content-between">
|
||||||
|
<div>
|
||||||
|
Showing {territorymanagersData?.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={territorymanagersData?.length < itemPerPage || loading}
|
||||||
|
className="btn btn-primary ml-2"
|
||||||
|
>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TerritoryManager;
|
Loading…
Reference in New Issue
Block a user