215 lines
6.4 KiB
TypeScript
215 lines
6.4 KiB
TypeScript
|
||
|
||
|
||
import { WalletIcon } from "../../icons/3dChartIcons";
|
||
import { useEffect, useRef, useState } from "react";
|
||
import { Line } from "react-chartjs-2";
|
||
import { useDroppedObjectsStore, Zones } from "../../../store/useDroppedObjectsStore";
|
||
|
||
const DroppedObjects: React.FC = () => {
|
||
const zones = useDroppedObjectsStore((state) => state.zones);
|
||
const updateObjectPosition = useDroppedObjectsStore((state) => state.updateObjectPosition);
|
||
const [draggingIndex, setDraggingIndex] = useState<{ zone: string; index: number } | null>(null);
|
||
const [offset, setOffset] = useState<[number, number] | null>(null);
|
||
const positionRef = useRef<[number, number] | null>(null);
|
||
const animationRef = useRef<number | null>(null);
|
||
|
||
// useEffect(() => {
|
||
// const initialZones: Record<string, Zones> = {
|
||
// "Zone 1": {
|
||
// zoneName: "Zone 1",
|
||
// zoneId: "2e996073-546c-470c-8323-55bd3700c6aa",
|
||
// objects: [
|
||
// {
|
||
// header: "Today’s Money",
|
||
// value: 53000, // ✅ Converted to number
|
||
// per: "+55%",
|
||
// className: "floating total-card",
|
||
// position: [146, 214], // ✅ No need for 'as' here
|
||
// },
|
||
// {
|
||
// header: "New Clients",
|
||
// value: 250, // ✅ Converted to number
|
||
// per: "+12%",
|
||
// className: "floating total-card",
|
||
// position: [344, 295],
|
||
// },
|
||
// ],
|
||
// },
|
||
// };
|
||
|
||
// useDroppedObjectsStore.setState({ zones: initialZones });
|
||
// }, []);
|
||
|
||
const zoneEntries = Object.entries(zones);
|
||
if (zoneEntries.length === 0) return null; // No zone, nothing to render
|
||
const [zoneName, zone] = zoneEntries[0]; // Only render the first zone
|
||
|
||
function handlePointerDown(event: React.PointerEvent, index: number) {
|
||
const obj = zone.objects[index];
|
||
const offsetX = event.clientX - obj.position[1];
|
||
const offsetY = event.clientY - obj.position[0];
|
||
|
||
setDraggingIndex({ zone: zoneName, index });
|
||
setOffset([offsetY, offsetX]);
|
||
}
|
||
|
||
function handlePointerMove(event: React.PointerEvent) {
|
||
if (!draggingIndex || !offset) return;
|
||
|
||
const container = document.getElementById("real-time-vis-canvas");
|
||
if (!container) return;
|
||
|
||
const rect = container.getBoundingClientRect();
|
||
|
||
let newX = event.clientX - offset[1];
|
||
let newY = event.clientY - offset[0];
|
||
|
||
newX = Math.max(0, Math.min(rect.width - 50, newX));
|
||
newY = Math.max(0, Math.min(rect.height - 50, newY));
|
||
|
||
positionRef.current = [newY, newX];
|
||
|
||
if (!animationRef.current) {
|
||
animationRef.current = requestAnimationFrame(() => {
|
||
if (positionRef.current) {
|
||
updateObjectPosition(zoneName, draggingIndex.index, positionRef.current);
|
||
}
|
||
animationRef.current = null;
|
||
});
|
||
}
|
||
}
|
||
|
||
function handlePointerUp() {
|
||
setDraggingIndex(null);
|
||
setOffset(null);
|
||
if (animationRef.current) {
|
||
cancelAnimationFrame(animationRef.current);
|
||
animationRef.current = null;
|
||
}
|
||
}
|
||
|
||
return (
|
||
<div onPointerMove={handlePointerMove} onPointerUp={handlePointerUp}>
|
||
{zone.objects.map((obj, index) => (
|
||
<div
|
||
key={`${zoneName}-${index}`}
|
||
className={obj.className}
|
||
style={{
|
||
top: obj.position[0] + "px",
|
||
left: obj.position[1] + "px",
|
||
transition: draggingIndex?.index === index ? "none" : "transform 0.1s ease-out",
|
||
}}
|
||
onPointerDown={(event) => handlePointerDown(event, index)}
|
||
>
|
||
{obj.className === "floating total-card" ? (
|
||
<div>
|
||
<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>
|
||
</div>
|
||
) : obj.className === "warehouseThroughput floating" ? (
|
||
<div>
|
||
<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>
|
||
</div>
|
||
) : obj.className === "fleetEfficiency floating" ? (
|
||
<div>
|
||
<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>
|
||
</div>
|
||
) : null}
|
||
</div>
|
||
))}
|
||
</div>
|
||
);
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
export default DroppedObjects;
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// import { Html } from "@react-three/drei";
|
||
// import { useDroppedObjectsStore } from "../../../store/store";
|
||
// import { CartIcon, DocumentIcon, GlobeIcon, WalletIcon } from "../../icons/3dChartIcons";
|
||
// import SimpleCard from "../realTimeVis/floating/SimpleCard";
|
||
|
||
// const ICON_MAP: Record<string, React.ComponentType<React.SVGProps<SVGSVGElement>>> = {
|
||
// WalletIcon,
|
||
// GlobeIcon,
|
||
// DocumentIcon,
|
||
// CartIcon
|
||
// };
|
||
// const DroppedObjects: React.FC = () => {
|
||
// const objects = useDroppedObjectsStore((state) => state.objects); // Get objects from Zustand store
|
||
//
|
||
|
||
// return (
|
||
// <>
|
||
// {objects.map((obj, index) => {
|
||
// const IconComponent = obj.Icon || WalletIcon; // Use obj.Icon directly if it exists
|
||
// return (
|
||
// <SimpleCard
|
||
// key={index}
|
||
// position={obj.position}
|
||
// header={obj.header}
|
||
// icon={IconComponent} // ✅ No need to look it up in ICON_MAP
|
||
// value={obj.value}
|
||
// per={obj.per}
|
||
// />
|
||
// );
|
||
// })}
|
||
// </>
|
||
// );
|
||
// };
|
||
|
||
// export default DroppedObjects;
|