import { WalletIcon } from "../../icons/3dChartIcons"; import { useEffect, useRef, useState } from "react"; import { useDroppedObjectsStore, Zones, } from "../../../store/useDroppedObjectsStore"; import useModuleStore from "../../../store/useModuleStore"; import { determinePosition } from "./functions/determinePosition"; import { getActiveProperties } from "./functions/getActiveProperties"; import { addingFloatingWidgets } from "../../../services/realTimeVisulization/zoneData/addFloatingWidgets"; import { DublicateIcon, KebabIcon, DeleteIcon, } from "../../icons/ExportCommonIcons"; import DistanceLines from "./DistanceLines"; // Import the DistanceLines component interface DraggingState { zone: string; index: number; initialPosition: { top: number | "auto"; left: number | "auto"; right: number | "auto"; bottom: number | "auto"; }; } const DroppedObjects: React.FC = () => { const zones = useDroppedObjectsStore((state) => state.zones); const [openKebabId, setOpenKebabId] = useState(null); const updateObjectPosition = useDroppedObjectsStore( (state) => state.updateObjectPosition ); const [draggingIndex, setDraggingIndex] = useState( null ); const [offset, setOffset] = useState<[number, number] | null>(null); const [activeEdges, setActiveEdges] = useState<{ vertical: "top" | "bottom"; horizontal: "left" | "right"; } | null>(null); // State to track active edges for distance lines const [currentPosition, setCurrentPosition] = useState<{ top: number | "auto"; left: number | "auto"; right: number | "auto"; bottom: number | "auto"; } | null>(null); // State to track the current position during drag const animationRef = useRef(null); const { activeModule } = useModuleStore(); // Clean up animation frame on unmount useEffect(() => { return () => { if (animationRef.current) { cancelAnimationFrame(animationRef.current); } }; }, []); const zoneEntries = Object.entries(zones); if (zoneEntries.length === 0) return null; const [zoneName, zone] = zoneEntries[0]; const handlePointerDown = (event: React.PointerEvent, index: number) => { const obj = zone.objects[index]; const container = document.getElementById("real-time-vis-canvas"); if (!container) return; const rect = container.getBoundingClientRect(); const relativeX = event.clientX - rect.left; const relativeY = event.clientY - rect.top; // Determine active properties for the initial position const [activeProp1, activeProp2] = getActiveProperties(obj.position); // Set active edges for distance lines const vertical = activeProp1 === "top" ? "top" : "bottom"; const horizontal = activeProp2 === "left" ? "left" : "right"; setActiveEdges({ vertical, horizontal }); // Store the initial position strategy and active edges setDraggingIndex({ zone: zoneName, index, initialPosition: { ...obj.position }, }); // Calculate offset from mouse to object edges let offsetX = 0; let offsetY = 0; if (activeProp1 === "top") { offsetY = relativeY - (obj.position.top as number); } else { offsetY = rect.height - relativeY - (obj.position.bottom as number); } if (activeProp2 === "left") { offsetX = relativeX - (obj.position.left as number); } else { offsetX = rect.width - relativeX - (obj.position.right as number); } setOffset([offsetY, offsetX]); }; const handlePointerMove = (event: React.PointerEvent) => { if (!draggingIndex || !offset) return; const container = document.getElementById("real-time-vis-canvas"); if (!container) return; const rect = container.getBoundingClientRect(); const relativeX = event.clientX - rect.left; const relativeY = event.clientY - rect.top; // Dynamically determine the current position strategy const newPositionStrategy = determinePosition(rect, relativeX, relativeY); const [activeProp1, activeProp2] = getActiveProperties(newPositionStrategy); // Update active edges for distance lines const vertical = activeProp1 === "top" ? "top" : "bottom"; const horizontal = activeProp2 === "left" ? "left" : "right"; setActiveEdges({ vertical, horizontal }); // Calculate new position based on the active properties let newY = 0; let newX = 0; if (activeProp1 === "top") { newY = relativeY - offset[0]; } else { newY = rect.height - (relativeY + offset[0]); } if (activeProp2 === "left") { newX = relativeX - offset[1]; } else { newX = rect.width - (relativeX + offset[1]); } // Apply boundaries newX = Math.max(0, Math.min(rect.width - 50, newX)); newY = Math.max(0, Math.min(rect.height - 50, newY)); // Create new position object const newPosition = { ...newPositionStrategy, [activeProp1]: newY, [activeProp2]: newX, // Clear opposite properties [activeProp1 === "top" ? "bottom" : "top"]: "auto", [activeProp2 === "left" ? "right" : "left"]: "auto", }; // Update the current position state for DistanceLines setCurrentPosition(newPosition); if (!animationRef.current) { animationRef.current = requestAnimationFrame(() => { updateObjectPosition(zoneName, draggingIndex.index, newPosition); animationRef.current = null; }); } }; const handlePointerUp = async (event: React.PointerEvent) => { try { if (!draggingIndex || !offset) return; const container = document.getElementById("real-time-vis-canvas"); if (!container) return; const rect = container.getBoundingClientRect(); const relativeX = event.clientX - rect.left; const relativeY = event.clientY - rect.top; // Only now determine the final position strategy const finalPosition = determinePosition(rect, relativeX, relativeY); const [activeProp1, activeProp2] = getActiveProperties(finalPosition); // Calculate final position using the new strategy let finalY = 0; let finalX = 0; if (activeProp1 === "top") { finalY = relativeY - offset[0]; } else { finalY = rect.height - (relativeY + offset[0]); } if (activeProp2 === "left") { finalX = relativeX - offset[1]; } else { finalX = rect.width - (relativeX + offset[1]); } // Apply boundaries finalX = Math.max(0, Math.min(rect.width - 50, finalX)); finalY = Math.max(0, Math.min(rect.height - 50, finalY)); const boundedPosition = { ...finalPosition, [activeProp1]: finalY, [activeProp2]: finalX, }; // Save to backend const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0]; const response = await addingFloatingWidgets(zone.zoneId, organization, { ...zone.objects[draggingIndex.index], position: boundedPosition, }); if (response.message === "Widget updated successfully") { updateObjectPosition(zoneName, draggingIndex.index, boundedPosition); } // Clean up setDraggingIndex(null); setOffset(null); setActiveEdges(null); // Clear active edges setCurrentPosition(null); // Reset current position if (animationRef.current) { cancelAnimationFrame(animationRef.current); animationRef.current = null; } } catch (error) { console.error("Error in handlePointerUp:", error); } }; const handleKebabClick = (id: string, event: React.MouseEvent) => { event.stopPropagation(); setOpenKebabId((prevId) => (prevId === id ? null : id)); }; const renderObjectContent = (obj: any) => { switch (obj.className) { case "floating total-card": return ( <>
{obj.header}
{obj.value}
{obj.per}
); case "warehouseThroughput floating": return ( <>

Warehouse Throughput

(+5) more in 2025

{/* */}
); case "fleetEfficiency floating": return ( <>

Fleet Efficiency

0%
{obj.per}%
Optimal
100%
); default: return null; } }; return (
{zone.objects.map((obj, index) => (
handlePointerDown(event, index)} > {renderObjectContent(obj)}
handleKebabClick(obj.id, event)} >
{openKebabId === obj.id && (
Duplicate
Delete
)}
))} {/* Render DistanceLines component during drag */} {draggingIndex !== null && activeEdges !== null && currentPosition !== null && ( )}
); }; export default DroppedObjects; // in pointer move even when i goes to top right the value not changes to top right same problem in bottom left