diff --git a/src/components/Directory/CardViewDirectory.jsx b/src/components/Directory/CardViewDirectory.jsx index 9f7128a0..a18f0f18 100644 --- a/src/components/Directory/CardViewDirectory.jsx +++ b/src/components/Directory/CardViewDirectory.jsx @@ -1,7 +1,11 @@ import React from "react"; import Avatar from "../common/Avatar"; - -const CardViewDirectory = ({ contact, setSelectedContact, setIsOpenModal,setOpen_contact,setIsOpenModalNote }) => { +import {getBucketNameById} from "./DirectoryUtils"; +import {useBuckets} from "../../hooks/useDirectory"; +import { getPhoneIcon } from "./DirectoryUtils"; +const CardViewDirectory = ( {contact, setSelectedContact, setIsOpenModal, setOpen_contact, setIsOpenModalNote, IsDeleted} ) => +{ + const {buckets} = useBuckets() return (
@@ -48,7 +52,7 @@ const CardViewDirectory = ({ contact, setSelectedContact, setIsOpenModal,setOpen
  • - + IsDeleted(contact.id)}> Delete @@ -87,7 +91,7 @@ const CardViewDirectory = ({ contact, setSelectedContact, setIsOpenModal,setOpen {contact.contactPhones[0] && (
    • - +
    • {contact.contactPhones[0]?.phoneNumber} @@ -103,6 +107,20 @@ const CardViewDirectory = ({ contact, setSelectedContact, setIsOpenModal,setOpen {contact.contactCategory.name}
    + +
      + {contact.bucketIds.map( ( bucketId ) => ( + <> + +
    • + +
    • +
    • + {getBucketNameById(buckets,bucketId)} +
    • + ))} + +
  • ); diff --git a/src/components/Directory/DirectoryUtils.js b/src/components/Directory/DirectoryUtils.js new file mode 100644 index 00000000..7dc436be --- /dev/null +++ b/src/components/Directory/DirectoryUtils.js @@ -0,0 +1,26 @@ +import {useBuckets} from "../../hooks/useDirectory"; + +export const getEmailIcon = (type) => { + switch (type) { + case 'Work': return "bx bx-briefcase me-1 " ; + case 'Personal': return "bx bx-user me-1"; + case 'support': return "bx headphone-mic me-1"; + case 'billing': return "bx bx-receipt me-1"; + default: return "bx bx-envelope me-1"; + } +}; + +export const getPhoneIcon = (type) => { + switch (type) { + case 'Business': return "bx bx-phone me-1 "; + case 'Personal': return "bx bx-mobile me-1 "; + case 'Office': return "bx bx-phone me-1 "; + default: return "bx bx-phone me-1"; + } +}; + + +export const getBucketNameById = (buckets, id) => { + const bucket = buckets.find(b => b.id === id); + return bucket ? bucket.name : 'Unknown'; +}; diff --git a/src/components/Directory/ListViewDirectory.jsx b/src/components/Directory/ListViewDirectory.jsx index 538bdd3a..b9356f23 100644 --- a/src/components/Directory/ListViewDirectory.jsx +++ b/src/components/Directory/ListViewDirectory.jsx @@ -1,33 +1,16 @@ import React from 'react' import Avatar from '../common/Avatar'; +import { getEmailIcon,getPhoneIcon } from './DirectoryUtils'; -const getEmailIcon = (type) => { - switch (type) { - case 'work': return "bx bx-briefcase me-1 " ; - case 'personal': return "bx bx-user me-1"; - case 'support': return "bxr headphone-mic me-1"; - case 'billing': return "bx bx-receipt me-1"; - default: return "bx bx-envelope me-1"; - } -}; -const getPhoneIcon = (type) => { - switch (type) { - case 'business': return "bx bx-briefcase me-1 "; - case 'home': return "bx bx-mobile me-1 "; - case 'personal': return "bx bx-user me-1 "; - case 'landline': return "bx bx-phone me-1 "; - case 'fax': return "bx bx-printer me-1"; - case 'whatsapp': return "bxl-whatsapp me-1"; - case 'emergency': return "bx bx-error-circle me-1"; - default: return "bx bx-phone me-1"; - } -}; - -const ListViewDirectory = ({ contact,setSelectedContact,setIsOpenModal}) => { +const ListViewDirectory = ({ contact,setSelectedContact,setIsOpenModal,setOpen_contact,setIsOpenModalNote,IsDeleted}) => { return ( - + + { + setIsOpenModalNote(true) + setOpen_contact(contact) + }}>
    { setSelectedContact( contact ) setIsOpenModal(true) }}> - + IsDeleted(contact.id)}> ); diff --git a/src/components/Directory/NoteCardDirectory.jsx b/src/components/Directory/NoteCardDirectory.jsx index a7020732..71ef9843 100644 --- a/src/components/Directory/NoteCardDirectory.jsx +++ b/src/components/Directory/NoteCardDirectory.jsx @@ -120,7 +120,11 @@ const NoteCardDirectory = ({ noteItem, contactId, setProfileContact }) => { {noteItem.createdBy.firstName} {noteItem.createdBy.lastName} - {moment(noteItem.createdAt).format("MMMM DD, YYYY [at] hh:mm A")} + {moment + .utc(noteItem.createdAt) + .add(5, "hours") + .add(30, "minutes") + .format("MMMM DD, YYYY [at] hh:mm A")}
    diff --git a/src/components/Directory/NotesDirectory.jsx b/src/components/Directory/NotesDirectory.jsx index c92713c5..ba4c1b31 100644 --- a/src/components/Directory/NotesDirectory.jsx +++ b/src/components/Directory/NotesDirectory.jsx @@ -83,27 +83,19 @@ const NotesDirectory = ({ isLoading, contactProfile, setProfileContact }) => { return (
    -
    0 - ? "d-flex justify-content-between" - : "d-flex justify-content-end" - }`} - > - {contactProfile?.notes.length > 0 && ( -

    Notes :

    - )} - setAddNote(!addNote)} +
    +

    Notes :

    + setAddNote( !addNote )} > - - {addNote ? "" : "Add Note"} - {" "} - {" "} -
    + {/* */} + {addNote ? "close" : "Add Note"} +
    {addNote && (
    @@ -119,10 +111,7 @@ const NotesDirectory = ({ isLoading, contactProfile, setProfileContact }) => { )}
    )} -
    +
    {isLoading && (
    {" "} @@ -139,7 +128,8 @@ const NotesDirectory = ({ isLoading, contactProfile, setProfileContact }) => { setProfileContact={setProfileContact} key={noteItem.id} /> - ))} + ) )} +

    {!isLoading && contactProfile?.notes.length == 0 && !addNote && (

    No Notes Found

    ) }

    ); diff --git a/src/pages/Directory/Directory.jsx b/src/pages/Directory/Directory.jsx index 8ec2c23e..dfbcbb81 100644 --- a/src/pages/Directory/Directory.jsx +++ b/src/pages/Directory/Directory.jsx @@ -6,7 +6,7 @@ import ManageDirectory from "../../components/Directory/ManageDirectory"; import ListViewDirectory from "../../components/Directory/ListViewDirectory"; import { useBuckets, useDirectory } from "../../hooks/useDirectory"; import { DirectoryRepository } from "../../repositories/DirectoryRepository"; -import { getCachedData } from "../../slices/apiDataManager"; +import { cacheData, getCachedData } from "../../slices/apiDataManager"; import showToast from "../../services/toastService"; import UpdateContact from "../../components/Directory/UpdateContact"; import CardViewDirectory from "../../components/Directory/CardViewDirectory"; @@ -14,6 +14,7 @@ import { useContactCategory } from "../../hooks/masterHook/useMaster"; import usePagination from "../../hooks/usePagination"; import { ITEMS_PER_PAGE } from "../../utils/constants"; import ProfileContactDirectory from "../../components/Directory/ProfileContactDirectory"; +import ConfirmModal from "../../components/common/ConfirmModal"; const Directory = () => { const [isOpenModal, setIsOpenModal] = useState(false); @@ -25,6 +26,11 @@ const Directory = () => { const [searchText, setSearchText] = useState(""); const [listView, setListView] = useState(false); const [selectedBucketIds, setSelectedBucketIds] = useState([]); + const [deleteContact, setDeleteContact] = useState(null); + const [IsDeleting, setIsDeletng] = useState(false); + + const [tempSelectedBucketIds, setTempSelectedBucketIds] = useState([]); + const [tempSelectedCategoryIds, setTempSelectedCategoryIds] = useState([]); const { contacts, loading } = useDirectory(); const { contactCategory, loading: contactCategoryLoading } = @@ -61,36 +67,64 @@ const Directory = () => { } }; + const handleDeleteContact = async () => { + try { + setIsDeletng(true); + const contacts_cache = getCachedData("contacts") || []; + + const response = await DirectoryRepository.DeleteContact(deleteContact); + const updatedContacts = ContactList.filter((c) => c.id !== deleteContact); + setContactList(updatedContacts); + cacheData("Contacts", updatedContacts); + showToast("Contact deleted successfully", "success"); + setDeleteContact(null); + + setIsDeletng(false); + } catch (error) { + const msg = + error.response.data.message || + error.message || + "Error occured during API calling"; + showToast(msg, "error"); + setIsDeletng(false); + } + }; + const closedModel = () => { setIsOpenModal(false); setSelectedContact(null); setOpen_contact(null); }; - useEffect(() => { - setContactList(contacts); - }, [contacts]); - const [selectedCategoryIds, setSelectedCategoryIds] = useState( contactCategory.map((category) => category.id) ); + useEffect(() => { + setContactList(contacts); + + // Set temp filter list only (UI checkboxes, not actual filtering yet) + setTempSelectedCategoryIds([]); + setTempSelectedBucketIds([]); + }, [contacts]); + const usedCategoryIds = [ ...new Set(contacts.map((c) => c.contactCategory?.id)), ]; const filteredCategories = contactCategory.filter((category) => usedCategoryIds.includes(category.id) ); - const handleCategoryChange = (id) => { - setSelectedCategoryIds((prev) => + const handleTempBucketChange = (id) => { + setTempSelectedBucketIds((prev) => + prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id] + ); + }; + + const handleTempCategoryChange = (id) => { + setTempSelectedCategoryIds((prev) => prev.includes(id) ? prev.filter((cid) => cid !== id) : [...prev, id] ); }; - const handleBucketChange = (id) => { - setSelectedBucketIds((prev) => - prev.includes(id) ? prev.filter((bid) => bid !== id) : [...prev, id] - ); - }; const usedBucketIds = [ ...new Set(contacts.flatMap((c) => c.bucketIds || [])), ]; @@ -117,6 +151,18 @@ const Directory = () => { }).sort((a, b) => a.name.localeCompare(b.name)); }, [ContactList, searchText, selectedCategoryIds, selectedBucketIds]); + const applyFilter = () => { + setSelectedBucketIds(tempSelectedBucketIds); + setSelectedCategoryIds(tempSelectedCategoryIds); + }; + + const clearFilter = () => { + setTempSelectedBucketIds([]); + setTempSelectedCategoryIds([]); + setSelectedBucketIds([]); + setSelectedCategoryIds([]); + }; + const { currentPage, totalPages, currentItems, paginate } = usePagination( filteredContacts, ITEMS_PER_PAGE @@ -145,7 +191,7 @@ const Directory = () => { @@ -179,6 +225,28 @@ const Directory = () => { )} )} + {deleteContact && ( +
    + setDeleteContact(null)} + loading={IsDeleting} + /> +
    + )} +
    @@ -219,69 +287,108 @@ const Directory = () => {
    -
    - -
      -

      Filter by

      -
      - {/* Bucket Filter */} -
      -

      Buckets

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

      Categories

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

        Filter by

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

        Buckets

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

        Categories

        +
        + {filteredCategories.map(({ id, name }) => ( +
        + handleTempCategoryChange(id)} + /> + +
        + ))} +
        +
        + +
        + + +
        -
      -
    + +
    -
    +
    {!listView && loading &&

    Loading...

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

    Not Found Contact

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

    No Matching Contact Found

    + )} {listView ? (
    @@ -343,10 +452,7 @@ const Directory = () => { - + @@ -355,13 +461,12 @@ const Directory = () => { )} - {!loading && - currentItems.length === 0 && ( - - - - )} - + {!loading && currentItems.length === 0 && ( + + + + )} + {!loading && currentItems.map((contact) => ( { contact={contact} setSelectedContact={setSelectedContact} setIsOpenModal={setIsOpenModal} + setOpen_contact={setOpen_contact} + setIsOpenModalNote={setIsOpenModalNote} + IsDeleted={setDeleteContact} /> ))} @@ -387,13 +495,14 @@ const Directory = () => { setIsOpenModal={setIsOpenModal} setOpen_contact={setOpen_contact} setIsOpenModalNote={setIsOpenModalNote} + IsDeleted={setDeleteContact} /> ))} )} - {!loading && ( + {!loading && currentItems < ITEMS_PER_PAGE && (
    Category - Action - Action
    Loading...
    Not Found Contact
    No Matching Contact Found