diff --git a/src/components/Activities/Attendance.jsx b/src/components/Activities/Attendance.jsx index fed34f34..2dde2938 100644 --- a/src/components/Activities/Attendance.jsx +++ b/src/components/Activities/Attendance.jsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useCallback } from "react"; +import React, { useState, useEffect, useCallback, useMemo } from "react"; import moment from "moment"; import Avatar from "../common/Avatar"; import { convertShortTime } from "../../utils/dateUtils"; @@ -10,16 +10,18 @@ import { useAttendance } from "../../hooks/useAttendance"; import { useSelector } from "react-redux"; import { useQueryClient } from "@tanstack/react-query"; import eventBus from "../../services/eventBus"; +import { useSelectedproject } from "../../slices/apiDataManager"; -const Attendance = ({ getRole, handleModalData }) => { +const Attendance = ({ getRole, handleModalData, searchTerm }) => { const queryClient = useQueryClient(); const [loading, setLoading] = useState(false); const navigate = useNavigate(); const [todayDate, setTodayDate] = useState(new Date()); const [ShowPending, setShowPending] = useState(false); - const selectedProject = useSelector( - (store) => store.localVariables.projectId - ); + // const selectedProject = useSelector( + // (store) => store.localVariables.projectId + // ); + const selectedProject = useSelectedproject(); const { attendance, loading: attLoading, @@ -28,8 +30,8 @@ const Attendance = ({ getRole, handleModalData }) => { } = useAttendance(selectedProject); const filteredAttendance = ShowPending ? attendance?.filter( - (att) => att?.checkInTime !== null && att?.checkOutTime === null - ) + (att) => att?.checkInTime !== null && att?.checkOutTime === null + ) : attendance; const attendanceList = Array.isArray(filteredAttendance) @@ -48,18 +50,40 @@ const Attendance = ({ getRole, handleModalData }) => { .filter((d) => d.activity === 0) .sort(sortByName); - const filteredData = [...group1, ...group2]; + const finalFilteredData = useMemo(() => { + const combinedData = [...group1, ...group2]; + if (!searchTerm) { + return combinedData; + } + const lowercasedSearchTerm = searchTerm.toLowerCase(); + + return combinedData.filter((item) => { + const fullName = `${item.firstName} ${item.lastName}`.toLowerCase(); + const role = item.jobRoleName?.toLowerCase() || ""; + return ( + fullName.includes(lowercasedSearchTerm) || + role.includes(lowercasedSearchTerm) // ✅ also search by role + ); + }); + }, [group1, group2, searchTerm]); + + const { currentPage, totalPages, currentItems, paginate } = usePagination( - filteredData, + finalFilteredData, ITEMS_PER_PAGE ); + // Reset pagination when the filter or search term changes + useEffect(() => { + }, [finalFilteredData]); + + const handler = useCallback( (msg) => { if (selectedProject == msg.projectId) { queryClient.setQueryData(["attendance", selectedProject], (oldData) => { if (!oldData) { - queryClient.invalidateQueries({queryKey:["attendance"]}) + queryClient.invalidateQueries({ queryKey: ["attendance"] }) }; return oldData.map((record) => record.employeeId === msg.response.employeeId ? { ...record, ...msg.response } : record @@ -72,7 +96,7 @@ const Attendance = ({ getRole, handleModalData }) => { const employeeHandler = useCallback( (msg) => { - if (attendances.some((item) => item.employeeId == msg.employeeId)) { + if (attendance.some((item) => item.employeeId == msg.employeeId)) { attrecall(); } }, @@ -106,7 +130,9 @@ const Attendance = ({ getRole, handleModalData }) => { - {Array.isArray(attendance) && attendance.length > 0 ? ( + {attLoading ? ( +
Loading...
+ ) : currentItems?.length > 0 ? ( <> @@ -188,13 +214,12 @@ const Attendance = ({ getRole, handleModalData }) => {
- {!loading && filteredData.length > 20 && ( + {!loading && finalFilteredData.length > ITEMS_PER_PAGE && ( )} - ) : attLoading ? ( -
Loading...
) : ( -
- {Array.isArray(attendance) - ? "No employees assigned to the project" - : "Attendance data unavailable"} +
+ {searchTerm + ? "No results found for your search." + : attendanceList.length === 0 + ? "No employees assigned to the project." + : "No pending records available."}
)} - - {currentItems?.length == 0 && attendance.length > 0 && ( -
No Pending Record Available !
- )}
); diff --git a/src/components/Activities/AttendcesLogs.jsx b/src/components/Activities/AttendcesLogs.jsx index 0a28ffd3..548175d9 100644 --- a/src/components/Activities/AttendcesLogs.jsx +++ b/src/components/Activities/AttendcesLogs.jsx @@ -6,7 +6,7 @@ import RenderAttendanceStatus from "./RenderAttendanceStatus"; import { useSelector, useDispatch } from "react-redux"; import { fetchAttendanceData } from "../../slices/apiSlice/attedanceLogsSlice"; import DateRangePicker from "../common/DateRangePicker"; -import { clearCacheKey, getCachedData } from "../../slices/apiDataManager"; +import { clearCacheKey, getCachedData, useSelectedproject } from "../../slices/apiDataManager"; import eventBus from "../../services/eventBus"; import AttendanceRepository from "../../repositories/AttendanceRepository"; import { useAttendancesLogs } from "../../hooks/useAttendance"; @@ -33,12 +33,11 @@ const usePagination = (data, itemsPerPage) => { }; }; -const AttendanceLog = ({ - handleModalData, -}) => { - const selectedProject = useSelector( - (store) => store.localVariables.projectId - ); +const AttendanceLog = ({ handleModalData, searchTerm }) => { + // const selectedProject = useSelector( + // (store) => store.localVariables.projectId + // ); + const selectedProject = useSelectedproject(); const [dateRange, setDateRange] = useState({ startDate: "", endDate: "" }); const dispatch = useDispatch(); const [loading, setLoading] = useState(false); @@ -139,17 +138,29 @@ const AttendanceLog = ({ filtering(data); }, [data, showPending]); + // New useEffect to handle search filtering + const filteredSearchData = useMemo(() => { + if (!searchTerm) { + return processedData; + } + const lowercasedSearchTerm = searchTerm.toLowerCase(); + return processedData.filter((item) => { + const fullName = `${item.firstName} ${item.lastName}`.toLowerCase(); + return fullName.includes(lowercasedSearchTerm); + }); + }, [processedData, searchTerm]); + const { currentPage, totalPages, currentItems: paginatedAttendances, paginate, resetPage, - } = usePagination(processedData, 20); + } = usePagination(filteredSearchData, 20); useEffect(() => { resetPage(); - }, [processedData, resetPage]); + }, [filteredSearchData, resetPage]); const handler = useCallback( (msg) => { @@ -160,20 +171,23 @@ const AttendanceLog = ({ startDate <= checkIn && checkIn <= endDate ) { - queryClient.setQueriesData(["attendanceLogs"],(oldData)=>{ - if(!oldData) { - queryClient.invalidateQueries({queryKey:["attendanceLogs"]}) + queryClient.setQueriesData(["attendanceLogs"], (oldData) => { + if (!oldData) { + queryClient.invalidateQueries({ queryKey: ["attendanceLogs"] }); + return; } - return oldData.map((record) => - record.id === msg.response.id ? { ...record, ...msg.response } : record - ); - }) - - filtering(updatedAttendance); + const updatedAttendance = oldData.map((record) => + record.id === msg.response.id + ? { ...record, ...msg.response } + : record + ); + filtering(updatedAttendance); + return updatedAttendance; + }); resetPage(); } }, - [selectedProject, dateRange, data, filtering, resetPage] + [selectedProject, dateRange, filtering, resetPage] ); useEffect(() => { @@ -196,7 +210,7 @@ const AttendanceLog = ({ refetch() } }, - [selectedProject, dateRange, data] + [selectedProject, dateRange, data, refetch] ); useEffect(() => { @@ -240,8 +254,10 @@ const AttendanceLog = ({
{isLoading ? ( -

Loading...

- ) : data?.length > 0 ? ( +
+

Loading...

+
+ ) : filteredSearchData?.length > 0 ? ( @@ -332,10 +348,12 @@ const AttendanceLog = ({
No Record Available !
)} - {paginatedAttendances?.length == 0 && data?.length > 0 && ( -
No Pending Record Available !
- )} - {processedData.length > 10 && ( + {paginatedAttendances?.length == 0 && filteredSearchData?.length > 0 && ( +
+ No Pending Record Available ! +
+ )} + {filteredSearchData.length > 10 && (
) : (
- {" "} - No Requests Found ! + + {searchTerm ? "No results found for your search." : "No Requests Found !"} +
)} {!loading && totalPages > 1 && ( diff --git a/src/components/Activities/RegularizationActions.jsx b/src/components/Activities/RegularizationActions.jsx index 4ec9b7b9..318b8382 100644 --- a/src/components/Activities/RegularizationActions.jsx +++ b/src/components/Activities/RegularizationActions.jsx @@ -4,7 +4,7 @@ import useAttendanceStatus, { ACTIONS } from '../../hooks/useAttendanceStatus'; import { useDispatch, useSelector } from 'react-redux'; import { usePositionTracker } from '../../hooks/usePositionTracker'; import {markCurrentAttendance} from '../../slices/apiSlice/attendanceAllSlice'; -import {cacheData, getCachedData} from '../../slices/apiDataManager'; +import {cacheData, getCachedData, useSelectedproject} from '../../slices/apiDataManager'; import showToast from '../../services/toastService'; import { useMarkAttendance } from '../../hooks/useAttendance'; import { useQueryClient } from '@tanstack/react-query'; @@ -17,7 +17,8 @@ const [loadingReject,setLoadingForReject] = useState(false) const {mutate:MarkAttendance,isPending} = useMarkAttendance() const queryClient = useQueryClient() -const projectId = useSelector((store)=>store.localVariables.projectId) +// const projectId = useSelector((store)=>store.localVariables.projectId) +const projectId = useSelectedproject(); const {latitude,longitude} = usePositionTracker(); const dispatch = useDispatch() diff --git a/src/components/Dashboard/AttendanceChart.jsx b/src/components/Dashboard/AttendanceChart.jsx index df99b07d..1ac04954 100644 --- a/src/components/Dashboard/AttendanceChart.jsx +++ b/src/components/Dashboard/AttendanceChart.jsx @@ -98,42 +98,42 @@ const AttendanceOverview = () => { colors: roles.map((_, i) => flatColors[i % flatColors.length]), }; - return ( -
- {/* Header */} -
-
-
Attendance Overview
-

Role-wise present count

-
-
- - - -
-
+ return ( +
+ {/* Header */} +
+
+
Attendance Overview
+

Role-wise present count

+
+
+ + + +
+
{/* Content */}
diff --git a/src/components/Directory/ManageBucket.jsx b/src/components/Directory/ManageBucket.jsx index 0af5108a..58344a15 100644 --- a/src/components/Directory/ManageBucket.jsx +++ b/src/components/Directory/ManageBucket.jsx @@ -19,7 +19,7 @@ import { useProfile } from "../../hooks/useProfile"; const ManageBucket = () => { const { profile } = useProfile(); const [bucketList, setBucketList] = useState([]); - const {employeesList} = useAllEmployees( false ); + const { employeesList } = useAllEmployees(false); const [selectedEmployee, setSelectEmployee] = useState([]); const { buckets, loading, refetch } = useBuckets(); const [action_bucket, setAction_bucket] = useState(false); @@ -237,9 +237,8 @@ const ManageBucket = () => { onChange={(e) => setSearchTerm(e.target.value)} /> refetch()} /> @@ -248,9 +247,8 @@ const ManageBucket = () => { +
+
+
+ {/* Document Name */} +
+ + + {errors.name && ( +
{errors.name}
+ )} +
+ + {/* Document Number */} +
+ + + {errors.documentNumber && ( +
{errors.documentNumber}
+ )} +
+ + {/* Category Dropdown */} +
+ + + {errors.category && ( +
{errors.category}
+ )} +
+ + {/* Document Type Dropdown */} +
+ + + {errors.documentType && ( +
{errors.documentType}
+ )} +
+ + {/* File Uploader */} +
+
+ +
+ document.getElementById("billAttachments").click() + } + > + + + Click to select or click here to browse + + + (PDF, JPG, PNG, max 5MB) + + (e.target.value = null)} + /> +
+ {errors.files && ( +
+ {errors.files} +
+ )} + {files.length > 0 && ( + + )} +
+
+ + {/* Buttons */} +
+ + +
+
+
+
+
+ ); +}; + +export default DocumentForm; \ No newline at end of file diff --git a/src/components/Employee/EmpDashboard.jsx b/src/components/Employee/EmpDashboard.jsx index 8f029443..b25f6803 100644 --- a/src/components/Employee/EmpDashboard.jsx +++ b/src/components/Employee/EmpDashboard.jsx @@ -20,58 +20,58 @@ const EmpDashboard = ({ profile }) => {
- + My Projects - {" "} +
    - {selectedProjectLoding && Loading} - {projectList.map((project) => ( -
  • - {/* Project Info */} -
    -
    -
    -
    - - - -
    -
    -
    {project.projectShortName}
    - {project.projectName} -
    - Assigned:{" "} - {project.assignedDate ? ( - new Date(project.assignedDate).toLocaleDateString() - ) : ( - NA - )} -
    -
    -
    -
    - - {project.designation} - -
    -
    + {selectedProjectLoding && Loading} + {projectList.map((project) => ( +
  • + {/* Project Info */} +
    +
    +
    +
    + + + +
    +
    +
    {project.projectShortName}
    + {project.projectName} +
    + Assigned:{" "} + {project.assignedDate ? ( + new Date(project.assignedDate).toLocaleDateString() + ) : ( + NA + )} +
    +
    +
    +
    + + {project.designation} + +
    +
    - {/* Dates */} - {project.removedDate && ( -
    -
    - Unassigned:{" "} - {new Date(project.removedDate).toLocaleDateString()} -
    -
    - )} -
    -
  • - ))} -
+ {/* Dates */} + {project.removedDate && ( +
+
+ Unassigned:{" "} + {new Date(project.removedDate).toLocaleDateString()} +
+
+ )} +
+ + ))} +
diff --git a/src/components/Employee/EmpDocuments.jsx b/src/components/Employee/EmpDocuments.jsx index 46aa33d0..680097a1 100644 --- a/src/components/Employee/EmpDocuments.jsx +++ b/src/components/Employee/EmpDocuments.jsx @@ -1,12 +1,244 @@ -import React, { useState, useEffect } from "react"; -import { ComingSoonPage } from "../../pages/Misc/ComingSoonPage"; +import React, { useState } from "react"; +import DocumentForm from "./DocumentForm"; +import ConfirmModal from "../common/ConfirmModal"; + +const EmpDocuments = () => { + const [searchText, setSearchText] = useState(""); + const [documents, setDocuments] = useState([ + { + name: "Adhar Card", + documentNumber: "1234-5678-9012", + category: "private", + documentType: "Aadhar Card", + uploadedDate: "21 Aug, 2025", + uploadedBy: "Alice Johnson", + fileType: "PDF", + url: "#", + initials: "AC", + files: [], + }, + { + name: "Pan Card", + documentNumber: "ABCDE1234F", + category: "public", + documentType: "Pan Card", + uploadedDate: "15 Jul, 2025", + uploadedBy: "Bob Smith", + fileType: "Excel", + url: "#", + initials: "PC", + files: [], + }, + { + name: "Driving Licence", + documentNumber: "DL-2025-12345", + category: "private", + documentType: "Driving License", + uploadedDate: "10 Aug, 2025", + uploadedBy: "Carol Lee", + fileType: "Word", + url: "#", + initials: "DL", + files: [], + }, + ]); + + const [showForm, setShowForm] = useState(false); + const [currentDocument, setCurrentDocument] = useState(null); + + const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [documentToDelete, setDocumentToDelete] = useState(null); + + const filteredDocuments = documents.filter((doc) => + (doc.name || "Unnamed Document").toLowerCase().includes(searchText.toLowerCase()) + ); + + const handleSearch = (e) => { + setSearchText(e.target.value); + }; + + const handleCreateClick = () => { + setCurrentDocument(null); + setShowForm(true); + }; + + const handleEditClick = (doc) => { + setCurrentDocument(doc); + setShowForm(true); + }; + + const handleSave = (newDoc) => { + // Helper function to get the file type from the file name + const getFileType = (fileName) => { + const parts = fileName.split('.'); + return parts.length > 1 ? parts.pop().toUpperCase() : 'N/A'; + }; + + // Create a new document object with all required fields + const updatedDoc = { + ...newDoc, + uploadedDate: new Date().toLocaleDateString("en-US", { day: '2-digit', month: 'short', year: 'numeric' }), + uploadedBy: "Current User", // Replace with actual user name + initials: newDoc.name ? newDoc.name.slice(0, 2).toUpperCase() : "--", + // Infer fileType from the first file name if available + fileType: newDoc.files && newDoc.files.length > 0 ? getFileType(newDoc.files[0].fileName) : 'N/A', + }; + + if (currentDocument) { + // Edit an existing document + setDocuments( + documents.map((doc) => (doc === currentDocument ? { ...updatedDoc, initials: doc.initials } : doc)) + ); + } else { + // Create a new document + setDocuments([updatedDoc, ...documents]); // Prepend new doc for better visibility + } + setShowForm(false); + setCurrentDocument(null); + }; + + const handleCancel = () => { + setShowForm(false); + setCurrentDocument(null); + }; + + const handleDelete = (doc) => { + setDocumentToDelete(doc); + setIsDeleteModalOpen(true); + }; + + const handleConfirmDelete = () => { + if (documentToDelete) { + setDocuments(documents.filter((doc) => doc !== documentToDelete)); + setIsDeleteModalOpen(false); + setDocumentToDelete(null); + } + }; + + const handleCloseDeleteModal = () => { + setIsDeleteModalOpen(false); + setDocumentToDelete(null); + }; -const EmpDocuments = ({ profile, loggedInUser }) => { return ( - <> - - +
+ {/* Header: Search & Create */} +
+
+ +
+
+ +
+
+ + {/* Table */} +
+ + + + + + + + {/* */} + + + + + {filteredDocuments.length > 0 ? ( + filteredDocuments.map((doc, index) => ( + + + + + + {/* */} + + + )) + ) : ( + + + + )} + +
Document NameDocument NumberDocument TypeUploaded DateUploaded ByAction
+
+
+ {doc.initials || (doc.name ? doc.name.slice(0, 2).toUpperCase() : "--")} +
+ + +
+
{doc.documentNumber}{doc.documentType}{doc.uploadedDate}{doc.uploadedBy} + handleEditClick(doc)} + > + handleDelete(doc)} + > +
+ No documents available. +
+
+ + {/* Document Form Modal */} + {showForm && ( +
+ +
+ )} + + {/* Delete Confirmation Modal */} + {isDeleteModalOpen && ( +
+ +
+ )} +
); }; -export default EmpDocuments; +export default EmpDocuments; \ No newline at end of file diff --git a/src/components/Employee/EmpOverview.jsx b/src/components/Employee/EmpOverview.jsx index 467a2a58..6b396745 100644 --- a/src/components/Employee/EmpOverview.jsx +++ b/src/components/Employee/EmpOverview.jsx @@ -1,109 +1,163 @@ import React from "react"; -import Avatar from "../common/Avatar"; import { useProfile } from "../../hooks/useProfile"; const EmpOverview = ({ profile }) => { const { loggedInUserProfile } = useProfile(); + return ( - <> - {" "} -
-
-
-
- - About - -
    -
  • - - Full Name:{" "} - {`${profile?.firstName} ${profile?.lastName}`} -
  • -
  • - - Status:{" "} - Active -
  • -
  • - - Role:{" "} - {profile?.jobRole || NA} -
  • -
  • - - Gender:{" "} - {profile?.gender || NA} -
  • {" "} -
  • - - Birth Date:{" "} - - {profile?.birthDate ? ( - new Date(profile.birthDate).toLocaleDateString() - ) : ( - NA - )} - -
  • -
  • - - Joining Date:{" "} - - {profile?.joiningDate ? ( - new Date(profile.joiningDate).toLocaleDateString() - ) : ( - NA - )} - -
  • -
- - Contacts - -
    -
  • - - Contact:{" "} - {profile?.phoneNumber || NA} -
  • -
  • - - Email:{" "} - - {" "} - {profile?.email || NA} - -
  • -
  • - - - {" "} - Emergency Contact: - {" "} - {profile?.emergencyContactPerson || NA} -
  • -
  • - - Emergency Phone:{" "} - {profile?.emergencyPhoneNumber || NA} -
  • -
  • -
    -
    - Address: -
    -
    - {profile?.currentAddress || NA} -
    -
    -
  • -
+
+
+
+
+ + {/* About Heading */} + + About + + + {/* Full Name */} +
+ + + Full Name + + : + + {profile?.firstName || NA} {profile?.lastName || ""} +
+ + {/* Status */} +
+ + + Status + + : + Active +
+ + {/* Role */} +
+ + + Role + + : + {profile?.jobRole || NA} +
+ + {/* Gender */} +
+ + + Gender + + : + {profile?.gender || NA} +
+ + {/* Birth Date */} +
+ + + Birth Date + + : + + {profile?.birthDate + ? new Date(profile.birthDate).toLocaleDateString() + : NA} + +
+ + {/* Joining Date */} +
+ + + Joining Date + + : + + {profile?.joiningDate + ? new Date(profile.joiningDate).toLocaleDateString() + : NA} + +
+ + {/* Contacts Heading */} + + Contacts + + + {/* Contact Number */} +
+ + + Contact + + : + {profile?.phoneNumber || NA} +
+ + {/* Email */} +
+ + + Email + + : + + {profile?.email ? ( + {profile.email} + ) : ( + NA + )} + +
+ + + {/* Emergency Contact */} +
+ + + Emergency Contact + + : + + {profile?.emergencyContactPerson || NA} + +
+ + {/* Emergency Phone */} +
+ + + Emergency Phone + + : + + {profile?.emergencyPhoneNumber || NA} + +
+ + {/* Address */} +
+ + + Address + + : + + {profile?.currentAddress || NA} + +
+
- +
); }; + export default EmpOverview; diff --git a/src/components/Employee/ManageEmployee.jsx b/src/components/Employee/ManageEmployee.jsx index 1f1b3a62..1805220b 100644 --- a/src/components/Employee/ManageEmployee.jsx +++ b/src/components/Employee/ManageEmployee.jsx @@ -16,13 +16,13 @@ import { getCachedData, } from "../../slices/apiDataManager"; import { clearApiCacheKey } from "../../slices/apiCacheSlice"; -import {useMutation} from "@tanstack/react-query"; +import { useMutation } from "@tanstack/react-query"; const mobileNumberRegex = /^[0-9]\d{9}$/; -const ManageEmployee = ({ employeeId, onClosed,IsAllEmployee }) => { +const ManageEmployee = ({ employeeId, onClosed, IsAllEmployee }) => { const dispatch = useDispatch(); -const { mutate: updateEmployee, isPending } = useUpdateEmployee(); + const { mutate: updateEmployee, isPending } = useUpdateEmployee(); const { employee, @@ -130,12 +130,11 @@ const { mutate: updateEmployee, isPending } = useUpdateEmployee(); .min(1, { message: "Phone Number is required" }) .regex(mobileNumberRegex, { message: "Invalid phone number " }), jobRoleId: z.string().min(1, { message: "Role is required" }), - } ); - - useEffect( () => - { + }); + + useEffect(() => { refetch() - },[]) + }, []) const { register, @@ -169,19 +168,19 @@ const { mutate: updateEmployee, isPending } = useUpdateEmployee(); }); const AadharNumberValue = watch("aadharNumber") || ""; - - const onSubmit = (data) => { - if (data.email === "") { - data.email = null; - } - updateEmployee({...data,IsAllEmployee},{ - onSuccess: () => { - reset(); - onClosed(); - }, - }); -}; + const onSubmit = (data) => { + if (data.email === "") { + data.email = null; + } + + updateEmployee({ ...data, IsAllEmployee }, { + onSuccess: () => { + reset(); + onClosed(); + }, + }); + }; useEffect(() => { @@ -212,7 +211,7 @@ const { mutate: updateEmployee, isPending } = useUpdateEmployee(); phoneNumber: currentEmployee.phoneNumber || "", jobRoleId: currentEmployee.jobRoleId?.toString() || "", } - : {} + : {} ); setCurrentAddressLength(currentEmployee?.currentAddress?.length || 0); setPermanentAddressLength(currentEmployee?.permanentAddress?.length || 0); @@ -220,66 +219,82 @@ const { mutate: updateEmployee, isPending } = useUpdateEmployee(); return ( <> -
+

{employee ? "Update Employee" : "Create Employee"}

-
-
- {" "} -
First Name
- - {errors.firstName && ( -
- {errors.firstName.message} -
- )} -
{" "} -
-
Middle Name
- +
+
+
First Name
{ + e.target.value = e.target.value.replace(/[^A-Za-z\s]/g, ""); + }} /> - {errors.middleName && ( -
- {errors.middleName.message} + {errors.firstName && ( +
+ {errors.firstName.message}
)}
+
+
Middle Name
+ { + e.target.value = e.target.value.replace(/[^A-Za-z\s]/g, ""); + }} + /> + {errors.middleName && ( +
+ {errors.middleName.message} +
+ )} +
+
Last Name
{ + e.target.value = e.target.value.replace(/[^A-Za-z\s]/g, ""); + }} /> {errors.lastName && ( -
+
{errors.lastName.message}
)}
+
@@ -330,7 +345,7 @@ const { mutate: updateEmployee, isPending } = useUpdateEmployee();
Gender
-
+
Joining Date
-
+
Official Designation
-
+
- {groupByList.map((group) => ( - - ))} - -
+ +
- - {jobRoleData?.map((user) => ( -
  • - + {selectedRolesCount} + + )} + + {/* Dropdown Menu with Scroll */} +
      + {/* All Roles */} +
    • +
      + + handleRoleChange(e, e.target.value) + } + /> + +
    • - ))} -
    + + {/* Dynamic Roles */} + {jobRolesForDropdown?.map((role) => ( +
  • +
    + + handleRoleChange(e, e.target.value) + } + /> + +
    +
  • + ))} + +
    + + {/* Search Box */} +
    -
    -
    - {selectedRole !== "" && ( -
    - {employeeLoading ? ( -
    -

    Loading employees...

    -
    - ) : filteredEmployees?.length > 0 ? ( - filteredEmployees.map((emp) => { - const jobRole = jobRoleData?.find( - (role) => role?.id === emp?.jobRoleId - ); + {/* Employees list */} +
    + {selectedRoles?.length > 0 && ( +
    + {employeeLoading ? ( +
    +

    Loading employees...

    +
    + ) : filteredEmployees?.length > 0 ? ( + filteredEmployees.map((emp) => { + const jobRole = jobRoleData?.find( + (role) => role?.id === emp?.jobRoleId + ); - return ( -
    -
    - ( - { - handleCheckboxChange(e, emp); - }} - /> + return ( +
    +
    + ( + { + handleCheckboxChange(e, emp); + }} + /> + )} + /> +
    +

    + {emp.firstName} {emp.lastName} +

    + + {loading ? ( + + + + ) : ( + jobRole?.name || "Unknown Role" )} - /> -
    -

    - {emp.firstName} {emp.lastName} -

    - - {loading ? ( - - - - ) : ( - jobRole?.name || "Unknown Role" - )} - -
    +
    - ); - }) - ) : ( -
    -

    +

    + ); + }) + ) : ( +
    +

    No employees found for the selected role. -

    -
    - )} -
    - )} -
    +

    +
    + )} +
    + )}
    {
    -
    @@ -397,10 +501,7 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => { {/* Target for Today input and validation */}
    -
    )} />
    {errors.plannedTask && ( -
    - {errors.plannedTask.message} -
    - )} - - {isHelpVisible && ( -
    - {/* Add your help content here */} -

    - Enter the target value for today's task. -

    -
    +
    {errors.plannedTask.message}
    )}
    @@ -476,12 +543,7 @@ const AssignTask = ({ assignData, onClose, setAssigned }) => { name="description" control={control} render={({ field }) => ( -