Compare commits
No commits in common. "927b1840b45614fd00afa0e418d0229935df681d" and "c3720df294007c9880434c421b258805c9524c5e" have entirely different histories.
927b1840b4
...
c3720df294
@ -205,7 +205,7 @@ const TaskReportList = () => {
|
|||||||
id="total_pending_task"
|
id="total_pending_task"
|
||||||
title="Total Pending Task"
|
title="Total Pending Task"
|
||||||
content={
|
content={
|
||||||
<div className="text-wrap" style={{ minWidth: "200px" }}>
|
<div className="text-wrap" style={{ maxWidth: "200px" }}>
|
||||||
This shows the total pending tasks for each activity on that date.
|
This shows the total pending tasks for each activity on that date.
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,7 +69,7 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
id="STATUS_CHANEG"
|
id="STATUS_CHANEG"
|
||||||
Mode="click"
|
Mode="click"
|
||||||
className=""
|
className=""
|
||||||
align="left"
|
align="right"
|
||||||
content={
|
content={
|
||||||
<ChangeStatus
|
<ChangeStatus
|
||||||
statusId={data?.status?.id}
|
statusId={data?.status?.id}
|
||||||
@ -141,7 +141,7 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
{data?.projectBranch && (
|
{data?.projectBranch && (
|
||||||
<div className="d-flex gap-3 my-2 position-relative" ref={drawerRef} >
|
<div className="d-flex gap-3 my-2 position-relative" ref={drawerRef} >
|
||||||
<span className="text-secondary">
|
<span className="text-secondary">
|
||||||
<i className="bx bx-buildings"></i> Branch Name:
|
<i className="bx bx-buildings"></i> Branch Name:
|
||||||
</span>
|
</span>
|
||||||
@ -149,8 +149,7 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
<HoverPopup
|
<HoverPopup
|
||||||
id="BRANCH_DETAILS"
|
id="BRANCH_DETAILS"
|
||||||
Mode="click"
|
Mode="click"
|
||||||
align="right"
|
align="auto"
|
||||||
minWidth="340px"
|
|
||||||
boundaryRef={drawerRef}
|
boundaryRef={drawerRef}
|
||||||
content={<BranchDetails branch={data?.projectBranch?.id} />}
|
content={<BranchDetails branch={data?.projectBranch?.id} />}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -6,6 +6,10 @@ import {
|
|||||||
togglePopup,
|
togglePopup,
|
||||||
} from "../../slices/localVariablesSlice";
|
} from "../../slices/localVariablesSlice";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* align: "auto" | "left" | "right"
|
||||||
|
* boundaryRef: optional ref to the drawer/container element to use as boundary
|
||||||
|
*/
|
||||||
const HoverPopup = ({
|
const HoverPopup = ({
|
||||||
id,
|
id,
|
||||||
title,
|
title,
|
||||||
@ -13,9 +17,7 @@ const HoverPopup = ({
|
|||||||
children,
|
children,
|
||||||
className = "",
|
className = "",
|
||||||
Mode = "hover",
|
Mode = "hover",
|
||||||
align = "auto", // <-- dynamic placement
|
align = "auto",
|
||||||
minWidth = "250px",
|
|
||||||
maxWidth = "350px",
|
|
||||||
boundaryRef = null,
|
boundaryRef = null,
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -24,15 +26,20 @@ const HoverPopup = ({
|
|||||||
const triggerRef = useRef(null);
|
const triggerRef = useRef(null);
|
||||||
const popupRef = useRef(null);
|
const popupRef = useRef(null);
|
||||||
|
|
||||||
const handleMouseEnter = () => Mode === "hover" && dispatch(openPopup(id));
|
const handleMouseEnter = () => {
|
||||||
const handleMouseLeave = () => Mode === "hover" && dispatch(closePopup(id));
|
if (Mode === "hover") dispatch(openPopup(id));
|
||||||
|
};
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
if (Mode === "hover") dispatch(closePopup(id));
|
||||||
|
};
|
||||||
const handleClick = (e) => {
|
const handleClick = (e) => {
|
||||||
if (Mode !== "click") return;
|
if (Mode === "click") {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
dispatch(togglePopup(id));
|
dispatch(togglePopup(id));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Close popup when clicking outside (click mode)
|
// Close on outside click when using click mode
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Mode !== "click" || !visible) return;
|
if (Mode !== "click" || !visible) return;
|
||||||
|
|
||||||
@ -49,68 +56,40 @@ const HoverPopup = ({
|
|||||||
|
|
||||||
document.addEventListener("click", handler);
|
document.addEventListener("click", handler);
|
||||||
return () => document.removeEventListener("click", handler);
|
return () => document.removeEventListener("click", handler);
|
||||||
}, [visible, Mode, id, dispatch]);
|
}, [Mode, visible, dispatch, id]);
|
||||||
|
|
||||||
// ---------- DYNAMIC POSITIONING LOGIC ----------
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!visible || !popupRef.current || !triggerRef.current) return;
|
if (!visible || !popupRef.current || !triggerRef.current) return;
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
const popup = popupRef.current;
|
const popup = popupRef.current;
|
||||||
const trigger = triggerRef.current;
|
const boundaryEl = (boundaryRef && boundaryRef.current) || popup.parentElement;
|
||||||
|
if (!boundaryEl) return;
|
||||||
const boundaryEl =
|
|
||||||
(boundaryRef && boundaryRef.current) || popup.parentElement;
|
|
||||||
|
|
||||||
const boundaryRect = boundaryEl.getBoundingClientRect();
|
const boundaryRect = boundaryEl.getBoundingClientRect();
|
||||||
const triggerRect = trigger.getBoundingClientRect();
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
||||||
|
popup.style.left = "";
|
||||||
|
popup.style.right = "";
|
||||||
|
popup.style.transform = "";
|
||||||
|
popup.style.top = "";
|
||||||
|
|
||||||
const popupRect = popup.getBoundingClientRect();
|
const popupRect = popup.getBoundingClientRect();
|
||||||
|
const triggerCenterX = triggerRect.left + triggerRect.width / 2 - boundaryRect.left;
|
||||||
|
let left = triggerCenterX - popupRect.width / 2;
|
||||||
|
|
||||||
let left;
|
// Clamp to boundaries
|
||||||
|
left = Math.max(0, Math.min(left, boundaryRect.width - popupRect.width));
|
||||||
// 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.left = `${left}px`;
|
||||||
popup.style.top = `100%`;
|
|
||||||
});
|
});
|
||||||
}, [visible, align, boundaryRef]);
|
}, [visible, align, boundaryRef]);
|
||||||
|
|
||||||
// ------------------------------------------------
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="d-inline-block position-relative" style={{ overflow: "visible" }}>
|
<div
|
||||||
|
className="d-inline-block position-relative" // <-- ADD THIS !!
|
||||||
|
style={{ overflow: "visible" }}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
|
|
||||||
ref={triggerRef}
|
ref={triggerRef}
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
@ -124,20 +103,22 @@ const HoverPopup = ({
|
|||||||
<div
|
<div
|
||||||
ref={popupRef}
|
ref={popupRef}
|
||||||
className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
|
className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
|
||||||
style={{
|
style={{
|
||||||
zIndex: 2000,
|
zIndex: 2000,
|
||||||
minWidth,
|
top: "100%",
|
||||||
maxWidth,
|
minWidth: "200px",
|
||||||
|
maxWidth: "300px",
|
||||||
wordWrap: "break-word",
|
wordWrap: "break-word",
|
||||||
}}
|
}}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
|
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
|
||||||
{content}
|
<div>{content}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HoverPopup;
|
export default HoverPopup;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user