Dwinzo_dev/app/src/components/ui/componets/RealTimeVisulization.tsx

172 lines
5.3 KiB
TypeScript
Raw Normal View History

2025-03-25 06:17:41 +00:00
import React, { useEffect, useState, useRef } from "react";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import Panel from "./Panel";
import AddButtons from "./AddButtons";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
import DisplayZone from "./DisplayZone";
2025-03-25 11:00:33 +00:00
import Scene from "../../../modules/scene/scene";
import useModuleStore from "../../../store/useModuleStore";
2025-03-27 12:34:16 +00:00
2025-03-27 06:58:17 +00:00
import DroppedObjects from "./DroppedFloatingWidgets";
2025-03-27 12:34:16 +00:00
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
import { useZones } from "../../../store/store";
2025-03-25 06:17:41 +00:00
type Side = "top" | "bottom" | "left" | "right";
type FormattedZoneData = Record<
string,
{
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[]
widgets: Widget[];
}
>;
type Widget = {
2025-03-25 06:17:41 +00:00
id: string;
type: string;
title: string;
panel: Side;
data: any;
};
2025-03-25 06:17:41 +00:00
const RealTimeVisulization: React.FC = () => {
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
const containerRef = useRef<HTMLDivElement>(null);
const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore();
2025-03-27 06:58:17 +00:00
const [droppedObjects, setDroppedObjects] = useState<any[]>([]);
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
2025-03-25 06:17:41 +00:00
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { zones } = useZones()
2025-03-25 06:17:41 +00:00
useEffect(() => {
const data = Array.isArray(zones) ? zones : [];
2025-03-27 06:58:17 +00:00
const formattedData = data.reduce<FormattedZoneData>((acc, zone) => {
acc[zone.zoneName] = {
activeSides: [],
panelOrder: [],
lockedPanels: [],
zoneId: zone.zoneId,
zoneViewPortTarget: zone.viewPortCenter,
zoneViewPortPosition: zone.viewPortposition,
widgets: [],
};
return acc;
}, {});
setZonesData(formattedData);
}, [zones]);
useEffect(() => {
setZonesData((prev) => {
if (!selectedZone) return prev;
return {
...prev,
[selectedZone.zoneName]: {
...prev[selectedZone.zoneName], // Keep existing properties
activeSides: selectedZone.activeSides || [],
panelOrder: selectedZone.panelOrder || [],
lockedPanels: selectedZone.lockedPanels || [],
zoneId: selectedZone.zoneId || "",
zoneViewPortTarget: selectedZone.zoneViewPortTarget || [],
zoneViewPortPosition: selectedZone.zoneViewPortPosition || [],
widgets: selectedZone.widgets || [],
},
};
});
2025-03-25 06:17:41 +00:00
}, [selectedZone]);
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
2025-03-27 12:34:16 +00:00
const data = event.dataTransfer.getData("text/plain");
if (!data || !selectedZone.zoneName) return;
const droppedData = JSON.parse(data);
const canvasElement = document.getElementById("real-time-vis-canvas");
if (!canvasElement) return;
const canvasRect = canvasElement.getBoundingClientRect();
const relativeX = event.clientX - canvasRect.left;
const relativeY = event.clientY - canvasRect.top;
const newObject = {
...droppedData,
position: [relativeY, relativeX], // Y first because of top/left style
};
console.log("newObject: ", newObject);
// Only set zone if its not already in the store (prevents overwriting objects)
const existingZone = useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
if (!existingZone) {
useDroppedObjectsStore.getState().setZone(selectedZone.zoneName, selectedZone.zoneId);
}
2025-03-27 12:34:16 +00:00
// Add the dropped object to the zone
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, newObject);
};
2025-03-27 12:34:16 +00:00
2025-03-25 06:17:41 +00:00
return (
<div
ref={containerRef}
id="real-time-vis-canvas"
2025-03-26 08:22:10 +00:00
className={`realTime-viz canvas ${isPlaying ? "playingFlase" : ""}`}
2025-03-25 06:17:41 +00:00
style={{
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
2025-03-25 06:17:41 +00:00
}}
>
2025-03-25 11:00:33 +00:00
<div
className="scene-container"
style={{
height: "100%",
width: "100%",
2025-03-27 05:24:40 +00:00
borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
2025-03-27 06:58:17 +00:00
onDrop={(event) => handleDrop(event)}
onDragOver={(event) => event.preventDefault()}
2025-03-25 11:00:33 +00:00
>
2025-03-27 12:34:16 +00:00
2025-03-25 11:00:33 +00:00
<Scene />
</div>
2025-03-27 12:34:16 +00:00
<DroppedObjects />
{activeModule === "visualization" && (
<>
<DisplayZone
zonesData={zonesData}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
{!isPlaying && selectedZone?.zoneName !== "" && (
<AddButtons
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
)}
<Panel
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
2025-03-26 07:02:09 +00:00
hiddenPanels={hiddenPanels}
2025-03-27 05:24:40 +00:00
setZonesData={setZonesData}
/>
</>
2025-03-25 11:00:33 +00:00
)}
2025-03-25 06:17:41 +00:00
</div>
);
};
export default RealTimeVisulization;