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

326 lines
10 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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";
import Scene from "../../../modules/scene/scene";
import useModuleStore from "../../../store/useModuleStore";
import { useDroppedObjectsStore } from "../../../store/useDroppedObjectsStore";
import {
useAsset3dWidget,
useSocketStore,
useWidgetSubOption,
useZones,
} from "../../../store/store";
import { getZone2dData } from "../../../services/realTimeVisulization/zoneData/getZoneData";
import { generateUniqueId } from "../../../functions/generateUniqueId";
import { determinePosition } from "./functions/determinePosition";
import { addingFloatingWidgets } from "../../../services/realTimeVisulization/zoneData/addFloatingWidgets";
import SocketRealTimeViz from "../../../modules/visualization/realTimeVizSocket.dev";
import RenderOverlay from "../../templates/Overlay";
import ConfirmationPopup from "../../layout/confirmationPopup/ConfirmationPopup";
import DroppedObjects from "./DroppedFloatingWidgets";
import EditWidgetOption from "../menu/EditWidgetOption";
import { useEditWidgetOptionsStore, useRightClickSelected, useRightSelected } from "../../../store/useZone3DWidgetStore";
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 = {
id: string;
type: string;
title: string;
panel: Side;
data: any;
};
const RealTimeVisulization: React.FC = () => {
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
const containerRef = useRef<HTMLDivElement>(null);
const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore();
const [droppedObjects, setDroppedObjects] = useState<any[]>([]);
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { rightSelect, setRightSelect } = useRightSelected()
const { editWidgetOptions, setEditWidgetOptions } = useEditWidgetOptionsStore()
const { rightClickSelected, setRightClickSelected } = useRightClickSelected()
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
const [floatingWidgets, setFloatingWidgets] = useState<
Record<string, { zoneName: string; zoneId: string; objects: any[] }>
>({});
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
useEffect(() => {
async function GetZoneData() {
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
try {
const response = await getZone2dData(organization);
// console.log('response: ', response);
if (!Array.isArray(response)) {
return;
}
const formattedData = response.reduce<FormattedZoneData>(
(acc, zone) => {
acc[zone.zoneName] = {
activeSides: [],
panelOrder: [],
lockedPanels: [],
zoneId: zone.zoneId,
zoneViewPortTarget: zone.viewPortCenter,
zoneViewPortPosition: zone.viewPortposition,
widgets: [],
};
return acc;
},
{}
);
setZonesData(formattedData);
} catch (error) { }
}
GetZoneData();
}, [activeModule]); // Removed `zones` from dependencies
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 || [],
},
};
});
}, [selectedZone]);
// useEffect(() => {}, [floatingWidgets]);
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
try {
event.preventDefault();
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
const data = event.dataTransfer.getData("text/plain");
// if (widgetSelect !== "") return;
if (widgetSubOption === "3D") return;
if (!data || selectedZone.zoneName === "") return;
const droppedData = JSON.parse(data);
const canvasElement = document.getElementById("real-time-vis-canvas");
if (!canvasElement) throw new Error("Canvas element not found");
const canvasRect = canvasElement.getBoundingClientRect();
const relativeX = event.clientX - canvasRect.left;
const relativeY = event.clientY - canvasRect.top;
const newPosition = determinePosition(canvasRect, relativeX, relativeY);
console.log("newPosition: ", newPosition);
const newObject = {
...droppedData,
id: generateUniqueId(),
position: determinePosition(canvasRect, relativeX, relativeY),
};
// 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);
}
let addFloatingWidget = {
organization: organization,
widget: newObject,
zoneId: selectedZone.zoneId,
};
console.log("newObject: ", newObject);
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget);
}
// let response = await addingFloatingWidgets(
// selectedZone.zoneId,
// organization,
// newObject
// );
// Add the dropped object to the zone if the API call is successful
// if (response.message === "FloatWidget created successfully") {
useDroppedObjectsStore
.getState()
.addObject(selectedZone.zoneName, newObject);
// }
// Update floating widgets state
setFloatingWidgets((prevWidgets) => ({
...prevWidgets,
[selectedZone.zoneName]: {
...prevWidgets[selectedZone.zoneName],
zoneName: selectedZone.zoneName,
zoneId: selectedZone.zoneId,
objects: [
...(prevWidgets[selectedZone.zoneName]?.objects || []),
newObject,
],
},
}));
} catch (error) { }
};
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const editWidgetOptions = document.querySelector(
".editWidgetOptions-wrapper"
);
if (
editWidgetOptions &&
!editWidgetOptions.contains(event.target as Node)
) {
setRightClickSelected(null);
setRightSelect(null);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [setRightClickSelected]);
// Add this useEffect hook to your component
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const editWidgetOptions = document.querySelector(
".editWidgetOptions-wrapper"
);
if (
editWidgetOptions &&
!editWidgetOptions.contains(event.target as Node)
) {
setRightClickSelected(null);
setRightSelect(null);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [setRightClickSelected]);
return (
<div
ref={containerRef}
id="real-time-vis-canvas"
className={`realTime-viz canvas ${isPlaying ? "playingFlase" : ""}`}
style={{
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
}}
>
{openConfirmationPopup && (
<RenderOverlay>
<ConfirmationPopup
message={"Are you sure want to delete?"}
onConfirm={() => console.log("confirm")}
onCancel={() => setOpenConfirmationPopup(false)}
/>
</RenderOverlay>
)}
<div
className="scene-container"
style={{
height: "100%",
width: "100%",
borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
onDrop={(event) => handleDrop(event)}
onDragOver={(event) => event.preventDefault()}
>
<Scene />
</div>
{activeModule === "visualization" && selectedZone.zoneName !== "" && (
<DroppedObjects />
)}
{activeModule === "visualization" && <SocketRealTimeViz />}
{activeModule === "visualization" &&
editWidgetOptions &&
rightClickSelected && (
<EditWidgetOption
options={[
"Duplicate",
"Vertical Move",
"Horizontal Move",
"RotateX",
"RotateY",
"Delete",
]}
/>
)}
{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}
hiddenPanels={hiddenPanels}
setZonesData={setZonesData}
/>
</>
)}
</div>
);
};
export default RealTimeVisulization;