rtViz #9

Merged
Vishnu merged 8 commits from rtViz into main 2025-03-27 07:29:38 +00:00
18 changed files with 1465 additions and 1162 deletions
Showing only changes of commit 558236c458 - Show all commits

View File

@@ -49,25 +49,22 @@ const SideBarRight: React.FC = () => {
{activeModule === "simulation" && ( {activeModule === "simulation" && (
<> <>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
subModule === "mechanics" ? "active" : "" }`}
}`}
onClick={() => setSubModule("mechanics")} onClick={() => setSubModule("mechanics")}
> >
<MechanicsIcon isActive={activeList === "mechanics"} /> <MechanicsIcon isActive={activeList === "mechanics"} />
</div> </div>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
subModule === "simulations" ? "active" : "" }`}
}`}
onClick={() => setSubModule("simulations")} onClick={() => setSubModule("simulations")}
> >
<SimulationIcon isActive={activeList === "simulations"} /> <SimulationIcon isActive={activeList === "simulations"} />
</div> </div>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
subModule === "analysis" ? "active" : "" }`}
}`}
onClick={() => setSubModule("analysis")} onClick={() => setSubModule("analysis")}
> >
<AnalysisIcon isActive={activeList === "analysis"} /> <AnalysisIcon isActive={activeList === "analysis"} />
@@ -78,7 +75,18 @@ const SideBarRight: React.FC = () => {
)} )}
{/* process builder */} {/* process builder */}
{toggleUI && {toggleUI &&
activeList === "properties" && subModule === "zoneProperties" &&
activeModule === "builder" && (
<div className="sidebar-right-container">
<div className="sidebar-right-content-container">
{/* <GlobalProperties /> */}
<ZoneProperties />
{/* <AsstePropertiies /> */}
</div>
</div>
)}
{toggleUI &&
subModule === "properties" &&
activeModule !== "visualization" && ( activeModule !== "visualization" && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
@@ -88,7 +96,6 @@ const SideBarRight: React.FC = () => {
</div> </div>
</div> </div>
)} )}
{/* simulation */} {/* simulation */}
{toggleUI && activeModule === "simulation" && ( {toggleUI && activeModule === "simulation" && (

View File

@@ -1,9 +1,11 @@
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import RenameInput from "../../../ui/inputs/RenameInput"; import RenameInput from "../../../ui/inputs/RenameInput";
import Vector3Input from "../customInput/Vector3Input"; import Vector3Input from "../customInput/Vector3Input";
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
const ZoneProperties: React.FC = () => { const ZoneProperties: React.FC = () => {
const [Edit, setEdit] = useState(false); const [Edit, setEdit] = useState(false);
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
function handleSetView() { function handleSetView() {
setEdit(false); setEdit(false);
@@ -16,17 +18,21 @@ const ZoneProperties: React.FC = () => {
setEdit(true); setEdit(true);
} }
} }
useEffect(() => {
console.log(' selectedZone.zoneName: ', selectedZone.zoneName);
}, [selectedZone])
return ( return (
<div className="zone-properties-container"> <div className="zone-properties-container">
<div className="header"> <div className="header">
<RenameInput value="Selected Zone Name" /> <RenameInput value={selectedZone.zoneName ? selectedZone.zoneName : ""} />
<div className="button" onClick={handleEditView}> <div className="button" onClick={handleEditView}>
{Edit ? "Cancel" : "Edit"} {Edit ? "Cancel" : "Edit"}
</div> </div>
</div> </div>
<Vector3Input onChange={() => {}} header="Viewport Target" /> <Vector3Input onChange={() => { }} header="Viewport Target" />
<Vector3Input onChange={() => {}} header="Viewport Position" /> <Vector3Input onChange={() => { }} header="Viewport Position" />
{Edit && ( {Edit && (
<div className="button-save" onClick={handleSetView}> <div className="button-save" onClick={handleSetView}>
Set View Set View

View File

@@ -1,193 +1,212 @@
import React from "react"; import React from "react";
import { import {
CleanPannel, CleanPannel,
EyeIcon, EyeIcon,
LockIcon, LockIcon,
} from "../../icons/RealTimeVisulationIcons"; } from "../../icons/RealTimeVisulationIcons";
import { panelData } from "../../../services/realTimeVisulization/zoneData/panel";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right"; // Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
// Define the type for the props passed to the Buttons component
interface ButtonsProps { // Define the type for the props passed to the Buttons component
selectedZone: { interface ButtonsProps {
zoneName: string; selectedZone: {
activeSides: Side[]; zoneName: string;
panelOrder: Side[]; activeSides: Side[];
lockedPanels: Side[]; panelOrder: Side[];
widgets: { lockedPanels: Side[];
id: string; zoneId: string;
type: string; zoneViewPortTarget: number[];
title: string; zoneViewPortPosition: number[]
panel: Side; widgets: {
data: any; id: string;
}[]; type: string;
}; title: string;
setSelectedZone: React.Dispatch< panel: Side;
React.SetStateAction<{ data: any;
zoneName: string; }[];
activeSides: Side[]; };
panelOrder: Side[]; setSelectedZone: React.Dispatch<
lockedPanels: Side[]; React.SetStateAction<{
widgets: { zoneName: string;
id: string; activeSides: Side[];
type: string; panelOrder: Side[];
title: string; lockedPanels: Side[];
panel: Side; zoneId: string;
data: any; zoneViewPortTarget: number[];
}[]; zoneViewPortPosition: number[]
}> widgets: {
>; id: string;
hiddenPanels: Side[]; // Add this prop for hidden panels type: string;
setHiddenPanels: React.Dispatch<React.SetStateAction<Side[]>>; // Add this prop for updating hidden panels title: string;
} panel: Side;
data: any;
const AddButtons: React.FC<ButtonsProps> = ({ }[];
selectedZone, }>
setSelectedZone, >;
setHiddenPanels, hiddenPanels: Side[]; // Add this prop for hidden panels
hiddenPanels, setHiddenPanels: React.Dispatch<React.SetStateAction<Side[]>>; // Add this prop for updating hidden panels
}) => { }
// Local state to track hidden panels
const AddButtons: React.FC<ButtonsProps> = ({
// Function to toggle lock/unlock a panel selectedZone,
const toggleLockPanel = (side: Side) => { setSelectedZone,
const newLockedPanels = selectedZone.lockedPanels.includes(side) setHiddenPanels,
? selectedZone.lockedPanels.filter((panel) => panel !== side) hiddenPanels,
: [...selectedZone.lockedPanels, side]; }) => {
// Local state to track hidden panels
const updatedZone = {
...selectedZone, // Function to toggle lock/unlock a panel
lockedPanels: newLockedPanels, const toggleLockPanel = (side: Side) => {
}; const newLockedPanels = selectedZone.lockedPanels.includes(side)
? selectedZone.lockedPanels.filter((panel) => panel !== side)
// Update the selectedZone state : [...selectedZone.lockedPanels, side];
setSelectedZone(updatedZone);
}; const updatedZone = {
...selectedZone,
// Function to toggle visibility of a panel lockedPanels: newLockedPanels,
const toggleVisibility = (side: Side) => { };
const isHidden = hiddenPanels.includes(side);
if (isHidden) { // Update the selectedZone state
// If the panel is already hidden, remove it from the hiddenPanels array setSelectedZone(updatedZone);
setHiddenPanels(hiddenPanels.filter((panel) => panel !== side)); };
} else {
// If the panel is visible, add it to the hiddenPanels array // Function to toggle visibility of a panel
setHiddenPanels([...hiddenPanels, side]); const toggleVisibility = (side: Side) => {
} const isHidden = hiddenPanels.includes(side);
}; if (isHidden) {
// If the panel is already hidden, remove it from the hiddenPanels array
// Function to clean all widgets from a panel setHiddenPanels(hiddenPanels.filter((panel) => panel !== side));
const cleanPanel = (side: Side) => { } else {
const cleanedWidgets = selectedZone.widgets.filter( // If the panel is visible, add it to the hiddenPanels array
(widget) => widget.panel !== side setHiddenPanels([...hiddenPanels, side]);
); }
};
const updatedZone = {
...selectedZone, // Function to clean all widgets from a panel
widgets: cleanedWidgets, const cleanPanel = (side: Side) => {
}; const cleanedWidgets = selectedZone.widgets.filter(
(widget) => widget.panel !== side
// Update the selectedZone state );
setSelectedZone(updatedZone);
}; const updatedZone = {
...selectedZone,
// Function to handle "+" button click widgets: cleanedWidgets,
const handlePlusButtonClick = (side: Side) => { };
if (selectedZone.activeSides.includes(side)) {
// If the panel is already active, remove all widgets and close the panel // Update the selectedZone state
const cleanedWidgets = selectedZone.widgets.filter( setSelectedZone(updatedZone);
(widget) => widget.panel !== side };
);
const newActiveSides = selectedZone.activeSides.filter((s) => s !== side); // Function to handle "+" button click
const handlePlusButtonClick = (side: Side) => {
const updatedZone = { if (selectedZone.activeSides.includes(side)) {
...selectedZone, // If the panel is already active, remove all widgets and close the panel
widgets: cleanedWidgets, const cleanedWidgets = selectedZone.widgets.filter(
activeSides: newActiveSides, (widget) => widget.panel !== side
panelOrder: newActiveSides, );
}; const newActiveSides = selectedZone.activeSides.filter((s) => s !== side);
// Update the selectedZone state const updatedZone = {
console.log('updatedZone: ', updatedZone); ...selectedZone,
setSelectedZone(updatedZone); widgets: cleanedWidgets,
} else { activeSides: newActiveSides,
// If the panel is not active, activate it panelOrder: newActiveSides,
const newActiveSides = [...selectedZone.activeSides, side]; };
const updatedZone = { // Delete the selectedZone state
...selectedZone, console.log('updatedZone: ', updatedZone);
activeSides: newActiveSides, setSelectedZone(updatedZone);
panelOrder: newActiveSides, } else {
}; // If the panel is not active, activate it
const newActiveSides = [...selectedZone.activeSides, side];
// Update the selectedZone state
console.log('updatedZone: ', updatedZone); const updatedZone = {
setSelectedZone(updatedZone); ...selectedZone,
} activeSides: newActiveSides,
}; panelOrder: newActiveSides,
};
return ( const email = localStorage.getItem('email')
<div> const organization = (email!.split("@")[1]).split(".")[0];
{(["top", "right", "bottom", "left"] as Side[]).map((side) => ( let response = panelData(organization, selectedZone.zoneId, newActiveSides)
<div key={side} className={`side-button-container ${side}`}> console.log('response: ', response);
<button
className={`side-button ${side}`} // Update the selectedZone state
onClick={() => handlePlusButtonClick(side)} console.log('updatedZone: ', updatedZone);
title={ setSelectedZone(updatedZone);
selectedZone.activeSides.includes(side) }
? `Remove all items and close ${side} panel` };
: `Activate ${side} panel`
} return (
> <>
+
</button> <div>
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
{/* Extra Buttons */} <div key={side} className={`side-button-container ${side}`}>
{selectedZone.activeSides.includes(side) && ( {/* "+" Button */}
<div className="extra-Bs"> <button
{/* Hide Panel */} className={`side-button ${side}`}
<div onClick={() => handlePlusButtonClick(side)}
className={`icon ${hiddenPanels.includes(side) ? "active" : "" title={
}`} selectedZone.activeSides.includes(side)
title={ ? `Remove all items and close ${side} panel`
hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel" : `Activate ${side} panel`
} }
onClick={() => toggleVisibility(side)} >
> +
<EyeIcon </button>
fill={hiddenPanels.includes(side) ? "white" : "#1D1E21"}
/> {/* Extra Buttons */}
</div> {selectedZone.activeSides.includes(side) && (
<div className="extra-Bs">
{/* Clean Panel */} {/* Hide Panel */}
<div <div
className="icon" className={`icon ${hiddenPanels.includes(side) ? "active" : ""
title="Clean Panel" }`}
onClick={() => cleanPanel(side)} title={
> hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
<CleanPannel /> }
</div> onClick={() => toggleVisibility(side)}
>
{/* Lock/Unlock Panel */} <EyeIcon
<div fill={
className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : "" hiddenPanels.includes(side)
}`} ? "white"
title={ : "#1D1E21"
selectedZone.lockedPanels.includes(side) }
? "Unlock Panel" />
: "Lock Panel" </div>
}
onClick={() => toggleLockPanel(side)} {/* Clean Panel */}
> <div
<LockIcon fill={selectedZone.lockedPanels.includes(side) ? "#ffffff" : "#1D1E21"} /> className="icon"
</div> title="Clean Panel"
</div> onClick={() => cleanPanel(side)}
)} >
</div> <CleanPannel />
))} </div>
</div>
); {/* Lock/Unlock Panel */}
}; <div
className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : ""
export default AddButtons; }`}
title={
selectedZone.lockedPanels.includes(side)
? "Unlock Panel"
: "Lock Panel"
}
onClick={() => toggleLockPanel(side)}
>
<LockIcon fill={selectedZone.lockedPanels.includes(side) ? "#ffffff" : "#1D1E21"} />
</div>
</div>
)}
</div>
))}
</div>
</>
);
};
export default AddButtons;

View File

@@ -11,6 +11,9 @@ interface DisplayZoneProps {
panelOrder: Side[]; panelOrder: Side[];
lockedPanels: Side[]; lockedPanels: Side[];
widgets: Widget[]; widgets: Widget[];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
}; };
}; };
selectedZone: { selectedZone: {
@@ -18,6 +21,9 @@ interface DisplayZoneProps {
activeSides: Side[]; activeSides: Side[];
panelOrder: Side[]; panelOrder: Side[];
lockedPanels: Side[]; lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: { widgets: {
id: string; id: string;
type: string; type: string;
@@ -32,6 +38,9 @@ interface DisplayZoneProps {
activeSides: Side[]; activeSides: Side[];
panelOrder: Side[]; panelOrder: Side[];
lockedPanels: Side[]; lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: { widgets: {
id: string; id: string;
type: string; type: string;
@@ -152,16 +161,16 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
return ( return (
<div <div
ref={containerRef} ref={containerRef}
className={`zoon-wrapper ${selectedZone.activeSides.includes("bottom") && "bottom" className={`zoon-wrapper ${selectedZone?.activeSides?.includes("bottom") && "bottom"
}`} }`}
> >
{Object.keys(zonesData).map((zoneName, index) => ( {Object.keys(zonesData).map((zoneName, index) => (
<div <div
key={index} key={index}
className={`zone ${selectedZone.zoneName === zoneName ? "active" : "" className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
console.log('zoneName: ', zoneName);
setSelectedZone({ setSelectedZone({
zoneName, zoneName,
@@ -169,12 +178,15 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
panelOrder: zonesData[zoneName].panelOrder || [], panelOrder: zonesData[zoneName].panelOrder || [],
lockedPanels: zonesData[zoneName].lockedPanels || [], lockedPanels: zonesData[zoneName].lockedPanels || [],
widgets: zonesData[zoneName].widgets || [], widgets: zonesData[zoneName].widgets || [],
}) zoneId: zonesData[zoneName]?.zoneId || "",
zoneViewPortTarget: zonesData[zoneName].zoneViewPortTarget || [],
zoneViewPortPosition:
zonesData[zoneName].zoneViewPortPosition || [],
});
// setSelectedZone({ // setSelectedZone({
// zoneName, // zoneName,
// ...zonesData[zoneName], // ...zonesData[zoneName],
// }); // });
console.log(selectedZone);
}} }}
> >
{zoneName} {zoneName}
@@ -184,4 +196,4 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
); );
}; };
export default DisplayZone; export default DisplayZone;

View File

@@ -0,0 +1,59 @@
import { useState } from "react";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
const DroppedObjects = () => {
const { camera } = useThree(); // Now inside Canvas ✅
const [objects, setObjects] = useState<{ id: number; position: [number, number, number] }[]>([]);
// Function to convert drop event into 3D position
const handleDrop = (event: DragEvent) => {
event.preventDefault();
const data = event.dataTransfer?.getData("text/plain");
if (!data) return;
try {
const cardData = JSON.parse(data);
if (!cardData.className.includes("floating total-card")) {
console.log("Drop rejected: Incorrect element.");
return;
}
// Convert 2D drop position to 3D world coordinates
const x = (event.clientX / window.innerWidth) * 2 - 1;
const y = -(event.clientY / window.innerHeight) * 2 + 1;
// Raycasting to determine the drop position in 3D
const raycaster = new THREE.Raycaster();
const mouseVector = new THREE.Vector2(x, y);
raycaster.setFromCamera(mouseVector, camera);
// Intersect with a ground plane (assume y = 0)
const groundPlane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
const intersection = new THREE.Vector3();
raycaster.ray.intersectPlane(groundPlane, intersection);
console.log("Spawn Object at:", intersection);
// Add the dropped object to the scene state
setObjects((prev) => [...prev, { id: Date.now(), position: [intersection.x, intersection.y, intersection.z] }]);
} catch (error) {
console.error("Invalid data:", error);
}
};
return (
<group>
{/* Render dropped objects as green boxes */}
{objects.map((obj) => (
<mesh key={obj.id} position={obj.position}>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color="green" />
</mesh>
))}
</group>
);
};
export default DroppedObjects;

View File

@@ -1,245 +1,251 @@
import React, { useEffect, useMemo, useRef, useState } from "react"; import React, { useEffect, useMemo, useRef, useState } from "react";
import { useWidgetStore } from "../../../store/useWidgetStore"; import { useWidgetStore } from "../../../store/useWidgetStore";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import { DraggableWidget } from "./DraggableWidget"; import { DraggableWidget } from "./DraggableWidget";
import { arrayMove } from "@dnd-kit/sortable"; import { arrayMove } from "@dnd-kit/sortable";
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
interface Widget { interface Widget {
id: string; id: string;
type: string; type: string;
title: string; title: string;
panel: Side; panel: Side;
data: any; data: any;
} }
interface PanelProps { interface PanelProps {
selectedZone: { selectedZone: {
zoneName: string; zoneName: string;
activeSides: Side[]; activeSides: Side[];
panelOrder: Side[]; panelOrder: Side[];
lockedPanels: Side[]; lockedPanels: Side[];
widgets: Widget[]; zoneId: string;
}; zoneViewPortTarget: number[];
setSelectedZone: React.Dispatch< zoneViewPortPosition: number[]
React.SetStateAction<{ widgets: Widget[];
zoneName: string; };
activeSides: Side[]; setSelectedZone: React.Dispatch<
panelOrder: Side[]; React.SetStateAction<{
lockedPanels: Side[]; zoneName: string;
widgets: Widget[]; activeSides: Side[];
}> panelOrder: Side[];
>; lockedPanels: Side[];
hiddenPanels: string[]; zoneId: string;
} zoneViewPortTarget: number[];
zoneViewPortPosition: number[]
const generateUniqueId = () => widgets: Widget[];
`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; }>
>;
const Panel: React.FC<PanelProps> = ({ hiddenPanels: string[];
selectedZone, }
setSelectedZone,
hiddenPanels, const generateUniqueId = () =>
}) => { `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
const [panelDimensions, setPanelDimensions] = useState<{ const Panel: React.FC<PanelProps> = ({
[side in Side]?: { width: number; height: number }; selectedZone,
}>({}); setSelectedZone,
hiddenPanels,
const { isPlaying } = usePlayButtonStore(); }) => {
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
const getPanelStyle = useMemo( const [panelDimensions, setPanelDimensions] = useState<{
() => (side: Side) => { [side in Side]?: { width: number; height: number };
const currentIndex = selectedZone.panelOrder.indexOf(side); }>({});
const previousPanels = selectedZone.panelOrder.slice(0, currentIndex);
const leftActive = previousPanels.includes("left"); const { isPlaying } = usePlayButtonStore();
const rightActive = previousPanels.includes("right");
const topActive = previousPanels.includes("top"); const getPanelStyle = useMemo(
const bottomActive = previousPanels.includes("bottom"); () => (side: Side) => {
const panelSize = isPlaying ? 300 : 210; const currentIndex = selectedZone.panelOrder.indexOf(side);
const previousPanels = selectedZone.panelOrder.slice(0, currentIndex);
switch (side) { const leftActive = previousPanels.includes("left");
case "top": const rightActive = previousPanels.includes("right");
case "bottom": const topActive = previousPanels.includes("top");
return { const bottomActive = previousPanels.includes("bottom");
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0) const panelSize = isPlaying ? 300 : 210;
}px)`,
height: `${panelSize - 5}px`, switch (side) {
left: leftActive ? `${panelSize}px` : "0", case "top":
right: rightActive ? `${panelSize}px` : "0", case "bottom":
[side]: "0", return {
}; width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
case "left": }px)`,
case "right": height: `${panelSize - 5}px`,
return { left: leftActive ? `${panelSize}px` : "0",
width: `${panelSize - 5}px`, right: rightActive ? `${panelSize}px` : "0",
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0) [side]: "0",
}px)`, };
top: topActive ? `${panelSize}px` : "0", case "left":
bottom: bottomActive ? `${panelSize}px` : "0", case "right":
[side]: "0", return {
}; width: `${panelSize - 5}px`,
default: height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
return {}; }px)`,
} top: topActive ? `${panelSize}px` : "0",
}, bottom: bottomActive ? `${panelSize}px` : "0",
[selectedZone.panelOrder, isPlaying] [side]: "0",
); };
default:
const handleDrop = (e: React.DragEvent, panel: Side) => { return {};
e.preventDefault(); }
const { draggedAsset } = useWidgetStore.getState(); },
if (!draggedAsset) return; [selectedZone.panelOrder, isPlaying]
if (isPanelLocked(panel)) return; );
const currentWidgetsCount = getCurrentWidgetCount(panel); const handleDrop = (e: React.DragEvent, panel: Side) => {
const maxCapacity = calculatePanelCapacity(panel); e.preventDefault();
const { draggedAsset } = useWidgetStore.getState();
if (currentWidgetsCount >= maxCapacity) return; if (!draggedAsset) return;
if (isPanelLocked(panel)) return;
console.log('draggedAsset: ', draggedAsset);
console.log('panel: ', panel); const currentWidgetsCount = getCurrentWidgetCount(panel);
addWidgetToPanel(draggedAsset, panel); const maxCapacity = calculatePanelCapacity(panel);
};
if (currentWidgetsCount >= maxCapacity) return;
const isPanelLocked = (panel: Side) =>
selectedZone.lockedPanels.includes(panel); console.log('draggedAsset: ', draggedAsset);
console.log('panel: ', panel);
const getCurrentWidgetCount = (panel: Side) => addWidgetToPanel(draggedAsset, panel);
selectedZone.widgets.filter((w) => w.panel === panel).length; };
const calculatePanelCapacity = (panel: Side) => { const isPanelLocked = (panel: Side) =>
const CHART_WIDTH = 150; selectedZone.lockedPanels.includes(panel);
const CHART_HEIGHT = 150;
const FALLBACK_HORIZONTAL_CAPACITY = 5; const getCurrentWidgetCount = (panel: Side) =>
const FALLBACK_VERTICAL_CAPACITY = 3; selectedZone.widgets.filter((w) => w.panel === panel).length;
const dimensions = panelDimensions[panel]; const calculatePanelCapacity = (panel: Side) => {
if (!dimensions) { const CHART_WIDTH = 150;
return panel === "top" || panel === "bottom" const CHART_HEIGHT = 150;
? FALLBACK_HORIZONTAL_CAPACITY const FALLBACK_HORIZONTAL_CAPACITY = 5;
: FALLBACK_VERTICAL_CAPACITY; const FALLBACK_VERTICAL_CAPACITY = 3;
}
const dimensions = panelDimensions[panel];
return panel === "top" || panel === "bottom" if (!dimensions) {
? Math.floor(dimensions.width / CHART_WIDTH) return panel === "top" || panel === "bottom"
: Math.floor(dimensions.height / CHART_HEIGHT); ? FALLBACK_HORIZONTAL_CAPACITY
}; : FALLBACK_VERTICAL_CAPACITY;
}
const addWidgetToPanel = (asset: any, panel: Side) => {
const newWidget = { return panel === "top" || panel === "bottom"
...asset, ? Math.floor(dimensions.width / CHART_WIDTH)
id: generateUniqueId(), : Math.floor(dimensions.height / CHART_HEIGHT);
panel, };
};
const addWidgetToPanel = (asset: any, panel: Side) => {
setSelectedZone((prev) => ({ const newWidget = {
...prev, ...asset,
widgets: [...prev.widgets, newWidget], id: generateUniqueId(),
})); panel,
}; };
useEffect(() => { setSelectedZone((prev) => ({
const observers: ResizeObserver[] = []; ...prev,
const currentPanelRefs = panelRefs.current; widgets: [...prev.widgets, newWidget],
}));
selectedZone.activeSides.forEach((side) => { };
const element = currentPanelRefs[side];
if (element) { useEffect(() => {
const observer = new ResizeObserver((entries) => { const observers: ResizeObserver[] = [];
for (const entry of entries) { const currentPanelRefs = panelRefs.current;
const { width, height } = entry.contentRect;
setPanelDimensions((prev) => ({ selectedZone.activeSides.forEach((side) => {
...prev, const element = currentPanelRefs[side];
[side]: { width, height }, if (element) {
})); const observer = new ResizeObserver((entries) => {
} for (const entry of entries) {
}); const { width, height } = entry.contentRect;
observer.observe(element); setPanelDimensions((prev) => ({
observers.push(observer); ...prev,
} [side]: { width, height },
}); }));
}
return () => { });
observers.forEach((observer) => observer.disconnect()); observer.observe(element);
}; observers.push(observer);
}, [selectedZone.activeSides]); }
});
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
if (!selectedZone) return; // Ensure selectedZone is not null return () => {
console.log('selectedZone: ', selectedZone); observers.forEach((observer) => observer.disconnect());
};
setSelectedZone((prev) => { }, [selectedZone.activeSides]);
if (!prev) return prev; // Ensure prev is not null
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
// Filter widgets for the specified panel if (!selectedZone) return; // Ensure selectedZone is not null
const widgetsInPanel = prev.widgets.filter((w) => w.panel === panel); console.log('selectedZone: ', selectedZone);
// Reorder widgets within the same panel setSelectedZone((prev) => {
const reorderedWidgets = arrayMove(widgetsInPanel, fromIndex, toIndex); if (!prev) return prev; // Ensure prev is not null
// Merge the reordered widgets back into the full list while preserving the order // Filter widgets for the specified panel
const updatedWidgets = prev.widgets const widgetsInPanel = prev.widgets.filter((w) => w.panel === panel);
.filter((widget) => widget.panel !== panel) // Keep widgets from other panels
.concat(reorderedWidgets); // Add the reordered widgets for the specified panel // Reorder widgets within the same panel
const reorderedWidgets = arrayMove(widgetsInPanel, fromIndex, toIndex);
return {
...prev, // Merge the reordered widgets back into the full list while preserving the order
widgets: updatedWidgets, const updatedWidgets = prev.widgets
}; .filter((widget) => widget.panel !== panel) // Keep widgets from other panels
}); .concat(reorderedWidgets); // Add the reordered widgets for the specified panel
};
return {
...prev,
widgets: updatedWidgets,
};
return ( });
<> };
{selectedZone.activeSides.map((side) => (
<div
key={side}
className={`panel ${side}-panel absolute ${isPlaying && ""}`}
style={getPanelStyle(side)} return (
onDrop={(e) => handleDrop(e, side)} <>
onDragOver={(e) => e.preventDefault()} {selectedZone.activeSides.map((side) => (
ref={(el) => { <div
if (el) { key={side}
panelRefs.current[side] = el; className={`panel ${side}-panel absolute ${isPlaying && ""}`}
} else { style={getPanelStyle(side)}
delete panelRefs.current[side]; onDrop={(e) => handleDrop(e, side)}
} onDragOver={(e) => e.preventDefault()}
}} ref={(el) => {
> if (el) {
<div panelRefs.current[side] = el;
className={`panel-content ${isPlaying && "fullScreen"}`} } else {
style={{ delete panelRefs.current[side];
pointerEvents: selectedZone.lockedPanels.includes(side) }
? "none" }}
: "auto", >
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1", <div
}} className={`panel-content ${isPlaying && "fullScreen"}`}
> style={{
{selectedZone.widgets pointerEvents: selectedZone.lockedPanels.includes(side)
.filter((w) => w.panel === side) ? "none"
.map((widget, index) => ( : "auto",
<DraggableWidget opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
hiddenPanels={hiddenPanels} }}
widget={widget} >
key={widget.id} {selectedZone.widgets
index={index} .filter((w) => w.panel === side)
onReorder={(fromIndex, toIndex) => .map((widget, index) => (
handleReorder(fromIndex, toIndex, side) <DraggableWidget
} hiddenPanels={hiddenPanels}
/> widget={widget}
))} key={widget.id}
</div> index={index}
</div> onReorder={(fromIndex, toIndex) =>
))} handleReorder(fromIndex, toIndex, side)
</> }
); />
}; ))}
</div>
export default Panel; </div>
))}
</>
);
};
export default Panel;

View File

@@ -1,147 +1,157 @@
import React, { useEffect, useState, useRef } from "react"; import React, { useEffect, useState, useRef } from "react";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import Panel from "./Panel"; import Panel from "./Panel";
import AddButtons from "./AddButtons"; import AddButtons from "./AddButtons";
import { useSelectedZoneStore } from "../../../store/useZoneStore"; import { useSelectedZoneStore } from "../../../store/useZoneStore";
import DisplayZone from "./DisplayZone"; import DisplayZone from "./DisplayZone";
import Scene from "../../../modules/scene/scene"; import Scene from "../../../modules/scene/scene";
import useModuleStore from "../../../store/useModuleStore"; import useModuleStore from "../../../store/useModuleStore";
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones"; import { useZones } from "../../../store/store";
type Side = "top" | "bottom" | "left" | "right";
type Side = "top" | "bottom" | "left" | "right";
type FormattedZoneData = Record<
string, type FormattedZoneData = Record<
{ string,
activeSides: Side[]; {
panelOrder: Side[]; activeSides: Side[];
lockedPanels: Side[]; panelOrder: Side[];
zoneCentrePoint: number[]; lockedPanels: Side[];
widgets: Widget[]; zoneId: string;
} zoneViewPortTarget: number[];
>; zoneViewPortPosition: number[]
type Widget = { widgets: Widget[];
id: string; }
type: string; >;
title: string; type Widget = {
panel: Side; id: string;
data: any; type: string;
}; title: string;
type Zone = { panel: Side;
zoneId: string; data: any;
zoneName: string; };
points: number[][];
layer: number; const RealTimeVisulization: React.FC = () => {
}; const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
const containerRef = useRef<HTMLDivElement>(null);
const RealTimeVisulization: React.FC = () => { const { isPlaying } = usePlayButtonStore();
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]); const { activeModule } = useModuleStore();
const containerRef = useRef<HTMLDivElement>(null);
const { isPlaying } = usePlayButtonStore(); const [zonesData, setZonesData] = useState<FormattedZoneData>({});
const { activeModule } = useModuleStore(); const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { zones } = useZones()
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
const { selectedZone, setSelectedZone } = useSelectedZoneStore(); useEffect(() => {
const data = Array.isArray(zones) ? zones : [];
useEffect(() => { console.log('data: ', data);
async function GetZoneData() { const formattedData = data.reduce<FormattedZoneData>((acc, zone) => {
try { acc[zone.zoneName] = {
const response: { data: Zone[] } | undefined = await getZonesApi( activeSides: [],
"hexrfactory" panelOrder: [],
); lockedPanels: [],
zoneId: zone.zoneId,
if (!response || !response.data) { zoneViewPortTarget: zone.viewPortCenter,
return; zoneViewPortPosition: zone.viewPortposition,
} widgets: [],
const formattedData = response?.data?.reduce<FormattedZoneData>( };
(acc, zone) => { return acc;
acc[zone.zoneName] = { }, {});
activeSides: [],
panelOrder: [], setZonesData(formattedData);
lockedPanels: [], }, [zones]);
zoneCentrePoint: [],
widgets: [], useEffect(() => {
}; setZonesData((prev) => {
return acc; if (!selectedZone) return prev;
}, return {
{} ...prev,
); [selectedZone.zoneName]: {
setZonesData(formattedData); ...prev[selectedZone.zoneName], // Keep existing properties
} catch (error) { } activeSides: selectedZone.activeSides || [],
} panelOrder: selectedZone.panelOrder || [],
GetZoneData(); lockedPanels: selectedZone.lockedPanels || [],
}, []); zoneId: selectedZone.zoneId || "",
zoneViewPortTarget: selectedZone.zoneViewPortTarget || [],
useEffect(() => { zoneViewPortPosition: selectedZone.zoneViewPortPosition || [],
widgets: selectedZone.widgets || [],
console.log('zonesData: ', zonesData); },
}, [zonesData]); };
});
useEffect(() => { }, [selectedZone]);
setZonesData((prev) => {
if (!selectedZone) return prev; const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
return { const canvas = document.querySelector(".scene-container");
...prev, if (canvas) {
[selectedZone.zoneName]: { // Extract relevant properties manually
...prev[selectedZone.zoneName], // Keep existing properties const dragEvent = new DragEvent("drop", {
activeSides: selectedZone.activeSides || [], bubbles: true,
panelOrder: selectedZone.panelOrder || [], cancelable: true,
lockedPanels: selectedZone.lockedPanels || [], dataTransfer: event.dataTransfer, // Attach dataTransfer manually ✅
widgets: selectedZone.widgets || [], });
},
}; console.log('dragEvent: ', dragEvent);
}); canvas.dispatchEvent(dragEvent);
}, [selectedZone]); }
};
return (
<div
ref={containerRef} return (
id="real-time-vis-canvas" <div
className={`realTime-viz canvas ${isPlaying ? "playingFlase" : ""}`} ref={containerRef}
style={{ id="real-time-vis-canvas"
height: isPlaying || activeModule !== "visualization" ? "100vh" : "", className={`realTime-viz canvas ${isPlaying ? "playingFlase" : ""}`}
width: isPlaying || activeModule !== "visualization" ? "100vw" : "", style={{
left: isPlaying || activeModule !== "visualization" ? "0%" : "", height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
}} width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
> left: isPlaying || activeModule !== "visualization" ? "0%" : "",
<div }}
className="scene-container" >
style={{ <div
height: "100%", className="scene-container"
width: "100%", style={{
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px", height: "100%",
}} width: "100%",
> borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px",
<Scene /> }}
</div> onDrop={handleDrop}
{activeModule === "visualization" && ( >
<> {/* {objects.map((obj) => (
<DisplayZone <mesh key={obj.id} position={obj.position}>
zonesData={zonesData} <boxGeometry args={[1, 1, 1]} />
selectedZone={selectedZone} <meshStandardMaterial color="green" />
setSelectedZone={setSelectedZone} </mesh>
/> ))} */}
<Scene />
{!isPlaying && ( </div>
<AddButtons {activeModule === "visualization" && (
hiddenPanels={hiddenPanels} <>
setHiddenPanels={setHiddenPanels} <DisplayZone
selectedZone={selectedZone} zonesData={zonesData}
setSelectedZone={setSelectedZone} selectedZone={selectedZone}
/> setSelectedZone={setSelectedZone}
)} />
<Panel {!isPlaying && selectedZone?.zoneName !== "" && (
selectedZone={selectedZone} <AddButtons
setSelectedZone={setSelectedZone} hiddenPanels={hiddenPanels}
hiddenPanels={hiddenPanels} setHiddenPanels={setHiddenPanels}
/> selectedZone={selectedZone}
</> setSelectedZone={setSelectedZone}
)} />
</div> )}
);
}; <Panel
hiddenPanels={hiddenPanels}
export default RealTimeVisulization; selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
</>
)}
</div>
);
};
export default RealTimeVisulization;

View File

@@ -0,0 +1,96 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
export default function ZoneCentreTarget() {
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const [previousZoneCentre, setPreviousZoneCentre] = useState<number[] | null>(null);
const sphereRef = useRef<THREE.Mesh>(null);
const { camera, controls }: any = useThree();
useEffect(() => {
if (
selectedZone.zoneViewPortTarget &&
JSON.stringify(previousZoneCentre) !== JSON.stringify(selectedZone.zoneViewPortTarget)
) {
setPreviousZoneCentre(selectedZone.zoneViewPortTarget);
}
}, [selectedZone.zoneViewPortTarget, previousZoneCentre]);
const centrePoint = useMemo(() => {
if (!previousZoneCentre || !selectedZone.zoneViewPortTarget) return null;
return previousZoneCentre.map((value, index) =>
(value + selectedZone.zoneViewPortTarget[index]) / 2
);
}, [previousZoneCentre, selectedZone.zoneViewPortTarget]);
useEffect(() => {
if (selectedZone.zoneName !== "") {
if (sphereRef.current) {
sphereRef.current.position.set(selectedZone.zoneViewPortTarget[0], selectedZone.zoneViewPortTarget[1], selectedZone.zoneViewPortTarget[2]);
}
if (centrePoint) {
if (centrePoint.length > 0) {
let camPosition = new THREE.Vector3(...selectedZone.zoneViewPortPosition);
let CamTarget = new THREE.Vector3(...selectedZone.zoneViewPortTarget);
const direction = new THREE.Vector3().subVectors(CamTarget, camPosition).normalize();
const worldUp = new THREE.Vector3(0, 0, 1);
const right = new THREE.Vector3().crossVectors(worldUp, direction).normalize();
const up = new THREE.Vector3().crossVectors(direction, right).normalize();
const offsetPosition = up.clone().multiplyScalar(20);
camPosition.add(offsetPosition);
const setCam = async () => {
controls.setLookAt(centrePoint[0], 100, centrePoint[2], ...centrePoint, true);
setTimeout(() => {
controls?.setLookAt(
...camPosition.toArray(),
selectedZone.zoneViewPortTarget[0],
selectedZone.zoneViewPortTarget[1],
selectedZone.zoneViewPortTarget[2],
true
);
}, 400)
};
setCam();
} else {
let camPosition = new THREE.Vector3(...selectedZone.zoneViewPortPosition);
let CamTarget = new THREE.Vector3(...selectedZone.zoneViewPortTarget);
const direction = new THREE.Vector3().subVectors(CamTarget, camPosition).normalize();
const worldUp = new THREE.Vector3(0, 0, 1);
const right = new THREE.Vector3().crossVectors(worldUp, direction).normalize();
const up = new THREE.Vector3().crossVectors(direction, right).normalize();
const offsetPosition = up.clone().multiplyScalar(20);
camPosition.add(offsetPosition);
const setCam = async () => {
controls?.setLookAt(
...camPosition.toArray(),
selectedZone.zoneViewPortTarget[0],
selectedZone.zoneViewPortTarget[1],
selectedZone.zoneViewPortTarget[2],
true
);
};
setCam();
}
}
}
}, [selectedZone.zoneViewPortTarget, camera, controls]);
return (
<> </>
);
}

View File

@@ -2,7 +2,8 @@ import React, { useEffect, useState } from "react";
import List from "./List"; import List from "./List";
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons"; import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect"; import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones"; import { useZones } from "../../../store/store";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
interface DropDownListProps { interface DropDownListProps {
value?: string; // Value to display in the DropDownList value?: string; // Value to display in the DropDownList
@@ -29,24 +30,23 @@ const DropDownList: React.FC<DropDownListProps> = ({
defaultOpen = false, defaultOpen = false,
listType = "default", listType = "default",
}) => { }) => {
const [isOpen, setIsOpen] = useState<boolean>(defaultOpen); const [isOpen, setIsOpen] = useState<boolean>(defaultOpen);
const { zones, setZones } = useZones()
const handleToggle = () => { const handleToggle = () => {
setIsOpen((prev) => !prev); // Toggle the state setIsOpen((prev) => !prev); // Toggle the state
}; };
const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]); const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]);
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
useEffect(() => { useEffect(() => {
async function GetZoneData() { const value = (zones || []).map((val: { zoneId: string; zoneName: string }) => ({
const response = await getZonesApi("hexrfactory") id: val.zoneId,
console.log('response: ', response.data); name: val.zoneName
setZoneDataList([{ id: "1", name: "zone1" }, }));
{ id: "2", name: "Zone 2" },]) setZoneDataList(prev => (JSON.stringify(prev) !== JSON.stringify(value) ? value : prev));
} }, [zones]);
GetZoneData()
}, [])
return ( return (
<div className="dropdown-list-container"> <div className="dropdown-list-container">

View File

@@ -1,6 +1,9 @@
import React from "react"; import React from "react";
import RenameInput from "../inputs/RenameInput"; import RenameInput from "../inputs/RenameInput";
import { EyeIcon, LockIcon, RmoveIcon } from "../../icons/ExportCommonIcons"; import { EyeIcon, LockIcon, RmoveIcon } from "../../icons/ExportCommonIcons";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
import { getZoneData } from "../../../services/realTimeVisulization/zoneData/getZones";
import { useSubModuleStore } from "../../../store/useModuleStore";
interface ListProps { interface ListProps {
items?: { id: string; name: string }[]; // Optional array of items to render items?: { id: string; name: string }[]; // Optional array of items to render
@@ -8,7 +11,28 @@ interface ListProps {
} }
const List: React.FC<ListProps> = ({ items = [] }) => { const List: React.FC<ListProps> = ({ items = [] }) => {
console.log('items: ', items); const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { subModule, setSubModule } = useSubModuleStore();
async function handleSelectZone(id: string) {
setSubModule("zoneProperties")
const email = localStorage.getItem('email')
const organization = (email!.split("@")[1]).split(".")[0];
let response = await getZoneData(id, organization)
console.log('response: ', response);
setSelectedZone({
zoneName: response?.zoneName,
activeSides: response?.activeSides || [],
panelOrder: response?.panelOrder || [],
lockedPanels: response?.lockedPanels || [],
widgets: response?.widgets || [],
zoneId: response?.zoneId,
zoneViewPortTarget: response?.viewPortCenter || [],
zoneViewPortPosition:
response?.viewPortposition || [],
});
}
return ( return (
<> <>
{items.length > 0 ? ( {items.length > 0 ? (
@@ -16,7 +40,7 @@ const List: React.FC<ListProps> = ({ items = [] }) => {
{items.map((item, index) => ( {items.map((item, index) => (
<li key={index} className="list-container"> <li key={index} className="list-container">
<div className="list-item"> <div className="list-item">
<div className="value"> <div className="value" onClick={() => handleSelectZone(item.id)}>
<RenameInput value={item.name} /> <RenameInput value={item.name} />
</div> </div>
<div className="options-container"> <div className="options-container">

View File

@@ -13,8 +13,19 @@ const SimpleCard: React.FC<SimpleCardProps> = ({
value, value,
per, per,
}) => { }) => {
const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => {
const cardData = JSON.stringify({
header,
value,
per,
className: event.currentTarget.className, // Store the class name
});
event.dataTransfer.setData("text/plain", cardData);
};
return ( return (
<div className="floating total-card" draggable> <div className="floating total-card" draggable onDragStart={handleDragStart}>
<div className="header-wrapper"> <div className="header-wrapper">
<div className="header">{header}</div> <div className="header">{header}</div>
<div className="data-values"> <div className="data-values">

View File

@@ -112,7 +112,7 @@ export default async function assetManager(
) { ) {
if (!activePromises.get(taskId)) return; // Stop processing if task is canceled if (!activePromises.get(taskId)) return; // Stop processing if task is canceled
const existingModel = itemsGroup.current.getObjectByProperty("uuid", item.modeluuid); const existingModel = itemsGroup?.current?.getObjectByProperty("uuid", item.modeluuid);
if (existingModel) { if (existingModel) {
// console.log(`Model ${item.modelname} already exists in the scene.`); // console.log(`Model ${item.modelname} already exists in the scene.`);
resolve(); resolve();

File diff suppressed because it is too large Load Diff

View File

@@ -745,6 +745,7 @@ export default function SocketResponses({
return return
} }
if (data.message === "zone deleted") { if (data.message === "zone deleted") {
console.log('data: ', data);
const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId); const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId);
setZones(updatedZones); setZones(updatedZones);

View File

@@ -1,4 +1,4 @@
import { useMemo } from "react"; import { useMemo, useState } from "react";
import { Canvas } from "@react-three/fiber"; import { Canvas } from "@react-three/fiber";
import { Environment, KeyboardControls } from "@react-three/drei"; import { Environment, KeyboardControls } from "@react-three/drei";
@@ -15,6 +15,11 @@ import background from "../../assets/textures/hdr/mudroadpuresky2k.hdr";
import SelectionControls from "./controls/selection/selectionControls"; import SelectionControls from "./controls/selection/selectionControls";
import MeasurementTool from "./tools/measurementTool"; import MeasurementTool from "./tools/measurementTool";
import Simulation from "../simulation/simulation"; import Simulation from "../simulation/simulation";
import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import DroppedObjects from "../../components/ui/componets/DroppedFloatingWidgets";
// import Simulation from "./simulationtemp/simulation"; // import Simulation from "./simulationtemp/simulation";
export default function Scene() { export default function Scene() {
@@ -27,6 +32,9 @@ export default function Scene() {
// { name: "jump", keys: ["Space"] }, // { name: "jump", keys: ["Space"] },
], []) ], [])
return ( return (
<KeyboardControls map={map}> <KeyboardControls map={map}>
<Canvas <Canvas
@@ -36,12 +44,15 @@ export default function Scene() {
onContextMenu={(e) => { onContextMenu={(e) => {
e.preventDefault(); e.preventDefault();
}} }}
> >
<DroppedObjects/>
<Controls /> <Controls />
<TransformControl /> <TransformControl />
<SelectionControls /> <SelectionControls />
<MeasurementTool /> <MeasurementTool />
<World /> <World />
<ZoneCentreTarget />
{/* <Simulation /> */} {/* <Simulation /> */}
<Simulation /> <Simulation />
<PostProcessing /> <PostProcessing />

View File

@@ -1,25 +1,23 @@
let url_Backend_dwinzo = `http://185.100.212.76:5000`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const getZonesApi = async (organization: string) => { export const getZoneData = async (zoneId: string, organization: string) => {
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/v2/findZones/${organization}`, { const response = await fetch(
method: "GET", `${url_Backend_dwinzo}/api/v2/A_zone/${zoneId}/${organization}`,
headers: { {
"Content-Type": "application/json", method: "GET",
}, headers: {
}); "Content-Type": "application/json",
},
// if (!response.ok) { }
// throw new Error("Failed to get Zones"); );
// }
if (!response.ok) {
const result = await response.json(); throw new Error("Failed to fetch zoneData");
return result; }
} catch (error) {
if (error instanceof Error) { return await response.json();
throw new Error(error.message); } catch (error: any) {
} else { throw new Error(error.message);
throw new Error("An unknown error occurred"); }
} };
}
};

View File

@@ -0,0 +1,31 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
type Side = "top" | "bottom" | "left" | "right";
export const panelData = async (organization: string, zoneID: string, panelOrder: Side[]) => {
console.log('panelOrder: ', panelOrder);
console.log('zoneID: ', zoneID);
console.log('organization: ', organization);
try {
const response = await fetch(`${url_Backend_dwinzo}/api/v1/panel/save`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ organization, zoneID, panelOrder }),
});
if (!response.ok) {
throw new Error("Failed to add panelOrder for Zone");
}
const result = await response.json();
return result;
} catch (error) {
if (error instanceof Error) {
throw new Error(error.message);
} else {
throw new Error("An unknown error occurred");
}
}
};

View File

@@ -15,21 +15,31 @@ interface SelectedZoneState {
activeSides: Side[]; activeSides: Side[];
panelOrder: Side[]; panelOrder: Side[];
lockedPanels: Side[]; lockedPanels: Side[];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: Widget[]; widgets: Widget[];
} }
interface SelectedZoneStore { interface SelectedZoneStore {
selectedZone: SelectedZoneState; selectedZone: SelectedZoneState;
setSelectedZone: (zone: Partial<SelectedZoneState> | ((prev: SelectedZoneState) => SelectedZoneState)) => void; setSelectedZone: (
zone:
| Partial<SelectedZoneState>
| ((prev: SelectedZoneState) => SelectedZoneState)
) => void;
} }
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({ export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
selectedZone: { selectedZone: {
zoneName: "", zoneName: "", // Empty string initially
activeSides: [], activeSides: [], // Empty array
panelOrder: [], panelOrder: [], // Empty array
lockedPanels: [], lockedPanels: [], // Empty array
widgets: [], zoneId: "",
zoneViewPortTarget: [],
zoneViewPortPosition: [],
widgets: [], // Empty array
}, },
setSelectedZone: (zone) => setSelectedZone: (zone) =>
set((state) => ({ set((state) => ({
@@ -38,4 +48,4 @@ export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
? zone(state.selectedZone) // Handle functional updates ? zone(state.selectedZone) // Handle functional updates
: { ...state.selectedZone, ...zone }, // Handle partial updates : { ...state.selectedZone, ...zone }, // Handle partial updates
})), })),
})); }));