From 9554caf25f43f7d9d85e64bbca5a28bdd6da7e20 Mon Sep 17 00:00:00 2001 From: Kartik sharma Date: Mon, 30 Jun 2025 15:53:01 +0530 Subject: [PATCH] Changes in Directory in Filter, removing unnessary gaps and changing color of HideEditor. --- .../Directory/NoteCardDirectoryEditable.jsx | 8 +- .../Directory/NotesCardViewDirectory.jsx | 14 +- src/components/Directory/NotesDirectory.jsx | 2 +- src/pages/Directory/DirectoryPageHeader.jsx | 1020 +++++++++-------- 4 files changed, 531 insertions(+), 513 deletions(-) diff --git a/src/components/Directory/NoteCardDirectoryEditable.jsx b/src/components/Directory/NoteCardDirectoryEditable.jsx index e6991c2e..7759e62a 100644 --- a/src/components/Directory/NoteCardDirectoryEditable.jsx +++ b/src/components/Directory/NoteCardDirectoryEditable.jsx @@ -115,7 +115,7 @@ const NoteCardDirectoryEditable = ({ )}
contactProfile(noteItem.contactId)}> {noteItem?.contactName} - ( {noteItem?.organizationName}) + ({noteItem?.organizationName}) @@ -220,7 +220,7 @@ const NoteCardDirectoryEditable = ({ ) : (
)} diff --git a/src/components/Directory/NotesCardViewDirectory.jsx b/src/components/Directory/NotesCardViewDirectory.jsx index d29354d7..0dbbe5bd 100644 --- a/src/components/Directory/NotesCardViewDirectory.jsx +++ b/src/components/Directory/NotesCardViewDirectory.jsx @@ -133,11 +133,11 @@ const NotesCardViewDirectory = ({ notes, setNotesForFilter, searchText, filterAp style={{ marginBottom: '70px' }}> {/* Previous Button */} @@ -148,10 +148,8 @@ const NotesCardViewDirectory = ({ notes, setNotesForFilter, searchText, filterAp return ( diff --git a/src/components/Directory/NotesDirectory.jsx b/src/components/Directory/NotesDirectory.jsx index 5ddb37c8..61908853 100644 --- a/src/components/Directory/NotesDirectory.jsx +++ b/src/components/Directory/NotesDirectory.jsx @@ -135,7 +135,7 @@ const NotesDirectory = ({
setAddNote(!addNote)} > {addNote ? "Hide Editor" : "Add a Note"} diff --git a/src/pages/Directory/DirectoryPageHeader.jsx b/src/pages/Directory/DirectoryPageHeader.jsx index 48e28f28..3e2b3d7b 100644 --- a/src/pages/Directory/DirectoryPageHeader.jsx +++ b/src/pages/Directory/DirectoryPageHeader.jsx @@ -2,538 +2,558 @@ import React, { useEffect, useState } from "react"; import { exportToCSV, exportToExcel, printTable, exportToPDF } from "../../utils/tableExportUtils"; const DirectoryPageHeader = ({ - searchText, - setSearchText, - setIsActive, - viewType, - setViewType, - filteredBuckets, - tempSelectedBucketIds, - handleTempBucketChange, - filteredCategories, - tempSelectedCategoryIds, - handleTempCategoryChange, - clearFilter, - applyFilter, - loading, - IsActive, - contactsToExport, - notesToExport, - selectedNoteNames, - setSelectedNoteNames, - notesForFilter, - setFilterAppliedNotes + searchText, + setSearchText, + setIsActive, + viewType, + setViewType, + filteredBuckets, + tempSelectedBucketIds, + handleTempBucketChange, + filteredCategories, + tempSelectedCategoryIds, + handleTempCategoryChange, + clearFilter, + applyFilter, + loading, + IsActive, + contactsToExport, + notesToExport, + 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([]); - const [selectedOrgs, setSelectedOrgs] = useState([]); + 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([]); + const [selectedOrgs, setSelectedOrgs] = useState([]); - useEffect(() => { - setFiltered(tempSelectedBucketIds?.length + tempSelectedCategoryIds?.length); - }, [tempSelectedBucketIds, tempSelectedCategoryIds]); + useEffect(() => { + setFiltered(tempSelectedBucketIds?.length + tempSelectedCategoryIds?.length); + }, [tempSelectedBucketIds, tempSelectedCategoryIds]); + // New state to track active filters for notes + const [notesFilterCount, setNotesFilterCount] = useState(0); - useEffect(() => { - if (viewType === "notes") { - if (notesToExport && notesToExport.length > 0) { - const uniqueNames = [...new Set(notesToExport.map(note => { - const firstName = note.createdBy?.firstName || ""; - const lastName = note.createdBy?.lastName || ""; - return `${firstName} ${lastName}`.trim(); - }).filter(name => name !== ""))]; - setNoteCreators(uniqueNames.sort()); - } else { - setNoteCreators([]); - } - } else { - setNoteCreators([]); - } - }, [notesToExport, viewType]); + useEffect(() => { + // Calculate the number of active filters for notes + setNotesFilterCount(selectedCreators.length + selectedOrgs.length); + }, [selectedCreators, selectedOrgs]); - // Separate effect to clear selection only when switching away from notes - useEffect(() => { - if (viewType !== "notes" && selectedNoteNames.length > 0) { - setSelectedNoteNames([]); - } - }, [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 => { - if (prevSelectedNames.includes(name)) { - return prevSelectedNames.filter(n => n !== name); - } else { - return [...prevSelectedNames, name]; - } - }); - }; - - 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); + useEffect(() => { + if (viewType === "notes") { + if (notesToExport && notesToExport.length > 0) { + const uniqueNames = [...new Set(notesToExport.map(note => { + const firstName = note.createdBy?.firstName || ""; + const lastName = note.createdBy?.lastName || ""; + return `${firstName} ${lastName}`.trim(); + }).filter(name => name !== ""))]; + setNoteCreators(uniqueNames.sort()); + } else { + setNoteCreators([]); + } + } else { + setNoteCreators([]); } - } - }); + }, [notesToExport, viewType]); - 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 = []; - - if (viewType === "notes") { - if (!notesToExport || notesToExport.length === 0) { - console.warn("No notes to export."); - return; - } - - const decodeHtmlEntities = (html) => { - const textarea = document.createElement("textarea"); - textarea.innerHTML = html; - return textarea.value; - }; - - const cleanNoteText = (html) => { - if (!html) return ""; - const stripped = html.replace(/<[^>]+>/g, ""); - const decoded = decodeHtmlEntities(stripped); - return decoded.replace(/\u00A0/g, " ").replace(/\s+/g, " ").trim(); - }; - - const cleanName = (name) => { - if (!name) return ""; - return name.replace(/\u00A0/g, " ").replace(/\s+/g, " ").trim(); - }; - - dataToExport = notesToExport.map(note => ({ - "Name": cleanName(`${note.createdBy?.firstName || ""} ${note.createdBy?.lastName || ""}`), - "Notes": cleanNoteText(note.note), - "Created At": note.createdAt - ? new Date(note.createdAt).toLocaleString("en-IN") - : "", - "Updated At": note.updatedAt - ? new Date(note.updatedAt).toLocaleString("en-IN") - : "", - "Updated By": cleanName( - `${note.updatedBy?.firstName || ""} ${note.updatedBy?.lastName || ""}` - ), - })); - - } else { - if (!contactsToExport || contactsToExport.length === 0) { - console.warn("No contacts to export."); - return; - } - - dataToExport = contactsToExport.map(contact => ({ - Name: contact.name || '', - Organization: contact.organization || '', - Email: contact.contactEmails?.map(email => email.emailAddress).join(', ') || '', - Phone: contact.contactPhones?.map(phone => phone.phoneNumber).join(', ') || '', - Category: contact.contactCategory?.name || '', - Tags: contact.tags?.map(tag => tag.name).join(', ') || '', - })); - } - - const today = new Date(); - const formattedDate = `${today.getFullYear()}${String(today.getMonth() + 1).padStart(2, '0')}${String(today.getDate()).padStart(2, '0')}`; - - const filename = - viewType === "notes" - ? `Directory_Notes_${formattedDate}` - : `Directory_Contacts_${formattedDate}`; - - switch (type) { - case "csv": - exportToCSV(dataToExport, filename); - break; - case "excel": - exportToExcel(dataToExport, filename); - break; - case "pdf": - exportToPDF(dataToExport, filename); - break; - case "print": - printTable(dataToExport, filename); - break; - default: - break; - } - }; - - 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); - } + // Separate effect to clear selection only when switching away from notes + useEffect(() => { + if (viewType !== "notes" && selectedNoteNames.length > 0) { + setSelectedNoteNames([]); } - }; - extractStrings(noteItem); - stringValues.push(plainNote, creator.toLowerCase()); + }, [viewType]); - const matchesSearch = stringValues.some((val) => val.includes(lowerSearch)); + useEffect(() => { + const creatorsSet = new Set(); + const orgsSet = new Set(); - return matchesCreator && matchesOrg && matchesSearch; - }); + notesForFilter.forEach((note) => { + const creator = `${note.createdBy?.firstName || ""} ${note.createdBy?.lastName || ""}`.trim(); + if (creator) creatorsSet.add(creator); - setFilteredNotes(filtered); - setFilterAppliedNotes(filtered); - }; + const org = note.organizationName; + if (org) orgsSet.add(org); + }); - return ( - <> -
-
-
    -
  • - -
  • -
  • - -
  • -
-
-
-
+ setAllCreators([...creatorsSet].sort()); + setAllOrganizations([...orgsSet].sort()); + setFilteredOrganizations([...orgsSet].sort()); + }, [notesForFilter]) -
-
- setSearchText(e.target.value)} - style={{ width: "200px",height: "30px" }} - /> + const handleToggleNoteName = (name) => { + setSelectedNoteNames(prevSelectedNames => { + if (prevSelectedNames.includes(name)) { + return prevSelectedNames.filter(n => n !== name); + } else { + return [...prevSelectedNames, name]; + } + }); + }; - {/* Filter by funnel icon for Notes view */} - {viewType === "notes" && ( -
- + const updateFilteredOrganizations = () => { + if (selectedCreators.length === 0) { + setFilteredOrganizations(allOrganizations); + return; + } -
-
- {/* Created By */} -
-

Created By

- {allCreators.map((name, idx) => ( -
- handleToggleCreator(name)} - /> - -
- ))} -
+ 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); + } + } + }); - {/* Organization */} -
-

Organization

- {filteredOrganizations.map((org, idx) => ( -
- handleToggleOrg(org)} - /> - -
- ))} -
+ 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); + }; + + const handleExport = (type) => { + let dataToExport = []; + + if (viewType === "notes") { + if (!notesToExport || notesToExport.length === 0) { + console.warn("No notes to export."); + return; + } + + const decodeHtmlEntities = (html) => { + const textarea = document.createElement("textarea"); + textarea.innerHTML = html; + return textarea.value; + }; + + const cleanNoteText = (html) => { + if (!html) return ""; + const stripped = html.replace(/<[^>]+>/g, ""); + const decoded = decodeHtmlEntities(stripped); + return decoded.replace(/\u00A0/g, " ").replace(/\s+/g, " ").trim(); + }; + + const cleanName = (name) => { + if (!name) return ""; + return name.replace(/\u00A0/g, " ").replace(/\s+/g, " ").trim(); + }; + + dataToExport = notesToExport.map(note => ({ + "Name": cleanName(`${note.createdBy?.firstName || ""} ${note.createdBy?.lastName || ""}`), + "Notes": cleanNoteText(note.note), + "Created At": note.createdAt + ? new Date(note.createdAt).toLocaleString("en-IN") + : "", + "Updated At": note.updatedAt + ? new Date(note.updatedAt).toLocaleString("en-IN") + : "", + "Updated By": cleanName( + `${note.updatedBy?.firstName || ""} ${note.updatedBy?.lastName || ""}` + ), + })); + + } else { + if (!contactsToExport || contactsToExport.length === 0) { + console.warn("No contacts to export."); + return; + } + + dataToExport = contactsToExport.map(contact => ({ + Name: contact.name || '', + Organization: contact.organization || '', + Email: contact.contactEmails?.map(email => email.emailAddress).join(', ') || '', + Phone: contact.contactPhones?.map(phone => phone.phoneNumber).join(', ') || '', + Category: contact.contactCategory?.name || '', + Tags: contact.tags?.map(tag => tag.name).join(', ') || '', + })); + } + + const today = new Date(); + const formattedDate = `${today.getFullYear()}${String(today.getMonth() + 1).padStart(2, '0')}${String(today.getDate()).padStart(2, '0')}`; + + const filename = + viewType === "notes" + ? `Directory_Notes_${formattedDate}` + : `Directory_Contacts_${formattedDate}`; + + switch (type) { + case "csv": + exportToCSV(dataToExport, filename); + break; + case "excel": + exportToExcel(dataToExport, filename); + break; + case "pdf": + exportToPDF(dataToExport, filename); + break; + case "print": + printTable(dataToExport, filename); + break; + default: + break; + } + }; + + 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 ( + <> +
+
+
    +
  • + +
  • +
  • + +
  • +
- - {/* Buttons */} -
- - -
-
-
- )} +
+
+
- {(viewType === "card" || viewType === "list") && ( -
+ setSearchText(e.target.value)} + style={{ width: "200px", height: "30px" }} + /> - - -
- )} +
+ {/* Scrollable Filter Content */} +
+
+ {/* Created By */} +
+
+

Created By

+
+ {allCreators.map((name, idx) => ( +
+ handleToggleCreator(name)} + /> + +
+ ))} +
- {/* Filter by funnel icon for Contacts view (retains numerical badge) */} - {viewType !== "notes" && ( -
- + {/* Organization */} +
+
+

Organization

+
+ {filteredOrganizations.map((org, idx) => ( +
+ handleToggleOrg(org)} + /> + +
+ ))} +
+
-
    -

    Filter by

    +
-
-
-

Buckets

-
- {filteredBuckets.map(({ id, name }) => ( -
- handleTempBucketChange(id)} - /> - + {/* Sticky Footer Buttons */} +
+ + +
+
- ))} -
-
-
-

Categories

-
- {filteredCategories.map(({ id, name }) => ( -
- handleTempCategoryChange(id)} - /> - + )} + + + {(viewType === "card" || viewType === "list") && ( +
+ + +
- ))} + )} + + {/* Filter by funnel icon for Contacts view (retains numerical badge) */} + {viewType !== "notes" && ( +
+ + +
    +

    Filter by

    + +
    +
    +

    Buckets

    +
    + {filteredBuckets.map(({ id, name }) => ( +
    + handleTempBucketChange(id)} + /> + +
    + ))} +
    +
    +
    +

    Categories

    +
    + {filteredCategories.map(({ id, name }) => ( +
    + handleTempCategoryChange(id)} + /> + +
    + ))} +
    +
    +
    + +
    + + +
    +
+
+ )} +
+ +
+ {(viewType === "list" || viewType === "card") && ( + + )} + + -
-
-
- -
-
- )} -
- -
- {(viewType === "list" || viewType === "card") && ( - - )} - - - -
-
- - ); + + ); }; export default DirectoryPageHeader; \ No newline at end of file