Refactor_Directory And Project Level Permsssion #404
@ -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 && (
|
||||
<div
|
||||
className={`modal fade show`}
|
||||
tabIndex="-1"
|
||||
role="dialog"
|
||||
style={{
|
||||
display: "block",
|
||||
backgroundColor: "rgba(0,0,0,0.5)",
|
||||
}}
|
||||
aria-hidden="false"
|
||||
>
|
||||
<ConfirmModal
|
||||
type="delete"
|
||||
header="Delete Contact"
|
||||
message="Are you sure you want delete?"
|
||||
onSubmit={handleActiveInactive}
|
||||
onClose={() => setIsDeleteModalOpen(false)}
|
||||
loading={isPending}
|
||||
paramData={contact.id}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div
|
||||
className="card text-start border-1"
|
||||
style={{ background: `${!IsActive ? "#f8f6f6" : ""}` }}
|
||||
@ -67,10 +97,7 @@ const CardViewContact = ({
|
||||
</button>
|
||||
<ul className="dropdown-menu dropdown-menu-end w-auto">
|
||||
<li
|
||||
onClick={() => {
|
||||
setSelectedContact(contact);
|
||||
setIsOpenModal(true);
|
||||
}}
|
||||
onClick={()=>setManageContact({isOpen:true,contactId:contact?.id})}
|
||||
>
|
||||
<a className="dropdown-item px-2 cursor-pointer py-1">
|
||||
<i className="bx bx-edit bx-xs text-primary me-2"></i>
|
||||
@ -80,7 +107,7 @@ const CardViewContact = ({
|
||||
<li>
|
||||
<a
|
||||
className="dropdown-item px-2 cursor-pointer py-1"
|
||||
onClick={() => IsDeleted(contact?.id)}
|
||||
onClick={() => setIsDeleteModalOpen(true)}
|
||||
>
|
||||
<i className="bx bx-trash text-danger bx-xs me-2"></i>
|
||||
<span className="align-left">Delete</span>
|
||||
@ -92,15 +119,12 @@ const CardViewContact = ({
|
||||
{!IsActive && (
|
||||
<i
|
||||
className={`bx ${
|
||||
dirActions.action && dirActions.id === contact.id
|
||||
isPending
|
||||
? "bx-loader-alt bx-spin"
|
||||
: "bx-recycle"
|
||||
} me-1 text-primary cursor-pointer`}
|
||||
title="Restore"
|
||||
onClick={() => {
|
||||
setDirActions({ action: false, id: contact.id });
|
||||
restore(contact.id);
|
||||
}}
|
||||
onClick={()=>handleActiveInactive(contact.id)}
|
||||
></i>
|
||||
)}
|
||||
</div>
|
||||
@ -197,6 +221,7 @@ const CardViewContact = ({
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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 && (
|
||||
<div
|
||||
className={`modal fade show`}
|
||||
tabIndex="-1"
|
||||
role="dialog"
|
||||
style={{
|
||||
display: "block",
|
||||
backgroundColor: "rgba(0,0,0,0.5)",
|
||||
}}
|
||||
aria-hidden="false"
|
||||
>
|
||||
<ConfirmModal
|
||||
type="delete"
|
||||
header="Delete Contact"
|
||||
message="Are you sure you want delete?"
|
||||
onSubmit={handleActiveInactive}
|
||||
onClose={() => setDeleteContact({contactId:null,Open:false})}
|
||||
loading={isPending}
|
||||
paramData={deleteContact.contactId}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="card ">
|
||||
<div className="card-datatable table-responsive" id="horizontal-example">
|
||||
<div className="dataTables_wrapper no-footer ">
|
||||
@ -86,20 +122,44 @@ const ListViewContact = ({ data, Pagination }) => {
|
||||
<tbody>
|
||||
{Array.isArray(data) && data.length > 0 ? (
|
||||
data.map((row, i) => (
|
||||
<tr key={i}>
|
||||
<tr
|
||||
key={i}
|
||||
style={{ background: `${!showActive ? "#f8f6f6" : ""}` }}
|
||||
>
|
||||
{contactList.map((col) => (
|
||||
<td key={col.key} className={col.align}>
|
||||
{col.getValue(row)}
|
||||
</td>
|
||||
))}
|
||||
<td className="text-center">
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i className="bx bx-show text-primary cursor-pointer"></i>
|
||||
{showActive ? (
|
||||
<div className="d-flex justify-content-center gap-2">
|
||||
<i className="bx bx-show text-primary cursor-pointer"></i>
|
||||
|
||||
<i className="bx bx-edit text-secondary cursor-pointer"></i>
|
||||
<i
|
||||
className="bx bx-edit text-secondary cursor-pointer"
|
||||
onClick={() =>
|
||||
setManageContact({
|
||||
isOpen: true,
|
||||
contactId: row.id,
|
||||
})
|
||||
}
|
||||
></i>
|
||||
|
||||
<i className="bx bx-trash text-danger cursor-pointer"></i>
|
||||
</div>
|
||||
<i className="bx bx-trash text-danger cursor-pointer" onClick={()=>setDeleteContact({contactId:row.id,Open:true})}></i>
|
||||
</div>
|
||||
) : (
|
||||
<i
|
||||
className={`bx ${
|
||||
isPending && activeContact === row.id ? "bx-loader-alt bx-spin" : "bx-recycle"
|
||||
} me-1 text-primary cursor-pointer`}
|
||||
title="Restore"
|
||||
onClick={() => {
|
||||
setActiveContact(row.id)
|
||||
handleActiveInactive(row.id)
|
||||
}}
|
||||
></i>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
@ -118,6 +178,7 @@ const ListViewContact = ({ data, Pagination }) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -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 (
|
||||
<FormProvider {...methods}>
|
||||
<form className="p-2 p-sm-0" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className="d-flex justify-content-center align-items-center">
|
||||
<h6 className="m-0 fw-18"> Create New Contact</h6>
|
||||
<h6 className="m-0 fw-18">
|
||||
{contactId ? "Edit Contact" : "Create New Contact"}
|
||||
</h6>
|
||||
</div>
|
||||
|
||||
{/* Name + Organization */}
|
||||
<div className="row">
|
||||
<div className="col-md-6 text-start">
|
||||
<Label htmlFor={"name"} required>Name</Label>
|
||||
<div className="col-md-6 text-start">
|
||||
<Label htmlFor={"name"} required>
|
||||
Name
|
||||
</Label>
|
||||
<input
|
||||
className="form-control form-control-sm"
|
||||
{...register("name")}
|
||||
@ -172,9 +201,10 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
<small className="danger-text">{errors.name.message}</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-md-6 text-start">
|
||||
<Label htmlFor={"Organization"} required>Organization</Label>
|
||||
<div className="col-md-6 text-start">
|
||||
<Label htmlFor={"organization"} required>
|
||||
Organization
|
||||
</Label>
|
||||
<InputSuggestions
|
||||
organizationList={organizationList}
|
||||
value={getValues("organization") || ""}
|
||||
@ -183,9 +213,13 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Designation */}
|
||||
<div className="row mt-1">
|
||||
<div className="col-md-6 text-start">
|
||||
<Label htmlFor={"Designation"} required>Designation</Label>
|
||||
<div className="col-md-6 text-start position-relative">
|
||||
<Label htmlFor={"designation"} required>
|
||||
Designation
|
||||
</Label>
|
||||
<input
|
||||
className="form-control form-control-sm"
|
||||
{...register("designation")}
|
||||
@ -199,26 +233,14 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
overflowY: "auto",
|
||||
marginTop: "2px",
|
||||
zIndex: 1000,
|
||||
borderRadius: "0px",
|
||||
}}
|
||||
>
|
||||
{filteredDesignationList.map((designation) => (
|
||||
<li
|
||||
key={designation}
|
||||
className="list-group-item list-group-item-action border-none "
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
padding: "5px 12px",
|
||||
fontSize: "14px",
|
||||
transition: "background-color 0.2s",
|
||||
}}
|
||||
className="list-group-item list-group-item-action"
|
||||
style={{ cursor: "pointer", fontSize: "14px" }}
|
||||
onMouseDown={() => handleSelectDesignation(designation)}
|
||||
onMouseEnter={(e) =>
|
||||
(e.currentTarget.style.backgroundColor = "#f8f9fa")
|
||||
}
|
||||
onMouseLeave={(e) =>
|
||||
(e.currentTarget.style.backgroundColor = "transparent")
|
||||
}
|
||||
>
|
||||
{designation}
|
||||
</li>
|
||||
@ -232,6 +254,8 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Emails + Phones */}
|
||||
<div className="row mt-1">
|
||||
<div className="col-md-6">
|
||||
{emailFields.map((field, index) => (
|
||||
@ -239,7 +263,7 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
key={field.id}
|
||||
className="row d-flex align-items-center mb-1"
|
||||
>
|
||||
<div className="col-5 text-start">
|
||||
<div className="col-5 text-start">
|
||||
<label className="form-label">Label</label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
@ -249,13 +273,8 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
<option value="Personal">Personal</option>
|
||||
<option value="Other">Other</option>
|
||||
</select>
|
||||
{errors.contactEmails?.[index]?.label && (
|
||||
<small className="danger-text">
|
||||
{errors.contactEmails[index].label.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-7 text-start">
|
||||
<div className="col-7 text-start">
|
||||
<label className="form-label">Email</label>
|
||||
<div className="d-flex align-items-center">
|
||||
<input
|
||||
@ -271,7 +290,7 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
/>
|
||||
) : (
|
||||
<i
|
||||
className="bx bx-minus-circle bx-xs ms-1 cursor-pointer text-primary"
|
||||
className="bx bx-minus-circle bx-xs ms-1 cursor-pointer text-danger"
|
||||
onClick={() => removeEmail(index)}
|
||||
/>
|
||||
)}
|
||||
@ -285,13 +304,14 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="col-md-6">
|
||||
{phoneFields.map((field, index) => (
|
||||
<div
|
||||
key={field.id}
|
||||
className="row d-flex align-items-center mb-2"
|
||||
>
|
||||
<div className="col-5 text-start">
|
||||
<div className="col-5 text-start">
|
||||
<label className="form-label">Label</label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
@ -301,13 +321,8 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
<option value="Personal">Personal</option>
|
||||
<option value="Business">Business</option>
|
||||
</select>
|
||||
{errors.phone?.[index]?.label && (
|
||||
<small className="danger-text">
|
||||
{errors.ContactPhones[index].label.message}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="col-7 text-start">
|
||||
<div className="col-7 text-start">
|
||||
<label className="form-label">Phone</label>
|
||||
<div className="d-flex align-items-center">
|
||||
<input
|
||||
@ -323,7 +338,7 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
/>
|
||||
) : (
|
||||
<i
|
||||
className="bx bx-minus-circle bx-xs ms-1 cursor-pointer text-danager"
|
||||
className="bx bx-minus-circle bx-xs ms-1 cursor-pointer text-danger"
|
||||
onClick={() => removePhone(index)}
|
||||
/>
|
||||
)}
|
||||
@ -337,13 +352,11 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{errors.contactPhone?.message && (
|
||||
<div className="danger-text">{errors.contactPhone.message}</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Category + Projects */}
|
||||
<div className="row my-1">
|
||||
<div className="col-md-6 text-start">
|
||||
<div className="col-md-6 text-start">
|
||||
<label className="form-label">Category</label>
|
||||
<select
|
||||
className="form-select form-select-sm"
|
||||
@ -387,24 +400,31 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Tags */}
|
||||
<div className="col-12 text-start">
|
||||
<TagInput name="tags" label="Tags" options={contactTags} isRequired={true} />
|
||||
<TagInput
|
||||
name="tags"
|
||||
label="Tags"
|
||||
options={contactTags}
|
||||
isRequired={true}
|
||||
/>
|
||||
{errors.tags && (
|
||||
<small className="danger-text">{errors.tags.message}</small>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Buckets */}
|
||||
<div className="row">
|
||||
<div className="col-md-12 mt-1 text-start">
|
||||
<label className="form-label ">Select Bucket</label>
|
||||
|
||||
<ul className="d-flex flex-wrap px-1 list-unstyled mb-0">
|
||||
<ul className="d-flex flex-wrap px-1 list-unstyled mb-0">
|
||||
{bucketsLoaging && <p>Loading...</p>}
|
||||
{buckets?.map((item) => (
|
||||
<li
|
||||
key={item.id}
|
||||
className="list-inline-item flex-shrink-0 me-6 mb-1"
|
||||
>
|
||||
<div className="form-check ">
|
||||
<div className="form-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="form-check-input"
|
||||
@ -423,13 +443,12 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
))}
|
||||
</ul>
|
||||
{errors.bucketIds && (
|
||||
<small className="danger-text mt-0">
|
||||
{errors.bucketIds.message}
|
||||
</small>
|
||||
<small className="danger-text">{errors.bucketIds.message}</small>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Address + Description */}
|
||||
<div className="col-12 text-start">
|
||||
<label className="form-label">Address</label>
|
||||
<textarea
|
||||
@ -438,7 +457,6 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
{...register("address")}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="col-12 text-start">
|
||||
<label className="form-label">Description</label>
|
||||
<textarea
|
||||
@ -451,6 +469,7 @@ const ManageContact = ({ submitContact, onCLosed }) => {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="d-flex justify-content-end gap-3 py-2">
|
||||
<button className="btn btn-sm btn-primary" type="submit">
|
||||
{isPending ? "Please Wait..." : "Submit"}
|
||||
|
@ -3,6 +3,7 @@ import { DirectoryRepository } from "../repositories/DirectoryRepository";
|
||||
import { cacheData, getCachedData } from "../slices/apiDataManager";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import showToast from "../services/toastService";
|
||||
import { queryClient } from "../layouts/AuthLayout";
|
||||
|
||||
export const useDirectory = (isActive, prefernceContacts) => {
|
||||
const [contacts, setContacts] = useState([]);
|
||||
@ -270,7 +271,7 @@ export const useContactList = (
|
||||
],
|
||||
queryFn: async () => {
|
||||
const cleanedFilter = cleanFilter(filter);
|
||||
const resp = await DirectoryRepository.GetContact(
|
||||
const resp = await DirectoryRepository.GetContacts(
|
||||
isActive,
|
||||
projectId,
|
||||
pageSize,
|
||||
@ -294,6 +295,20 @@ export const useContactFilter = ()=>{
|
||||
}
|
||||
|
||||
|
||||
export const useContactDetails = (contactId)=>{
|
||||
return useQuery({
|
||||
queryKey:["Contact",contactId],
|
||||
queryFn:async()=>{
|
||||
const resp = await await DirectoryRepository.GetContact(contactId);
|
||||
return resp.data
|
||||
},
|
||||
enabled:!!contactId
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ---------------------------Mutation------------------------------------------------------------------
|
||||
|
||||
export const useCreateBucket =(onSuccessCallBack)=>{
|
||||
@ -376,12 +391,12 @@ export const useDeleteBucket = (onSuccessCallBack) => {
|
||||
});
|
||||
};
|
||||
|
||||
export const useCreateContact = ()=>{
|
||||
export const useCreateContact = (onSuccessCallBack)=>{
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn:async(contactPayload) => await DirectoryRepository.CreateContact(contactPayload),
|
||||
onSuccess: (_, variables) => {
|
||||
// queryClient.invalidateQueries({queryKey: ["bucketList"]})
|
||||
queryClient.invalidateQueries({queryKey: ["contacts"]})
|
||||
showToast("Contact created Successfully", "success");
|
||||
if (onSuccessCallBack) onSuccessCallBack();
|
||||
},
|
||||
@ -397,12 +412,12 @@ export const useCreateContact = ()=>{
|
||||
}
|
||||
|
||||
|
||||
export const useUpdateContact =()=>{
|
||||
export const useUpdateContact =(onSuccessCallBack)=>{
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn:async({conatctId,contactPayload})=> await DirectoryRepository.UpdateContact(conatctId,contactPayload),
|
||||
mutationFn:async({contactId,contactPayload})=> await DirectoryRepository.UpdateContact(contactId,contactPayload),
|
||||
onSuccess: (_, variables) => {
|
||||
// queryClient.invalidateQueries({queryKey: ["bucketList"]})
|
||||
queryClient.invalidateQueries({queryKey: ["contacts"]})
|
||||
showToast("Contact updated Successfully", "success");
|
||||
if (onSuccessCallBack) onSuccessCallBack();
|
||||
},
|
||||
@ -414,4 +429,24 @@ export const useUpdateContact =()=>{
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export const useActiveInActiveContact =(onSuccessCallBack)=>{
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn:async({contactId,contactStatus})=> await DirectoryRepository.DeleteContact(contactId,contactStatus),
|
||||
onSuccess: (_, variables) => {
|
||||
const {contactStatus} = variables;
|
||||
queryClient.invalidateQueries({queryKey: ["contacts"]})
|
||||
showToast(`Contact ${contactStatus ? "Active":"In-Active"} Successfully`, "success");
|
||||
if (onSuccessCallBack) onSuccessCallBack();
|
||||
},
|
||||
onError: (error) => {
|
||||
showToast(
|
||||
error.response.data.message ||
|
||||
"Something went wrong.Please try again later.",
|
||||
"error"
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
@ -37,8 +37,10 @@ export default function DirectoryPage({ IsPage = true }) {
|
||||
const [activeTab, setActiveTab] = useState("notes");
|
||||
const { setActions } = useFab();
|
||||
const [gridView, setGridView] = useState(false);
|
||||
const [isOpenBucket, setOpenBucket] = useState(false);
|
||||
const [isManageContact, setManageContact] = useState(false);
|
||||
const [isOpenBucket, setOpenBucket] = useState({});
|
||||
const [isManageContact, setManageContact] = useState({
|
||||
isOpen:false,contactId:null
|
||||
});
|
||||
const [showActive, setShowActive] = useState(true);
|
||||
|
||||
const { data, isLoading, isError, error } = useBucketList();
|
||||
@ -64,7 +66,7 @@ export default function DirectoryPage({ IsPage = true }) {
|
||||
label: "New Contact",
|
||||
icon: "bx bx-plus-circle",
|
||||
color: "warning",
|
||||
onClick: () => setManageContact(true),
|
||||
onClick: () => setManageContact({isOpen:true,contactId:null}),
|
||||
});
|
||||
}
|
||||
|
||||
@ -77,6 +79,7 @@ export default function DirectoryPage({ IsPage = true }) {
|
||||
showActive,
|
||||
gridView,
|
||||
data,
|
||||
setManageContact
|
||||
};
|
||||
|
||||
if (isLoading) return <div>Loading...</div>;
|
||||
@ -227,13 +230,13 @@ export default function DirectoryPage({ IsPage = true }) {
|
||||
</GlobalModel>
|
||||
)}
|
||||
|
||||
{isManageContact && (
|
||||
{isManageContact.isOpen && (
|
||||
<GlobalModel
|
||||
size="lg"
|
||||
isOpen={isManageContact}
|
||||
closeModal={() => setManageContact(false)}
|
||||
closeModal={() => setManageContact({isOpen:false,contactId:null})}
|
||||
>
|
||||
<ManageContact closeModal={() => setManageContact(false)} />
|
||||
<ManageContact contactId={isManageContact.contactId} closeModal={() => setManageContact({isOpen:false,contactId:null})} />
|
||||
</GlobalModel>
|
||||
)}
|
||||
</div>
|
||||
|
@ -3,18 +3,9 @@ import { api } from "../utils/axiosClient";
|
||||
export const DirectoryRepository = {
|
||||
GetOrganizations: () => api.get("/api/directory/organization"),
|
||||
GetDesignations: () => api.get("/api/directory/designations"),
|
||||
GetContacts: (isActive, projectId) => {
|
||||
const params = new URLSearchParams();
|
||||
params.append("active", isActive);
|
||||
GetContact:(id)=>api.get(`/api/Directory/profile/${id}`),
|
||||
|
||||
if (projectId) {
|
||||
params.append("projectId", projectId);
|
||||
}
|
||||
|
||||
return api.get(`/api/Directory?${params.toString()}`);
|
||||
},
|
||||
|
||||
GetContact: (isActive, projectId, pageSize, pageNumber, filter, searchString) => {
|
||||
GetContacts: (isActive, projectId, pageSize, pageNumber, filter, searchString) => {
|
||||
const payloadJsonString = JSON.stringify(filter);
|
||||
return api.get(
|
||||
`/api/Directory/list?active=${isActive}` +
|
||||
|
Loading…
x
Reference in New Issue
Block a user