Merge pull request 'Correction in HoverPopup at Jobs View panel.' (#525) from Jobs_Side_Panel into Purchase_Invoice_Management

Reviewed-on: #525
Merged
This commit is contained in:
pramod.mahajan 2025-12-03 04:18:02 +00:00
commit 927b1840b4
3 changed files with 65 additions and 45 deletions

View File

@ -205,7 +205,7 @@ const TaskReportList = () => {
id="total_pending_task"
title="Total Pending Task"
content={
<div className="text-wrap" style={{ maxWidth: "200px" }}>
<div className="text-wrap" style={{ minWidth: "200px" }}>
This shows the total pending tasks for each activity on that date.
</div>
}

View File

@ -69,7 +69,7 @@ const ManageJobTicket = ({ Job }) => {
id="STATUS_CHANEG"
Mode="click"
className=""
align="right"
align="left"
content={
<ChangeStatus
statusId={data?.status?.id}
@ -149,7 +149,8 @@ const ManageJobTicket = ({ Job }) => {
<HoverPopup
id="BRANCH_DETAILS"
Mode="click"
align="auto"
align="right"
minWidth="340px"
boundaryRef={drawerRef}
content={<BranchDetails branch={data?.projectBranch?.id} />}
>

View File

@ -6,10 +6,6 @@ import {
togglePopup,
} from "../../slices/localVariablesSlice";
/**
* align: "auto" | "left" | "right"
* boundaryRef: optional ref to the drawer/container element to use as boundary
*/
const HoverPopup = ({
id,
title,
@ -17,7 +13,9 @@ const HoverPopup = ({
children,
className = "",
Mode = "hover",
align = "auto",
align = "auto", // <-- dynamic placement
minWidth = "250px",
maxWidth = "350px",
boundaryRef = null,
}) => {
const dispatch = useDispatch();
@ -26,20 +24,15 @@ const HoverPopup = ({
const triggerRef = useRef(null);
const popupRef = useRef(null);
const handleMouseEnter = () => {
if (Mode === "hover") dispatch(openPopup(id));
};
const handleMouseLeave = () => {
if (Mode === "hover") dispatch(closePopup(id));
};
const handleMouseEnter = () => Mode === "hover" && dispatch(openPopup(id));
const handleMouseLeave = () => Mode === "hover" && dispatch(closePopup(id));
const handleClick = (e) => {
if (Mode === "click") {
if (Mode !== "click") return;
e.stopPropagation();
dispatch(togglePopup(id));
}
};
// Close on outside click when using click mode
// Close popup when clicking outside (click mode)
useEffect(() => {
if (Mode !== "click" || !visible) return;
@ -56,40 +49,68 @@ const HoverPopup = ({
document.addEventListener("click", handler);
return () => document.removeEventListener("click", handler);
}, [Mode, visible, dispatch, id]);
}, [visible, Mode, id, dispatch]);
// ---------- DYNAMIC POSITIONING LOGIC ----------
useEffect(() => {
if (!visible || !popupRef.current || !triggerRef.current) return;
requestAnimationFrame(() => {
const popup = popupRef.current;
const boundaryEl = (boundaryRef && boundaryRef.current) || popup.parentElement;
if (!boundaryEl) return;
const trigger = triggerRef.current;
const boundaryEl =
(boundaryRef && boundaryRef.current) || popup.parentElement;
const boundaryRect = boundaryEl.getBoundingClientRect();
const triggerRect = triggerRef.current.getBoundingClientRect();
popup.style.left = "";
popup.style.right = "";
popup.style.transform = "";
popup.style.top = "";
const triggerRect = trigger.getBoundingClientRect();
const popupRect = popup.getBoundingClientRect();
const triggerCenterX = triggerRect.left + triggerRect.width / 2 - boundaryRect.left;
let left = triggerCenterX - popupRect.width / 2;
// Clamp to boundaries
left = Math.max(0, Math.min(left, boundaryRect.width - popupRect.width));
let left;
// AUTO ALIGN (smart)
if (align === "auto") {
const center =
triggerRect.left +
triggerRect.width / 2 -
boundaryRect.left -
popupRect.width / 2;
left = Math.max(
0,
Math.min(center, boundaryRect.width - popupRect.width)
);
}
// LEFT ALIGN
else if (align === "left") {
left = triggerRect.left - boundaryRect.left;
if (left + popupRect.width > boundaryRect.width) {
left = boundaryRect.width - popupRect.width; // clamp right
}
}
// RIGHT ALIGN
else if (align === "right") {
left =
triggerRect.left +
triggerRect.width -
boundaryRect.left -
popupRect.width;
if (left < 0) left = 0; // clamp left
}
popup.style.left = `${left}px`;
popup.style.top = `100%`;
});
}, [visible, align, boundaryRef]);
return (
<div
className="d-inline-block position-relative" // <-- ADD THIS !!
style={{ overflow: "visible" }}
>
<div
// ------------------------------------------------
return (
<div className="d-inline-block position-relative" style={{ overflow: "visible" }}>
<div
ref={triggerRef}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
@ -105,20 +126,18 @@ const HoverPopup = ({
className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
style={{
zIndex: 2000,
top: "100%",
minWidth: "200px",
maxWidth: "300px",
minWidth,
maxWidth,
wordWrap: "break-word",
}}
onClick={(e) => e.stopPropagation()}
>
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
<div>{content}</div>
{content}
</div>
)}
</div>
);
};
export default HoverPopup;