No code changes detected; skipping commit.
This commit is contained in:
@@ -56,113 +56,159 @@ const DroppedObjects: React.FC = () => {
|
|||||||
);
|
);
|
||||||
const [offset, setOffset] = useState<[number, number] | null>(null);
|
const [offset, setOffset] = useState<[number, number] | null>(null);
|
||||||
const { setSelectedChartId } = useWidgetStore();
|
const { setSelectedChartId } = useWidgetStore();
|
||||||
const positionRef = useRef<[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<number | null>(null);
|
const animationRef = useRef<number | null>(null);
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
|
||||||
// Get the first zone and its objects
|
// Clean up animation frame on unmount
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (animationRef.current) {
|
||||||
|
cancelAnimationFrame(animationRef.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
const zoneEntries = Object.entries(zones);
|
const zoneEntries = Object.entries(zones);
|
||||||
if (zoneEntries.length === 0) return null; // No zone, nothing to render
|
if (zoneEntries.length === 0) return null;
|
||||||
const [zoneName, zone] = zoneEntries[0]; // Only render the first zone
|
const [zoneName, zone] = zoneEntries[0];
|
||||||
console.log("zone", zone);
|
|
||||||
|
function handleDuplicate(zoneName: string, index: number) {
|
||||||
|
setOpenKebabId(null)
|
||||||
|
duplicateObject(zoneName, index); // Call the duplicateObject method from the store
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDelete(zoneName: string, id: string, index: number) {
|
||||||
|
try {
|
||||||
|
const email = localStorage.getItem("email") || "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
|
||||||
|
let res = await deleteFloatingWidgetApi(id, organization);
|
||||||
|
console.log('res: ', res);
|
||||||
|
|
||||||
|
if (res.message === "FloatingWidget deleted successfully") {
|
||||||
|
deleteObject(zoneName, index); // Call the deleteObject method from the store
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error deleting floating widget:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handlePointerDown = (event: React.PointerEvent, index: number) => {
|
||||||
|
const obj = zone.objects[index];
|
||||||
|
const container = document.getElementById("real-time-vis-canvas");
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
// Handle pointer down event
|
const rect = container.getBoundingClientRect();
|
||||||
function handlePointerDown(event: React.PointerEvent, index: number) {
|
const relativeX = event.clientX - rect.left;
|
||||||
|
const relativeY = event.clientY - rect.top;
|
||||||
|
|
||||||
const [activeEdges, setActiveEdges] = useState<{
|
// Determine active properties for the initial position
|
||||||
vertical: "top" | "bottom";
|
const [activeProp1, activeProp2] = getActiveProperties(obj.position);
|
||||||
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<number | null>(null);
|
|
||||||
const { activeModule } = useModuleStore();
|
|
||||||
|
|
||||||
// Clean up animation frame on unmount
|
// Set active edges for distance lines
|
||||||
useEffect(() => {
|
const vertical = activeProp1 === "top" ? "top" : "bottom";
|
||||||
return () => {
|
const horizontal = activeProp2 === "left" ? "left" : "right";
|
||||||
if (animationRef.current) {
|
setActiveEdges({ vertical, horizontal });
|
||||||
cancelAnimationFrame(animationRef.current);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const zoneEntries = Object.entries(zones);
|
// Store the initial position strategy and active edges
|
||||||
if (zoneEntries.length === 0) return null;
|
setDraggingIndex({
|
||||||
const [zoneName, zone] = zoneEntries[0];
|
zone: zoneName,
|
||||||
|
index,
|
||||||
|
initialPosition: { ...obj.position },
|
||||||
|
});
|
||||||
|
|
||||||
function handleDuplicate(zoneName: string, index: number) {
|
// Calculate offset from mouse to object edges
|
||||||
setOpenKebabId(null)
|
let offsetX = 0;
|
||||||
duplicateObject(zoneName, index); // Call the duplicateObject method from the store
|
let offsetY = 0;
|
||||||
|
|
||||||
|
if (activeProp1 === "top") {
|
||||||
|
offsetY = relativeY - (obj.position.top as number);
|
||||||
|
} else {
|
||||||
|
offsetY = rect.height - relativeY - (obj.position.bottom as number);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDelete(zoneName: string, id: string, index: number) {
|
if (activeProp2 === "left") {
|
||||||
try {
|
offsetX = relativeX - (obj.position.left as number);
|
||||||
const email = localStorage.getItem("email") || "";
|
} else {
|
||||||
const organization = email?.split("@")[1]?.split(".")[0];
|
offsetX = rect.width - relativeX - (obj.position.right as number);
|
||||||
|
|
||||||
let res = await deleteFloatingWidgetApi(id, organization);
|
|
||||||
console.log('res: ', res);
|
|
||||||
|
|
||||||
if (res.message === "FloatingWidget deleted successfully") {
|
|
||||||
deleteObject(zoneName, index); // Call the deleteObject method from the store
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error deleting floating widget:", error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setOffset([offsetY, offsetX]);
|
||||||
|
};
|
||||||
|
|
||||||
const handlePointerDown = (event: React.PointerEvent, index: number) => {
|
const handlePointerMove = (event: React.PointerEvent) => {
|
||||||
const obj = zone.objects[index];
|
if (!draggingIndex || !offset) return;
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
|
||||||
if (!container) return;
|
|
||||||
|
|
||||||
const rect = container.getBoundingClientRect();
|
const container = document.getElementById("real-time-vis-canvas");
|
||||||
const relativeX = event.clientX - rect.left;
|
if (!container) return;
|
||||||
const relativeY = event.clientY - rect.top;
|
|
||||||
|
|
||||||
// Determine active properties for the initial position
|
const rect = container.getBoundingClientRect();
|
||||||
const [activeProp1, activeProp2] = getActiveProperties(obj.position);
|
const relativeX = event.clientX - rect.left;
|
||||||
|
const relativeY = event.clientY - rect.top;
|
||||||
|
|
||||||
// Set active edges for distance lines
|
// Dynamically determine the current position strategy
|
||||||
const vertical = activeProp1 === "top" ? "top" : "bottom";
|
const newPositionStrategy = determinePosition(rect, relativeX, relativeY);
|
||||||
const horizontal = activeProp2 === "left" ? "left" : "right";
|
const [activeProp1, activeProp2] = getActiveProperties(newPositionStrategy);
|
||||||
setActiveEdges({ vertical, horizontal });
|
|
||||||
|
|
||||||
// Store the initial position strategy and active edges
|
// Update active edges for distance lines
|
||||||
setDraggingIndex({
|
const vertical = activeProp1 === "top" ? "top" : "bottom";
|
||||||
zone: zoneName,
|
const horizontal = activeProp2 === "left" ? "left" : "right";
|
||||||
index,
|
setActiveEdges({ vertical, horizontal });
|
||||||
initialPosition: { ...obj.position },
|
|
||||||
});
|
|
||||||
|
|
||||||
// Calculate offset from mouse to object edges
|
// Calculate new position based on the active properties
|
||||||
let offsetX = 0;
|
let newY = 0;
|
||||||
let offsetY = 0;
|
let newX = 0;
|
||||||
|
|
||||||
if (activeProp1 === "top") {
|
if (activeProp1 === "top") {
|
||||||
offsetY = relativeY - (obj.position.top as number);
|
newY = relativeY - offset[0];
|
||||||
} else {
|
} else {
|
||||||
offsetY = rect.height - relativeY - (obj.position.bottom as number);
|
newY = rect.height - (relativeY + offset[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeProp2 === "left") {
|
if (activeProp2 === "left") {
|
||||||
offsetX = relativeX - (obj.position.left as number);
|
newX = relativeX - offset[1];
|
||||||
} else {
|
} else {
|
||||||
offsetX = rect.width - relativeX - (obj.position.right as number);
|
newX = rect.width - (relativeX + offset[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
setOffset([offsetY, offsetX]);
|
// 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",
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePointerMove = (event: React.PointerEvent) => {
|
// 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<HTMLDivElement>) => {
|
||||||
|
try {
|
||||||
if (!draggingIndex || !offset) return;
|
if (!draggingIndex || !offset) return;
|
||||||
|
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
const container = document.getElementById("real-time-vis-canvas");
|
||||||
@@ -172,299 +218,237 @@ const DroppedObjects: React.FC = () => {
|
|||||||
const relativeX = event.clientX - rect.left;
|
const relativeX = event.clientX - rect.left;
|
||||||
const relativeY = event.clientY - rect.top;
|
const relativeY = event.clientY - rect.top;
|
||||||
|
|
||||||
// Dynamically determine the current position strategy
|
// Only now determine the final position strategy
|
||||||
const newPositionStrategy = determinePosition(rect, relativeX, relativeY);
|
const finalPosition = determinePosition(rect, relativeX, relativeY);
|
||||||
const [activeProp1, activeProp2] = getActiveProperties(newPositionStrategy);
|
const [activeProp1, activeProp2] = getActiveProperties(finalPosition);
|
||||||
|
|
||||||
// Update active edges for distance lines
|
// Calculate final position using the new strategy
|
||||||
const vertical = activeProp1 === "top" ? "top" : "bottom";
|
let finalY = 0;
|
||||||
const horizontal = activeProp2 === "left" ? "left" : "right";
|
let finalX = 0;
|
||||||
setActiveEdges({ vertical, horizontal });
|
|
||||||
|
|
||||||
// Calculate new position based on the active properties
|
|
||||||
let newY = 0;
|
|
||||||
let newX = 0;
|
|
||||||
|
|
||||||
if (activeProp1 === "top") {
|
if (activeProp1 === "top") {
|
||||||
newY = relativeY - offset[0];
|
finalY = relativeY - offset[0];
|
||||||
} else {
|
} else {
|
||||||
newY = rect.height - (relativeY + offset[0]);
|
finalY = rect.height - (relativeY + offset[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeProp2 === "left") {
|
if (activeProp2 === "left") {
|
||||||
newX = relativeX - offset[1];
|
finalX = relativeX - offset[1];
|
||||||
} else {
|
} else {
|
||||||
newX = rect.width - (relativeX + offset[1]);
|
finalX = rect.width - (relativeX + offset[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply boundaries
|
// Apply boundaries
|
||||||
newX = Math.max(0, Math.min(rect.width - 50, newX));
|
finalX = Math.max(0, Math.min(rect.width - 50, finalX));
|
||||||
newY = Math.max(0, Math.min(rect.height - 50, newY));
|
finalY = Math.max(0, Math.min(rect.height - 50, finalY));
|
||||||
|
|
||||||
// Create new position object
|
const boundedPosition = {
|
||||||
const newPosition = {
|
...finalPosition,
|
||||||
...newPositionStrategy,
|
[activeProp1]: finalY,
|
||||||
[activeProp1]: newY,
|
[activeProp2]: finalX,
|
||||||
[activeProp2]: newX,
|
|
||||||
// Clear opposite properties
|
|
||||||
[activeProp1 === "top" ? "bottom" : "top"]: "auto",
|
|
||||||
[activeProp2 === "left" ? "right" : "left"]: "auto",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Update the current position state for DistanceLines
|
// Save to backend
|
||||||
setCurrentPosition(newPosition);
|
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 (!animationRef.current) {
|
if (response.message === "Widget updated successfully") {
|
||||||
animationRef.current = requestAnimationFrame(() => {
|
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
|
||||||
updateObjectPosition(zoneName, draggingIndex.index, newPosition);
|
|
||||||
animationRef.current = null;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const handlePointerUp = async (event: React.PointerEvent<HTMLDivElement>) => {
|
// Clean up
|
||||||
try {
|
setDraggingIndex(null);
|
||||||
if (!draggingIndex || !offset) return;
|
setOffset(null);
|
||||||
|
setActiveEdges(null); // Clear active edges
|
||||||
const container = document.getElementById("real-time-vis-canvas");
|
setCurrentPosition(null); // Reset current position
|
||||||
if (!container) return;
|
if (animationRef.current) {
|
||||||
|
cancelAnimationFrame(animationRef.current);
|
||||||
const rect = container.getBoundingClientRect();
|
animationRef.current = null;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
};
|
} 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 (
|
|
||||||
<>
|
|
||||||
<div className="header-wrapper">
|
|
||||||
<div className="header">{obj.header}</div>
|
|
||||||
<div className="data-values">
|
|
||||||
<div className="value">{obj.value}</div>
|
|
||||||
<div className="per">{obj.per}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="icon">
|
|
||||||
<WalletIcon />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
case "warehouseThroughput floating":
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="header">
|
|
||||||
<h2>Warehouse Throughput</h2>
|
|
||||||
<p>
|
|
||||||
<span>(+5) more</span> in 2025
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="lineGraph" style={{ height: "100%" }}>
|
|
||||||
{/* <Line data={lineGraphData} options={lineGraphOptions} /> */}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
case "fleetEfficiency floating":
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<h2 className="header">Fleet Efficiency</h2>
|
|
||||||
<div className="progressContainer">
|
|
||||||
<div className="progress">
|
|
||||||
<div className="barOverflow">
|
|
||||||
<div
|
|
||||||
className="bar"
|
|
||||||
style={{ transform: `rotate(${obj.value}deg)` }}
|
|
||||||
></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="scaleLabels">
|
|
||||||
<span>0%</span>
|
|
||||||
<div className="centerText">
|
|
||||||
<div className="percentage">{obj.per}%</div>
|
|
||||||
<div className="status">Optimal</div>
|
|
||||||
</div>
|
|
||||||
<span>100%</span>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
onPointerMove={handlePointerMove}
|
|
||||||
onPointerUp={handlePointerUp}
|
|
||||||
className="floating-wrapper"
|
|
||||||
>
|
|
||||||
{zone.objects.map((obj, index) => (
|
|
||||||
<div
|
|
||||||
key={`${zoneName}-${index}`}
|
|
||||||
className={obj.className}
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
top:
|
|
||||||
typeof obj.position.top === "number"
|
|
||||||
? `${obj.position.top}px`
|
|
||||||
: "auto",
|
|
||||||
left:
|
|
||||||
typeof obj.position.left === "number"
|
|
||||||
? `${obj.position.left}px`
|
|
||||||
: "auto",
|
|
||||||
right:
|
|
||||||
typeof obj.position.right === "number"
|
|
||||||
? `${obj.position.right}px`
|
|
||||||
: "auto",
|
|
||||||
bottom:
|
|
||||||
typeof obj.position.bottom === "number"
|
|
||||||
? `${obj.position.bottom}px`
|
|
||||||
: "auto",
|
|
||||||
}}
|
|
||||||
onPointerDown={(event) => handlePointerDown(event, index)}
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedChartId(obj)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{obj.className === "floating total-card" ? (
|
|
||||||
<>
|
|
||||||
<TotalCardComponent object={obj} />
|
|
||||||
</>
|
|
||||||
) : obj.className === "warehouseThroughput floating" ? (
|
|
||||||
<>
|
|
||||||
<WarehouseThroughputComponent />
|
|
||||||
</>
|
|
||||||
) : obj.className === "fleetEfficiency floating" ? (
|
|
||||||
<>
|
|
||||||
<FleetEfficiencyComponent object={obj} />
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
{renderObjectContent(obj)}
|
|
||||||
<div
|
|
||||||
className="icon kebab"
|
|
||||||
onClick={(event) => handleKebabClick(obj.id, event)}
|
|
||||||
>
|
|
||||||
<KebabIcon />
|
|
||||||
</div>
|
|
||||||
{openKebabId === obj.id && (
|
|
||||||
<div className="kebab-options">
|
|
||||||
<div className="dublicate btn" onClick={(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
handleDuplicate(zoneName, index); // Call the duplicate handler
|
|
||||||
}}>
|
|
||||||
<div className="icon">
|
|
||||||
<DublicateIcon />
|
|
||||||
</div>
|
|
||||||
<div className="label">Duplicate</div>
|
|
||||||
</div>
|
|
||||||
<div className="edit btn" onClick={(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
handleDelete(zoneName, obj.id, index); // Call the delete handler
|
|
||||||
}}>
|
|
||||||
<div className="icon">
|
|
||||||
<DeleteIcon />
|
|
||||||
</div>
|
|
||||||
<div className="label">Delete</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
|
|
||||||
{/* Render DistanceLines component during drag */}
|
|
||||||
{draggingIndex !== null &&
|
|
||||||
activeEdges !== null &&
|
|
||||||
currentPosition !== null && (
|
|
||||||
<DistanceLines
|
|
||||||
obj={{
|
|
||||||
position: {
|
|
||||||
top:
|
|
||||||
currentPosition.top !== "auto"
|
|
||||||
? currentPosition.top
|
|
||||||
: undefined,
|
|
||||||
bottom:
|
|
||||||
currentPosition.bottom !== "auto"
|
|
||||||
? currentPosition.bottom
|
|
||||||
: undefined,
|
|
||||||
left:
|
|
||||||
currentPosition.left !== "auto"
|
|
||||||
? currentPosition.left
|
|
||||||
: undefined,
|
|
||||||
right:
|
|
||||||
currentPosition.right !== "auto"
|
|
||||||
? currentPosition.right
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
activeEdges={activeEdges}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
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 (
|
||||||
|
<>
|
||||||
|
<div className="header-wrapper">
|
||||||
|
<div className="header">{obj.header}</div>
|
||||||
|
<div className="data-values">
|
||||||
|
<div className="value">{obj.value}</div>
|
||||||
|
<div className="per">{obj.per}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="icon">
|
||||||
|
<WalletIcon />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
case "warehouseThroughput floating":
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="header">
|
||||||
|
<h2>Warehouse Throughput</h2>
|
||||||
|
<p>
|
||||||
|
<span>(+5) more</span> in 2025
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="lineGraph" style={{ height: "100%" }}>
|
||||||
|
{/* <Line data={lineGraphData} options={lineGraphOptions} /> */}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
case "fleetEfficiency floating":
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h2 className="header">Fleet Efficiency</h2>
|
||||||
|
<div className="progressContainer">
|
||||||
|
<div className="progress">
|
||||||
|
<div className="barOverflow">
|
||||||
|
<div
|
||||||
|
className="bar"
|
||||||
|
style={{ transform: `rotate(${obj.value}deg)` }}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="scaleLabels">
|
||||||
|
<span>0%</span>
|
||||||
|
<div className="centerText">
|
||||||
|
<div className="percentage">{obj.per}%</div>
|
||||||
|
<div className="status">Optimal</div>
|
||||||
|
</div>
|
||||||
|
<span>100%</span>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
onPointerMove={handlePointerMove}
|
||||||
|
onPointerUp={handlePointerUp}
|
||||||
|
className="floating-wrapper"
|
||||||
|
>
|
||||||
|
{zone.objects.map((obj, index) => (
|
||||||
|
<div
|
||||||
|
key={`${zoneName}-${index}`}
|
||||||
|
className={obj.className}
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top:
|
||||||
|
typeof obj.position.top === "number"
|
||||||
|
? `${obj.position.top}px`
|
||||||
|
: "auto",
|
||||||
|
left:
|
||||||
|
typeof obj.position.left === "number"
|
||||||
|
? `${obj.position.left}px`
|
||||||
|
: "auto",
|
||||||
|
right:
|
||||||
|
typeof obj.position.right === "number"
|
||||||
|
? `${obj.position.right}px`
|
||||||
|
: "auto",
|
||||||
|
bottom:
|
||||||
|
typeof obj.position.bottom === "number"
|
||||||
|
? `${obj.position.bottom}px`
|
||||||
|
: "auto",
|
||||||
|
}}
|
||||||
|
onPointerDown={(event) => handlePointerDown(event, index)}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedChartId(obj)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{obj.className === "floating total-card" ? (
|
||||||
|
<>
|
||||||
|
<TotalCardComponent object={obj} />
|
||||||
|
</>
|
||||||
|
) : obj.className === "warehouseThroughput floating" ? (
|
||||||
|
<>
|
||||||
|
<WarehouseThroughputComponent />
|
||||||
|
</>
|
||||||
|
) : obj.className === "fleetEfficiency floating" ? (
|
||||||
|
<>
|
||||||
|
<FleetEfficiencyComponent object={obj} />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
{renderObjectContent(obj)}
|
||||||
|
<div
|
||||||
|
className="icon kebab"
|
||||||
|
onClick={(event) => handleKebabClick(obj.id, event)}
|
||||||
|
>
|
||||||
|
<KebabIcon />
|
||||||
|
</div>
|
||||||
|
{openKebabId === obj.id && (
|
||||||
|
<div className="kebab-options">
|
||||||
|
<div className="dublicate btn" onClick={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
handleDuplicate(zoneName, index); // Call the duplicate handler
|
||||||
|
}}>
|
||||||
|
<div className="icon">
|
||||||
|
<DublicateIcon />
|
||||||
|
</div>
|
||||||
|
<div className="label">Duplicate</div>
|
||||||
|
</div>
|
||||||
|
<div className="edit btn" onClick={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
handleDelete(zoneName, obj.id, index); // Call the delete handler
|
||||||
|
}}>
|
||||||
|
<div className="icon">
|
||||||
|
<DeleteIcon />
|
||||||
|
</div>
|
||||||
|
<div className="label">Delete</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Render DistanceLines component during drag */}
|
||||||
|
{draggingIndex !== null &&
|
||||||
|
activeEdges !== null &&
|
||||||
|
currentPosition !== null && (
|
||||||
|
<DistanceLines
|
||||||
|
obj={{
|
||||||
|
position: {
|
||||||
|
top:
|
||||||
|
currentPosition.top !== "auto"
|
||||||
|
? currentPosition.top
|
||||||
|
: undefined,
|
||||||
|
bottom:
|
||||||
|
currentPosition.bottom !== "auto"
|
||||||
|
? currentPosition.bottom
|
||||||
|
: undefined,
|
||||||
|
left:
|
||||||
|
currentPosition.left !== "auto"
|
||||||
|
? currentPosition.left
|
||||||
|
: undefined,
|
||||||
|
right:
|
||||||
|
currentPosition.right !== "auto"
|
||||||
|
? currentPosition.right
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
activeEdges={activeEdges}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default DroppedObjects;
|
export default DroppedObjects;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user