Compare commits
65 Commits
main
...
Kartik_Bug
Author | SHA1 | Date | |
---|---|---|---|
43963715d2 | |||
37c651a948 | |||
fa944c2fa6 | |||
553936acc7 | |||
cbec3d9f3e | |||
ad886b7da3 | |||
9774c54c2c | |||
f695cc5c04 | |||
cb730e70ad | |||
19e21980e8 | |||
683c0bedd5 | |||
cb2db46e21 | |||
116fe04f97 | |||
49d9034a45 | |||
e2d99a07b2 | |||
8f16fa9b5d | |||
a1f7b7b2eb | |||
1fc3a4b6f9 | |||
fb0e48fe4a | |||
393cc8b19f | |||
1387b47d07 | |||
ef3a62086c | |||
e98b46f702 | |||
4eacc4f510 | |||
e0fa59e747 | |||
2cb601dc16 | |||
7556234635 | |||
313fb88bf0 | |||
740a730f7a | |||
236f1b23ac | |||
88439f86c0 | |||
617f180eab | |||
fcdcb10f70 | |||
9ce6da35fb | |||
7709483a76 | |||
6cfe8f5bfb | |||
46ed1f5645 | |||
ff85aa4a73 | |||
7d7797a969 | |||
bb61741158 | |||
4347de8efc | |||
9e06f7d8e5 | |||
029b8300ff | |||
a9f764379a | |||
48d61520fc | |||
f939721792 | |||
0202b81983 | |||
f5e577e287 | |||
18501507bb | |||
a5e969f4c4 | |||
019efafdbb | |||
954a961dd1 | |||
b7f7e7a846 | |||
5d4c616573 | |||
77e384dc6e | |||
c1620eade5 | |||
8478c2160d | |||
3993dcfc4e | |||
832685fedd | |||
2bba01211e | |||
200e52dcc2 | |||
29946a87d1 | |||
e3d0b440f8 | |||
01a045a364 | |||
a811eb8463 |
@ -107,13 +107,13 @@ const CardViewDirectory = ({
|
||||
{/* <li className="list-inline-item me-1 small">
|
||||
<i className="fa-solid fa-briefcase me-2"></i>
|
||||
</li> */}
|
||||
<li className="list-inline-item text-break small ms-5">
|
||||
<li className="list-inline-item text-break small ms-5 px-1">
|
||||
{contact.organization}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
className={`card-footer text-start px-1 py-1 ${IsActive && "cursor-pointer"
|
||||
className={`card-footer text-start mx-4 px-4 py-1 ${IsActive && "cursor-pointer"
|
||||
}`}
|
||||
onClick={() => {
|
||||
if (IsActive) {
|
||||
|
@ -4,7 +4,6 @@ import Avatar from "../common/Avatar";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { showText } from "pdf-lib";
|
||||
import { DirectoryRepository } from "../../repositories/DirectoryRepository";
|
||||
import moment from "moment";
|
||||
import { cacheData, getCachedData } from "../../slices/apiDataManager";
|
||||
@ -19,15 +18,17 @@ const schema = z.object({
|
||||
const NotesDirectory = ({
|
||||
refetchProfile,
|
||||
isLoading,
|
||||
contactProfile,
|
||||
contactProfile, // This contactProfile now reliably includes firstName, middleName, lastName, and fullName
|
||||
setProfileContact,
|
||||
}) => {
|
||||
const [IsActive, setIsActive] = useState(true);
|
||||
const { contactNotes, refetch } = useContactNotes(contactProfile?.id, true);
|
||||
const { contactNotes, refetch } = useContactNotes(
|
||||
contactProfile?.id,
|
||||
IsActive
|
||||
);
|
||||
|
||||
const [NotesData, setNotesData] = useState();
|
||||
const [IsSubmitting, setIsSubmitting] = useState(false);
|
||||
const [addNote, setAddNote] = useState(true);
|
||||
const [showEditor, setShowEditor] = useState(false);
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
@ -67,102 +68,118 @@ const NotesDirectory = ({
|
||||
) {
|
||||
const updatedProfile = {
|
||||
...cached_contactProfile.data,
|
||||
notes: [...(cached_contactProfile.notes || []), createdNote],
|
||||
notes: [...(cached_contactProfile.data.notes || []), createdNote],
|
||||
};
|
||||
cacheData("Contact Profile", updatedProfile);
|
||||
cacheData("Contact Profile", {
|
||||
contactId: contactProfile?.id,
|
||||
data: updatedProfile,
|
||||
});
|
||||
}
|
||||
|
||||
setValue("note", "");
|
||||
setIsSubmitting(false);
|
||||
showToast("Note added successfully!", "success");
|
||||
setAddNote(true);
|
||||
setShowEditor(false);
|
||||
setIsActive(true);
|
||||
refetch(contactProfile?.id, true);
|
||||
} catch (error) {
|
||||
setIsSubmitting(false);
|
||||
const msg =
|
||||
error.response.data.message ||
|
||||
error.message ||
|
||||
"Error occured during API calling";
|
||||
error.response?.data?.message || error.message || "Error occurred during API calling";
|
||||
showToast(msg, "error");
|
||||
}
|
||||
};
|
||||
|
||||
const onCancel = () => {
|
||||
setValue( "note", "" );
|
||||
|
||||
setValue("note", "");
|
||||
setShowEditor(false);
|
||||
};
|
||||
|
||||
const handleSwitch = () => {
|
||||
setIsActive(!IsActive);
|
||||
if (IsActive) {
|
||||
refetch(contactProfile?.id, false);
|
||||
}
|
||||
setIsActive((prevIsActive) => {
|
||||
const newState = !prevIsActive;
|
||||
refetch(contactProfile?.id, newState);
|
||||
return newState;
|
||||
});
|
||||
};
|
||||
|
||||
// Use the fullName from contactProfile, which now includes middle and last names if available
|
||||
const contactName =
|
||||
contactProfile?.fullName || contactProfile?.firstName || "Contact";
|
||||
const noNotesMessage = `Be the first to share your insights! ${contactName} currently has no notes.`;
|
||||
|
||||
const notesToDisplay = IsActive
|
||||
? contactProfile?.notes || []
|
||||
: contactNotes || [];
|
||||
|
||||
return (
|
||||
<div className="text-start">
|
||||
<div className="text-start mt-10">
|
||||
<div className="d-flex align-items-center justify-content-between">
|
||||
<p className="fw-semibold m-0">Notes :</p>
|
||||
<div className="row w-100 align-items-center">
|
||||
<div className="col col-2">
|
||||
<p className="fw-semibold m-0 ms-3">Notes :</p>
|
||||
</div>
|
||||
<div className="col d-flex justify-content-end gap-2 pe-0">
|
||||
{" "}
|
||||
<div className="d-flex align-items-center justify-content-between">
|
||||
<label
|
||||
className="switch switch-primary"
|
||||
style={{
|
||||
visibility:
|
||||
contactProfile?.notes?.length > 0 ||
|
||||
contactNotes?.length > 0
|
||||
? "visible"
|
||||
: "hidden",
|
||||
}}
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
className="switch-input"
|
||||
checked={!IsActive} // checked when showing *in*active notes (i.e., when IsActive is false)
|
||||
onChange={handleSwitch}
|
||||
/>
|
||||
<span className="switch-toggle-slider">
|
||||
<span className="switch-on"></span>
|
||||
<span className="switch-off"></span>
|
||||
</span>
|
||||
<span className="switch-label">Include Deleted Notes</span>
|
||||
</label>
|
||||
{!showEditor && (
|
||||
<div className="d-flex justify-content-end">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm d-flex align-items-center"
|
||||
onClick={() => setShowEditor(true)}
|
||||
style={{
|
||||
color: "#6c757d",
|
||||
backgroundColor: "transparent",
|
||||
boxShadow: "none",
|
||||
border: "none",
|
||||
}}
|
||||
>
|
||||
<i
|
||||
className="bx bx-plus-circle me-0 text-primary"
|
||||
style={{ fontSize: "1.5rem", color: "#6c757d" }}
|
||||
></i>
|
||||
Add a Note
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="d-flex align-items-center justify-content-between mb-5">
|
||||
<div className="m-0 d-flex align-items-center">
|
||||
{contactNotes?.length > 0 ? (
|
||||
<label className="switch switch-primary">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="switch-input"
|
||||
onChange={() => handleSwitch(!IsActive)}
|
||||
value={IsActive}
|
||||
/>
|
||||
<span className="switch-toggle-slider">
|
||||
<span className="switch-on"></span>
|
||||
<span className="switch-off"></span>
|
||||
</span>
|
||||
<span className="switch-label">Include Deleted Notes</span>
|
||||
</label>
|
||||
) : (
|
||||
<div style={{ visibility: "hidden" }}>
|
||||
<label className="switch switch-primary">
|
||||
<input type="checkbox" className="switch-input" />
|
||||
<span className="switch-toggle-slider">
|
||||
<span className="switch-on"></span>
|
||||
<span className="switch-off"></span>
|
||||
</span>
|
||||
<span className="switch-label">Include Deleted Notes</span>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="d-flex justify-content-end">
|
||||
<span
|
||||
className={`btn btn-sm ${addNote ? "btn-secondary" : "btn-primary"}`}
|
||||
onClick={() => setAddNote(!addNote)}
|
||||
>
|
||||
{addNote ? "Hide Editor" : "Add a Note"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{addNote && (
|
||||
<div className="card m-2 mb-5">
|
||||
<button
|
||||
{showEditor && (
|
||||
<div className="card m-2 mb-5 position-relative">
|
||||
<span
|
||||
type="button"
|
||||
class="btn btn-close btn-secondary position-absolute top-0 end-0 m-2 mt-3 rounded-circle"
|
||||
className="position-absolute top-0 end-0 mt-3 bg-secondary rounded-circle"
|
||||
aria-label="Close"
|
||||
style={{ backgroundColor: "#eee", color: "white" }}
|
||||
onClick={() => setAddNote(!addNote)}
|
||||
></button>
|
||||
{/* <div className="d-flex justify-content-end px-2">
|
||||
<span
|
||||
className={`btn btn-sm ${
|
||||
addNote ? "btn-danger" : "btn-primary"
|
||||
}`}
|
||||
onClick={() => setAddNote(!addNote)}
|
||||
>
|
||||
{addNote ? "Hide Editor" : "Add Note"}
|
||||
</span>
|
||||
</div> */}
|
||||
onClick={() => setShowEditor(false)}
|
||||
>
|
||||
<i className="bx bx-x fs-5 p-1 text-white"></i>
|
||||
</span>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Editor
|
||||
value={noteValue}
|
||||
@ -171,52 +188,42 @@ const NotesDirectory = ({
|
||||
onCancel={onCancel}
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
/>
|
||||
{errors.notes && (
|
||||
{errors.note && (
|
||||
<p className="text-danger small mt-1">{errors.note.message}</p>
|
||||
)}
|
||||
</form>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className=" justify-content-start px-1 mt-1">
|
||||
<div className="justify-content-start px-1 mt-1">
|
||||
{isLoading && (
|
||||
<div className="text-center">
|
||||
{" "}
|
||||
<p>Loading...</p>{" "}
|
||||
</div>
|
||||
)}
|
||||
{!isLoading &&
|
||||
[...(IsActive ? contactProfile?.notes || [] : contactNotes || [])]
|
||||
.reverse()
|
||||
.map((noteItem) => (
|
||||
<NoteCardDirectory
|
||||
refetchProfile={refetchProfile}
|
||||
refetchNotes={refetch}
|
||||
refetchContact={refetch}
|
||||
noteItem={noteItem}
|
||||
contactId={contactProfile?.id}
|
||||
setProfileContact={setProfileContact}
|
||||
key={noteItem.id}
|
||||
/>
|
||||
))}
|
||||
|
||||
{IsActive && (
|
||||
<div>
|
||||
{!isLoading && contactProfile?.notes.length == 0 && !addNote && (
|
||||
<div className="text-center mt-5">No Notes Found</div>
|
||||
{!isLoading && notesToDisplay.length > 0
|
||||
? notesToDisplay
|
||||
.slice()
|
||||
.reverse()
|
||||
.map((noteItem) => (
|
||||
<NoteCardDirectory
|
||||
refetchProfile={refetchProfile}
|
||||
refetchNotes={refetch}
|
||||
refetchContact={refetch}
|
||||
noteItem={noteItem}
|
||||
contactId={contactProfile?.id}
|
||||
setProfileContact={setProfileContact}
|
||||
key={noteItem.id}
|
||||
/>
|
||||
))
|
||||
: !isLoading &&
|
||||
!showEditor && (
|
||||
<div className="text-center mt-5">{noNotesMessage}</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{!IsActive && (
|
||||
<div>
|
||||
{!isLoading && contactNotes.length == 0 && !addNote && (
|
||||
<div className="text-center mt-5">No Notes Found</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotesDirectory;
|
||||
export default NotesDirectory;
|
@ -8,9 +8,10 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
|
||||
const { contactProfile, loading, refetch } = useContactProfile(contact?.id);
|
||||
const [copiedIndex, setCopiedIndex] = useState(null);
|
||||
|
||||
const [profileContact, setProfileContact] = useState();
|
||||
const [profileContactState, setProfileContactState] = useState(null);
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
const description = contactProfile?.description || "";
|
||||
|
||||
const description = profileContactState?.description || "";
|
||||
const limit = 500;
|
||||
|
||||
const toggleReadMore = () => setExpanded(!expanded);
|
||||
@ -19,14 +20,51 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
|
||||
const displayText = expanded
|
||||
? description
|
||||
: description.slice(0, limit) + (isLong ? "..." : "");
|
||||
|
||||
useEffect(() => {
|
||||
setProfileContact(contactProfile);
|
||||
}, [contactProfile]);
|
||||
if (contactProfile) {
|
||||
const names = (contact?.name || "").trim().split(" ");
|
||||
let firstName = "";
|
||||
let middleName = "";
|
||||
let lastName = "";
|
||||
let fullName = contact?.name || "";
|
||||
|
||||
// Logic to determine first, middle, and last names
|
||||
if (names.length === 1) {
|
||||
firstName = names[0];
|
||||
} else if (names.length === 2) {
|
||||
firstName = names[0];
|
||||
lastName = names[1];
|
||||
} else if (names.length >= 3) {
|
||||
firstName = names[0];
|
||||
middleName = names[1]; // This was an error in the original prompt, corrected to names[1]
|
||||
lastName = names[names.length - 1];
|
||||
// Reconstruct full name to be precise with spacing
|
||||
fullName = `${firstName} ${middleName ? middleName + ' ' : ''}${lastName}`;
|
||||
} else {
|
||||
// Fallback if no names or empty string
|
||||
firstName = "Contact";
|
||||
fullName = "Contact";
|
||||
}
|
||||
|
||||
|
||||
setProfileContactState({
|
||||
...contactProfile,
|
||||
firstName: contactProfile.firstName || firstName,
|
||||
// Adding middleName and lastName to the state for potential future use or more granular access
|
||||
middleName: contactProfile.middleName || middleName,
|
||||
lastName: contactProfile.lastName || lastName,
|
||||
fullName: contactProfile.fullName || fullName, // Prioritize fetched fullName, fallback to derived
|
||||
});
|
||||
}
|
||||
}, [contactProfile, contact?.name]);
|
||||
|
||||
const handleCopy = (email, index) => {
|
||||
navigator.clipboard.writeText(email);
|
||||
setCopiedIndex(index);
|
||||
setTimeout(() => setCopiedIndex(null), 2000); // Reset after 2 seconds
|
||||
setTimeout(() => setCopiedIndex(null), 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-1">
|
||||
<div className="text-center m-0 p-0">
|
||||
@ -47,32 +85,35 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
|
||||
<div className="d-flex flex-column text-start ms-1">
|
||||
<span className="m-0 fw-semibold">{contact?.name}</span>
|
||||
<small className="text-secondary small-text">
|
||||
{/* {contactProfile?.tags?.map((tag) => tag.name).join(" | ")} */}
|
||||
{contactProfile?.designation}
|
||||
{profileContactState?.designation}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="row ms-9">
|
||||
<div className="col-12 col-md-6 d-flex flex-column text-start">
|
||||
{contactProfile?.contactEmails?.length > 0 && (
|
||||
<div className="d-flex mb-2">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Email:</p>
|
||||
{profileContactState?.contactEmails?.length > 0 && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div
|
||||
className="d-flex align-items-start"
|
||||
style={{ width: "100px", minWidth: "130px" }}
|
||||
>
|
||||
<span className="d-flex">
|
||||
<i className="bx bx-envelope bx-xs me-2 mt-1"></i>
|
||||
<span>Email</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "45px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div style={{ flex: 1 }}>
|
||||
<ul className="list-unstyled mb-0">
|
||||
{contactProfile.contactEmails.map((email, idx) => (
|
||||
{profileContactState.contactEmails.map((email, idx) => (
|
||||
<li className="d-flex align-items-center mb-1" key={idx}>
|
||||
<i className="bx bx-envelope bx-xs me-1 mt-1"></i>
|
||||
<span className="me-1 flex-grow text-break overflow-wrap">
|
||||
<span className="me-1 text-break overflow-wrap">
|
||||
{email.emailAddress}
|
||||
</span>
|
||||
<i
|
||||
className={`bx bx-copy-alt cursor-pointer bx-xs text-start ${
|
||||
copiedIndex === idx
|
||||
? "text-secondary"
|
||||
: "text-primary"
|
||||
}`}
|
||||
className={`bx bx-copy-alt cursor-pointer bx-xs text-start ${copiedIndex === idx ? "text-secondary" : "text-primary"
|
||||
}`}
|
||||
title={copiedIndex === idx ? "Copied!" : "Copy Email"}
|
||||
style={{ flexShrink: 0 }}
|
||||
onClick={() => handleCopy(email.emailAddress, idx)}
|
||||
@ -84,17 +125,22 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{contactProfile?.contactPhones?.length > 0 && (
|
||||
<div className="d-flex mb-2">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Phone : </p>
|
||||
{profileContactState?.contactPhones?.length > 0 && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-center">
|
||||
<i className="bx bx-phone bx-xs me-2"></i>
|
||||
<span>Phone</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "40px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul className="list-inline mb-0">
|
||||
{contactProfile?.contactPhones.map((phone, idx) => (
|
||||
<li className="list-inline-item me-3" key={idx}>
|
||||
<i className="bx bx-phone bx-xs me-1"></i>
|
||||
{profileContactState.contactPhones.map((phone, idx) => (
|
||||
<li className="list-inline-item me-1" key={idx}>
|
||||
{phone.phoneNumber}
|
||||
{idx < profileContactState.contactPhones.length - 1 && ","}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
@ -102,74 +148,93 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{contactProfile?.createdAt && (
|
||||
<div className="d-flex mb-2">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Created : </p>
|
||||
{profileContactState?.createdAt && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-center">
|
||||
<i className="bx bx-calendar-week bx-xs me-2"></i>
|
||||
<span>Created</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "30px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div className="d-flex align-items-center">
|
||||
<li className="list-inline-item">
|
||||
<i className="bx bx-calendar-week bx-xs me-1"></i>
|
||||
{moment(contactProfile.createdAt).format("MMMM, DD YYYY")}
|
||||
</li>
|
||||
<span>
|
||||
{moment(profileContactState.createdAt).format("MMMM DD, YYYY")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{contactProfile?.address && (
|
||||
<div className="d-flex mb-2">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Location:</p>
|
||||
</div>
|
||||
<div className="d-flex align-items-center">
|
||||
<i className="bx bx-map bx-xs me-1 "></i>
|
||||
<span className="text-break small">
|
||||
{contactProfile.address}
|
||||
|
||||
{profileContactState?.address && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-start">
|
||||
<i className="bx bx-map bx-xs me-2 mt-1"></i>
|
||||
<span>Location</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "26px" }}>:</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-break small">{profileContactState.address}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="col-12 col-md-6 d-flex flex-column text-start">
|
||||
{contactProfile?.organization && (
|
||||
<div className="d-flex mb-2">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Orgnization : </p>
|
||||
{profileContactState?.organization && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-center">
|
||||
<i className="fa-solid fa-briefcase me-2"></i>
|
||||
<span>Organization</span>
|
||||
</span>
|
||||
<span className="ms-2">:</span>
|
||||
</div>
|
||||
<div className="d-flex align-items-center">
|
||||
<i className="fa-solid fa-briefcase me-2"></i>
|
||||
|
||||
<div className="d-flex align-items-center">
|
||||
<span style={{ wordBreak: "break-word" }}>
|
||||
{contactProfile.organization}
|
||||
{profileContactState.organization}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{contactProfile?.contactCategory && (
|
||||
<div className="d-flex mb-2">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Category : </p>
|
||||
|
||||
{profileContactState?.contactCategory && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-center">
|
||||
<i className="bx bx-user bx-xs me-2"></i>
|
||||
<span>Category</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "28px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul className="list-inline mb-0">
|
||||
<li className="list-inline-item">
|
||||
<i className="bx bx-user bx-xs me-1"></i>
|
||||
{contactProfile.contactCategory.name}
|
||||
{profileContactState.contactCategory.name}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{contactProfile?.tags?.length > 0 && (
|
||||
<div className="d-flex mb-2">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Tags : </p>
|
||||
|
||||
{profileContactState?.tags?.length > 0 && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-center">
|
||||
<i className="fa-solid fa-tag me-2"></i>
|
||||
<span>Tags</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "60px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul className="list-inline mb-0">
|
||||
{contactProfile.tags.map((tag, index) => (
|
||||
{profileContactState.tags.map((tag, index) => (
|
||||
<li key={index} className="list-inline-item">
|
||||
<i className="fa-solid fa-tag me-1"></i>
|
||||
{tag.name}
|
||||
</li>
|
||||
))}
|
||||
@ -178,75 +243,93 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{contactProfile?.buckets?.length > 0 && (
|
||||
<div className="d-flex ">
|
||||
{contactProfile?.contactEmails?.length > 0 && (
|
||||
<div className="d-flex mb-2 align-items-center">
|
||||
<div style={{ width: "100px", minWidth: "100px" }}>
|
||||
<p className="m-0">Buckets : </p>
|
||||
</div>
|
||||
<div>
|
||||
<ul className="list-inline mb-0">
|
||||
{contactProfile.buckets.map((bucket) => (
|
||||
<li className="list-inline-item me-2" key={bucket.id}>
|
||||
<span className="badge bg-label-primary my-1">
|
||||
{bucket.name}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{profileContactState?.buckets?.length > 0 && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-center">
|
||||
<i className="bx bx-layer me-1"></i>
|
||||
<span>Buckets</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "35px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ul className="list-inline mb-0">
|
||||
{profileContactState.buckets.map((bucket) => (
|
||||
<li className="list-inline-item me-2" key={bucket.id}>
|
||||
<span className="badge bg-label-primary my-1">
|
||||
{bucket.name}
|
||||
</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{contactProfile?.projects?.length > 0 && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div style={{ minWidth: "100px" }}>
|
||||
<p className="m-0 text-start">Projects :</p>
|
||||
</div>
|
||||
<div className="text-start">
|
||||
<ul className="list-inline mb-0">
|
||||
{contactProfile.projects.map((project, index) => (
|
||||
<li className="list-inline-item me-2" key={project.id}>
|
||||
{project.name}
|
||||
{index < contactProfile.projects.length - 1 && ","}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div style={{ minWidth: "100px" }}>
|
||||
<p className="m-0 text-start">Description :</p>
|
||||
{profileContactState?.projects?.length > 0 && (
|
||||
<div className="d-flex mb-2 align-items-start">
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-center">
|
||||
<i className="bx bx-building-house me-1"></i>
|
||||
<span>Projects</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "28px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div className="text-start">
|
||||
<ul className="list-inline mb-0">
|
||||
{profileContactState.projects.map((project, index) => (
|
||||
<li className="list-inline-item me-2" key={project.id}>
|
||||
{project.name}
|
||||
{index < profileContactState.projects.length - 1 && ","}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="d-flex mb-2 align-items-start" style={{ marginLeft: "3rem" }}>
|
||||
<div className="d-flex" style={{ minWidth: "130px" }}>
|
||||
<span className="d-flex align-items-start">
|
||||
<i className="bx bx-book me-1"></i>
|
||||
<span>Description</span>
|
||||
</span>
|
||||
<span style={{ marginLeft: "10px" }}>:</span>
|
||||
</div>
|
||||
|
||||
<div className="text-start">
|
||||
{displayText}
|
||||
{isLong && (
|
||||
<span
|
||||
onClick={toggleReadMore}
|
||||
className="text-primary mx-1 cursor-pointer"
|
||||
>
|
||||
{expanded ? "Read less" : "Read more"}
|
||||
</span>
|
||||
<>
|
||||
<br />
|
||||
<span
|
||||
onClick={toggleReadMore}
|
||||
className="text-primary mx-1 cursor-pointer"
|
||||
>
|
||||
{expanded ? "Read less" : "Read more"}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<hr className="my-1" />
|
||||
<NotesDirectory
|
||||
refetchProfile={refetch}
|
||||
isLoading={loading}
|
||||
contactProfile={profileContact}
|
||||
setProfileContact={setProfileContact}
|
||||
contactProfile={profileContactState}
|
||||
setProfileContact={setProfileContactState}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfileContactDirectory;
|
||||
export default ProfileContactDirectory;
|
@ -8,7 +8,6 @@ import {
|
||||
import Breadcrumb from "../../components/common/Breadcrumb";
|
||||
import AttendanceLog from "../../components/Activities/AttendcesLogs";
|
||||
import Attendance from "../../components/Activities/Attendance";
|
||||
// import AttendanceModel from "../../components/Activities/AttendanceModel";
|
||||
import showToast from "../../services/toastService";
|
||||
import Regularization from "../../components/Activities/Regularization";
|
||||
import { useAttendance } from "../../hooks/useAttendance";
|
||||
@ -18,12 +17,12 @@ import { markCurrentAttendance } from "../../slices/apiSlice/attendanceAllSlice"
|
||||
import { useHasUserPermission } from "../../hooks/useHasUserPermission";
|
||||
import { REGULARIZE_ATTENDANCE } from "../../utils/constants";
|
||||
import eventBus from "../../services/eventBus";
|
||||
// import AttendanceRepository from "../../repositories/AttendanceRepository";
|
||||
import AttendanceRepository from "../../repositories/AttendanceRepository"; // Make sure this is imported if used
|
||||
import { useProjectName } from "../../hooks/useProjects";
|
||||
import GlobalModel from "../../components/common/GlobalModel";
|
||||
import CheckCheckOutmodel from "../../components/Activities/CheckCheckOutForm";
|
||||
import AttendLogs from "../../components/Activities/AttendLogs";
|
||||
// import Confirmation from "../../components/Activities/Confirmation";
|
||||
import Confirmation from "../../components/Activities/Confirmation"; // Make sure this is imported if used
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
const AttendancePage = () => {
|
||||
@ -37,7 +36,7 @@ const AttendancePage = () => {
|
||||
attendance,
|
||||
loading: attLoading,
|
||||
recall: attrecall,
|
||||
} = useAttendace(selectedProject);
|
||||
} = useAttendance(selectedProject); // Corrected typo: useAttendace to useAttendance
|
||||
const [attendances, setAttendances] = useState();
|
||||
const [empRoles, setEmpRoles] = useState(null);
|
||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||
@ -58,10 +57,10 @@ const AttendancePage = () => {
|
||||
// Ensure attendances is not null before mapping
|
||||
const updatedAttendance = attendances
|
||||
? attendances.map((item) =>
|
||||
item.employeeId === msg.response.employeeId
|
||||
? { ...item, ...msg.response }
|
||||
: item
|
||||
)
|
||||
item.employeeId === msg.response.employeeId
|
||||
? { ...item, ...msg.response }
|
||||
: item
|
||||
)
|
||||
: [msg.response]; // If attendances is null, initialize with new response
|
||||
|
||||
cacheData("Attendance", {
|
||||
@ -71,12 +70,13 @@ const AttendancePage = () => {
|
||||
setAttendances(updatedAttendance);
|
||||
}
|
||||
},
|
||||
[selectedProject, attendances] // Removed attrecall as it's not a direct dependency for this state update
|
||||
[selectedProject, attendances]
|
||||
);
|
||||
|
||||
const employeeHandler = useCallback(
|
||||
(msg) => {
|
||||
if (attendances?.some((item) => item.employeeId === msg.employeeId)) {
|
||||
// Ensure AttendanceRepository is imported and available
|
||||
AttendanceRepository.getAttendance(selectedProject)
|
||||
.then((response) => {
|
||||
cacheData("Attendance", { data: response.data, selectedProject });
|
||||
@ -127,10 +127,10 @@ const AttendancePage = () => {
|
||||
if (action.payload && action.payload.employeeId) {
|
||||
const updatedAttendance = attendances
|
||||
? attendances.map((item) =>
|
||||
item.employeeId === action.payload.employeeId
|
||||
? { ...item, ...action.payload }
|
||||
: item
|
||||
)
|
||||
item.employeeId === action.payload.employeeId
|
||||
? { ...item, ...action.payload }
|
||||
: item
|
||||
)
|
||||
: [action.payload]; // If attendances is null, initialize with new payload
|
||||
|
||||
cacheData("Attendance", {
|
||||
@ -151,6 +151,7 @@ const AttendancePage = () => {
|
||||
const handleToggle = (event) => {
|
||||
setShowPending(event.target.checked);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedProject === null && projectNames.length > 0) {
|
||||
dispatch(setProjectId(projectNames[0]?.id));
|
||||
@ -162,8 +163,8 @@ const AttendancePage = () => {
|
||||
if (modelConfig !== null) {
|
||||
openModel();
|
||||
}
|
||||
}, [modelConfig]); // Removed isCreateModalOpen from here as it's set by openModel()
|
||||
|
||||
}, [modelConfig]);
|
||||
|
||||
useEffect(() => {
|
||||
setAttendances(attendance);
|
||||
}, [attendance]);
|
||||
@ -204,27 +205,8 @@ const AttendancePage = () => {
|
||||
return () => eventBus.off("attendance", handler);
|
||||
}, [handler]);
|
||||
|
||||
// useEffect(() => {
|
||||
// eventBus.on("employee", employeeHandler);
|
||||
// return () => eventBus.off("employee", employeeHandler);
|
||||
// }, [employeeHandler]);
|
||||
return (
|
||||
<>
|
||||
{/* {isCreateModalOpen && modelConfig && (
|
||||
<div
|
||||
className="modal fade show"
|
||||
style={{ display: "block" }}
|
||||
id="check-Out-modalg"
|
||||
tabIndex="-1"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<AttendanceModel
|
||||
modelConfig={modelConfig}
|
||||
closeModal={closeModal}
|
||||
handleSubmitForm={handleSubmit}
|
||||
/>
|
||||
</div>
|
||||
)} */}
|
||||
{isCreateModalOpen && modelConfig && (
|
||||
<GlobalModel
|
||||
isOpen={isCreateModalOpen}
|
||||
@ -309,16 +291,14 @@ const AttendancePage = () => {
|
||||
</ul>
|
||||
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3" >
|
||||
{activeTab === "all" && (
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<Attendance
|
||||
attendance={filteredAndSearchedTodayAttendance()}
|
||||
handleModalData={handleModalData}
|
||||
getRole={getRole}
|
||||
setshowOnlyCheckout={setShowPending}
|
||||
showOnlyCheckout={showPending}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="tab-pane fade show active py-0">
|
||||
<Attendance
|
||||
attendance={filteredAndSearchedTodayAttendance()}
|
||||
handleModalData={handleModalData}
|
||||
getRole={getRole}
|
||||
setshowOnlyCheckout={setShowPending}
|
||||
showOnlyCheckout={showPending}
|
||||
/>
|
||||
{!attLoading && filteredAndSearchedTodayAttendance()?.length === 0 && (
|
||||
<p>
|
||||
{" "}
|
||||
@ -327,7 +307,7 @@ const AttendancePage = () => {
|
||||
: "No Employee assigned yet."}{" "}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === "logs" && (
|
||||
<div className="tab-pane fade show active py-0">
|
||||
|
Loading…
x
Reference in New Issue
Block a user