From cb5cacaee05b45005b927c4cb01147d8a03063e2 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 21 May 2025 17:44:17 +0530 Subject: [PATCH 1/2] added filtering by category and buckets --- src/pages/Directory/Directory.jsx | 110 ++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 30 deletions(-) diff --git a/src/pages/Directory/Directory.jsx b/src/pages/Directory/Directory.jsx index 6e00e720..d66e8651 100644 --- a/src/pages/Directory/Directory.jsx +++ b/src/pages/Directory/Directory.jsx @@ -4,7 +4,7 @@ import IconButton from "../../components/common/IconButton"; import GlobalModel from "../../components/common/GlobalModel"; import ManageDirectory from "../../components/Directory/ManageDirectory"; import ListViewDirectory from "../../components/Directory/ListViewDirectory"; -import { useDirectory } from "../../hooks/useDirectory"; +import { useBuckets, useDirectory } from "../../hooks/useDirectory"; import { DirectoryRepository } from "../../repositories/DirectoryRepository"; import { getCachedData } from "../../slices/apiDataManager"; import showToast from "../../services/toastService"; @@ -20,14 +20,17 @@ const Directory = () => { const [isOpenModalNote, setIsOpenModalNote] = useState(false); const [selectedContact, setSelectedContact] = useState(null); const [open_contact, setOpen_contact] = useState(null); - const [ContatList, setContactList] = useState([]); + const [ContactList, setContactList] = useState([]); const [contactCategories, setContactCategories] = useState([]); const [searchText, setSearchText] = useState(""); - const [listView, setListView] = useState(false); + const [ listView, setListView ] = useState( false ); + const [selectedBucketIds, setSelectedBucketIds] = useState([]); + const { contacts, loading } = useDirectory(); const { contactCategory, loading: contactCategoryLoading } = useContactCategory(); + const {buckets} = useBuckets() const submitContact = async (data) => { try { let response; @@ -83,17 +86,38 @@ const Directory = () => { prev.includes(id) ? prev.filter((cid) => cid !== id) : [...prev, id] ); }; - const filteredContacts = useMemo(() => { - return ContatList.filter((c) => { - const matchesSearch = - c.name.toLowerCase().includes(searchText.toLowerCase()) || - c.organization.toLowerCase().includes(searchText.toLowerCase()); - const matchesCategory = - selectedCategoryIds.length === 0 || - selectedCategoryIds.includes(c.contactCategory?.id); - return matchesSearch && matchesCategory; - }).sort((a, b) => a.name.localeCompare(b.name)); - }, [ContatList, searchText, selectedCategoryIds]); + + const handleBucketChange = (id) => { + setSelectedBucketIds((prev) => + prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id] + ); +}; +const usedBucketIds = [ + ...new Set(contacts.flatMap((c) => c.bucketIds || [])), +]; + +const filteredBuckets = buckets.filter((bucket) => + usedBucketIds.includes(bucket.id) +); + +const filteredContacts = useMemo(() => { + return ContactList.filter((c) => { + const matchesSearch = + c.name.toLowerCase().includes(searchText.toLowerCase()) || + c.organization.toLowerCase().includes(searchText.toLowerCase()); + + const matchesCategory = + selectedCategoryIds.length === 0 || + selectedCategoryIds.includes(c.contactCategory?.id); + + const matchesBucket = + selectedBucketIds.length === 0 || + (c.bucketIds || []).some((id) => selectedBucketIds.includes(id)); + + return matchesSearch && matchesCategory && matchesBucket; + }).sort((a, b) => a.name.localeCompare(b.name)); +}, [ContactList, searchText, selectedCategoryIds, selectedBucketIds]); + const { currentPage, totalPages, currentItems, paginate } = usePagination( filteredContacts, ITEMS_PER_PAGE @@ -201,22 +225,48 @@ const Directory = () => { + + +

Apply Bucket Filter

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

    Apply Category Filter

    + {filteredCategories.map(({ id, name }) => ( +
  • +
    + handleCategoryChange(id)} + /> + +
    +
  • + ))} + + + + + -- 2.43.0 From 228c178acf2975f3c2d93a31c6f9ed464fd75b58 Mon Sep 17 00:00:00 2001 From: Pramod Mahajan Date: Wed, 21 May 2025 18:18:49 +0530 Subject: [PATCH 2/2] add side-by-side filtering UI for Buckets and Categories with flex layout --- src/pages/Directory/Directory.jsx | 177 ++++++++++++++++-------------- 1 file changed, 93 insertions(+), 84 deletions(-) diff --git a/src/pages/Directory/Directory.jsx b/src/pages/Directory/Directory.jsx index d66e8651..8ec2c23e 100644 --- a/src/pages/Directory/Directory.jsx +++ b/src/pages/Directory/Directory.jsx @@ -23,14 +23,13 @@ const Directory = () => { const [ContactList, setContactList] = useState([]); const [contactCategories, setContactCategories] = useState([]); const [searchText, setSearchText] = useState(""); - const [ listView, setListView ] = useState( false ); + const [listView, setListView] = useState(false); const [selectedBucketIds, setSelectedBucketIds] = useState([]); - const { contacts, loading } = useDirectory(); const { contactCategory, loading: contactCategoryLoading } = useContactCategory(); - const {buckets} = useBuckets() + const { buckets } = useBuckets(); const submitContact = async (data) => { try { let response; @@ -88,35 +87,35 @@ const Directory = () => { }; const handleBucketChange = (id) => { - setSelectedBucketIds((prev) => - prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id] + setSelectedBucketIds((prev) => + prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id] + ); + }; + const usedBucketIds = [ + ...new Set(contacts.flatMap((c) => c.bucketIds || [])), + ]; + + const filteredBuckets = buckets.filter((bucket) => + usedBucketIds.includes(bucket.id) ); -}; -const usedBucketIds = [ - ...new Set(contacts.flatMap((c) => c.bucketIds || [])), -]; -const filteredBuckets = buckets.filter((bucket) => - usedBucketIds.includes(bucket.id) -); + const filteredContacts = useMemo(() => { + return ContactList.filter((c) => { + const matchesSearch = + c.name.toLowerCase().includes(searchText.toLowerCase()) || + c.organization.toLowerCase().includes(searchText.toLowerCase()); -const filteredContacts = useMemo(() => { - return ContactList.filter((c) => { - const matchesSearch = - c.name.toLowerCase().includes(searchText.toLowerCase()) || - c.organization.toLowerCase().includes(searchText.toLowerCase()); + const matchesCategory = + selectedCategoryIds.length === 0 || + selectedCategoryIds.includes(c.contactCategory?.id); - const matchesCategory = - selectedCategoryIds.length === 0 || - selectedCategoryIds.includes(c.contactCategory?.id); + const matchesBucket = + selectedBucketIds.length === 0 || + (c.bucketIds || []).some((id) => selectedBucketIds.includes(id)); - const matchesBucket = - selectedBucketIds.length === 0 || - (c.bucketIds || []).some((id) => selectedBucketIds.includes(id)); - - return matchesSearch && matchesCategory && matchesBucket; - }).sort((a, b) => a.name.localeCompare(b.name)); -}, [ContactList, searchText, selectedCategoryIds, selectedBucketIds]); + return matchesSearch && matchesCategory && matchesBucket; + }).sort((a, b) => a.name.localeCompare(b.name)); + }, [ContactList, searchText, selectedCategoryIds, selectedBucketIds]); const { currentPage, totalPages, currentItems, paginate } = usePagination( filteredContacts, @@ -153,10 +152,9 @@ const filteredContacts = useMemo(() => { {isOpenModal && ( - { - setSelectedContact(null) - setIsOpenModal(false) + closeModal={() => { + setSelectedContact(null); + setIsOpenModal(false); }} size="lg" > @@ -166,14 +164,19 @@ const filteredContacts = useMemo(() => { {isOpenModalNote && ( - { - setOpen_contact(null) - setIsOpenModalNote(false) + closeModal={() => { + setOpen_contact(null); + setIsOpenModalNote(false); }} size="lg" > - {open_contact && setIsOpenModalNote(false)} />} + {open_contact && ( + setIsOpenModalNote(false)} + /> + )} )}
    @@ -224,49 +227,57 @@ const filteredContacts = useMemo(() => { > -
      - - -

      Apply Bucket Filter

      - {filteredBuckets.map(({ id, name }) => ( -
    • -
      - handleBucketChange(id)} - /> - -
      -
    • - ) )} -
      -

      Apply Category Filter

      - {filteredCategories.map(({ id, name }) => ( -
    • -
      - handleCategoryChange(id)} - /> - -
      -
    • - ))} - - - -
    +
      +

      Filter by

      +
      + {/* Bucket Filter */} +
      +

      Buckets

      + {filteredBuckets.map(({ id, name }) => ( +
      + handleBucketChange(id)} + /> + +
      + ))} +
      + {/* Category Filter */} +
      +

      Categories

      + {filteredCategories.map(({ id, name }) => ( +
      + handleCategoryChange(id)} + /> + +
      + ))} +
      +
      +
    @@ -282,6 +293,7 @@ const filteredContacts = useMemo(() => { {!listView && loading &&

    Loading...

    } + {!listView && !loading && currentItems.length == 0 &&

    Not Found Contact

    } {listView ? (
    @@ -332,9 +344,6 @@ const filteredContacts = useMemo(() => { @@ -347,12 +356,12 @@ const filteredContacts = useMemo(() => { )} {!loading && - contacts.length == 0 && - ContatList.length === 0 && ( + currentItems.length === 0 && ( - + )} + {!loading && currentItems.map((contact) => (
    Category Action
    No Contact FoundNot Found Contact