2025-05-26 12:52:17 +05:30

386 lines
13 KiB
JavaScript

import React, { useEffect, useMemo, useState } from "react";
import Breadcrumb from "../../components/common/Breadcrumb";
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 { useBuckets, useDirectory } from "../../hooks/useDirectory";
import { DirectoryRepository } from "../../repositories/DirectoryRepository";
import { cacheData, getCachedData } from "../../slices/apiDataManager";
import showToast from "../../services/toastService";
import UpdateContact from "../../components/Directory/UpdateContact";
import CardViewDirectory from "../../components/Directory/CardViewDirectory";
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";
import DirectoryListTableHeader from "./DirectoryListTableHeader";
import DirectoryPageHeader from "./DirectoryPageHeader";
import ManageBucket from "../../components/Directory/ManageBucket";
const Directory = () =>
{
const[IsActive,setIsActive] = useState(true)
const [isOpenModal, setIsOpenModal] = useState(false);
const [isOpenModalNote, setIsOpenModalNote] = useState(false);
const [selectedContact, setSelectedContact] = useState(null);
const [open_contact, setOpen_contact] = useState(null);
const [ContactList, setContactList] = useState([]);
const [contactCategories, setContactCategories] = useState([]);
const [searchText, setSearchText] = useState("");
const [listView, setListView] = useState(false);
const [selectedBucketIds, setSelectedBucketIds] = useState([]);
const [deleteContact, setDeleteContact] = useState(null);
const [ IsDeleting, setIsDeletng ] = useState( false );
const [openBucketModal,setOpenBucketModal] = useState(false)
const [tempSelectedBucketIds, setTempSelectedBucketIds] = useState([]);
const [tempSelectedCategoryIds, setTempSelectedCategoryIds] = useState([]);
const { contacts, loading } = useDirectory(IsActive);
const { contactCategory, loading: contactCategoryLoading } =
useContactCategory();
const {buckets} = useBuckets();
const submitContact = async (data) => {
try {
let response;
let updatedContacts;
const contacts_cache = getCachedData("contacts")?.data || [];
if (selectedContact) {
response = await DirectoryRepository.UpdateContact(data.id, data);
updatedContacts = contacts_cache.map((contact) =>
contact.id === data.id ? response.data : contact
);
showToast("Contact updated successfully", "success");
setIsOpenModal(false);
setSelectedContact(null);
} else {
response = await DirectoryRepository.CreateContact(data);
updatedContacts = [...contacts_cache, response.data];
showToast("Contact created successfully", "success");
setIsOpenModal(false);
}
cacheData("Contacts", {data:updatedContacts,isActive:IsActive});
setContactList(updatedContacts);
} catch (error) {
const msg =
error.response?.data?.message ||
error.message ||
"Error occurred during API call!";
showToast(msg, "error");
}
};
const handleDeleteContact = async () => {
try {
setIsDeletng(true);
const contacts_cache = getCachedData("contacts")?.data || [];
const response = await DirectoryRepository.DeleteContact(deleteContact);
const updatedContacts = ContactList.filter((c) => c.id !== deleteContact);
setContactList(updatedContacts);
cacheData("Contacts", {data:updatedContacts,isActive:IsActive});
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);
};
const [selectedCategoryIds, setSelectedCategoryIds] = useState(
contactCategory.map((category) => category.id)
);
useEffect(() => {
setContactList(contacts);
setTempSelectedCategoryIds([]);
setTempSelectedBucketIds([]);
}, [contacts]);
const usedCategoryIds = [
...new Set(contacts.map((c) => c.contactCategory?.id)),
];
const filteredCategories = contactCategory.filter((category) =>
usedCategoryIds.includes(category.id)
);
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 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 applyFilter = () => {
setSelectedBucketIds(tempSelectedBucketIds);
setSelectedCategoryIds(tempSelectedCategoryIds);
};
const clearFilter = () => {
setTempSelectedBucketIds([]);
setTempSelectedCategoryIds([]);
setSelectedBucketIds([]);
setSelectedCategoryIds([]);
};
const { currentPage, totalPages, currentItems, paginate } = usePagination(
filteredContacts,
ITEMS_PER_PAGE
);
const renderModalContent = () => {
if (selectedContact) {
return (
<UpdateContact
existingContact={selectedContact}
submitContact={submitContact}
onCLosed={closedModel}
/>
);
}
if (!open_contact) {
return (
<ManageDirectory submitContact={submitContact} onCLosed={closedModel} />
);
}
};
return (
<div className="container-xxl flex-grow-1 container-p-y">
<Breadcrumb
data={[
{ label: "Home", link: "/dashboard" },
{ label: "Directory", link: null },
]}
></Breadcrumb>
{isOpenModal && (
<GlobalModel
isOpen={isOpenModal}
closeModal={() => {
setSelectedContact(null);
setIsOpenModal(false);
}}
size="lg"
>
{renderModalContent()}
</GlobalModel>
)}
{isOpenModalNote && (
<GlobalModel
isOpen={isOpenModalNote}
closeModal={() => {
setOpen_contact(null);
setIsOpenModalNote(false);
}}
size="lg"
>
{open_contact && (
<ProfileContactDirectory
contact={open_contact}
setOpen_contact={setOpen_contact}
closeModal={() => setIsOpenModalNote(false)}
/>
)}
</GlobalModel>
)}
{deleteContact && (
<div
className={`modal fade ${deleteContact ? "show" : ""}`}
tabIndex="-1"
role="dialog"
style={{
display: deleteContact ? "block" : "none",
backgroundColor: deleteContact ? "rgba(0,0,0,0.5)" : "transparent",
}}
aria-hidden="false"
>
<ConfirmModal
type={"delete"}
header={"Delete Contact"}
message={"Are you sure you want delete?"}
onSubmit={handleDeleteContact}
onClose={() => setDeleteContact(null)}
loading={IsDeleting}
/>
</div>
)}
{openBucketModal && (
<GlobalModel
isOpen={openBucketModal}
closeModal={() =>setOpenBucketModal(false)}
size="lg"
>
<ManageBucket buckets={buckets} />
</GlobalModel>
)}
<div className="card p-2">
<DirectoryPageHeader
searchText={searchText}
setSearchText={setSearchText}
setIsActive={setIsActive}
listView={listView}
setListView={setListView}
filteredBuckets={filteredBuckets}
tempSelectedBucketIds={tempSelectedBucketIds}
handleTempBucketChange={handleTempBucketChange}
filteredCategories={filteredCategories}
tempSelectedCategoryIds={tempSelectedCategoryIds}
handleTempCategoryChange={handleTempCategoryChange}
clearFilter={clearFilter}
applyFilter={applyFilter}
loading={loading}
IsActive={IsActive}
setIsOpenModal={setIsOpenModal}
setOpenBucketModal={setOpenBucketModal}
/>
{!listView && loading && <p>Loading...</p>}
{!listView && !loading && currentItems.length == 0 && (
<p>No Matching Contact Found</p>
)}
{listView ? (
<DirectoryListTableHeader IsActive={IsActive}>
{loading && (
<tr>
<td colSpan={10}>Loading...</td>
</tr>
)}
{!loading && currentItems.length === 0 && (
<tr>
<td colSpan={10}>No Matching Contact Found</td>
</tr>
)}
{!loading &&
currentItems.map((contact) => (
<ListViewDirectory
key={contact.id}
IsActive={IsActive}
contact={contact}
setSelectedContact={setSelectedContact}
setIsOpenModal={setIsOpenModal}
setOpen_contact={setOpen_contact}
setIsOpenModalNote={setIsOpenModalNote}
IsDeleted={setDeleteContact}
/>
))}
</DirectoryListTableHeader>
) : (
<div className="row">
{!loading && currentItems.map((contact, index) => (
<div
key={contact.id}
className="col-12 col-sm-6 col-md-4 col-lg-4 mb-4"
>
<CardViewDirectory
IsActive={IsActive}
contact={contact}
setSelectedContact={setSelectedContact}
setIsOpenModal={setIsOpenModal}
setOpen_contact={setOpen_contact}
setIsOpenModalNote={setIsOpenModalNote}
IsDeleted={setDeleteContact}
/>
</div>
))}
</div>
)}
{!loading && currentItems < ITEMS_PER_PAGE && (
<nav aria-label="Page ">
<ul className="pagination pagination-sm justify-content-end py-1">
<li
className={`page-item ${currentPage === 1 ? "disabled" : ""}`}
>
<button
className="page-link btn-xs"
onClick={() => paginate(currentPage - 1)}
>
&laquo;
</button>
</li>
{[...Array(totalPages)].map((_, index) => (
<li
key={index}
className={`page-item ${
currentPage === index + 1 ? "active" : ""
}`}
>
<button
className="page-link "
onClick={() => paginate(index + 1)}
>
{index + 1}
</button>
</li>
))}
<li
className={`page-item ${
currentPage === totalPages ? "disabled" : ""
}`}
>
<button
className="page-link "
onClick={() => paginate(currentPage + 1)}
>
&raquo;
</button>
</li>
</ul>
</nav>
)}
</div>
</div>
);
};
export default Directory;