diff --git a/app/src/components/layout/3D-cards/CardsScene.tsx b/app/src/components/layout/3D-cards/CardsScene.tsx index 9318ce3..a23cdd0 100644 --- a/app/src/components/layout/3D-cards/CardsScene.tsx +++ b/app/src/components/layout/3D-cards/CardsScene.tsx @@ -8,7 +8,7 @@ import StateWorking from "./cards/StateWorking"; const CardsScene = () => { return (
- + {/* */} {/* 3d-cards */} {/* */} @@ -16,8 +16,8 @@ const CardsScene = () => { {/* */} {/* */} - - + {/* */} + {/* */}
); }; diff --git a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx index 05c2814..4ec9fdd 100644 --- a/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx +++ b/app/src/components/layout/3D-cards/cards/ProductionCapacity.tsx @@ -30,11 +30,13 @@ interface ProductionCapacityProps { id: string; type: string; position: [number, number, number]; + onContextMenu?: (event: React.MouseEvent) => void; + // onPointerDown:any } -const ProductionCapacity : React.FC = ({ id, type, position }) => { +const ProductionCapacity: React.FC = ({ id, type, position, onContextMenu }) => { - const { selectedChartId,setSelectedChartId } = useWidgetStore(); + const { selectedChartId, setSelectedChartId } = useWidgetStore(); const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); const [measurements, setmeasurements] = useState({}); @@ -111,7 +113,7 @@ const ProductionCapacity : React.FC = ({ id, type, posi }; - const startStream = () => { + const startStream = () => { socket.emit("lineInput", inputData); }; @@ -146,8 +148,8 @@ const ProductionCapacity : React.FC = ({ id, type, posi }; }, [measurements, duration, iotApiUrl]); - const fetchSavedInputes = async() => { - + const fetchSavedInputes = async () => { + if (id !== "") { try { const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`); @@ -173,20 +175,18 @@ const ProductionCapacity : React.FC = ({ id, type, posi fetchSavedInputes(); } } - ,[chartMeasurements, chartDuration, widgetName]) + , [chartMeasurements, chartDuration, widgetName]) return ( - +
setSelectedChartId({ - id: id, - type: type - }) - }> + onClick={() => setSelectedChartId({ id: id, type: type })} + onContextMenu={onContextMenu} + >
Production Capacity
@@ -207,7 +207,7 @@ const ProductionCapacity : React.FC = ({ id, type, posi
{" "}
{/* Bar Chart */} - 0 ? chartData : defaultChartData } options={chartOptions} /> + 0 ? chartData : defaultChartData} options={chartOptions} />
diff --git a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx index 8c2f3ea..96fc305 100644 --- a/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx +++ b/app/src/components/layout/3D-cards/cards/ReturnOfInvestment.tsx @@ -43,10 +43,11 @@ interface ReturnOfInvestmentProps { id: string; type: string; position: [number, number, number]; + onContextMenu?: (event: React.MouseEvent) => void; } -const ReturnOfInvestment: React.FC = ({ id, type, position }) => { +const ReturnOfInvestment: React.FC = ({ id, type, position, onContextMenu }) => { - const { selectedChartId,setSelectedChartId } = useWidgetStore(); + const { selectedChartId, setSelectedChartId } = useWidgetStore(); const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); const [measurements, setmeasurements] = useState({}); const [duration, setDuration] = useState("1h") @@ -138,7 +139,7 @@ const ReturnOfInvestment: React.FC = ({ id, type, posit }; - const startStream = () => { + const startStream = () => { socket.emit("lineInput", inputData); }; @@ -155,8 +156,8 @@ const ReturnOfInvestment: React.FC = ({ id, type, posit return { label: datasetKey, data: responseData[datasetKey]?.values ?? [], - borderColor: index === 0 ? "rgba(75, 192, 192, 1)": "rgba(255, 99, 132, 1)", // Light blue color - backgroundColor: index === 0 ? "rgba(75, 192, 192, 0.2)": "rgba(255, 99, 132, 0.2)", + borderColor: index === 0 ? "rgba(75, 192, 192, 1)" : "rgba(255, 99, 132, 1)", // Light blue color + backgroundColor: index === 0 ? "rgba(75, 192, 192, 0.2)" : "rgba(255, 99, 132, 0.2)", fill: true, tension: 0.4, // Smooth curve effect pointRadius: 0, // Hide dots @@ -174,8 +175,8 @@ const ReturnOfInvestment: React.FC = ({ id, type, posit }; }, [measurements, duration, iotApiUrl]); - const fetchSavedInputes = async() => { - + const fetchSavedInputes = async () => { + if (id !== "") { try { const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`); @@ -201,21 +202,18 @@ const ReturnOfInvestment: React.FC = ({ id, type, posit fetchSavedInputes(); } } - ,[chartMeasurements, chartDuration, widgetName]) + , [chartMeasurements, chartDuration, widgetName]) return (
setSelectedChartId({ - id: id, - type: type - }) - }> + onClick={() => setSelectedChartId({ id: id, type: type })} + onContextMenu={onContextMenu} + >
Return of Investment
{/* Smooth curve graph with two datasets */} diff --git a/app/src/components/layout/3D-cards/cards/StateWorking.tsx b/app/src/components/layout/3D-cards/cards/StateWorking.tsx index d0fdb95..efd4e7d 100644 --- a/app/src/components/layout/3D-cards/cards/StateWorking.tsx +++ b/app/src/components/layout/3D-cards/cards/StateWorking.tsx @@ -7,11 +7,12 @@ import io from "socket.io-client"; // import image from "../../../../assets/image/temp/image.png"; interface StateWorkingProps { - id:string; + id: string; type: string; position: [number, number, number]; + onContextMenu?: (event: React.MouseEvent) => void; } -const StateWorking: React.FC = ({ id, type, position }) => { +const StateWorking: React.FC = ({ id, type, position, onContextMenu }) => { const { selectedChartId, setSelectedChartId } = useWidgetStore(); const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); const [measurements, setmeasurements] = useState({}); @@ -38,14 +39,14 @@ const StateWorking: React.FC = ({ id, type, position }) => { duration, interval: 1000, }; - const startStream = () => { + const startStream = () => { socket.emit("lastInput", inputData); }; socket.on("connect", startStream); socket.on("lastOutput", (response) => { const responseData = response; - console.log("responceeeeeeeeeee",response); - + console.log("responceeeeeeeeeee", response); + setDatas(responseData); }); @@ -56,8 +57,8 @@ const StateWorking: React.FC = ({ id, type, position }) => { }; }, [measurements, duration, iotApiUrl]); - const fetchSavedInputes = async() => { - + const fetchSavedInputes = async () => { + if (id !== "") { try { const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`); @@ -74,8 +75,8 @@ const StateWorking: React.FC = ({ id, type, position }) => { } } - console.log("dataaaaa",datas); - + console.log("dataaaaa", datas); + useEffect(() => { fetchSavedInputes(); @@ -86,27 +87,24 @@ const StateWorking: React.FC = ({ id, type, position }) => { fetchSavedInputes(); } } - ,[chartMeasurements, chartDuration, widgetName]) + , [chartMeasurements, chartDuration, widgetName]) return (
setSelectedChartId({ - id: id, - type: type - }) - }> + onClick={() => setSelectedChartId({ id: id, type: type })} + onContextMenu={onContextMenu} + >
State - {datas?.input1 ? datas.input1 : 'input1'} . + {datas?.input1 ? datas.input1 : 'input1'} .
@@ -126,24 +124,24 @@ const StateWorking: React.FC = ({ id, type, position }) => {
{datas?.input2 ? datas.input2 : 'data'}
-
{measurements?.input3?.fields ? measurements.input3.fields : 'input3'}
-
{datas?.input3 ? datas.input3 : 'data'}
+
{measurements?.input3?.fields ? measurements.input3.fields : 'input3'}
+
{datas?.input3 ? datas.input3 : 'data'}
-
{measurements?.input4?.fields ? measurements.input4.fields : 'input4'}
-
{datas?.input4 ? datas.input4 : 'data'}
+
{measurements?.input4?.fields ? measurements.input4.fields : 'input4'}
+
{datas?.input4 ? datas.input4 : 'data'}
-
{measurements?.input5?.fields ? measurements.input5.fields : 'input5'}
-
{datas?.input5 ? datas.input5 : 'data'}
+
{measurements?.input5?.fields ? measurements.input5.fields : 'input5'}
+
{datas?.input5 ? datas.input5 : 'data'}
-
{measurements?.input6?.fields ? measurements.input6.fields : 'input6'}
-
{datas?.input6 ? datas.input6 : 'data'}
+
{measurements?.input6?.fields ? measurements.input6.fields : 'input6'}
+
{datas?.input6 ? datas.input6 : 'data'}
-
{measurements?.input7?.fields ? measurements.input7.fields : 'input7'}
-
{datas?.input7 ? datas.input7 : 'data'}
+
{measurements?.input7?.fields ? measurements.input7.fields : 'input7'}
+
{datas?.input7 ? datas.input7 : 'data'}
diff --git a/app/src/components/layout/3D-cards/cards/Throughput.tsx b/app/src/components/layout/3D-cards/cards/Throughput.tsx index 32cd350..5d6fab9 100644 --- a/app/src/components/layout/3D-cards/cards/Throughput.tsx +++ b/app/src/components/layout/3D-cards/cards/Throughput.tsx @@ -45,11 +45,12 @@ interface ThroughputProps { id: string; type: string; position: [number, number, number]; + onContextMenu?: (event: React.MouseEvent) => void; } -const Throughput: React.FC = ({ id, type, position }) => { +const Throughput: React.FC = ({ id, type, position, onContextMenu }) => { - const { selectedChartId,setSelectedChartId } = useWidgetStore(); + const { selectedChartId, setSelectedChartId } = useWidgetStore(); const { measurements: chartMeasurements, duration: chartDuration, name: widgetName } = useChartStore(); const [measurements, setmeasurements] = useState({}); const [duration, setDuration] = useState("1h") @@ -121,7 +122,7 @@ const Throughput: React.FC = ({ id, type, position }) => { }; - const startStream = () => { + const startStream = () => { socket.emit("lineInput", inputData); }; @@ -154,8 +155,8 @@ const Throughput: React.FC = ({ id, type, position }) => { }; }, [measurements, duration, iotApiUrl]); - const fetchSavedInputes = async() => { - + const fetchSavedInputes = async () => { + if (id !== "") { try { const response = await axios.get(`http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}/api/v2/widget3D/${id}/${organization}`); @@ -181,7 +182,7 @@ const Throughput: React.FC = ({ id, type, position }) => { fetchSavedInputes(); } } - ,[chartMeasurements, chartDuration, widgetName]) + , [chartMeasurements, chartDuration, widgetName]) return ( = ({ id, type, position }) => { transform zIndexRange={[1, 0]} sprite> -
setSelectedChartId({ - id: id, - type: type - }) - }> +
setSelectedChartId({ id: id, type: type })} + onContextMenu={onContextMenu} + >
{name}
diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/InputSelecterComponent.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/InputSelecterComponent.tsx index 3b44fc2..2d82225 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/InputSelecterComponent.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/InputSelecterComponent.tsx @@ -14,8 +14,6 @@ import { useWidgetStore } from '../../../../../store/useWidgetStore' const InputSelecterComponent = () => { const { selectedChartId } = useWidgetStore(); - console.log('selectedChartId:',selectedChartId); - if (selectedChartId && selectedChartId.type && selectedChartId.type === 'bar' ) { return ( diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx index bad0afc..c6d1509 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget2InputCard3D.tsx @@ -21,8 +21,6 @@ const Widget2InputCard3D = (props: Props) => { const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0] - console.log(selectedChartId); - useEffect(() => { const fetchZoneData = async () => { diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx index c720e66..95fdc33 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget3InputCard3D.tsx @@ -19,9 +19,7 @@ const Widget3InputCard3D = () => { const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0] - console.log(selectedChartId); - - + useEffect(() => { const fetchZoneData = async () => { try { diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx index 0be5489..3244773 100644 --- a/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/Widget4InputCard3D.tsx @@ -21,9 +21,7 @@ const Widget4InputCard3D = (props: Props) => { const iotApiUrl = process.env.REACT_APP_IOT_SOCKET_SERVER_URL; const email = localStorage.getItem("email") || ""; const organization = email?.split("@")[1]?.split(".")[0] - console.log(selectedChartId); - - + useEffect(() => { const fetchZoneData = async () => { try { diff --git a/app/src/components/ui/componets/Dropped3dWidget.tsx b/app/src/components/ui/componets/Dropped3dWidget.tsx index f0d5e66..f43cce5 100644 --- a/app/src/components/ui/componets/Dropped3dWidget.tsx +++ b/app/src/components/ui/componets/Dropped3dWidget.tsx @@ -1,5 +1,5 @@ import { useThree } from "@react-three/fiber"; -import React, { useState, useEffect } from "react"; +import React, { useState, useEffect, useRef } from "react"; import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../store/store"; import useModuleStore from "../../../store/useModuleStore"; import { ThreeState } from "../../../types/world/worldTypes"; @@ -13,30 +13,43 @@ import { generateUniqueId } from "../../../functions/generateUniqueId"; import { adding3dWidgets } from "../../../services/realTimeVisulization/zoneData/add3dWidget"; import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zoneData/get3dWidgetData"; import { use3DWidget } from "../../../store/useDroppedObjectsStore"; -import { useZoneWidgetStore } from "../../../store/useZone3DWidgetStore"; +import { useLeftData, useRightClickSelected, useRightSelected, useTopData, useZoneWidgetStore } from "../../../store/useZone3DWidgetStore"; +import { useWidgetStore } from "../../../store/useWidgetStore"; +import EditWidgetOption from "../menu/EditWidgetOption"; export default function Dropped3dWidgets() { const { widgetSelect } = useAsset3dWidget(); const { activeModule } = useModuleStore(); - const { raycaster, gl, scene }: ThreeState = useThree(); + const { raycaster, gl, scene, mouse, camera }: ThreeState = useThree(); const { widgetSubOption } = useWidgetSubOption(); const { selectedZone } = useSelectedZoneStore(); + const { top, setTop } = useTopData() + const { left, setLeft } = useLeftData() + const { rightSelect, setRightSelect } = useRightSelected() // ✅ Use Zustand Store instead of useState - const { zoneWidgetData, setZoneWidgetData, addWidget } = useZoneWidgetStore(); + const { zoneWidgetData, setZoneWidgetData, addWidget, updateWidgetPosition } = useZoneWidgetStore(); const { setWidgets3D } = use3DWidget(); const { visualizationSocket } = useSocketStore(); + const { rightClickSelected, setRightClickSelected } = useRightClickSelected() + + const plane = useRef(new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)); // Floor plane for horizontal move + const verticalPlane = useRef(new THREE.Plane(new THREE.Vector3(0, 0, 1), 0)); // Vertical plane for vertical move + const planeIntersect = useRef(new THREE.Vector3()); + // let [verticalPlane, setFloorPlanesVertical] = useState( + // new THREE.Plane(new THREE.Vector3(0, 1, 0)) + // ); useEffect(() => { if (activeModule !== "visualization") return; if (!selectedZone.zoneId) return; - const email = localStorage.getItem("email") || ""; - const organization = email?.split("@")[1]?.split(".")[0]; + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; async function get3dWidgetData() { let result = await get3dWidgetZoneData(selectedZone.zoneId, organization); - console.log('result: ', result); + setWidgets3D(result); const formattedWidgets = result.map((widget: any) => ({ @@ -89,13 +102,13 @@ export default function Dropped3dWidgets() { widget: newWidget, zoneId: selectedZone.zoneId } - console.log('add3dWidget: ', add3dWidget); + if (visualizationSocket) { visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget) } // let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget); - // console.log('response: ', response); + // // if (response.message === "Widget created successfully") { addWidget(selectedZone.zoneId, newWidget); @@ -111,23 +124,142 @@ export default function Dropped3dWidgets() { const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || []; + useEffect(() => { + if (!rightClickSelected) return; + const email = localStorage.getItem("email") || ""; + const organization = email?.split("@")[1]?.split(".")[0]; + if (rightSelect === "Duplicate") { + const widgetToDuplicate = activeZoneWidgets.find(w => w.id === rightClickSelected); + if (!widgetToDuplicate) return; + const newWidget = { + id: generateUniqueId(), + type: widgetToDuplicate.type, + position: [ + widgetToDuplicate.position[0] + 0.5, // Slightly shift position + widgetToDuplicate.position[1], + widgetToDuplicate.position[2] + 0.5, + ] as [number, number, number], + }; + let add3dWidget = { + organization, + widget: newWidget, + zoneId: selectedZone.zoneId + }; + // if (visualizationSocket) { + // visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget); + // } + addWidget(selectedZone.zoneId, newWidget); + setRightSelect(null); + setRightClickSelected(null); + } + if (rightSelect === "Delete") { + let deleteWidget = { + organization, + widgetId: rightClickSelected, + zoneId: selectedZone.zoneId + }; + // if (visualizationSocket) { + // visualizationSocket.emit("v2:viz-3D-widget:delete", deleteWidget); + // } + setZoneWidgetData(selectedZone.zoneId, activeZoneWidgets.filter(w => w.id !== rightClickSelected)); + setRightClickSelected(null); + setRightSelect(null); + } + if (rightSelect === "Horizontal Move") { + + } + if (rightSelect === "Vertical Move") { + + } + + }, [rightSelect, rightClickSelected]); + + useEffect(() => { + const handleMouseMove = (event: MouseEvent) => { + if (!rightClickSelected || !rightSelect) return; + + + const selectedZone = Object.keys(zoneWidgetData).find(zoneId => + zoneWidgetData[zoneId].some(widget => widget.id === rightClickSelected) + ); + if (!selectedZone) return; + + const selectedWidget = zoneWidgetData[selectedZone].find(widget => widget.id === rightClickSelected); + if (!selectedWidget) return; + + const rect = gl.domElement.getBoundingClientRect(); + mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1; + mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1; + + raycaster.setFromCamera(mouse, camera); + + if (rightSelect === "Horizontal Move" && raycaster.ray.intersectPlane(plane.current, planeIntersect.current)) { + + updateWidgetPosition(selectedZone, rightClickSelected, [ + planeIntersect.current.x, + selectedWidget.position[1], + planeIntersect.current.z + ]); + } + + if (rightSelect === "Vertical Move") { + if (raycaster.ray.intersectPlane(verticalPlane.current, planeIntersect.current)) { + updateWidgetPosition(selectedZone, rightClickSelected, [ + selectedWidget.position[0], + planeIntersect.current.y, // Ensure Y value updates correctly + selectedWidget.position[2] + ]); + } else { + console.log("No Intersection with Vertical Plane"); + } + } + }; + + const handleMouseUp = () => { + + if (rightClickSelected && (rightSelect === "Horizontal Move" || rightSelect === "Vertical Move")) { + + setTimeout(() => { + setRightClickSelected(null); + setRightSelect(null); + }, 50); + } + }; + + // Attach events to window instead of gl.domElement + window.addEventListener("mousemove", handleMouseMove); + window.addEventListener("mouseup", handleMouseUp); + + return () => { + window.removeEventListener("mousemove", handleMouseMove); + window.removeEventListener("mouseup", handleMouseUp); + }; + }, [rightClickSelected, rightSelect, zoneWidgetData, gl]); + + + + return ( <> {activeZoneWidgets.map(({ id, type, position }) => { - console.log('Typeeeeeeeeeeee',type); + const handleRightClick = (event: React.MouseEvent) => { + event.preventDefault(); + setRightClickSelected(id) + }; switch (type) { case "ui-Widget 1": - return ; + return ; case "ui-Widget 2": - return ; + return ; case "ui-Widget 3": - return ; + return ; case "ui-Widget 4": - return ; + return ; default: return null; } })} + ); } diff --git a/app/src/components/ui/componets/RealTimeVisulization.tsx b/app/src/components/ui/componets/RealTimeVisulization.tsx index 619cbb0..915e3b3 100644 --- a/app/src/components/ui/componets/RealTimeVisulization.tsx +++ b/app/src/components/ui/componets/RealTimeVisulization.tsx @@ -23,6 +23,8 @@ import SocketRealTimeViz from "../../../modules/visualization/realTimeVizSocket. import RenderOverlay from "../../templates/Overlay"; import ConfirmationPopup from "../../layout/confirmationPopup/ConfirmationPopup"; import DroppedObjects from "./DroppedFloatingWidgets"; +import EditWidgetOption from "../menu/EditWidgetOption"; +import { useRightClickSelected } from "../../../store/useZone3DWidgetStore"; type Side = "top" | "bottom" | "left" | "right"; @@ -55,8 +57,9 @@ const RealTimeVisulization: React.FC = () => { const [droppedObjects, setDroppedObjects] = useState([]); const [zonesData, setZonesData] = useState({}); const { selectedZone, setSelectedZone } = useSelectedZoneStore(); - const { zones } = useZones(); + + const { rightClickSelected, setRightClickSelected } = useRightClickSelected() const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false); const [floatingWidgets, setFloatingWidgets] = useState< @@ -93,7 +96,7 @@ const RealTimeVisulization: React.FC = () => { {} ); setZonesData(formattedData); - } catch (error) {} + } catch (error) { } } GetZoneData(); @@ -178,7 +181,6 @@ const RealTimeVisulization: React.FC = () => { .getState() .addObject(selectedZone.zoneName, newObject); // } - // Update floating widgets state setFloatingWidgets((prevWidgets) => ({ ...prevWidgets, @@ -192,9 +194,10 @@ const RealTimeVisulization: React.FC = () => { ], }, })); - } catch (error) {} + } catch (error) { } }; + function handleRightClickSel(){} return (
{ left: isPlaying || activeModule !== "visualization" ? "0%" : "", }} > - {/* - - */} {openConfirmationPopup && ( {
{activeModule === "visualization" && selectedZone.zoneName !== "" && } {activeModule === "visualization" && } - {/* */} - {/* - - */} + + {activeModule === "visualization" && widgetSubOption === "3D" && rightClickSelected && } + {activeModule === "visualization" && ( <> { -// const { getTemplate } = useTemplateStore.getState(); -// const { setSelectedZone } = useSelectedZoneStore.getState(); - -// // Find the template by ID -// const template: Template | undefined = getTemplate(templateId); - -// if (!template) { -// console.error("Template not found!"); -// return; -// } - -// // Update the selected zone with the template data -// setSelectedZone((prev) => ({ -// ...prev, -// panelOrder: template.panelOrder, -// activeSides: Array.from(new Set([...prev.activeSides, ...template.panelOrder])), -// widgets: template.widgets, // Keep widget structure the same -// })); - -// console.log("Dropped template applied:", template); -// }; diff --git a/app/src/components/ui/menu/EditWidgetOption.tsx b/app/src/components/ui/menu/EditWidgetOption.tsx index 9ef67af..ce5261a 100644 --- a/app/src/components/ui/menu/EditWidgetOption.tsx +++ b/app/src/components/ui/menu/EditWidgetOption.tsx @@ -1,15 +1,26 @@ -import React from "react"; +import React, { useEffect } from "react"; +import { useLeftData, useRightSelected, useTopData } from "../../../store/useZone3DWidgetStore"; interface EditWidgetOptionProps { options: string[]; } const EditWidgetOption: React.FC = ({ options }) => { + const { top, setTop } = useTopData() + const { left, setLeft } = useLeftData() + const { rightSelect, setRightSelect } = useRightSelected() + + useEffect(() => { + + console.log('left: ', left); + console.log('top: ', top); + }, [top, left]) + return ( -
+
{options.map((option, index) => ( -
+
setRightSelect(option)}> {option}
))} diff --git a/app/src/store/store.ts b/app/src/store/store.ts index 87f937c..bd903f2 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -12,7 +12,7 @@ export const useSocketStore = create((set: any, get: any) => ({ } const socket = io( - `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}`, + `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`, { reconnection: false, auth: { email, organization }, diff --git a/app/src/store/useZone3DWidgetStore.ts b/app/src/store/useZone3DWidgetStore.ts index fbb8e74..850623f 100644 --- a/app/src/store/useZone3DWidgetStore.ts +++ b/app/src/store/useZone3DWidgetStore.ts @@ -1,33 +1,77 @@ + import { create } from "zustand"; type WidgetData = { - id: string; - type: string; - position: [number, number, number]; + id: string; + type: string; + position: [number, number, number]; + tempPosition?: [number, number, number]; }; type ZoneWidgetStore = { - zoneWidgetData: Record; - setZoneWidgetData: (zoneId: string, widgets: WidgetData[]) => void; - addWidget: (zoneId: string, widget: WidgetData) => void; + zoneWidgetData: Record; + setZoneWidgetData: (zoneId: string, widgets: WidgetData[]) => void; + addWidget: (zoneId: string, widget: WidgetData) => void; + updateWidgetPosition: (zoneId: string, widgetId: string, newPosition: [number, number, number]) => void; }; export const useZoneWidgetStore = create((set) => ({ - zoneWidgetData: {}, - - setZoneWidgetData: (zoneId, widgets) => - set((state) => ({ - zoneWidgetData: { - ...state.zoneWidgetData, - [zoneId]: widgets, - }, - })), - - addWidget: (zoneId, widget) => - set((state) => ({ - zoneWidgetData: { - ...state.zoneWidgetData, - [zoneId]: [...(state.zoneWidgetData[zoneId] || []), widget], - }, - })), + zoneWidgetData: {}, + + setZoneWidgetData: (zoneId, widgets) => + set((state) => ({ + zoneWidgetData: { ...state.zoneWidgetData, [zoneId]: widgets }, + })), + + addWidget: (zoneId, widget) => + set((state) => ({ + zoneWidgetData: { + ...state.zoneWidgetData, + [zoneId]: [...(state.zoneWidgetData[zoneId] || []), widget], + }, + })), + + updateWidgetPosition: (zoneId, widgetId, newPosition) => + set((state) => { + const widgets = state.zoneWidgetData[zoneId] || []; + return { + zoneWidgetData: { + ...state.zoneWidgetData, + [zoneId]: widgets.map((widget) => + widget.id === widgetId ? { ...widget, position: newPosition } : widget + ), + }, + }; + }), +})); + + +interface RightClickStore { + rightClickSelected: string | null; + setRightClickSelected: (x: string | null) => void; +} + +export const useRightClickSelected = create((set) => ({ + rightClickSelected: null, // Default to null + setRightClickSelected: (x) => set({ rightClickSelected: x }), +})); + +export const useTopData = create((set: any) => ({ + top: 0, + setTop: (x: any) => set({ top: x }), +})); + +export const useLeftData = create((set: any) => ({ + left: 0, + setLeft: (x: any) => set({ left: x }), +})); + +interface RightSelectStore { + rightSelect: string | null; + setRightSelect: (x: string | null) => void; +} + +export const useRightSelected = create((set) => ({ + rightSelect: null, // Default state is null + setRightSelect: (x) => set({ rightSelect: x }), })); diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss index e64ec08..a79823c 100644 --- a/app/src/styles/pages/realTimeViz.scss +++ b/app/src/styles/pages/realTimeViz.scss @@ -716,11 +716,6 @@ } -.editWidgetOptions-wrapper { - - height: 100vh; - width: 100vw; -} .editWidgetOptions { position: absolute;