322 lines
11 KiB
TypeScript
322 lines
11 KiB
TypeScript
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, useFloatingWidget } 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";
|
||
import Dropped3dWidgets from "./Dropped3dWidget";
|
||
|
||
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 { floatingWidget, setFloatingWidget } = useFloatingWidget()
|
||
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);
|
||
|
||
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>) => {
|
||
event.preventDefault();
|
||
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 it’s 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);
|
||
}
|
||
useDroppedObjectsStore
|
||
.getState()
|
||
.addObject(selectedZone.zoneName, newObject);
|
||
|
||
//I need to console here objects based on selectedZone.zoneId
|
||
// Console the objects after adding
|
||
const droppedObjectsStore = useDroppedObjectsStore.getState();
|
||
const currentZone = droppedObjectsStore.zones[selectedZone.zoneName];
|
||
|
||
if (currentZone && currentZone.zoneId === selectedZone.zoneId) {
|
||
console.log(
|
||
`Objects for Zone ID: ${selectedZone.zoneId}`,
|
||
currentZone.objects
|
||
);
|
||
setFloatingWidget(currentZone.objects)
|
||
} else {
|
||
console.warn("Zone not found or mismatched zoneId");
|
||
}
|
||
|
||
// 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") {
|
||
// }
|
||
|
||
// Update floating widgets state
|
||
|
||
} 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]);
|
||
|
||
|
||
|
||
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%" : "",
|
||
}}
|
||
>
|
||
<div className="realTime-viz-wrapper">
|
||
{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>
|
||
</div>
|
||
</>
|
||
);
|
||
};
|
||
|
||
export default RealTimeVisulization;
|