From 8f587978cb96bfb2a5db98ddbfd1a2f51dcad408 Mon Sep 17 00:00:00 2001 From: Sibunnayak Date: Wed, 24 Jul 2024 11:40:49 +0530 Subject: [PATCH] update --- src/_nav.js | 9 +- src/index.js | 4 +- src/routes.js | 36 +- .../AttendanceSalesCoordinator.js | 0 .../SingleAttendanceSalesCoordinator.js | 0 .../TodayAttendance.js} | 10 +- src/views/Leaves/LeaveSalesCoordinator.js | 319 ++++++++++++++++++ .../Leaves/SingleLeaveSalesCoordinator.js | 262 ++++++++++++++ src/views/Leaves/TodayLeaves.js | 283 ++++++++++++++++ .../addPrincipalDistributor.js | 55 ++- 10 files changed, 947 insertions(+), 31 deletions(-) rename src/views/{SalesAttendance => Attendance}/AttendanceSalesCoordinator.js (100%) rename src/views/{SalesAttendance => Attendance}/SingleAttendanceSalesCoordinator.js (100%) rename src/views/{SalesAttendance/TodayAttendanceSales.js => Attendance/TodayAttendance.js} (97%) create mode 100644 src/views/Leaves/LeaveSalesCoordinator.js create mode 100644 src/views/Leaves/SingleLeaveSalesCoordinator.js create mode 100644 src/views/Leaves/TodayLeaves.js diff --git a/src/_nav.js b/src/_nav.js index a38edbb..f264ed6 100644 --- a/src/_nav.js +++ b/src/_nav.js @@ -88,7 +88,14 @@ const _nav = [ name: "Attendance", icon: , to: "/attendance/today", - group: "AttendanceSalesCoOrdinator", + group: "Attendance", + }, + { + component: CNavItem, + name: "Leaves", + icon: , + to: "/leaves/today", + group: "Leaves", }, // { // component: CNavGroup, diff --git a/src/index.js b/src/index.js index b47a948..adbdd11 100644 --- a/src/index.js +++ b/src/index.js @@ -15,8 +15,8 @@ import { cibGmail } from "@coreui/icons"; import { createRoot } from "react-dom/client"; const setupAxios = () => { - // axios.defaults.baseURL = "http://localhost:5000"; - axios.defaults.baseURL = "https://cheminova-api-2.onrender.com"; + axios.defaults.baseURL = "http://localhost:5000"; + // axios.defaults.baseURL = "https://cheminova-api-2.onrender.com"; axios.defaults.headers = { "Cache-Control": "no-cache,no-store", diff --git a/src/routes.js b/src/routes.js index 8d46c8c..ec2ed38 100644 --- a/src/routes.js +++ b/src/routes.js @@ -127,9 +127,12 @@ import Currency from "./views/configuration/Currency"; import SalesCoOrdinator from "./views/SalesCoOrdinators/SalesCoOrdinator"; import EditSalesCoOrdinator from "./views/SalesCoOrdinators/EditSalesCoOrdinator"; import AddSalesCoOrdinator from "./views/SalesCoOrdinators/AddSalesCoOrdinator"; -import TodayAttendanceSales from "./views/SalesAttendance/TodayAttendanceSales"; -import AttendanceSalesCoordinator from "./views/SalesAttendance/AttendanceSalesCoordinator"; -import SingleAttendanceSalesCoOrdinator from "./views/SalesAttendance/SingleAttendanceSalesCoordinator"; +import TodayAttendance from "./views/Attendance/TodayAttendance"; +import AttendanceSalesCoordinator from "./views/Attendance/AttendanceSalesCoordinator"; +import SingleAttendanceSalesCoOrdinator from "./views/Attendance/SingleAttendanceSalesCoordinator"; +import TodayLeave from "./views/Leaves/TodayLeaves"; +import LeaveSalesCoordinator from "./views/Leaves/LeaveSalesCoordinator"; +import SingleLeaveSalesCoOrdinator from "./views/Leaves/SingleLeaveSalesCoordinator"; const routes = [ //dashboard @@ -197,12 +200,12 @@ const routes = [ element: AddSalesCoOrdinator, navName: "SalesCoOrdinators", }, - // Attendence SalesCoOrdinator + // Attendence { path: "/attendance/today", - name: "Today's Attendance SalesCoOrdinator", - element: TodayAttendanceSales, - navName: "AttendanceSalesCoOrdinator", + name: "Today's Attendance", + element: TodayAttendance, + navName: "Attendance", }, { path: "/salescoordinator/attendance", @@ -216,6 +219,25 @@ const routes = [ element: SingleAttendanceSalesCoOrdinator, navName: "AttendanceSalesCoOrdinator", }, + // Leaves + { + path: "/leaves/today", + name: "Today's leaves", + element: TodayLeave, + navName: "Leaves", + }, + { + path: "/salescoordinator/leave", + name: "Leave SalesCoOrdinator", + element: LeaveSalesCoordinator, + navName: "LeaveSalesCoOrdinator", + }, + { + path: "/leave/view/:id", + name: "Single SalesCoOrdinator Leave", + element: SingleLeaveSalesCoOrdinator, + navName: "LeaveSalesCoOrdinator", + }, //Gst tax { path: "/tax", diff --git a/src/views/SalesAttendance/AttendanceSalesCoordinator.js b/src/views/Attendance/AttendanceSalesCoordinator.js similarity index 100% rename from src/views/SalesAttendance/AttendanceSalesCoordinator.js rename to src/views/Attendance/AttendanceSalesCoordinator.js diff --git a/src/views/SalesAttendance/SingleAttendanceSalesCoordinator.js b/src/views/Attendance/SingleAttendanceSalesCoordinator.js similarity index 100% rename from src/views/SalesAttendance/SingleAttendanceSalesCoordinator.js rename to src/views/Attendance/SingleAttendanceSalesCoordinator.js diff --git a/src/views/SalesAttendance/TodayAttendanceSales.js b/src/views/Attendance/TodayAttendance.js similarity index 97% rename from src/views/SalesAttendance/TodayAttendanceSales.js rename to src/views/Attendance/TodayAttendance.js index 66243a5..ebcccdf 100644 --- a/src/views/SalesAttendance/TodayAttendanceSales.js +++ b/src/views/Attendance/TodayAttendance.js @@ -6,7 +6,7 @@ import { useNavigate } from "react-router-dom"; import { isAutheticated } from "src/auth"; import swal from "sweetalert"; -const TodayAttendanceSales = () => { +const TodayAttendance = () => { const token = isAutheticated(); const navigate = useNavigate(); const [loading, setLoading] = useState(false); @@ -151,7 +151,7 @@ const TodayAttendanceSales = () => { return ( - {attendance?.user?.id} + {attendance?.user?.uniqueId} {attendance?.user?.name} @@ -180,8 +180,8 @@ const TodayAttendanceSales = () => { )} - {attendance?.note ? ( - attendance?.note + {attendance?.notes ? ( + attendance?.notes ) : ( No Note Added! @@ -271,4 +271,4 @@ const TodayAttendanceSales = () => { ); }; -export default TodayAttendanceSales; +export default TodayAttendance; diff --git a/src/views/Leaves/LeaveSalesCoordinator.js b/src/views/Leaves/LeaveSalesCoordinator.js new file mode 100644 index 0000000..37212ed --- /dev/null +++ b/src/views/Leaves/LeaveSalesCoordinator.js @@ -0,0 +1,319 @@ +import React, { useState, useEffect, useRef } 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"; + +const LeaveSalesCoordinator = () => { + const token = isAutheticated(); + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [salescoordinatorsData, setSalesCoOrdinatorsData] = useState([]); + const nameRef = useRef(); + const mobileRef = useRef(); + const verifyRef = useRef(); + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [totalData, setTotalData] = useState(0); + + const getSalesCoOrdinatorsData = async () => { + setLoading(true); + try { + const res = await axios.get(`/api/salescoordinator/getAll/`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: currentPage, + show: itemPerPage, + name: nameRef.current.value, + mobileNumber: mobileRef.current.value, + isVerified: verifyRef.current.value, + }, + }); + setSalesCoOrdinatorsData(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(() => { + getSalesCoOrdinatorsData(); + }, [currentPage, itemPerPage]); + + const handleFilter = () => { + setCurrentPage(1); + getSalesCoOrdinatorsData(); + }; + + return ( +
+
+
+
+
+
+
+ Sales Coordinators Leaves +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + {loading ? ( + + + + ) : salescoordinatorsData.length > 0 ? ( + salescoordinatorsData.map((salescoordinator, i) => ( + + + + + + + + + )) + ) : ( + + + + )} + +
NameMobile No.EmailVerifyRegister OnAction
+ Loading... +
+ {salescoordinator?.name} + + {salescoordinator?.mobileNumber} + + {salescoordinator?.email || ( + + No Email Added! + + )} + + + {salescoordinator?.isVerified ? "YES" : "NO"} + + + {new Date( + salescoordinator.createdAt + ).toLocaleString("en-IN", { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + hour: "numeric", + minute: "numeric", + hour12: true, + })} + + + + +
+
No Sales Coordinators Available...
+
+
+ +
+
+
+ Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} + {Math.min(currentPage * itemPerPage, totalData)} of{" "} + {totalData} entries +
+
+ +
+
+
    +
  • + + setCurrentPage((prev) => + prev > 1 ? prev - 1 : prev + ) + } + > + Previous + +
  • +
  • = totalData + ? "paginate_button page-item next disabled" + : "paginate_button page-item next" + } + > + + setCurrentPage((prev) => + prev * itemPerPage < totalData + ? prev + 1 + : prev + ) + } + > + Next + +
  • +
+
+
+
+
+
+
+
+
+
+
+ ); +}; + +export default LeaveSalesCoordinator; diff --git a/src/views/Leaves/SingleLeaveSalesCoordinator.js b/src/views/Leaves/SingleLeaveSalesCoordinator.js new file mode 100644 index 0000000..0d2fa7b --- /dev/null +++ b/src/views/Leaves/SingleLeaveSalesCoordinator.js @@ -0,0 +1,262 @@ +import React, { useState, useEffect } from "react"; +import { useParams, useNavigate } from "react-router-dom"; +import axios from "axios"; +import Button from "@material-ui/core/Button"; +import { isAutheticated } from "src/auth"; +import swal from "sweetalert"; + +const SingleLeaveSalesCoOrdinator = () => { + const { id } = useParams(); + const token = isAutheticated(); + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [salesCoordinator, setSalesCoordinator] = useState({}); + const [leaveData, setLeaveData] = useState([]); + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [totalData, setTotalData] = useState(0); + + const getSingleSalesCoOrdinatorLeave = async () => { + setLoading(true); + try { + const res = await axios.get(`/api/v1/leave/${id}`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: currentPage, + show: itemPerPage, + }, + }); + // console.log(res.data); + setSalesCoordinator(res.data?.user); + setLeaveData(res.data?.leave); + 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(() => { + getSingleSalesCoOrdinatorLeave(); + }, [itemPerPage, currentPage]); + + return ( +
+
+
+
+
+
+
+ SalesCoOrdinator Leave +
+ {salesCoordinator.name} ({salesCoordinator.email}) +
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + {loading ? ( + + + + ) : leaveData?.length > 0 ? ( + leaveData?.map((leave, i) => ( + + + + + + + + )) + ) : ( + + + + )} + +
DateTimeLocationReason TypeReason
+ Loading... +
+ {new Date(leave?.date).toLocaleDateString( + "en-IN", + { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + } + )} + + {leave?.time || ( + + No Time Added! + + )} + + {leave?.location || ( + + No Location Added! + + )} + + {leave?.leaveType || ( + + No Reason Type Added! + + )} + + {leave?.reason || ( + + No Reason Added! + + )} +
+
No Leave Records Available...
+
+
+ +
+
+
+ Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} + {Math.min(currentPage * itemPerPage, totalData)} of{" "} + {totalData} entries +
+
+ +
+
+
    +
  • + + setCurrentPage((prev) => + prev > 1 ? prev - 1 : prev + ) + } + > + Previous + +
  • +
  • = totalData + ? "paginate_button page-item next disabled" + : "paginate_button page-item next" + } + > + + setCurrentPage((prev) => + prev * itemPerPage < totalData + ? prev + 1 + : prev + ) + } + > + Next + +
  • +
+
+
+
+
+
+
+
+
+
+
+ ); +}; + +export default SingleLeaveSalesCoOrdinator; diff --git a/src/views/Leaves/TodayLeaves.js b/src/views/Leaves/TodayLeaves.js new file mode 100644 index 0000000..ae8a9d7 --- /dev/null +++ b/src/views/Leaves/TodayLeaves.js @@ -0,0 +1,283 @@ +import React, { useState, useEffect } 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"; + +const TodayLeave = () => { + const token = isAutheticated(); + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [salescoordinatorsData, setSalesCoOrdinatorsData] = useState([]); + const [currentPage, setCurrentPage] = useState(1); + const [itemPerPage, setItemPerPage] = useState(10); + const [totalData, setTotalData] = useState(0); + + const getTodayLeaveData = async () => { + setLoading(true); + try { + const res = await axios.get(`/api/v1/leave/today`, { + headers: { + Authorization: `Bearer ${token}`, + }, + params: { + page: currentPage, + show: itemPerPage, + }, + }); + console.log(res.data); + setSalesCoOrdinatorsData(res.data?.leave); + 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(() => { + getTodayLeaveData(); + }, [itemPerPage, currentPage]); + + const today = new Date().toLocaleDateString("en-IN", { + weekday: "short", + month: "short", + day: "numeric", + year: "numeric", + }); + + return ( +
+
+
+
+
+
+
+ Today's SalesCoOrdinators Leave +
+ Date : {today} +
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ +
+ + + + + + + + + + + + + + + {loading ? ( + + + + ) : salescoordinatorsData?.length > 0 ? ( + salescoordinatorsData?.map((leave, i) => { + return ( + + + + + + + + + + ); + }) + ) : ( + + + + )} + +
IDNameEmailPositionTimeReasonTypeReason
+ Loading... +
+ {leave?.user?.uniqueId} + + {leave?.user?.name} + + {leave?.user?.email ? ( + leave?.user?.email + ) : ( + + No Email Added! + + )} + + {leave?.user?.userType || ( + + No Position Added! + + )} + + {leave?.time || ( + + No Time Added! + + )} + + {leave?.leaveType || ( + + No Reason Type Added! + + )} + + {leave?.reason ? ( + leave?.reason + ) : ( + + No Reason Added! + + )} +
+
No Leave Records Available...
+
+
+ +
+
+
+ Showing {currentPage * itemPerPage - itemPerPage + 1} to{" "} + {Math.min(currentPage * itemPerPage, totalData)} of{" "} + {totalData} entries +
+
+ +
+
+
    +
  • + + setCurrentPage((prev) => + prev > 1 ? prev - 1 : prev + ) + } + > + Previous + +
  • +
  • = totalData + ? "paginate_button page-item next disabled" + : "paginate_button page-item next" + } + > + + setCurrentPage((prev) => + prev * itemPerPage < totalData + ? prev + 1 + : prev + ) + } + > + Next + +
  • +
+
+
+
+
+
+
+
+
+
+
+ ); +}; + +export default TodayLeave; diff --git a/src/views/PrincipalDistributors/addPrincipalDistributor.js b/src/views/PrincipalDistributors/addPrincipalDistributor.js index 241e540..1dfee25 100644 --- a/src/views/PrincipalDistributors/addPrincipalDistributor.js +++ b/src/views/PrincipalDistributors/addPrincipalDistributor.js @@ -85,26 +85,43 @@ const AddPrincipalDistributor = () => { }; const generatePassword = (name, email) => { + // Combine name and email, and convert to lowercase const combinedStr = (name + email).toLowerCase(); + + // Define character pools const specialChars = "@#*"; - const alphaChars = combinedStr.match(/[a-zA-Z]/g); - const filteredChars = combinedStr.match(/[^\W_]/g); - let passwordChars = alphaChars.concat(filteredChars); - - const specialChar = specialChars.charAt( - Math.floor(Math.random() * specialChars.length) - ); - const randomIndex = Math.floor(Math.random() * (passwordChars.length + 1)); - passwordChars.splice(randomIndex, 0, specialChar); - + const numbers = "0123456789"; + const alphaLower = combinedStr.match(/[a-z]/g) || []; + const alphaUpper = combinedStr.match(/[A-Z]/g) || []; + + // Ensure at least one character from each category + const specialChar = specialChars.charAt(Math.floor(Math.random() * specialChars.length)); + const numberChar = numbers.charAt(Math.floor(Math.random() * numbers.length)); + const lowerChar = alphaLower.length > 0 ? alphaLower[Math.floor(Math.random() * alphaLower.length)] : String.fromCharCode(Math.floor(Math.random() * 26) + 97); + const upperChar = alphaUpper.length > 0 ? alphaUpper[Math.floor(Math.random() * alphaUpper.length)] : String.fromCharCode(Math.floor(Math.random() * 26) + 65); + + // Combine required characters + let passwordChars = [specialChar, numberChar, lowerChar, upperChar]; + + // Fill remaining positions with random characters from the combined string + const allChars = combinedStr + specialChars + numbers; + while (passwordChars.length < 8) { + passwordChars.push(allChars.charAt(Math.floor(Math.random() * allChars.length))); + } + + // Shuffle characters to ensure randomness passwordChars = passwordChars.sort(() => Math.random() - 0.5); - const password = passwordChars.join("").slice(0, 8); + + // Generate password of length 8 + const password = passwordChars.slice(0, 8).join(""); + return password; }; - + const handleFormSubmit = async (e) => { e.preventDefault(); try { + // Validate input fields if ( !user.name || !user.email || @@ -116,17 +133,21 @@ const AddPrincipalDistributor = () => { ) { throw new Error("Fill all fields!"); } + setLoading(true); const generatedPassword = generatePassword(user.name, user.email); - + + // Attempt to register user const userResponse = await axios.post("/api/v1/user/register", { ...user, password: generatedPassword, + role:"principal-Distributor", }); - - if (userResponse.status === 201) { + + if (userResponse.status === 201 || userResponse.status === 200) { const userId = userResponse.data.userId; - + + // Add address details for the user const addressResponse = await axios.post( `/api/shipping/address/admin/new/${userId}`, { @@ -140,6 +161,7 @@ const AddPrincipalDistributor = () => { }, } ); + setLoading(false); if (addressResponse.status === 201) { toast.success("Principal Distributor and Address Added Successfully"); @@ -152,6 +174,7 @@ const AddPrincipalDistributor = () => { toast.error(error.response?.data?.message || "Something went wrong!"); } }; + const handleCancel = () => { navigate("/principal-distributor");