In Directory changing filter logic and adding popup.
This commit is contained in:
parent
abc8bd8629
commit
deb7100899
@ -7,6 +7,8 @@ import showToast from "../../services/toastService";
|
||||
import { cacheData, getCachedData } from "../../slices/apiDataManager";
|
||||
import ConfirmModal from "../common/ConfirmModal"; // Make sure path is correct
|
||||
import "../common/TextEditor/Editor.css";
|
||||
import ProfileContactDirectory from "./ProfileContactDirectory";
|
||||
import GlobalModel from "../common/GlobalModel";
|
||||
|
||||
const NoteCardDirectoryEditable = ({
|
||||
noteItem,
|
||||
@ -20,6 +22,8 @@ const NoteCardDirectoryEditable = ({
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const [isRestoring, setIsRestoring] = useState(false);
|
||||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
const [open_contact, setOpen_contact] = useState(null);
|
||||
const [isOpenModalNote, setIsOpenModalNote] = useState(false);
|
||||
|
||||
const handleUpdateNote = async () => {
|
||||
try {
|
||||
@ -69,6 +73,13 @@ const NoteCardDirectoryEditable = ({
|
||||
}
|
||||
};
|
||||
|
||||
const contactProfile = (contactId) => {
|
||||
DirectoryRepository.GetContactProfile(contactId).then((res) => {
|
||||
setOpen_contact(res?.data);
|
||||
setIsOpenModalNote(true);
|
||||
});
|
||||
};
|
||||
|
||||
const handleRestore = async () => {
|
||||
try {
|
||||
setIsRestoring(true);
|
||||
@ -84,6 +95,25 @@ const NoteCardDirectoryEditable = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
{isOpenModalNote && (
|
||||
<GlobalModel
|
||||
isOpen={isOpenModalNote}
|
||||
closeModal={() => {
|
||||
setOpen_contact(null);
|
||||
setIsOpenModalNote(false);
|
||||
}}
|
||||
size="xl"
|
||||
>
|
||||
{open_contact && (
|
||||
<ProfileContactDirectory
|
||||
contact={open_contact}
|
||||
setOpen_contact={setOpen_contact}
|
||||
closeModal={() => setIsOpenModalNote(false)}
|
||||
/>
|
||||
)}
|
||||
</GlobalModel>
|
||||
)}
|
||||
<div
|
||||
className="card p-1 shadow-sm border-1 mb-4 rounded"
|
||||
style={{
|
||||
@ -95,23 +125,39 @@ const NoteCardDirectoryEditable = ({
|
||||
{/* Header */}
|
||||
<div className="d-flex justify-content-between align-items-center mb-1">
|
||||
<div className="d-flex align-items-center">
|
||||
|
||||
<Avatar
|
||||
size="xs"
|
||||
firstName={noteItem?.createdBy?.firstName}
|
||||
lastName={noteItem?.createdBy?.lastName}
|
||||
className="m-0"
|
||||
/>
|
||||
<div className="d-flex flex-column ms-0">
|
||||
<span className="fw-semibold small">
|
||||
{noteItem?.createdBy?.firstName} {noteItem?.createdBy?.lastName}
|
||||
</span>
|
||||
<span className="text-muted" style={{ fontSize: "10px" }}>
|
||||
{moment
|
||||
.utc(noteItem?.createdAt)
|
||||
.add(5, "hours")
|
||||
.add(30, "minutes")
|
||||
.format("MMMM DD, YYYY [at] hh:mm A")}
|
||||
</span>
|
||||
<div>
|
||||
<div className="d-flex ms-0 align-middle cursor-pointer" onClick={() =>contactProfile(noteItem.contactId)}>
|
||||
<span>
|
||||
<span className="fw-bold "> {noteItem?.contactName} </span> <span className="text-muted font-weight-normal">
|
||||
( {noteItem?.organizationName})
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div className="d-flex ms-0 align-middle">
|
||||
|
||||
|
||||
</div>
|
||||
<div className="d-flex ms-0 mt-2">
|
||||
<span className="text-muted">
|
||||
by <span className="fw-bold "> {noteItem?.createdBy?.firstName} {noteItem?.createdBy?.lastName} </span>
|
||||
<span className="text-muted">
|
||||
on {moment
|
||||
.utc(noteItem?.createdAt)
|
||||
.add(5, "hours")
|
||||
.add(30, "minutes")
|
||||
.format("MMMM DD, YYYY [at] hh:mm A")}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -2,20 +2,39 @@ import React, { useEffect, useState, useMemo } from "react";
|
||||
import { DirectoryRepository } from "../../repositories/DirectoryRepository";
|
||||
import NoteCardDirectoryEditable from "./NoteCardDirectoryEditable";
|
||||
|
||||
const NotesCardViewDirectory = ({ notes, setNotes, searchText, selectedNoteNames }) => { // ✅ Changed to array
|
||||
const NotesCardViewDirectory = ({ notes, setNotesForFilter, searchText, filterAppliedNotes }) => {
|
||||
const [allNotes, setAllNotes] = useState([]);
|
||||
const [filteredNotes, setFilteredNotes] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [totalPages, setTotalPages] = useState(1);
|
||||
const [selectedCreators, setSelectedCreators] = useState([]);
|
||||
const [selectedOrgs, setSelectedOrgs] = useState([]);
|
||||
const pageSize = 20;
|
||||
|
||||
useEffect(() => {
|
||||
fetchNotes();
|
||||
}, []);
|
||||
|
||||
const fetchNotes = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await DirectoryRepository.GetNotes(1000, 1);
|
||||
const fetchedNotes = response.data?.data || [];
|
||||
setAllNotes(fetchedNotes);
|
||||
setNotesForFilter(fetchedNotes)
|
||||
|
||||
const creatorsSet = new Set();
|
||||
const orgsSet = new Set();
|
||||
|
||||
fetchedNotes.forEach((note) => {
|
||||
const creator = `${note.createdBy?.firstName || ""} ${note.createdBy?.lastName || ""}`.trim();
|
||||
if (creator) creatorsSet.add(creator);
|
||||
|
||||
const org = note.organizationName;
|
||||
if (org) orgsSet.add(org);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch notes:", error);
|
||||
} finally {
|
||||
@ -23,52 +42,51 @@ const NotesCardViewDirectory = ({ notes, setNotes, searchText, selectedNoteNames
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchNotes();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
const applyCombinedFilter = () => {
|
||||
const lowerSearch = searchText?.toLowerCase() || "";
|
||||
|
||||
const filtered = allNotes.filter((noteItem) => {
|
||||
const creator = `${noteItem.createdBy?.firstName || ""} ${noteItem.createdBy?.lastName || ""}`.trim();
|
||||
const org = noteItem.organizationName;
|
||||
|
||||
const matchesCreator = selectedCreators.length === 0 || selectedCreators.includes(creator);
|
||||
const matchesOrg = selectedOrgs.length === 0 || selectedOrgs.includes(org);
|
||||
|
||||
const plainNote = noteItem?.note?.replace(/<[^>]+>/g, "").toLowerCase();
|
||||
const fullName = `${noteItem?.createdBy?.firstName || ""} ${noteItem?.createdBy?.lastName || ""}`.trim();
|
||||
const lowerFullName = fullName.toLowerCase();
|
||||
const createdDate = new Date(noteItem?.createdAt).toLocaleDateString("en-IN").toLowerCase();
|
||||
|
||||
// ✅ Collect all string values in the note object to search through
|
||||
const stringValues = [];
|
||||
|
||||
const extractStrings = (obj) => {
|
||||
for (const key in obj) {
|
||||
if (!obj.hasOwnProperty(key)) continue;
|
||||
const value = obj[key];
|
||||
if (typeof value === "string") {
|
||||
stringValues.push(value.toLowerCase());
|
||||
} else if (typeof value === "object" && value !== null) {
|
||||
extractStrings(value); // Recursively extract from nested objects
|
||||
extractStrings(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extractStrings(noteItem);
|
||||
// Add manually stripped note, full name, date, etc.
|
||||
stringValues.push(plainNote, lowerFullName, createdDate);
|
||||
stringValues.push(plainNote, creator.toLowerCase());
|
||||
|
||||
const matchesSearch = stringValues.some((val) => val.includes(lowerSearch));
|
||||
|
||||
const matchesNameFilter =
|
||||
selectedNoteNames.length === 0 || selectedNoteNames.includes(fullName);
|
||||
|
||||
return matchesSearch && matchesNameFilter;
|
||||
return matchesCreator && matchesOrg && matchesSearch;
|
||||
});
|
||||
|
||||
setFilteredNotes(filtered);
|
||||
setNotes(filtered);
|
||||
setCurrentPage(1);
|
||||
setTotalPages(Math.ceil(filtered.length / pageSize));
|
||||
}, [searchText, allNotes, selectedNoteNames]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
applyCombinedFilter();
|
||||
}, [searchText, allNotes]);
|
||||
|
||||
useEffect(() => {
|
||||
setFilteredNotes(filterAppliedNotes);
|
||||
}, [filterAppliedNotes])
|
||||
|
||||
const currentItems = useMemo(() => {
|
||||
const startIndex = (currentPage - 1) * pageSize;
|
||||
@ -81,19 +99,19 @@ const NotesCardViewDirectory = ({ notes, setNotes, searchText, selectedNoteNames
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <p className="mt-10 text-center">Loading notes...</p>;
|
||||
}
|
||||
if (loading) return <p className="mt-10 text-center">Loading notes...</p>;
|
||||
|
||||
if (!filteredNotes.length) return <p className="mt-10 text-center">No matching notes found</p>;
|
||||
|
||||
if (!filteredNotes.length) {
|
||||
return <p className="mt-10 text-center">No matching notes found</p>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-100 h-100"
|
||||
>
|
||||
<div className="d-flex flex-column text-start mt-4" style={{ gap: "0rem", minHeight: "100%" }}>
|
||||
<div className="w-100 h-100 ">
|
||||
{/* Filter Dropdown */}
|
||||
<div className="dropdown mb-3 ms-2">
|
||||
</div>
|
||||
|
||||
{/* Notes List */}
|
||||
<div className="d-flex flex-column text-start" style={{ gap: "0rem", minHeight: "100%" }}>
|
||||
{currentItems.map((noteItem) => (
|
||||
<NoteCardDirectoryEditable
|
||||
key={noteItem.id}
|
||||
@ -104,13 +122,12 @@ const NotesCardViewDirectory = ({ notes, setNotes, searchText, selectedNoteNames
|
||||
prevNotes.map((n) => (n.id === updatedNote.id ? updatedNote : n))
|
||||
);
|
||||
}}
|
||||
onNoteDelete={() => {
|
||||
fetchNotes();
|
||||
}}
|
||||
onNoteDelete={() => fetchNotes()}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Pagination */}
|
||||
{totalPages > 1 && (
|
||||
<div className="d-flex justify-content-end mt-3 me-3">
|
||||
<div className="d-flex align-items-center gap-2">
|
||||
@ -128,7 +145,8 @@ const NotesCardViewDirectory = ({ notes, setNotes, searchText, selectedNoteNames
|
||||
return (
|
||||
<button
|
||||
key={page}
|
||||
className={`btn btn-sm rounded-circle border ${page === currentPage ? "btn-primary text-white" : "btn-outline-primary"}`}
|
||||
className={`btn btn-sm rounded-circle border ${page === currentPage ? "btn-primary text-white" : "btn-outline-primary"
|
||||
}`}
|
||||
style={{ width: "32px", height: "32px", padding: 0 }}
|
||||
onClick={() => handlePageClick(page)}
|
||||
>
|
||||
@ -152,4 +170,4 @@ const NotesCardViewDirectory = ({ notes, setNotes, searchText, selectedNoteNames
|
||||
);
|
||||
};
|
||||
|
||||
export default NotesCardViewDirectory;
|
||||
export default NotesCardViewDirectory;
|
||||
|
@ -38,6 +38,8 @@ const Directory = ({ IsPage = true, prefernceContacts }) => {
|
||||
const [IsDeleting, setDeleting] = useState(false);
|
||||
const [openBucketModal, setOpenBucketModal] = useState(false);
|
||||
const [notes, setNotes] = useState([]);
|
||||
const [filterAppliedNotes, setFilterAppliedNotes] = useState([]);
|
||||
// const [selectedOrgs, setSelectedOrgs] = useState([]);
|
||||
|
||||
// ✅ Changed to an array for multiple selections
|
||||
const [selectedNoteNames, setSelectedNoteNames] = useState([]);
|
||||
@ -353,6 +355,8 @@ const Directory = ({ IsPage = true, prefernceContacts }) => {
|
||||
notesToExport={notes}
|
||||
selectedNoteNames={selectedNoteNames}
|
||||
setSelectedNoteNames={setSelectedNoteNames}
|
||||
notesForFilter={notes}
|
||||
setFilterAppliedNotes={setFilterAppliedNotes}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -421,9 +425,10 @@ const Directory = ({ IsPage = true, prefernceContacts }) => {
|
||||
<div className="mt-0">
|
||||
<NotesCardViewDirectory
|
||||
notes={notes}
|
||||
setNotes={setNotes}
|
||||
setNotesForFilter={setNotes}
|
||||
searchText={searchText}
|
||||
selectedNoteNames={selectedNoteNames}
|
||||
setIsOpenModalNote={setIsOpenModalNote}
|
||||
filterAppliedNotes={filterAppliedNotes}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
@ -19,12 +19,19 @@ const DirectoryPageHeader = ({
|
||||
IsActive,
|
||||
contactsToExport,
|
||||
notesToExport,
|
||||
selectedNoteNames, // ✅ Changed to array
|
||||
setSelectedNoteNames, // ✅ Changed to array
|
||||
selectedNoteNames,
|
||||
setSelectedNoteNames,
|
||||
notesForFilter,
|
||||
setFilterAppliedNotes
|
||||
}) => {
|
||||
const [filtered, setFiltered] = useState(0);
|
||||
|
||||
const [filteredNotes, setFilteredNotes] = useState([]);
|
||||
const [noteCreators, setNoteCreators] = useState([]);
|
||||
const [allCreators, setAllCreators] = useState([]);
|
||||
const [allOrganizations, setAllOrganizations] = useState([]);
|
||||
const [filteredOrganizations, setFilteredOrganizations] = useState([]);
|
||||
const [selectedCreators, setSelectedCreators] = useState([]); // Corrected to setSelectedCreators
|
||||
const [selectedOrgs, setSelectedOrgs] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
setFiltered(tempSelectedBucketIds?.length + tempSelectedCategoryIds?.length);
|
||||
@ -55,6 +62,23 @@ const DirectoryPageHeader = ({
|
||||
}
|
||||
}, [viewType]);
|
||||
|
||||
useEffect(() => {
|
||||
const creatorsSet = new Set();
|
||||
const orgsSet = new Set();
|
||||
|
||||
notesForFilter.forEach((note) => {
|
||||
const creator = `${note.createdBy?.firstName || ""} ${note.createdBy?.lastName || ""}`.trim();
|
||||
if (creator) creatorsSet.add(creator);
|
||||
|
||||
const org = note.organizationName;
|
||||
if (org) orgsSet.add(org);
|
||||
});
|
||||
|
||||
setAllCreators([...creatorsSet].sort());
|
||||
setAllOrganizations([...orgsSet].sort());
|
||||
setFilteredOrganizations([...orgsSet].sort());
|
||||
}, [notesForFilter])
|
||||
|
||||
|
||||
const handleToggleNoteName = (name) => {
|
||||
setSelectedNoteNames(prevSelectedNames => {
|
||||
@ -66,6 +90,45 @@ const DirectoryPageHeader = ({
|
||||
});
|
||||
};
|
||||
|
||||
const updateFilteredOrganizations = () => {
|
||||
if (selectedCreators.length === 0) {
|
||||
setFilteredOrganizations(allOrganizations);
|
||||
return;
|
||||
}
|
||||
|
||||
const filteredOrgsSet = new Set();
|
||||
notesForFilter.forEach((note) => {
|
||||
const creator = `${note.createdBy?.firstName || ""} ${note.createdBy?.lastName || ""}`.trim();
|
||||
if (selectedCreators.includes(creator)) {
|
||||
if (note.organizationName) {
|
||||
filteredOrgsSet.add(note.organizationName);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setFilteredOrganizations([...filteredOrgsSet].sort());
|
||||
};
|
||||
|
||||
const handleToggleCreator = (name) => {
|
||||
const updated = selectedCreators.includes(name)
|
||||
? selectedCreators.filter((n) => n !== name)
|
||||
: [...selectedCreators, name];
|
||||
|
||||
setSelectedCreators(updated);
|
||||
};
|
||||
|
||||
const handleToggleOrg = (name) => {
|
||||
const updated = selectedOrgs.includes(name)
|
||||
? selectedOrgs.filter((n) => n !== name)
|
||||
: [...selectedOrgs, name];
|
||||
|
||||
setSelectedOrgs(updated);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
updateFilteredOrganizations();
|
||||
}, [selectedCreators]);
|
||||
|
||||
const handleExport = (type) => {
|
||||
let dataToExport = [];
|
||||
|
||||
@ -149,6 +212,41 @@ const DirectoryPageHeader = ({
|
||||
}
|
||||
};
|
||||
|
||||
const applyCombinedFilter = () => {
|
||||
const lowerSearch = searchText?.toLowerCase() || "";
|
||||
|
||||
const filtered = notesForFilter.filter((noteItem) => {
|
||||
const creator = `${noteItem.createdBy?.firstName || ""} ${noteItem.createdBy?.lastName || ""}`.trim();
|
||||
const org = noteItem.organizationName;
|
||||
|
||||
const matchesCreator = selectedCreators.length === 0 || selectedCreators.includes(creator);
|
||||
const matchesOrg = selectedOrgs.length === 0 || selectedOrgs.includes(org);
|
||||
|
||||
const plainNote = noteItem?.note?.replace(/<[^>]+>/g, "").toLowerCase();
|
||||
|
||||
const stringValues = [];
|
||||
const extractStrings = (obj) => {
|
||||
for (const key in obj) {
|
||||
const value = obj[key];
|
||||
if (typeof value === "string") {
|
||||
stringValues.push(value.toLowerCase());
|
||||
} else if (typeof value === "object" && value !== null) {
|
||||
extractStrings(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
extractStrings(noteItem);
|
||||
stringValues.push(plainNote, creator.toLowerCase());
|
||||
|
||||
const matchesSearch = stringValues.some((val) => val.includes(lowerSearch));
|
||||
|
||||
return matchesCreator && matchesOrg && matchesSearch;
|
||||
});
|
||||
|
||||
setFilteredNotes(filtered);
|
||||
setFilterAppliedNotes(filtered);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="row mx-0 px-0 align-items-center mt-0">
|
||||
@ -189,52 +287,72 @@ const DirectoryPageHeader = ({
|
||||
style={{ width: "200px" }}
|
||||
/>
|
||||
|
||||
{/* Name Filter Dropdown - now with checkboxes */}
|
||||
{viewType === "notes" && noteCreators.length > 0 && (
|
||||
<div className="dropdown" style={{ width: "fit-content" }}>
|
||||
<button
|
||||
className="btn btn-sm btn-outline-secondary dropdown-toggle" // Added btn-sm for small size
|
||||
type="button"
|
||||
id="notesNameFilterDropdown"
|
||||
{/* Moved the "Filter by" dropdown to be triggered by the funnel icon */}
|
||||
{viewType === "notes" && (
|
||||
<div className="dropdown" style={{ width: "500px" }}>
|
||||
<a
|
||||
className="dropdown-toggle hide-arrow cursor-pointer d-flex align-items-center position-relative"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{selectedNoteNames.length > 0
|
||||
? `Names (${selectedNoteNames.length})`
|
||||
: "Filter by Name"}
|
||||
</button>
|
||||
<ul className="dropdown-menu p-2" aria-labelledby="notesNameFilterDropdown">
|
||||
{/* Option to clear all selections */}
|
||||
<li>
|
||||
<a
|
||||
className={`dropdown-item ${selectedNoteNames.length === 0 ? "active" : ""}`}
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
setSelectedNoteNames([]); // Clear all
|
||||
<i className={`fa-solid fa-filter ms-1 fs-5 ${selectedCreators.length > 0 || selectedOrgs.length > 0 ? "text-primary" : "text-muted"}`}></i>
|
||||
{(selectedCreators.length > 0 || selectedOrgs.length > 0) && (
|
||||
<span className="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-warning" style={{ fontSize: "0.4rem" }}>
|
||||
{selectedCreators.length + selectedOrgs.length}
|
||||
</span>
|
||||
)}
|
||||
</a>
|
||||
|
||||
<div className="dropdown-menu p-3" style={{ width: "300px", maxHeight: "400px", overflowY: "auto" }}>
|
||||
<p className="text-muted mb-1">Created By</p>
|
||||
{allCreators.map((name, idx) => (
|
||||
<div className="form-check mb-1" key={`creator-${idx}`}>
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
id={`creator-${idx}`}
|
||||
checked={selectedCreators.includes(name)}
|
||||
onChange={() => handleToggleCreator(name)}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor={`creator-${idx}`}>
|
||||
{name}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<p className="text-muted mt-3 mb-1">Organization</p>
|
||||
{filteredOrganizations.map((org, idx) => (
|
||||
<div className="form-check mb-1" key={`org-${idx}`}>
|
||||
<input
|
||||
className="form-check-input"
|
||||
type="checkbox"
|
||||
id={`org-${idx}`}
|
||||
checked={selectedOrgs.includes(org)}
|
||||
onChange={() => handleToggleOrg(org)}
|
||||
/>
|
||||
<label className="form-check-label" htmlFor={`org-${idx}`}>
|
||||
{org}
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="d-flex justify-content-between mt-2">
|
||||
<button
|
||||
className="btn btn-sm btn-outline-danger"
|
||||
onClick={() => {
|
||||
setSelectedCreators([]);
|
||||
setSelectedOrgs([]);
|
||||
setFilteredOrganizations(allOrganizations);
|
||||
applyCombinedFilter();
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
</a>
|
||||
</li>
|
||||
<li><hr className="dropdown-divider" /></li>
|
||||
{noteCreators.map((name, index) => (
|
||||
<li key={index}>
|
||||
<div className="form-check dropdown-item p-0">
|
||||
<input
|
||||
className="form-check-input ms-2"
|
||||
type="checkbox"
|
||||
id={`name-filter-${index}`}
|
||||
checked={selectedNoteNames.includes(name)}
|
||||
onChange={() => handleToggleNoteName(name)}
|
||||
/>
|
||||
<label className="form-check-label ms-2" htmlFor={`name-filter-${index}`}>
|
||||
{name}
|
||||
</label>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</button>
|
||||
<button className="btn btn-sm btn-primary" onClick={applyCombinedFilter}>
|
||||
Apply Filter
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user