UI Alignment and Icon Styling Issue in Contact Card Design in Directory. #292

Closed
kartik.sharma wants to merge 65 commits from Kartik_Bug#805 into Issues_July_4W
4 changed files with 337 additions and 267 deletions

View File

@ -107,13 +107,13 @@ const CardViewDirectory = ({
{/* <li className="list-inline-item me-1 small"> {/* <li className="list-inline-item me-1 small">
<i className="fa-solid fa-briefcase me-2"></i> <i className="fa-solid fa-briefcase me-2"></i>
</li> */} </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} {contact.organization}
</li> </li>
</ul> </ul>
</div> </div>
<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={() => { onClick={() => {
if (IsActive) { if (IsActive) {

View File

@ -4,7 +4,6 @@ import Avatar from "../common/Avatar";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { z } from "zod"; import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { showText } from "pdf-lib";
import { DirectoryRepository } from "../../repositories/DirectoryRepository"; import { DirectoryRepository } from "../../repositories/DirectoryRepository";
import moment from "moment"; import moment from "moment";
import { cacheData, getCachedData } from "../../slices/apiDataManager"; import { cacheData, getCachedData } from "../../slices/apiDataManager";
@ -19,15 +18,17 @@ const schema = z.object({
const NotesDirectory = ({ const NotesDirectory = ({
refetchProfile, refetchProfile,
isLoading, isLoading,
contactProfile, contactProfile, // This contactProfile now reliably includes firstName, middleName, lastName, and fullName
setProfileContact, setProfileContact,
}) => { }) => {
const [IsActive, setIsActive] = useState(true); 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 [IsSubmitting, setIsSubmitting] = useState(false);
const [addNote, setAddNote] = useState(true); const [showEditor, setShowEditor] = useState(false);
const { const {
register, register,
handleSubmit, handleSubmit,
@ -67,102 +68,118 @@ const NotesDirectory = ({
) { ) {
const updatedProfile = { const updatedProfile = {
...cached_contactProfile.data, ...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", ""); setValue("note", "");
setIsSubmitting(false); setIsSubmitting(false);
showToast("Note added successfully!", "success"); showToast("Note added successfully!", "success");
setAddNote(true); setShowEditor(false);
setIsActive(true); setIsActive(true);
refetch(contactProfile?.id, true);
} catch (error) { } catch (error) {
setIsSubmitting(false); setIsSubmitting(false);
const msg = const msg =
error.response.data.message || error.response?.data?.message || error.message || "Error occurred during API calling";
error.message ||
"Error occured during API calling";
showToast(msg, "error"); showToast(msg, "error");
} }
}; };
const onCancel = () => { const onCancel = () => {
setValue( "note", "" ); setValue("note", "");
setShowEditor(false);
}; };
const handleSwitch = () => { const handleSwitch = () => {
setIsActive(!IsActive); setIsActive((prevIsActive) => {
if (IsActive) { const newState = !prevIsActive;
refetch(contactProfile?.id, false); 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 ( return (
<div className="text-start"> <div className="text-start mt-10">
<div className="d-flex align-items-center justify-content-between"> <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>
<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"> {showEditor && (
<span <div className="card m-2 mb-5 position-relative">
className={`btn btn-sm ${addNote ? "btn-secondary" : "btn-primary"}`} <span
onClick={() => setAddNote(!addNote)}
>
{addNote ? "Hide Editor" : "Add a Note"}
</span>
</div>
</div>
{addNote && (
<div className="card m-2 mb-5">
<button
type="button" 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" aria-label="Close"
style={{ backgroundColor: "#eee", color: "white" }} onClick={() => setShowEditor(false)}
onClick={() => setAddNote(!addNote)} >
></button> <i className="bx bx-x fs-5  p-1 text-white"></i>
{/* <div className="d-flex justify-content-end px-2"> </span>
<span
className={`btn btn-sm ${
addNote ? "btn-danger" : "btn-primary"
}`}
onClick={() => setAddNote(!addNote)}
>
{addNote ? "Hide Editor" : "Add Note"}
</span>
</div> */}
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<Editor <Editor
value={noteValue} value={noteValue}
@ -171,52 +188,42 @@ const NotesDirectory = ({
onCancel={onCancel} onCancel={onCancel}
onSubmit={handleSubmit(onSubmit)} onSubmit={handleSubmit(onSubmit)}
/> />
{errors.notes && ( {errors.note && (
<p className="text-danger small mt-1">{errors.note.message}</p> <p className="text-danger small mt-1">{errors.note.message}</p>
)} )}
</form> </form>
</div> </div>
)} )}
<div className=" justify-content-start px-1 mt-1"> <div className="justify-content-start px-1 mt-1">
{isLoading && ( {isLoading && (
<div className="text-center"> <div className="text-center">
{" "} {" "}
<p>Loading...</p>{" "} <p>Loading...</p>{" "}
</div> </div>
)} )}
{!isLoading && {!isLoading && notesToDisplay.length > 0
[...(IsActive ? contactProfile?.notes || [] : contactNotes || [])] ? notesToDisplay
.reverse() .slice()
.map((noteItem) => ( .reverse()
<NoteCardDirectory .map((noteItem) => (
refetchProfile={refetchProfile} <NoteCardDirectory
refetchNotes={refetch} refetchProfile={refetchProfile}
refetchContact={refetch} refetchNotes={refetch}
noteItem={noteItem} refetchContact={refetch}
contactId={contactProfile?.id} noteItem={noteItem}
setProfileContact={setProfileContact} contactId={contactProfile?.id}
key={noteItem.id} setProfileContact={setProfileContact}
/> key={noteItem.id}
))} />
))
{IsActive && ( : !isLoading &&
<div> !showEditor && (
{!isLoading && contactProfile?.notes.length == 0 && !addNote && ( <div className="text-center mt-5">{noNotesMessage}</div>
<div className="text-center mt-5">No Notes Found</div>
)} )}
</div>
)}
{!IsActive && (
<div>
{!isLoading && contactNotes.length == 0 && !addNote && (
<div className="text-center mt-5">No Notes Found</div>
)}
</div>
)}
</div> </div>
</div> </div>
); );
}; };
export default NotesDirectory; export default NotesDirectory;

View File

@ -8,9 +8,10 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
const { contactProfile, loading, refetch } = useContactProfile(contact?.id); const { contactProfile, loading, refetch } = useContactProfile(contact?.id);
const [copiedIndex, setCopiedIndex] = useState(null); const [copiedIndex, setCopiedIndex] = useState(null);
const [profileContact, setProfileContact] = useState(); const [profileContactState, setProfileContactState] = useState(null);
const [expanded, setExpanded] = useState(false); const [expanded, setExpanded] = useState(false);
const description = contactProfile?.description || "";
const description = profileContactState?.description || "";
const limit = 500; const limit = 500;
const toggleReadMore = () => setExpanded(!expanded); const toggleReadMore = () => setExpanded(!expanded);
@ -19,14 +20,51 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
const displayText = expanded const displayText = expanded
? description ? description
: description.slice(0, limit) + (isLong ? "..." : ""); : description.slice(0, limit) + (isLong ? "..." : "");
useEffect(() => { useEffect(() => {
setProfileContact(contactProfile); if (contactProfile) {
}, [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) => { const handleCopy = (email, index) => {
navigator.clipboard.writeText(email); navigator.clipboard.writeText(email);
setCopiedIndex(index); setCopiedIndex(index);
setTimeout(() => setCopiedIndex(null), 2000); // Reset after 2 seconds setTimeout(() => setCopiedIndex(null), 2000);
}; };
return ( return (
<div className="p-1"> <div className="p-1">
<div className="text-center m-0 p-0"> <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"> <div className="d-flex flex-column text-start ms-1">
<span className="m-0 fw-semibold">{contact?.name}</span> <span className="m-0 fw-semibold">{contact?.name}</span>
<small className="text-secondary small-text"> <small className="text-secondary small-text">
{/* {contactProfile?.tags?.map((tag) => tag.name).join(" | ")} */} {profileContactState?.designation}
{contactProfile?.designation}
</small> </small>
</div> </div>
</div> </div>
<div className="row"> <div className="row ms-9">
<div className="col-12 col-md-6 d-flex flex-column text-start"> <div className="col-12 col-md-6 d-flex flex-column text-start">
{contactProfile?.contactEmails?.length > 0 && ( {profileContactState?.contactEmails?.length > 0 && (
<div className="d-flex mb-2"> <div className="d-flex mb-2 align-items-start">
<div style={{ width: "100px", minWidth: "100px" }}> <div
<p className="m-0">Email:</p> 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>
<div style={{ flex: 1 }}> <div style={{ flex: 1 }}>
<ul className="list-unstyled mb-0"> <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}> <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 text-break overflow-wrap">
<span className="me-1 flex-grow text-break overflow-wrap">
{email.emailAddress} {email.emailAddress}
</span> </span>
<i <i
className={`bx bx-copy-alt cursor-pointer bx-xs text-start ${ className={`bx bx-copy-alt cursor-pointer bx-xs text-start ${copiedIndex === idx ? "text-secondary" : "text-primary"
copiedIndex === idx }`}
? "text-secondary"
: "text-primary"
}`}
title={copiedIndex === idx ? "Copied!" : "Copy Email"} title={copiedIndex === idx ? "Copied!" : "Copy Email"}
style={{ flexShrink: 0 }} style={{ flexShrink: 0 }}
onClick={() => handleCopy(email.emailAddress, idx)} onClick={() => handleCopy(email.emailAddress, idx)}
@ -84,17 +125,22 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
</div> </div>
)} )}
{contactProfile?.contactPhones?.length > 0 && ( {profileContactState?.contactPhones?.length > 0 && (
<div className="d-flex mb-2"> <div className="d-flex mb-2 align-items-start">
<div style={{ width: "100px", minWidth: "100px" }}> <div className="d-flex" style={{ minWidth: "130px" }}>
<p className="m-0">Phone : </p> <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>
<div> <div>
<ul className="list-inline mb-0"> <ul className="list-inline mb-0">
{contactProfile?.contactPhones.map((phone, idx) => ( {profileContactState.contactPhones.map((phone, idx) => (
<li className="list-inline-item me-3" key={idx}> <li className="list-inline-item me-1" key={idx}>
<i className="bx bx-phone bx-xs me-1"></i>
{phone.phoneNumber} {phone.phoneNumber}
{idx < profileContactState.contactPhones.length - 1 && ","}
</li> </li>
))} ))}
</ul> </ul>
@ -102,74 +148,93 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
</div> </div>
)} )}
{contactProfile?.createdAt && ( {profileContactState?.createdAt && (
<div className="d-flex mb-2"> <div className="d-flex mb-2 align-items-start">
<div style={{ width: "100px", minWidth: "100px" }}> <div className="d-flex" style={{ minWidth: "130px" }}>
<p className="m-0">Created : </p> <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>
<div className="d-flex align-items-center"> <div className="d-flex align-items-center">
<li className="list-inline-item"> <span>
<i className="bx bx-calendar-week bx-xs me-1"></i> {moment(profileContactState.createdAt).format("MMMM DD, YYYY")}
{moment(contactProfile.createdAt).format("MMMM, DD YYYY")} </span>
</li>
</div> </div>
</div> </div>
)} )}
{contactProfile?.address && (
<div className="d-flex mb-2"> {profileContactState?.address && (
<div style={{ width: "100px", minWidth: "100px" }}> <div className="d-flex mb-2 align-items-start">
<p className="m-0">Location:</p> <div className="d-flex" style={{ minWidth: "130px" }}>
</div> <span className="d-flex align-items-start">
<div className="d-flex align-items-center"> <i className="bx bx-map bx-xs me-2 mt-1"></i>
<i className="bx bx-map bx-xs me-1 "></i> <span>Location</span>
<span className="text-break small">
{contactProfile.address}
</span> </span>
<span style={{ marginLeft: "26px" }}>:</span>
</div>
<div>
<span className="text-break small">{profileContactState.address}</span>
</div> </div>
</div> </div>
)} )}
</div> </div>
<div className="col-12 col-md-6 d-flex flex-column text-start"> <div className="col-12 col-md-6 d-flex flex-column text-start">
{contactProfile?.organization && ( {profileContactState?.organization && (
<div className="d-flex mb-2"> <div className="d-flex mb-2 align-items-start">
<div style={{ width: "100px", minWidth: "100px" }}> <div className="d-flex" style={{ minWidth: "130px" }}>
<p className="m-0">Orgnization : </p> <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>
<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" }}> <span style={{ wordBreak: "break-word" }}>
{contactProfile.organization} {profileContactState.organization}
</span> </span>
</div> </div>
</div> </div>
)} )}
{contactProfile?.contactCategory && (
<div className="d-flex mb-2"> {profileContactState?.contactCategory && (
<div style={{ width: "100px", minWidth: "100px" }}> <div className="d-flex mb-2 align-items-start">
<p className="m-0">Category : </p> <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>
<div> <div>
<ul className="list-inline mb-0"> <ul className="list-inline mb-0">
<li className="list-inline-item"> <li className="list-inline-item">
<i className="bx bx-user bx-xs me-1"></i> {profileContactState.contactCategory.name}
{contactProfile.contactCategory.name}
</li> </li>
</ul> </ul>
</div> </div>
</div> </div>
)} )}
{contactProfile?.tags?.length > 0 && (
<div className="d-flex mb-2"> {profileContactState?.tags?.length > 0 && (
<div style={{ width: "100px", minWidth: "100px" }}> <div className="d-flex mb-2 align-items-start">
<p className="m-0">Tags : </p> <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>
<div> <div>
<ul className="list-inline mb-0"> <ul className="list-inline mb-0">
{contactProfile.tags.map((tag, index) => ( {profileContactState.tags.map((tag, index) => (
<li key={index} className="list-inline-item"> <li key={index} className="list-inline-item">
<i className="fa-solid fa-tag me-1"></i>
{tag.name} {tag.name}
</li> </li>
))} ))}
@ -178,75 +243,93 @@ const ProfileContactDirectory = ({ contact, setOpen_contact, closeModal }) => {
</div> </div>
)} )}
{contactProfile?.buckets?.length > 0 && ( {profileContactState?.buckets?.length > 0 && (
<div className="d-flex "> <div className="d-flex mb-2 align-items-start">
{contactProfile?.contactEmails?.length > 0 && ( <div className="d-flex" style={{ minWidth: "130px" }}>
<div className="d-flex mb-2 align-items-center"> <span className="d-flex align-items-center">
<div style={{ width: "100px", minWidth: "100px" }}> <i className="bx bx-layer me-1"></i>
<p className="m-0">Buckets : </p> <span>Buckets</span>
</div> </span>
<div> <span style={{ marginLeft: "35px" }}>:</span>
<ul className="list-inline mb-0"> </div>
{contactProfile.buckets.map((bucket) => (
<li className="list-inline-item me-2" key={bucket.id}> <div>
<span className="badge bg-label-primary my-1"> <ul className="list-inline mb-0">
{bucket.name} {profileContactState.buckets.map((bucket) => (
</span> <li className="list-inline-item me-2" key={bucket.id}>
</li> <span className="badge bg-label-primary my-1">
))} {bucket.name}
</ul> </span>
</div> </li>
</div> ))}
)} </ul>
</div>
</div> </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"> {profileContactState?.projects?.length > 0 && (
<div style={{ minWidth: "100px" }}> <div className="d-flex mb-2 align-items-start">
<p className="m-0 text-start">Description :</p> <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>
<div className="text-start"> <div className="text-start">
{displayText} {displayText}
{isLong && ( {isLong && (
<span <>
onClick={toggleReadMore} <br />
className="text-primary mx-1 cursor-pointer" <span
> onClick={toggleReadMore}
{expanded ? "Read less" : "Read more"} className="text-primary mx-1 cursor-pointer"
</span> >
{expanded ? "Read less" : "Read more"}
</span>
</>
)} )}
</div> </div>
</div> </div>
<hr className="my-1" /> <hr className="my-1" />
<NotesDirectory <NotesDirectory
refetchProfile={refetch} refetchProfile={refetch}
isLoading={loading} isLoading={loading}
contactProfile={profileContact} contactProfile={profileContactState}
setProfileContact={setProfileContact} setProfileContact={setProfileContactState}
/> />
</div> </div>
</div> </div>
); );
}; };
export default ProfileContactDirectory; export default ProfileContactDirectory;

View File

@ -8,7 +8,6 @@ import {
import Breadcrumb from "../../components/common/Breadcrumb"; import Breadcrumb from "../../components/common/Breadcrumb";
import AttendanceLog from "../../components/Activities/AttendcesLogs"; import AttendanceLog from "../../components/Activities/AttendcesLogs";
import Attendance from "../../components/Activities/Attendance"; import Attendance from "../../components/Activities/Attendance";
// import AttendanceModel from "../../components/Activities/AttendanceModel";
import showToast from "../../services/toastService"; import showToast from "../../services/toastService";
import Regularization from "../../components/Activities/Regularization"; import Regularization from "../../components/Activities/Regularization";
import { useAttendance } from "../../hooks/useAttendance"; import { useAttendance } from "../../hooks/useAttendance";
@ -18,12 +17,12 @@ import { markCurrentAttendance } from "../../slices/apiSlice/attendanceAllSlice"
import { useHasUserPermission } from "../../hooks/useHasUserPermission"; import { useHasUserPermission } from "../../hooks/useHasUserPermission";
import { REGULARIZE_ATTENDANCE } from "../../utils/constants"; import { REGULARIZE_ATTENDANCE } from "../../utils/constants";
import eventBus from "../../services/eventBus"; 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 { useProjectName } from "../../hooks/useProjects";
import GlobalModel from "../../components/common/GlobalModel"; import GlobalModel from "../../components/common/GlobalModel";
import CheckCheckOutmodel from "../../components/Activities/CheckCheckOutForm"; import CheckCheckOutmodel from "../../components/Activities/CheckCheckOutForm";
import AttendLogs from "../../components/Activities/AttendLogs"; 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"; import { useQueryClient } from "@tanstack/react-query";
const AttendancePage = () => { const AttendancePage = () => {
@ -37,7 +36,7 @@ const AttendancePage = () => {
attendance, attendance,
loading: attLoading, loading: attLoading,
recall: attrecall, recall: attrecall,
} = useAttendace(selectedProject); } = useAttendance(selectedProject); // Corrected typo: useAttendace to useAttendance
const [attendances, setAttendances] = useState(); const [attendances, setAttendances] = useState();
const [empRoles, setEmpRoles] = useState(null); const [empRoles, setEmpRoles] = useState(null);
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false); const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
@ -58,10 +57,10 @@ const AttendancePage = () => {
// Ensure attendances is not null before mapping // Ensure attendances is not null before mapping
const updatedAttendance = attendances const updatedAttendance = attendances
? attendances.map((item) => ? attendances.map((item) =>
item.employeeId === msg.response.employeeId item.employeeId === msg.response.employeeId
? { ...item, ...msg.response } ? { ...item, ...msg.response }
: item : item
) )
: [msg.response]; // If attendances is null, initialize with new response : [msg.response]; // If attendances is null, initialize with new response
cacheData("Attendance", { cacheData("Attendance", {
@ -71,12 +70,13 @@ const AttendancePage = () => {
setAttendances(updatedAttendance); setAttendances(updatedAttendance);
} }
}, },
[selectedProject, attendances] // Removed attrecall as it's not a direct dependency for this state update [selectedProject, attendances]
); );
const employeeHandler = useCallback( const employeeHandler = useCallback(
(msg) => { (msg) => {
if (attendances?.some((item) => item.employeeId === msg.employeeId)) { if (attendances?.some((item) => item.employeeId === msg.employeeId)) {
// Ensure AttendanceRepository is imported and available
AttendanceRepository.getAttendance(selectedProject) AttendanceRepository.getAttendance(selectedProject)
.then((response) => { .then((response) => {
cacheData("Attendance", { data: response.data, selectedProject }); cacheData("Attendance", { data: response.data, selectedProject });
@ -127,10 +127,10 @@ const AttendancePage = () => {
if (action.payload && action.payload.employeeId) { if (action.payload && action.payload.employeeId) {
const updatedAttendance = attendances const updatedAttendance = attendances
? attendances.map((item) => ? attendances.map((item) =>
item.employeeId === action.payload.employeeId item.employeeId === action.payload.employeeId
? { ...item, ...action.payload } ? { ...item, ...action.payload }
: item : item
) )
: [action.payload]; // If attendances is null, initialize with new payload : [action.payload]; // If attendances is null, initialize with new payload
cacheData("Attendance", { cacheData("Attendance", {
@ -151,6 +151,7 @@ const AttendancePage = () => {
const handleToggle = (event) => { const handleToggle = (event) => {
setShowPending(event.target.checked); setShowPending(event.target.checked);
}; };
useEffect(() => { useEffect(() => {
if (selectedProject === null && projectNames.length > 0) { if (selectedProject === null && projectNames.length > 0) {
dispatch(setProjectId(projectNames[0]?.id)); dispatch(setProjectId(projectNames[0]?.id));
@ -162,8 +163,8 @@ const AttendancePage = () => {
if (modelConfig !== null) { if (modelConfig !== null) {
openModel(); openModel();
} }
}, [modelConfig]); // Removed isCreateModalOpen from here as it's set by openModel() }, [modelConfig]);
useEffect(() => { useEffect(() => {
setAttendances(attendance); setAttendances(attendance);
}, [attendance]); }, [attendance]);
@ -204,27 +205,8 @@ const AttendancePage = () => {
return () => eventBus.off("attendance", handler); return () => eventBus.off("attendance", handler);
}, [handler]); }, [handler]);
// useEffect(() => {
// eventBus.on("employee", employeeHandler);
// return () => eventBus.off("employee", employeeHandler);
// }, [employeeHandler]);
return ( 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 && ( {isCreateModalOpen && modelConfig && (
<GlobalModel <GlobalModel
isOpen={isCreateModalOpen} isOpen={isCreateModalOpen}
@ -309,16 +291,14 @@ const AttendancePage = () => {
</ul> </ul>
<div className="tab-content attedanceTabs py-0 px-1 px-sm-3" > <div className="tab-content attedanceTabs py-0 px-1 px-sm-3" >
{activeTab === "all" && ( {activeTab === "all" && (
<div className="tab-pane fade show active py-0"> <div className="tab-pane fade show active py-0">
<Attendance <Attendance
attendance={filteredAndSearchedTodayAttendance()} attendance={filteredAndSearchedTodayAttendance()}
handleModalData={handleModalData} handleModalData={handleModalData}
getRole={getRole} getRole={getRole}
setshowOnlyCheckout={setShowPending} setshowOnlyCheckout={setShowPending}
showOnlyCheckout={showPending} showOnlyCheckout={showPending}
/> />
</div>
)}
{!attLoading && filteredAndSearchedTodayAttendance()?.length === 0 && ( {!attLoading && filteredAndSearchedTodayAttendance()?.length === 0 && (
<p> <p>
{" "} {" "}
@ -327,7 +307,7 @@ const AttendancePage = () => {
: "No Employee assigned yet."}{" "} : "No Employee assigned yet."}{" "}
</p> </p>
)} )}
</> </div>
)} )}
{activeTab === "logs" && ( {activeTab === "logs" && (
<div className="tab-pane fade show active py-0"> <div className="tab-pane fade show active py-0">