Branch Name:
@@ -149,7 +149,8 @@ const ManageJobTicket = ({ Job }) => {
}
>
diff --git a/src/components/common/HoverPopup.jsx b/src/components/common/HoverPopup.jsx
index 232ced5d..9c5f8e13 100644
--- a/src/components/common/HoverPopup.jsx
+++ b/src/components/common/HoverPopup.jsx
@@ -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") {
- e.stopPropagation();
- dispatch(togglePopup(id));
- }
+ 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 (
-
-
+
e.stopPropagation()}
>
{title &&
{title}
}
-
{content}
+ {content}
)}
);
-
};
export default HoverPopup;
diff --git a/src/components/purchase/ManagePurchase.jsx b/src/components/purchase/ManagePurchase.jsx
index 262238bf..fb757b54 100644
--- a/src/components/purchase/ManagePurchase.jsx
+++ b/src/components/purchase/ManagePurchase.jsx
@@ -28,21 +28,21 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
const stepsConfig = useMemo(
() => [
{
- name: "Party Details",
+ name: "Vendor & Project Details",
icon: "bx bx-user bx-md",
- subtitle: "Supplier & project information",
+ subtitle: "Vendor information and project association",
component:
,
},
{
- name: "Invoice & Transport",
+ name: "Invoice & Logistics",
icon: "bx bx-receipt bx-md",
- subtitle: "Invoice, eWay bill & transport info",
+ subtitle: "Invoice, e-Way bill, and logistics information",
component:
,
},
{
- name: "Payment Details",
+ name: "Invoice & Tax Amount",
icon: "bx bx-credit-card bx-md",
- subtitle: "Amount, tax & due date",
+ subtitle: "Payment terms, tax breakdown, and due dates",
component:
,
},
],
@@ -127,8 +127,6 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
const onSubmit = useCallback(
(formData) => {
- if (activeTab !== 2) return;
-
if (purchaseId) {
const payload = generatePatchOps(formData);
updatePurchase({ purchaseId, payload });
@@ -136,7 +134,7 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
CreateInvoice(formData);
}
},
- [activeTab, purchaseId, generatePatchOps, updatePurchase, CreateInvoice]
+ [purchaseId, generatePatchOps, updatePurchase, CreateInvoice]
);
return (
@@ -184,50 +182,53 @@ const ManagePurchase = ({ onClose, purchaseId }) => {
{/* --- Form Content --- */}
-
+
-
+