added donut and pole area chart and added its iot data

This commit is contained in:
2025-03-31 19:22:37 +05:30
121 changed files with 4527 additions and 1424 deletions

View File

@@ -1,59 +1,88 @@
import { WalletIcon } from "../../icons/3dChartIcons";
import { useEffect, useRef, useState } from "react";
import { Line } from "react-chartjs-2";
import { useDroppedObjectsStore, Zones } from "../../../store/useDroppedObjectsStore";
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 TotalCardComponent from "../realTimeVis/floating/TotalCardComponent";
import WarehouseThroughputComponent from "../realTimeVis/floating/WarehouseThroughputComponent";
import FleetEfficiencyComponent from "../realTimeVis/floating/FleetEfficiencyComponent";
import { useWidgetStore } from "../../../store/useWidgetStore";
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 updateObjectPosition = useDroppedObjectsStore(
(state) => state.updateObjectPosition
);
const [draggingIndex, setDraggingIndex] = useState<{
zone: string;
index: number;
} | null>(null);
const [offset, setOffset] = useState<[number, number] | null>(null);
const { setSelectedChartId } = useWidgetStore();
const positionRef = useRef<[number, number] | null>(null);
const animationRef = useRef<number | null>(null);
const { activeModule } = useModuleStore();
// useEffect(() => {
// const initialZones: Record<string, Zones> = {
// "Zone 1": {
// zoneName: "Zone 1",
// zoneId: "2e996073-546c-470c-8323-55bd3700c6aa",
// objects: [
// {
// header: "Todays 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 });
// }, []);
// Get the first zone and its objects
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
console.log("zone", zone);
// Handle pointer down event
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];
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 which properties are active for this object
const [activeProp1, activeProp2] = getActiveProperties(obj.position);
// Calculate the offset based on the active properties
let offsetX = 0;
let offsetY = 0;
if (activeProp1 === "top") {
offsetY =
relativeY -
(typeof obj.position.top === "number" ? obj.position.top : 0);
} else if (activeProp1 === "bottom") {
offsetY =
rect.height -
relativeY -
(typeof obj.position.bottom === "number" ? obj.position.bottom : 0);
}
if (activeProp2 === "left") {
offsetX =
relativeX -
(typeof obj.position.left === "number" ? obj.position.left : 0);
} else if (activeProp2 === "right") {
offsetX =
rect.width -
relativeX -
(typeof obj.position.right === "number" ? obj.position.right : 0);
}
setDraggingIndex({ zone: zoneName, index });
setOffset([offsetY, offsetX]);
}
// Handle pointer move event
function handlePointerMove(event: React.PointerEvent) {
if (!draggingIndex || !offset) return;
@@ -61,34 +90,92 @@ const DroppedObjects: React.FC = () => {
if (!container) return;
const rect = container.getBoundingClientRect();
const relativeX = event.clientX - rect.left;
const relativeY = event.clientY - rect.top;
let newX = event.clientX - offset[1];
let newY = event.clientY - offset[0];
// Determine which properties are active for the dragged object
const obj = zone.objects[draggingIndex.index];
const [activeProp1, activeProp2] = getActiveProperties(obj.position);
// Calculate the new position based on the active properties
let newX = 0;
let newY = 0;
if (activeProp2 === "left") {
newX = relativeX - offset[1];
} else if (activeProp2 === "right") {
newX = rect.width - (relativeX + offset[1]);
}
if (activeProp1 === "top") {
newY = relativeY - offset[0];
} else if (activeProp1 === "bottom") {
newY = rect.height - (relativeY + offset[0]);
}
// Ensure the object stays within the canvas boundaries
newX = Math.max(0, Math.min(rect.width - 50, newX));
newY = Math.max(0, Math.min(rect.height - 50, newY));
// Update the position reference
positionRef.current = [newY, newX];
// Update the object's position using requestAnimationFrame for smoother animations
if (!animationRef.current) {
animationRef.current = requestAnimationFrame(() => {
if (positionRef.current) {
updateObjectPosition(zoneName, draggingIndex.index, positionRef.current);
updateObjectPosition(zoneName, draggingIndex.index, {
...obj.position,
[activeProp1]: positionRef.current[0],
[activeProp2]: positionRef.current[1],
});
}
animationRef.current = null;
});
}
}
function handlePointerUp() {
setDraggingIndex(null);
setOffset(null);
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
animationRef.current = null;
// Handle pointer up event
async function handlePointerUp(event: React.MouseEvent<HTMLDivElement>) {
try {
if (!draggingIndex || !offset) return;
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
const container = document.getElementById("real-time-vis-canvas");
if (!container) throw new Error("Canvas container not found");
const rect = container.getBoundingClientRect();
const relativeX = event.clientX - rect.left;
const relativeY = event.clientY - rect.top;
// Recalculate the position using determinePosition
const newPosition = determinePosition(rect, relativeX, relativeY);
// Validate the dragging index and get the object
if (!zone.objects[draggingIndex.index]) {
throw new Error("Dragged object not found in the zone");
}
const obj = { ...zone.objects[draggingIndex.index], position: newPosition };
let response = await addingFloatingWidgets(zone.zoneId, organization, obj);
if (response.message === "Widget updated successfully") {
updateObjectPosition(zoneName, draggingIndex.index, newPosition);
}
// Reset states
setDraggingIndex(null);
setOffset(null);
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
animationRef.current = null;
}
} catch (error) {
}
}
return (
<div onPointerMove={handlePointerMove} onPointerUp={handlePointerUp}>
{zone.objects.map((obj, index) => (
@@ -96,59 +183,42 @@ const DroppedObjects: React.FC = () => {
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",
position: "absolute",
top:
typeof obj.position.top !== "string"
? `${obj.position.top}px`
: "auto",
left:
typeof obj.position.left !== "string"
? `${obj.position.left}px`
: "auto",
right:
typeof obj.position.right !== "string"
? `${obj.position.right}px`
: "auto",
bottom:
typeof obj.position.bottom !== "string"
? `${obj.position.bottom}px`
: "auto",
// transition: draggingIndex?.index === index ? "none" : "transform 0.1s ease-out",
}}
onPointerDown={(event) => handlePointerDown(event, index)}
onClick={() => {
setSelectedChartId(obj)
}}
>
{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>
<>
<TotalCardComponent object={obj} />
</>
) : 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>
<>
<WarehouseThroughputComponent />
</>
) : 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>
<>
<FleetEfficiencyComponent object={obj} />
</>
) : null}
</div>
))}
@@ -156,59 +226,4 @@ const DroppedObjects: React.FC = () => {
);
};
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;