From b113675cc2f45542756c15e97ed6e9a39de524d3 Mon Sep 17 00:00:00 2001 From: pramod mahajan Date: Wed, 10 Sep 2025 00:07:34 +0530 Subject: [PATCH] contact Active and InActive refactored --- src/components/Directory/CardViewContact.jsx | 53 ++-- src/components/Directory/ListViewContact.jsx | 75 +++++- src/components/Directory/ManageContact.jsx | 247 ++++++++++--------- src/hooks/useDirectory.js | 47 +++- src/pages/Directory/DirectoryPage.jsx | 15 +- src/repositories/DirectoryRepository.jsx | 13 +- 6 files changed, 292 insertions(+), 158 deletions(-) diff --git a/src/components/Directory/CardViewContact.jsx b/src/components/Directory/CardViewContact.jsx index 7df4ec23..4fa2fc6c 100644 --- a/src/components/Directory/CardViewContact.jsx +++ b/src/components/Directory/CardViewContact.jsx @@ -1,10 +1,11 @@ -import React from "react"; +import React, { useState } from "react"; import Avatar from "../common/Avatar"; import { getBucketNameById } from "./DirectoryUtils"; -import { useBuckets } from "../../hooks/useDirectory"; +import { useActiveInActiveContact, useBuckets } from "../../hooks/useDirectory"; import { getPhoneIcon } from "./DirectoryUtils"; import { useDir } from "../../Context/DireContext"; import { useDirectoryContext } from "../../pages/Directory/DirectoryPage"; +import ConfirmModal from "../common/ConfirmModal"; const CardViewContact = ({ IsActive, contact, @@ -15,10 +16,39 @@ const CardViewContact = ({ IsDeleted, restore, }) => { - const { data } = useDirectoryContext(); - const { dirActions, setDirActions } = useDir(); + const { data , setManageContact} = useDirectoryContext(); + const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const {mutate:ActiveInActive,isPending} = useActiveInActiveContact() + const handleActiveInactive = (contactId) => { + ActiveInActive({ contactId, contactStatus: !IsActive }); +}; +const {dirActions} = useDir() return ( + <> + {IsDeleteModalOpen && ( +
+ setIsDeleteModalOpen(false)} + loading={isPending} + paramData={contact.id} + /> +
+ )} +
@@ -197,6 +221,7 @@ const CardViewContact = ({ + ); }; diff --git a/src/components/Directory/ListViewContact.jsx b/src/components/Directory/ListViewContact.jsx index f36738e2..d41eea5e 100644 --- a/src/components/Directory/ListViewContact.jsx +++ b/src/components/Directory/ListViewContact.jsx @@ -1,8 +1,15 @@ -import React from "react"; +import React, { useState } from "react"; import Avatar from "../common/Avatar"; import Pagination from "../common/Pagination"; +import { useDirectoryContext } from "../../pages/Directory/DirectoryPage"; +import { useActiveInActiveContact } from "../../hooks/useDirectory"; +import ConfirmModal from "../common/ConfirmModal"; const ListViewContact = ({ data, Pagination }) => { + const { showActive, setManageContact } = useDirectoryContext(); + const [deleteContact,setDeleteContact] = useState({contactId:null,Open:false}) + const [activeContact,setActiveContact] = useState(null) + const contactList = [ { key: "name", @@ -66,7 +73,36 @@ const ListViewContact = ({ data, Pagination }) => { }, ]; + const { mutate: ActiveInActive, isPending } = useActiveInActiveContact(()=>setDeleteContact({contactId:null,Open:false})); + + const handleActiveInactive = (contactId) => { + ActiveInActive({ contactId: contactId, contactStatus: !showActive }); + }; + return ( + <> + {deleteContact.Open && ( +
+ setDeleteContact({contactId:null,Open:false})} + loading={isPending} + paramData={deleteContact.contactId} + /> +
+ )}
@@ -86,20 +122,44 @@ const ListViewContact = ({ data, Pagination }) => { {Array.isArray(data) && data.length > 0 ? ( data.map((row, i) => ( - + {contactList.map((col) => ( {col.getValue(row)} ))} -
- + {showActive ? ( +
+ - + + setManageContact({ + isOpen: true, + contactId: row.id, + }) + } + > - -
+ setDeleteContact({contactId:row.id,Open:true})}> +
+ ) : ( + { + setActiveContact(row.id) + handleActiveInactive(row.id) + }} + > + )} )) @@ -118,6 +178,7 @@ const ListViewContact = ({ data, Pagination }) => {
+ ); }; diff --git a/src/components/Directory/ManageContact.jsx b/src/components/Directory/ManageContact.jsx index 161397dc..c4b05847 100644 --- a/src/components/Directory/ManageContact.jsx +++ b/src/components/Directory/ManageContact.jsx @@ -1,50 +1,45 @@ import React, { useEffect, useState } from "react"; -import { - useForm, - useFieldArray, - FormProvider, - useFormContext, -} from "react-hook-form"; +import { useForm, useFieldArray, FormProvider } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import TagInput from "../common/TagInput"; -import IconButton from "../common/IconButton"; -import useMaster, { - useContactCategory, - useContactTags, -} from "../../hooks/masterHook/useMaster"; -import { useDispatch, useSelector } from "react-redux"; -import { changeMaster } from "../../slices/localVariablesSlice"; import { useBuckets, + useContactDetails, useCreateContact, useDesignation, useOrganization, + useUpdateContact, } from "../../hooks/useDirectory"; import { useProjects } from "../../hooks/useProjects"; +import { + useContactCategory, + useContactTags, +} from "../../hooks/masterHook/useMaster"; import SelectMultiple from "../common/SelectMultiple"; import { ContactSchema, defaultContactValue } from "./DirectorySchema"; import InputSuggestions from "../common/InputSuggestion"; import Label from "../common/Label"; -const ManageContact = ({ submitContact, onCLosed }) => { - const selectedMaster = useSelector( - (store) => store.localVariables.selectedMaster - ); - const [categoryData, setCategoryData] = useState([]); - - const [TagsData, setTagsData] = useState([]); - const { data, loading } = useMaster(); +const ManageContact = ({ contactId, closeModal }) => { + // fetch master data const { buckets, loading: bucketsLoaging } = useBuckets(); const { projects, loading: projectLoading } = useProjects(); const { contactCategory, loading: contactCategoryLoading } = useContactCategory(); - const { organizationList, loading: orgLoading } = useOrganization(); - const { designationList, loading: designloading } = useDesignation(); - const { contactTags, loading: Tagloading } = useContactTags(); - const [IsSubmitting, setSubmitting] = useState(false); + const { organizationList } = useOrganization(); + const { designationList } = useDesignation(); + const { contactTags } = useContactTags(); + + // fetch contact details if editing + const { data: contactData, isLoading: isContactLoading } = useContactDetails( + contactId, + { + enabled: !!contactId, + } + ); + const [showSuggestions, setShowSuggestions] = useState(false); const [filteredDesignationList, setFilteredDesignationList] = useState([]); - const dispatch = useDispatch(); const methods = useForm({ resolver: zodResolver(ContactSchema), @@ -56,7 +51,6 @@ const ManageContact = ({ submitContact, onCLosed }) => { handleSubmit, control, getValues, - trigger, setValue, watch, reset, @@ -76,38 +70,49 @@ const ManageContact = ({ submitContact, onCLosed }) => { } = useFieldArray({ control, name: "contactPhones" }); useEffect(() => { - if (emailFields.length === 0) { - appendEmail({ label: "Work", emailAddress: "" }); - } - if (phoneFields.length === 0) { - appendPhone({ label: "Office", phoneNumber: "" }); - } - }, [emailFields.length, phoneFields.length]); + if (contactId && contactData) { + reset({ + name: contactData.name || "", + description: contactData.description || "", - const handleAddEmail = async () => { - const emails = getValues("contactEmails"); - const lastIndex = emails.length - 1; - const valid = await trigger(`contactEmails.${lastIndex}.emailAddress`); - if (valid) { - appendEmail({ label: "Work", emailAddress: "" }); + designation: contactData.designation || "", + organization: contactData.organization || "", + + contactEmails: contactData.contactEmails?.length + ? contactData.contactEmails + : [{ label: "Work", emailAddress: "" }], + + contactPhones: contactData.contactPhones?.length + ? contactData.contactPhones + : [{ label: "Office", phoneNumber: "" }], + + contactCategoryId: contactData.contactCategory?.id || "", + projectIds: contactData.projects?.map((p) => p.id) || [], + bucketIds: contactData.buckets?.map((b) => b.id) || [], + tags: contactData.tags || [], + }); } - }; + }, [contactId, contactData, reset]); - const handleAddPhone = async () => { - const phones = getValues("contactPhones"); - const lastIndex = phones.length - 1; - const valid = await trigger(`contactPhones.${lastIndex}.phoneNumber`); - if (valid) { - appendPhone({ label: "Office", phoneNumber: "" }); + useEffect(() => { + if (!contactId) { + if (emailFields.length === 0) + appendEmail({ label: "Work", emailAddress: "" }); + if (phoneFields.length === 0) + appendPhone({ label: "Office", phoneNumber: "" }); } - }; + }, [ + contactId, + emailFields.length, + phoneFields.length, + appendEmail, + appendPhone, + ]); - const watchBucketIds = watch("bucketIds"); + const watchBucketIds = watch("bucketIds") || []; - // handle logic when input of desgination is changed const handleDesignationChange = (e) => { const val = e.target.value; - const matches = designationList.filter((org) => org.toLowerCase().includes(val.toLowerCase()) ); @@ -121,24 +126,24 @@ const ManageContact = ({ submitContact, onCLosed }) => { setValue("designation", val); }; - const toggleBucketId = (id) => { - const updated = watchBucketIds?.includes(id) - ? watchBucketIds.filter((val) => val !== id) - : [...watchBucketIds, id]; - - setValue("bucketIds", updated, { shouldValidate: true }); - }; + // bucket toggle const handleCheckboxChange = (id) => { const updated = watchBucketIds.includes(id) ? watchBucketIds.filter((i) => i !== id) : [...watchBucketIds, id]; - setValue("bucketIds", updated, { shouldValidate: true }); }; - const {mutate:CreateContact,isPending} = useCreateContact(()=> handleClosed()) + // create & update mutations + const { mutate: CreateContact, isPending: creating } = useCreateContact(() => + handleClosed() + ); + const { mutate: UpdateContact, isPending: updating } = useUpdateContact(() => + handleClosed() + ); + const onSubmit = (data) => { - const contactPayload = { + const payload = { ...data, contactEmails: (data.contactEmails || []).filter( (e) => e.emailAddress?.trim() !== "" @@ -147,23 +152,47 @@ const ManageContact = ({ submitContact, onCLosed }) => { (p) => p.phoneNumber?.trim() !== "" ), }; - CreateContact(contactPayload) + if (contactId) { + const contactPayload = { ...data, id: contactId }; + UpdateContact({ + contactId: contactData.id, + contactPayload: contactPayload, + }); + } else { + CreateContact(payload); + } }; - const orgValue = watch("organization"); const handleClosed = () => { - onCLosed(); + closeModal(); }; + + const handleAddEmail = () => { + appendEmail({ label: "Work", emailAddress: "" }); + }; + + const handleAddPhone = () => { + appendPhone({ label: "Office", phoneNumber: "" }); + }; + + const isPending = updating || creating; + return (
-
Create New Contact
+
+ {contactId ? "Edit Contact" : "Create New Contact"} +
+ + {/* Name + Organization */}
-
- +
+ { {errors.name.message} )}
- -
- +
+ { />
+ + {/* Designation */}
-
- +
+ { overflowY: "auto", marginTop: "2px", zIndex: 1000, - borderRadius: "0px", }} > {filteredDesignationList.map((designation) => (
  • handleSelectDesignation(designation)} - onMouseEnter={(e) => - (e.currentTarget.style.backgroundColor = "#f8f9fa") - } - onMouseLeave={(e) => - (e.currentTarget.style.backgroundColor = "transparent") - } > {designation}
  • @@ -232,6 +254,8 @@ const ManageContact = ({ submitContact, onCLosed }) => { )}
    + + {/* Emails + Phones */}
    {emailFields.map((field, index) => ( @@ -239,7 +263,7 @@ const ManageContact = ({ submitContact, onCLosed }) => { key={field.id} className="row d-flex align-items-center mb-1" > -
    +
    - {errors.contactEmails?.[index]?.label && ( - - {errors.contactEmails[index].label.message} - - )}
    -
    +
    { /> ) : ( removeEmail(index)} /> )} @@ -285,13 +304,14 @@ const ManageContact = ({ submitContact, onCLosed }) => {
    ))}
    +
    {phoneFields.map((field, index) => (
    -
    +
    - {errors.phone?.[index]?.label && ( - - {errors.ContactPhones[index].label.message} - - )}
    -
    +
    { /> ) : ( removePhone(index)} /> )} @@ -337,13 +352,11 @@ const ManageContact = ({ submitContact, onCLosed }) => {
    ))}
    - {errors.contactPhone?.message && ( -
    {errors.contactPhone.message}
    - )}
    + {/* Category + Projects */}
    -
    +
    { ))} {errors.bucketIds && ( - - {errors.bucketIds.message} - + {errors.bucketIds.message} )}
    + {/* Address + Description */}