Changes in Attendance filter
This commit is contained in:
parent
9bdcc74486
commit
90b96864be
@ -12,7 +12,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
||||
import eventBus from "../../services/eventBus";
|
||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||
|
||||
const Attendance = ({ getRole, handleModalData, searchTerm, filters }) => {
|
||||
const Attendance = ({ getRole, handleModalData, searchTerm }) => {
|
||||
const queryClient = useQueryClient();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const navigate = useNavigate();
|
||||
@ -50,32 +50,14 @@ const Attendance = ({ getRole, handleModalData, searchTerm, filters }) => {
|
||||
.filter((d) => d.activity === 0)
|
||||
.sort(sortByName);
|
||||
|
||||
// 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 finalFilteredData = useMemo(() => {
|
||||
const combinedData = [...group1, ...group2];
|
||||
|
||||
let tempData = combinedData;
|
||||
|
||||
// Search filter
|
||||
if (searchTerm) {
|
||||
if (!searchTerm) {
|
||||
return combinedData;
|
||||
}
|
||||
const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||
tempData = tempData.filter((item) => {
|
||||
|
||||
return combinedData.filter((item) => {
|
||||
const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||
const role = item.jobRoleName?.toLowerCase() || "";
|
||||
return (
|
||||
@ -83,24 +65,42 @@ const Attendance = ({ getRole, handleModalData, searchTerm, filters }) => {
|
||||
role.includes(lowercasedSearchTerm) // also search by role
|
||||
);
|
||||
});
|
||||
}
|
||||
}, [group1, group2, searchTerm]);
|
||||
|
||||
// Organization filter
|
||||
if (filters?.selectedOrganization) {
|
||||
tempData = tempData.filter(
|
||||
(item) => item.organization?.name === filters.selectedOrganization
|
||||
);
|
||||
}
|
||||
// const finalFilteredData = useMemo(() => {
|
||||
// const combinedData = [...group1, ...group2];
|
||||
|
||||
// Services filter
|
||||
if (filters?.selectedServices?.length > 0) {
|
||||
tempData = tempData.filter((item) =>
|
||||
filters.selectedServices.includes(item.service?.name)
|
||||
);
|
||||
}
|
||||
// let tempData = combinedData;
|
||||
|
||||
return tempData;
|
||||
}, [group1, group2, searchTerm, filters]);
|
||||
// // Search filter
|
||||
// if (searchTerm) {
|
||||
// const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||
// tempData = tempData.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
|
||||
// );
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Organization filter
|
||||
// if (filters?.selectedOrganization) {
|
||||
// tempData = tempData.filter(
|
||||
// (item) => item.organization?.name === filters.selectedOrganization
|
||||
// );
|
||||
// }
|
||||
|
||||
// // Services filter
|
||||
// if (filters?.selectedServices?.length > 0) {
|
||||
// tempData = tempData.filter((item) =>
|
||||
// filters.selectedServices.includes(item.service?.name)
|
||||
// );
|
||||
// }
|
||||
|
||||
// return tempData;
|
||||
// }, [group1, group2, searchTerm, filters]);
|
||||
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ const usePagination = (data, itemsPerPage) => {
|
||||
};
|
||||
};
|
||||
|
||||
const AttendanceLog = ({ handleModalData, searchTerm, filters }) => {
|
||||
const AttendanceLog = ({ handleModalData, searchTerm }) => {
|
||||
// const selectedProject = useSelector(
|
||||
// (store) => store.localVariables.projectId
|
||||
// );
|
||||
@ -139,42 +139,42 @@ const AttendanceLog = ({ handleModalData, searchTerm, filters }) => {
|
||||
}, [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 filteredSearchData = useMemo(() => {
|
||||
let tempData = processedData;
|
||||
|
||||
if (searchTerm) {
|
||||
if (!searchTerm) {
|
||||
return processedData;
|
||||
}
|
||||
const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||
tempData = tempData.filter((item) => {
|
||||
return processedData.filter((item) => {
|
||||
const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||
return fullName.includes(lowercasedSearchTerm);
|
||||
});
|
||||
}
|
||||
}, [processedData, searchTerm]);
|
||||
|
||||
if (filters?.selectedOrganization) {
|
||||
tempData = tempData.filter(
|
||||
(item) => item.organization?.name === filters.selectedOrganization
|
||||
);
|
||||
}
|
||||
// const filteredSearchData = useMemo(() => {
|
||||
// let tempData = processedData;
|
||||
|
||||
if (filters?.selectedServices?.length > 0) {
|
||||
tempData = tempData.filter((item) =>
|
||||
filters.selectedServices.includes(item.service?.name)
|
||||
);
|
||||
}
|
||||
// if (searchTerm) {
|
||||
// const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||
// tempData = tempData.filter((item) => {
|
||||
// const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||
// return fullName.includes(lowercasedSearchTerm);
|
||||
// });
|
||||
// }
|
||||
|
||||
return tempData;
|
||||
}, [processedData, searchTerm, filters]);
|
||||
// if (filters?.selectedOrganization) {
|
||||
// tempData = tempData.filter(
|
||||
// (item) => item.organization?.name === filters.selectedOrganization
|
||||
// );
|
||||
// }
|
||||
|
||||
// if (filters?.selectedServices?.length > 0) {
|
||||
// tempData = tempData.filter((item) =>
|
||||
// filters.selectedServices.includes(item.service?.name)
|
||||
// );
|
||||
// }
|
||||
|
||||
// return tempData;
|
||||
// }, [processedData, searchTerm, filters]);
|
||||
|
||||
|
||||
const {
|
||||
@ -269,14 +269,7 @@ const AttendanceLog = ({ handleModalData, searchTerm, filters }) => {
|
||||
<label className="form-check-label ms-0">Show Pending</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-2 m-0 text-end">
|
||||
<i
|
||||
className={`bx bx-refresh cursor-pointer fs-4 ${isFetching ? "spin" : ""
|
||||
}`}
|
||||
title="Refresh"
|
||||
onClick={() => refetch()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="table-responsive text-nowrap" style={{ minHeight: "200px" }}>
|
||||
{isLoading ? (
|
||||
|
@ -10,7 +10,7 @@ import eventBus from "../../services/eventBus";
|
||||
import { cacheData, clearCacheKey, useSelectedProject } from "../../slices/apiDataManager";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
const Regularization = ({ handleRequest, searchTerm,filters }) => {
|
||||
const Regularization = ({ handleRequest, searchTerm }) => {
|
||||
const queryClient = useQueryClient();
|
||||
// var selectedProject = useSelector((store) => store.localVariables.projectId);
|
||||
const selectedProject = useSelectedProject();
|
||||
@ -47,46 +47,46 @@ const Regularization = ({ handleRequest, searchTerm,filters }) => {
|
||||
);
|
||||
|
||||
// Filter the data based on the search term and sort it
|
||||
// const filteredSearchData = useMemo(() => {
|
||||
// const sortedList = [...regularizesList].sort(sortByName);
|
||||
// if (!searchTerm) {
|
||||
// return sortedList;
|
||||
// }
|
||||
// const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||
// return sortedList.filter((item) => {
|
||||
// const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||
// return fullName.includes(lowercasedSearchTerm);
|
||||
// });
|
||||
// }, [regularizesList, searchTerm]);
|
||||
|
||||
const filteredSearchData = useMemo(() => {
|
||||
let sortedList = [...regularizesList].sort(sortByName);
|
||||
|
||||
// Search filter
|
||||
if (searchTerm) {
|
||||
const sortedList = [...regularizesList].sort(sortByName);
|
||||
if (!searchTerm) {
|
||||
return sortedList;
|
||||
}
|
||||
const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||
sortedList = sortedList.filter((item) => {
|
||||
return sortedList.filter((item) => {
|
||||
const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||
return fullName.includes(lowercasedSearchTerm);
|
||||
});
|
||||
}
|
||||
}, [regularizesList, searchTerm]);
|
||||
|
||||
// Organization filter
|
||||
if (filters?.selectedOrganization) {
|
||||
sortedList = sortedList.filter(
|
||||
(item) => item.organization?.name === filters.selectedOrganization
|
||||
);
|
||||
}
|
||||
// const filteredSearchData = useMemo(() => {
|
||||
// let sortedList = [...regularizesList].sort(sortByName);
|
||||
|
||||
// Services filter
|
||||
if (filters?.selectedServices?.length > 0) {
|
||||
sortedList = sortedList.filter((item) =>
|
||||
filters.selectedServices.includes(item.service?.name)
|
||||
);
|
||||
}
|
||||
// // Search filter
|
||||
// if (searchTerm) {
|
||||
// const lowercasedSearchTerm = searchTerm.toLowerCase();
|
||||
// sortedList = sortedList.filter((item) => {
|
||||
// const fullName = `${item.firstName} ${item.lastName}`.toLowerCase();
|
||||
// return fullName.includes(lowercasedSearchTerm);
|
||||
// });
|
||||
// }
|
||||
|
||||
return sortedList;
|
||||
}, [regularizesList, searchTerm, filters]);
|
||||
// // Organization filter
|
||||
// if (filters?.selectedOrganization) {
|
||||
// sortedList = sortedList.filter(
|
||||
// (item) => item.organization?.name === filters.selectedOrganization
|
||||
// );
|
||||
// }
|
||||
|
||||
// // Services filter
|
||||
// if (filters?.selectedServices?.length > 0) {
|
||||
// sortedList = sortedList.filter((item) =>
|
||||
// filters.selectedServices.includes(item.service?.name)
|
||||
// );
|
||||
// }
|
||||
|
||||
// return sortedList;
|
||||
// }, [regularizesList, searchTerm, filters]);
|
||||
|
||||
|
||||
const { currentPage, totalPages, currentItems, paginate } =
|
||||
|
@ -22,7 +22,6 @@ import GlobalModel from "../../components/common/GlobalModel";
|
||||
import CheckCheckOutmodel from "../../components/Activities/CheckCheckOutForm";
|
||||
import AttendLogs from "../../components/Activities/AttendLogs";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import FilterIconOrgServices from "./FilterIconOrgServices";
|
||||
|
||||
const AttendancePage = () => {
|
||||
const [activeTab, setActiveTab] = useState("all");
|
||||
@ -171,10 +170,38 @@ const AttendancePage = () => {
|
||||
</div>
|
||||
|
||||
{/* Single search input that moves */}
|
||||
<div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto d-flex gap-2 align-items-center">
|
||||
<FilterIconOrgServices
|
||||
onApplyFilters={(filters) => setAppliedFilters(filters)}
|
||||
{/* <div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto d-flex gap-2 align-items-center">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search Employee..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
style={{ minWidth: "200px" }}
|
||||
/>
|
||||
</div> */}
|
||||
|
||||
{/* Search + Organization filter */}
|
||||
<div className="col-12 col-md-auto mt-2 mt-md-0 ms-md-auto d-flex gap-2 align-items-center">
|
||||
{/* Organization Dropdown */}
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
style={{ minWidth: "180px" }}
|
||||
value={appliedFilters.selectedOrganization}
|
||||
onChange={(e) =>
|
||||
setAppliedFilters((prev) => ({
|
||||
...prev,
|
||||
selectedOrganization: e.target.value,
|
||||
}))
|
||||
}
|
||||
>
|
||||
<option value="">All Organizations</option>
|
||||
<option value="Org A">Org A</option>
|
||||
<option value="Org B">Org B</option>
|
||||
<option value="Org C">Org C</option>
|
||||
</select>
|
||||
|
||||
{/* Search Input */}
|
||||
<input
|
||||
type="text"
|
||||
className="form-control form-control-sm"
|
||||
@ -197,7 +224,6 @@ const AttendancePage = () => {
|
||||
handleModalData={handleModalData}
|
||||
getRole={getRole}
|
||||
searchTerm={searchTerm}
|
||||
filters={appliedFilters}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -206,7 +232,6 @@ const AttendancePage = () => {
|
||||
<AttendanceLog
|
||||
handleModalData={handleModalData}
|
||||
searchTerm={searchTerm}
|
||||
filters={appliedFilters}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@ -214,7 +239,7 @@ const AttendancePage = () => {
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<Regularization
|
||||
searchTerm={searchTerm}
|
||||
filters={appliedFilters} />
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
@ -1,189 +0,0 @@
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useSelectedProject } from "../../slices/apiDataManager";
|
||||
import { useProjectAssignedServices } from "../../hooks/useProjects";
|
||||
|
||||
const FilterIconOrgServices = ({ onApplyFilters }) => {
|
||||
const selectedProject = useSelectedProject();
|
||||
|
||||
// Fetch services from API
|
||||
const { data: servicesData = [], isLoading } = useProjectAssignedServices(selectedProject);
|
||||
|
||||
// Hardcoded organization list
|
||||
const organizations = ["Org A", "Org B", "Org C"];
|
||||
|
||||
const [selectedOrganization, setSelectedOrganization] = useState("");
|
||||
const [selectedServices, setSelectedServices] = useState([]);
|
||||
|
||||
const [appliedOrganization, setAppliedOrganization] = useState("");
|
||||
const [appliedServices, setAppliedServices] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedOrganization("");
|
||||
setSelectedServices([]);
|
||||
setAppliedOrganization("");
|
||||
setAppliedServices([]);
|
||||
}, [selectedProject]);
|
||||
|
||||
const handleFilterChange = (type, value) => {
|
||||
if (type === "organization") {
|
||||
setSelectedOrganization(value);
|
||||
} else if (type === "service") {
|
||||
setSelectedServices((prev) =>
|
||||
prev.includes(value) ? prev.filter((s) => s !== value) : [...prev, value]
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const applyFilters = () => {
|
||||
setAppliedOrganization(selectedOrganization);
|
||||
setAppliedServices(selectedServices);
|
||||
|
||||
onApplyFilters({
|
||||
selectedOrganization,
|
||||
selectedServices,
|
||||
});
|
||||
|
||||
document.getElementById("filterDropdown").click();
|
||||
};
|
||||
|
||||
const clearAllFilters = () => {
|
||||
setSelectedOrganization("");
|
||||
setSelectedServices([]);
|
||||
|
||||
setAppliedOrganization("");
|
||||
setAppliedServices([]);
|
||||
|
||||
onApplyFilters({
|
||||
selectedOrganization: "",
|
||||
selectedServices: [],
|
||||
});
|
||||
};
|
||||
|
||||
const appliedFilterCount =
|
||||
(appliedOrganization ? 1 : 0) + appliedServices.length;
|
||||
|
||||
return (
|
||||
<div className="dropdown" style={{ marginLeft: "-14px", position: "relative" }}>
|
||||
<a
|
||||
className="dropdown-toggle hide-arrow cursor-pointer"
|
||||
id="filterDropdown"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<div style={{ position: "relative", display: "inline-block" }}>
|
||||
<i
|
||||
className="bx bx-slider-alt"
|
||||
style={{
|
||||
color: appliedFilterCount > 0 ? "#7161EF" : "gray",
|
||||
fontSize: "20px",
|
||||
}}
|
||||
></i>
|
||||
{appliedFilterCount > 0 && (
|
||||
<span
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "-11px",
|
||||
right: "-6px",
|
||||
backgroundColor: "#FFC107",
|
||||
color: "white",
|
||||
fontSize: "10px",
|
||||
fontWeight: "bold",
|
||||
borderRadius: "50%",
|
||||
width: "18px",
|
||||
height: "18px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
border: "1px solid white",
|
||||
}}
|
||||
>
|
||||
{appliedFilterCount}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<ul
|
||||
className="dropdown-menu p-2 mt-2"
|
||||
aria-labelledby="filterDropdown"
|
||||
style={{ minWidth: "300px", fontSize: "13px" }}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
{/* Organization */}
|
||||
<li>
|
||||
<div className="fw-bold text-dark mb-3 mt-3">Organization</div>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
value={selectedOrganization}
|
||||
onChange={(e) => handleFilterChange("organization", e.target.value)}
|
||||
>
|
||||
<option value="">Select Organization</option>
|
||||
{organizations.map((org, idx) => (
|
||||
<option key={idx} value={org}>
|
||||
{org}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</li>
|
||||
|
||||
{/* Services */}
|
||||
<li><hr className="my-1" /></li>
|
||||
<li>
|
||||
<div className="fw-bold text-dark mb-3 mt-5">Services</div>
|
||||
<div className="row">
|
||||
{isLoading ? (
|
||||
<div className="col-12 text-muted">Loading services...</div>
|
||||
) : servicesData.length > 0 ? (
|
||||
servicesData.map((service, idx) => (
|
||||
<div className="col-6" key={idx}>
|
||||
<div className="form-check mb-1">
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
id={`service-${service.name || service}`}
|
||||
checked={selectedServices.includes(service.name || service)}
|
||||
onChange={() => handleFilterChange("service", service.name || service)}
|
||||
/>
|
||||
<label
|
||||
className="form-check-label"
|
||||
htmlFor={`service-${service.name || service}`}
|
||||
>
|
||||
{service.name || service}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="col-12 text-muted">No services found.</div>
|
||||
)}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
{/* Actions */}
|
||||
<li><hr className="my-1" /></li>
|
||||
{(appliedFilterCount > 0 ||
|
||||
selectedOrganization ||
|
||||
selectedServices.length > 0) && (
|
||||
<li className="d-flex justify-content-end gap-2 px-2 mt-5 mb-2">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-label-secondary btn-sm py-0 px-2"
|
||||
onClick={clearAllFilters}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-primary btn-sm py-0 px-2"
|
||||
onClick={applyFilters}
|
||||
>
|
||||
Apply
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FilterIconOrgServices;
|
Loading…
x
Reference in New Issue
Block a user