code structure updated

This commit is contained in:
Gomathi 2025-04-24 16:58:15 +05:30
parent 967f1741b0
commit 9b9f61369c
8 changed files with 169 additions and 608 deletions

View File

@ -45,7 +45,8 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
const [expandedZones, setExpandedZones] = useState<Record<string, boolean>>(
{}
);
const { floorItems, setFloorItems } = useFloorItems();
const { setFloorItems } = useFloorItems();
useEffect(() => {
useSelectedZoneStore.getState().setSelectedZone({
@ -143,6 +144,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
);
}
console.log('newName: ', newName);
}

View File

@ -1,5 +1,5 @@
import { useFrame, useThree } from "@react-three/fiber";
import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, } from "../../../store/store";
import { useActiveTool, useAsset3dWidget, useCamMode, useDeletableFloorItem, useDeleteTool, useFloorItems, useLoadingProgress, useRenderDistance, useSelectedFloorItem, useSelectedItem, useSimulationStates, useSocketStore, useToggleView, useTransformMode, useZoneAssetId, } from "../../../store/store";
import assetVisibility from "../geomentries/assets/assetVisibility";
import { useEffect } from "react";
import * as THREE from "three";
@ -32,12 +32,13 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
const { setSelectedFloorItem } = useSelectedFloorItem();
const { activeTool } = useActiveTool();
const { selectedItem, setSelectedItem } = useSelectedItem();
const { simulationStates, setSimulationStates } = useSimulationStates();
const { setSimulationStates } = useSimulationStates();
const { setLoadingProgress } = useLoadingProgress();
const { activeModule } = useModuleStore();
const { socket } = useSocketStore();
const loader = new GLTFLoader();
const dracoLoader = new DRACOLoader();
const { setZoneAssetId } = useZoneAssetId();
dracoLoader.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/gltf/");
loader.setDRACOLoader(dracoLoader);
@ -220,6 +221,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
const target = controls.getTarget(new THREE.Vector3());
await controls.setTarget(target.x, 0, target.z, true);
setSelectedFloorItem(null);
setZoneAssetId(null)
}
}
}
@ -314,14 +316,14 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
useFrame(() => {
if (controls)
// assetVisibility(itemsGroup, state.camera.position, renderDistance);
if (deleteTool && activeModule === "builder") {
DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem);
} else if (!deleteTool) {
if (hoveredDeletableFloorItem.current) {
hoveredDeletableFloorItem.current = undefined;
setDeletableFloorItem(null);
if (deleteTool && activeModule === "builder") {
DeletableHoveredFloorItems(state, itemsGroup, hoveredDeletableFloorItem, setDeletableFloorItem);
} else if (!deleteTool) {
if (hoveredDeletableFloorItem.current) {
hoveredDeletableFloorItem.current = undefined;
setDeletableFloorItem(null);
}
}
}
});
return <group ref={itemsGroup} name="itemsGroup"></group>;

View File

@ -795,7 +795,7 @@ export default function SocketResponses({
return
}
if (data.message === "zone deleted") {
const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId);
const updatedZones = zones?.filter((zone: any) => zone.zoneId !== data.data.zoneId);
setZones(updatedZones);
const zoneIndex = zones.findIndex((zone: any) => zone.zoneId === data.data.zoneId);

View File

@ -1,18 +1,11 @@
import React, { useEffect, useRef, useState, useCallback } from "react";
import { useWidgetStore, Widget } from "../../store/useWidgetStore";
import {
useDroppedObjectsStore,
useFloatingWidget,
} from "../../store/useDroppedObjectsStore";
import { Widget } from "../../store/useWidgetStore";
import {useDroppedObjectsStore, useFloatingWidget,} from "../../store/useDroppedObjectsStore";
import { getSelect2dZoneData } from "../../services/realTimeVisulization/zoneData/getSelect2dZoneData";
import { getFloatingZoneData } from "../../services/realTimeVisulization/zoneData/getFloatingData";
import { get3dWidgetZoneData } from "../../services/realTimeVisulization/zoneData/get3dWidgetData";
import {
MoveArrowLeft,
MoveArrowRight,
} from "../../components/icons/SimulationIcons";
import {MoveArrowLeft, MoveArrowRight,} from "../../components/icons/SimulationIcons";
import { InfoIcon } from "../../components/icons/ExportCommonIcons";
import { useSelectedZoneStore } from "../../store/useZoneStore";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
@ -34,62 +27,20 @@ interface DisplayZoneProps {
zoneViewPortPosition: number[];
};
};
selectedZone: {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
zoneId: string;
points: [];
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
}>
>;
hiddenPanels: HiddenPanels; // Updated prop type
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
}
const DisplayZone: React.FC<DisplayZoneProps> = ({
zonesData,
selectedZone,
setSelectedZone,
hiddenPanels,
}) => {
const DisplayZone: React.FC<DisplayZoneProps> = ({ zonesData, hiddenPanels }) => {
const [showLeftArrow, setShowLeftArrow] = useState(false);
const [showRightArrow, setShowRightArrow] = useState(false);
// Ref for the container element
const containerRef = useRef<HTMLDivElement | null>(null);
const scrollContainerRef = useRef<HTMLDivElement | null>(null);
// State to track overflow visibility
const [showLeftArrow, setShowLeftArrow] = useState(false);
const [showRightArrow, setShowRightArrow] = useState(false);
const { floatingWidget, setFloatingWidget } = useFloatingWidget();
const { setSelectedChartId } = useWidgetStore();
//zustand
const { setFloatingWidget } = useFloatingWidget();
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
// Function to calculate overflow state
const updateOverflowState = useCallback(() => {
@ -97,16 +48,9 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
if (container) {
const isOverflowing = container.scrollWidth > container.clientWidth;
const canScrollLeft = container.scrollLeft > 0;
const canScrollRight =
container.scrollLeft + container.clientWidth + 1 <
container.scrollWidth;
const canScrollRight = container.scrollLeft + container.clientWidth + 1 < container.scrollWidth;
setShowLeftArrow(isOverflowing && canScrollLeft);
setShowRightArrow(isOverflowing && canScrollRight);
// console.log('canScrollRight: ', canScrollRight);
// console.log('isOverflowing: ', isOverflowing);
}
}, []);
@ -126,10 +70,7 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
const handleWheel = (event: WheelEvent) => {
if (Math.abs(event.deltaY) > Math.abs(event.deltaX)) {
event.preventDefault();
container.scrollBy({
left: event.deltaY * 2,
behavior: "smooth",
});
container.scrollBy({ left: event.deltaY * 2, behavior: "smooth", });
}
};
@ -171,23 +112,11 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
if (selectedZone?.zoneId === zoneId) {
return;
}
// setSelectedChartId(null);
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
//api for getting 2d widget Data
let response = await getSelect2dZoneData(zoneId, organization);
console.log("response: ", response);
let res = await getFloatingZoneData(zoneId, organization);
console.log("res: ", res);
setFloatingWidget(res);
// Set the selected zone in the store
useDroppedObjectsStore.getState().setZone(zoneName, zoneId);
if (Array.isArray(res)) {
res.forEach((val) => {
useDroppedObjectsStore.getState().addObject(zoneName, val);
});
}
setSelectedZone({
zoneName,
activeSides: response.activeSides || [],
@ -199,62 +128,42 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
zoneViewPortTarget: response.viewPortCenter || {},
zoneViewPortPosition: response.viewPortposition || {},
});
} catch (error) {}
//api for getting floating widget Data
let res = await getFloatingZoneData(zoneId, organization);
setFloatingWidget(res);
useDroppedObjectsStore.getState().setZone(zoneName, zoneId);
if (Array.isArray(res)) {
res.forEach((val) => {
useDroppedObjectsStore.getState().addObject(zoneName, val);
});
}
} catch (error) { }
}
return (
<div
ref={containerRef}
className={`zone-wrapper ${
selectedZone?.activeSides?.includes("bottom") &&
!hiddenPanels[selectedZone.zoneId]?.includes("bottom")
? "bottom"
: ""
}`}
>
<div ref={containerRef} className={`zone-wrapper ${selectedZone?.activeSides?.includes("bottom") && !hiddenPanels[selectedZone.zoneId]?.includes("bottom") ? "bottom" : ""}`}>
{/* Left Arrow */}
{showLeftArrow && (
<button className="arrow left-arrow" onClick={handleScrollLeft}>
<MoveArrowLeft />
</button>
)}
{showLeftArrow && (<button className="arrow left-arrow" onClick={handleScrollLeft}><MoveArrowLeft /></button>)}
{/* Scrollable Zones Container */}
<div
ref={scrollContainerRef}
className="zones-wrapper"
style={{ overflowX: "auto", whiteSpace: "nowrap" }}
>
<div ref={scrollContainerRef} className="zones-wrapper" style={{ overflowX: "auto", whiteSpace: "nowrap" }}>
{Object.keys(zonesData).length !== 0 ? (
<>
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${
selectedZone.zoneName === zoneName ? "active" : ""
}`}
onClick={() =>
handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)
}
<div key={index} className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""}`}
onClick={() => handleSelect2dZoneData(zonesData[zoneName]?.zoneId, zoneName)}
>
{zoneName}
</div>
))}
</>
) : (
<div className="no-zone">
<InfoIcon />
No zones? Create one!
</div>
<div className="no-zone"><InfoIcon />No zones? Create one!</div>
)}
</div>
{/* Right Arrow */}
{showRightArrow && (
<button className="arrow right-arrow" onClick={handleScrollRight}>
<MoveArrowRight />
</button>
)}
{showRightArrow && (<button className="arrow right-arrow" onClick={handleScrollRight}><MoveArrowRight /></button>)}
</div>
);
};

View File

@ -6,32 +6,17 @@ import { useSelectedZoneStore } from "../../store/useZoneStore";
import DisplayZone from "./DisplayZone";
import Scene from "../scene/scene";
import useModuleStore from "../../store/useModuleStore";
import {
useDroppedObjectsStore,
useFloatingWidget,
} from "../../store/useDroppedObjectsStore";
import {
useAsset3dWidget,
useSocketStore,
useWidgetSubOption,
useZones,
} from "../../store/store";
import { useDroppedObjectsStore, useFloatingWidget, } from "../../store/useDroppedObjectsStore";
import { useAsset3dWidget, useSocketStore, useWidgetSubOption } 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 "./socket/realTimeVizSocket.dev";
import RenderOverlay from "../../components/templates/Overlay";
import ConfirmationPopup from "../../components/layout/confirmationPopup/ConfirmationPopup";
import DroppedObjects from "./widgets/floating/DroppedFloatingWidgets";
import EditWidgetOption from "../../components/ui/menu/EditWidgetOption";
import {
useEditWidgetOptionsStore,
useRightClickSelected,
useRightSelected,
} from "../../store/useZone3DWidgetStore";
import Dropped3dWidgets from "./widgets/3d/Dropped3dWidget";
import { useEditWidgetOptionsStore, useRightClickSelected, useRightSelected, } from "../../store/useZone3DWidgetStore";
import OuterClick from "../../utils/outerClick";
import { useWidgetStore } from "../../store/useWidgetStore";
import { getActiveProperties } from "./functions/getActiveProperties";
@ -65,36 +50,26 @@ interface HiddenPanels {
}
const RealTimeVisulization: React.FC = () => {
const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({});
const containerRef = useRef<HTMLDivElement>(null);
//zustand
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 { setRightSelect } = useRightSelected();
const { editWidgetOptions } = 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 { setFloatingWidget } = useFloatingWidget();
const { widgetSubOption } = useWidgetSubOption();
const { visualizationSocket } = useSocketStore();
const { setSelectedChartId } = useWidgetStore();
const [hiddenPanels, setHiddenPanels] = React.useState<HiddenPanels>({});
const containerRef = useRef<HTMLDivElement>(null);
const [openConfirmationPopup, setOpenConfirmationPopup] = useState(false);
const [zonesData, setZonesData] = useState<FormattedZoneData>({});
const [canvasDimensions, setCanvasDimensions] = useState({ width: 0, height: 0, });
OuterClick({
contextClassName: [
"chart-container",
"floating",
"sidebar-right-wrapper",
"card",
"dropdown-menu",
"dropdown-options",
],
contextClassName: ["chart-container","floating","sidebar-right-wrapper","card","dropdown-menu","dropdown-options",],
setMenuVisible: () => setSelectedChartId(null),
});
@ -104,7 +79,6 @@ const RealTimeVisulization: React.FC = () => {
const organization = email?.split("@")[1]?.split(".")[0];
try {
const response = await getZone2dData(organization);
// console.log('response: ', response);
if (!Array.isArray(response)) {
return;
@ -126,11 +100,11 @@ const RealTimeVisulization: React.FC = () => {
{}
);
setZonesData(formattedData);
} catch (error) {}
} catch (error) { }
}
GetZoneData();
}, [activeModule]); // Removed `zones` from dependencies
}, [activeModule]);
useEffect(() => {
setZonesData((prev) => {
@ -152,7 +126,6 @@ const RealTimeVisulization: React.FC = () => {
});
}, [selectedZone]);
// useEffect(() => {}, [floatingWidgets]);
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
@ -251,10 +224,10 @@ const RealTimeVisulization: React.FC = () => {
);
setFloatingWidget(currentZone.objects);
} else {
console.warn("Zone not found or zoneId mismatch");
}
} catch (error) {
console.error("Error in handleDrop:", error);
}
};
@ -278,10 +251,7 @@ const RealTimeVisulization: React.FC = () => {
};
}, [setRightClickSelected]);
const [canvasDimensions, setCanvasDimensions] = useState({
width: 0,
height: 0,
});
useEffect(() => {
const canvas = document.getElementById("real-time-vis-canvas");
if (!canvas) return;
@ -304,14 +274,7 @@ const RealTimeVisulization: React.FC = () => {
return (
<>
<style>
{`
:root {
--realTimeViz-container-width: ${canvasDimensions.width}px;
--realTimeViz-container-height: ${canvasDimensions.height}px;
}
`}
{`:root {--realTimeViz-container-width: ${canvasDimensions.width}px;--realTimeViz-container-height: ${canvasDimensions.height}px; }`}
</style>
<div
ref={containerRef}
@ -326,11 +289,7 @@ const RealTimeVisulization: React.FC = () => {
<div className="realTime-viz-wrapper">
{openConfirmationPopup && (
<RenderOverlay>
<ConfirmationPopup
message={"Are you sure want to delete?"}
onConfirm={() => console.log("Confirmed")}
onCancel={() => setOpenConfirmationPopup(false)}
/>
<ConfirmationPopup message={"Are you sure want to delete?"} onConfirm={() => { }} onCancel={() => setOpenConfirmationPopup(false)} />
</RenderOverlay>
)}
<div
@ -346,51 +305,15 @@ const RealTimeVisulization: React.FC = () => {
>
<Scene />
</div>
{activeModule === "visualization" && selectedZone.zoneName !== "" && (
<DroppedObjects />
)}
{activeModule === "visualization" && selectedZone.zoneName !== "" && (<DroppedObjects />)}
{activeModule === "visualization" && <SocketRealTimeViz />}
{activeModule === "visualization" &&
editWidgetOptions &&
rightClickSelected && (
<EditWidgetOption
options={[
"Duplicate",
"Vertical Move",
"Horizontal Move",
"RotateX",
"RotateY",
"Delete",
]}
/>
)}
{activeModule === "visualization" && editWidgetOptions && rightClickSelected && (<EditWidgetOption options={["Duplicate", "Vertical Move", "Horizontal Move", "RotateX", "RotateY", "Delete",]} />)}
{activeModule === "visualization" && (
<>
<DisplayZone
zonesData={zonesData}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
/>
{!isPlaying && selectedZone?.zoneName !== "" && (
<AddButtons
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
)}
<Panel
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
hiddenPanels={hiddenPanels}
setZonesData={setZonesData}
/>
<DisplayZone zonesData={zonesData} hiddenPanels={hiddenPanels} setHiddenPanels={setHiddenPanels} />
{!isPlaying && selectedZone?.zoneName !== "" &&
(<AddButtons hiddenPanels={hiddenPanels} setHiddenPanels={setHiddenPanels} />)}
<Panel hiddenPanels={hiddenPanels} setZonesData={setZonesData} />
</>
)}
</div>

View File

@ -6,100 +6,48 @@ import {
} from "../../../../components/icons/RealTimeVisulationIcons";
import { AddIcon } from "../../../../components/icons/ExportCommonIcons";
import { useSocketStore } from "../../../../store/store";
import { clearPanel } from "../../../../services/realTimeVisulization/zoneData/clearPanel";
import { lockPanel } from "../../../../services/realTimeVisulization/zoneData/lockPanel";
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
// Define the type for HiddenPanels, where keys are zone IDs and values are arrays of hidden sides
interface HiddenPanels {
[zoneId: string]: Side[];
}
// Define the type for the props passed to the Buttons component
interface ButtonsProps {
selectedZone: {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
}>
>;
hiddenPanels: HiddenPanels; // Updated prop type
setHiddenPanels: React.Dispatch<React.SetStateAction<HiddenPanels>>; // Updated prop type
}
const AddButtons: React.FC<ButtonsProps> = ({
selectedZone,
setSelectedZone,
setHiddenPanels,
hiddenPanels,
}) => {
const AddButtons: React.FC<ButtonsProps> = ({ setHiddenPanels, hiddenPanels, }) => {
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { visualizationSocket } = useSocketStore();
// Function to toggle visibility of a panel
const toggleVisibility = (side: Side) => {
const isHidden = hiddenPanels[selectedZone.zoneId]?.includes(side) ?? false;
if (isHidden) {
// If the panel is already hidden, remove it from the hiddenPanels array for this zone
setHiddenPanels((prevHiddenPanels) => ({
...prevHiddenPanels,
[selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter(
(panel) => panel !== side
),
[selectedZone.zoneId]: prevHiddenPanels[selectedZone.zoneId].filter((panel) => panel !== side),
}));
} else {
// If the panel is visible, add it to the hiddenPanels array for this zone
setHiddenPanels((prevHiddenPanels) => ({
...prevHiddenPanels,
[selectedZone.zoneId]: [
...(prevHiddenPanels[selectedZone.zoneId] || []),
side,
],
[selectedZone.zoneId]: [...(prevHiddenPanels[selectedZone.zoneId] || []), side,],
}));
}
};
// Function to toggle lock/unlock a panel
const toggleLockPanel = async (side: Side) => {
// console.log('side: ', side);
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
//add api
const newLockedPanels = selectedZone.lockedPanels.includes(side)
? selectedZone.lockedPanels.filter((panel) => panel !== side)
: [...selectedZone.lockedPanels, side];
const newLockedPanels = selectedZone.lockedPanels.includes(side) ? selectedZone.lockedPanels.filter((panel) => panel !== side) : [...selectedZone.lockedPanels, side];
const updatedZone = {
...selectedZone,
@ -114,10 +62,9 @@ const AddButtons: React.FC<ButtonsProps> = ({
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-panel:locked", lockedPanel);
}
setSelectedZone(updatedZone);
// let response = await lockPanel(selectedZone.zoneId, organization, newLockedPanels)
// console.log('response: ', response);
//
// if (response.message === 'locked panel updated successfully') {
// // Update the selectedZone state
// setSelectedZone(updatedZone);
@ -126,17 +73,9 @@ const AddButtons: React.FC<ButtonsProps> = ({
// Function to clean all widgets from a panel
const cleanPanel = async (side: Side) => {
//add api
// console.log('side: ', side);
if (
hiddenPanels[selectedZone.zoneId]?.includes(side) ||
selectedZone.lockedPanels.includes(side)
)
return;
if (hiddenPanels[selectedZone.zoneId]?.includes(side) || selectedZone.lockedPanels.includes(side)) return;
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
let clearPanel = {
organization: organization,
panelName: side,
@ -145,54 +84,33 @@ const AddButtons: React.FC<ButtonsProps> = ({
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-panel:clear", clearPanel);
}
const cleanedWidgets = selectedZone.widgets.filter(
(widget) => widget.panel !== side
);
const cleanedWidgets = selectedZone.widgets.filter((widget) => widget.panel !== side);
const updatedZone = {
...selectedZone,
widgets: cleanedWidgets,
};
// Update the selectedZone state
// console.log('updatedZone: ', updatedZone);
setSelectedZone(updatedZone);
// let response = await clearPanel(selectedZone.zoneId, organization, side)
// console.log('response: ', response);
// if (response.message === 'PanelWidgets cleared successfully') {
// const cleanedWidgets = selectedZone.widgets.filter(
// (widget) => widget.panel !== side
// );
// const updatedZone = {
// ...selectedZone,
// widgets: cleanedWidgets,
// };
// // Update the selectedZone state
// setSelectedZone(updatedZone);
// }
};
// Function to handle "+" button click
const handlePlusButtonClick = async (side: Side) => {
// Get email and organization safely with a default fallback
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
if (selectedZone.activeSides.includes(side)) {
console.log("open");
// Panel already exists: Remove widgets from that side and update activeSides
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0]; // Fallback value
// Remove all widgets associated with the side and update active sides
const cleanedWidgets = selectedZone.widgets.filter(
(widget) => widget.panel !== side
);
const cleanedWidgets = selectedZone.widgets.filter((widget) => widget.panel !== side);
const newActiveSides = selectedZone.activeSides.filter((s) => s !== side);
const updatedZone = {
...selectedZone,
widgets: cleanedWidgets,
activeSides: newActiveSides,
panelOrder: newActiveSides,
};
let deletePanel = {
organization: organization,
panelName: side,
@ -202,41 +120,17 @@ const AddButtons: React.FC<ButtonsProps> = ({
visualizationSocket.emit("v2:viz-panel:delete", deletePanel);
}
setSelectedZone(updatedZone);
if (hiddenPanels[selectedZone.zoneId]?.includes(side)) {
setHiddenPanels((prev) => ({
...prev,
[selectedZone.zoneId]: prev[selectedZone.zoneId].filter(
(s) => s !== side
),
[selectedZone.zoneId]: prev[selectedZone.zoneId].filter((s) => s !== side),
}));
}
// if(hiddenPanels[selectedZone.zoneId].includes(side))
// API call to delete the panel
// try {
// const response = await deletePanelApi(selectedZone.zoneId, side, organization);
//
// if (response.message === "Panel deleted successfully") {
// } else {
//
// }
// } catch (error) {
//
// }
} else {
// Panel does not exist: Create panel
try {
// Get email and organization safely with a default fallback
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
// Prevent duplicate side entries
const newActiveSides = selectedZone.activeSides.includes(side)
? [...selectedZone.activeSides]
: [...selectedZone.activeSides, side];
const newActiveSides = selectedZone.activeSides.includes(side)? [...selectedZone.activeSides]: [...selectedZone.activeSides, side];
const updatedZone = {
...selectedZone,
activeSides: newActiveSides,
@ -251,15 +145,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
visualizationSocket.emit("v2:viz-panel:add", addPanel);
}
setSelectedZone(updatedZone);
// API call to create panels
// const response = await panelData(organization, selectedZone.zoneId, newActiveSides);
//
// if (response.message === "Panels created successfully") {
// } else {
//
// }
} catch (error) {}
} catch (error) { }
}
};
return (
@ -268,20 +154,11 @@ const AddButtons: React.FC<ButtonsProps> = ({
{(["top", "right", "bottom", "left"] as Side[]).map((side) => (
<div key={side} className={`side-button-container ${side}`}>
{/* "+" Button */}
<button
className={`side-button ${side}${
selectedZone.activeSides.includes(side) ? " active" : ""
}`}
<button className={`side-button ${side}${selectedZone.activeSides.includes(side) ? " active" : ""}`}
onClick={() => handlePlusButtonClick(side)}
title={
selectedZone.activeSides.includes(side)
? `Remove all items and close ${side} panel`
: `Activate ${side} panel`
}
title={selectedZone.activeSides.includes(side) ? `Remove all items and close ${side} panel` : `Activate ${side} panel`}
>
<div className="add-icon">
<AddIcon />
</div>
<div className="add-icon"><AddIcon /></div>
</button>
{/* Extra Buttons */}
@ -289,62 +166,28 @@ const AddButtons: React.FC<ButtonsProps> = ({
<div className="extra-Bs">
{/* Hide Panel */}
<div
className={`icon ${
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "active"
: ""
}`}
title={
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "Show Panel"
: "Hide Panel"
}
className={`icon ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "active" : ""}`}
title={hiddenPanels[selectedZone.zoneId]?.includes(side) ? "Show Panel" : "Hide Panel"}
onClick={() => toggleVisibility(side)}
>
<EyeIcon
fill={
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "var(--primary-color)"
: "var(--text-color)"
}
/>
<EyeIcon fill={hiddenPanels[selectedZone.zoneId]?.includes(side) ? "var(--primary-color)" : "var(--text-color)"} />
</div>
{/* Clean Panel */}
<div
className="icon"
title="Clean Panel"
<div className="icon" title="Clean Panel"
onClick={() => cleanPanel(side)}
style={{
cursor:
hiddenPanels[selectedZone.zoneId]?.includes(side) ||
selectedZone.lockedPanels.includes(side)
? "not-allowed"
: "pointer",
}}
style={{ cursor: hiddenPanels[selectedZone.zoneId]?.includes(side) || selectedZone.lockedPanels.includes(side) ? "not-allowed" : "pointer", }}
>
<CleanPannel />
</div>
{/* Lock/Unlock Panel */}
<div
className={`icon ${
selectedZone.lockedPanels.includes(side) ? "active" : ""
}`}
title={
selectedZone.lockedPanels.includes(side)
? "Unlock Panel"
: "Lock Panel"
}
className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : ""}`}
title={selectedZone.lockedPanels.includes(side) ? "Unlock Panel" : "Lock Panel"}
onClick={() => toggleLockPanel(side)}
>
<LockIcon
fill={
selectedZone.lockedPanels.includes(side)
? "var(--primary-color)"
: "var(--text-color)"
}
/>
<LockIcon fill={selectedZone.lockedPanels.includes(side) ? "var(--primary-color)" : "var(--text-color)"} />
</div>
</div>
)}

View File

@ -5,94 +5,46 @@ import { useAsset3dWidget, useSocketStore } from "../../../../store/store";
import { usePlayButtonStore } from "../../../../store/usePlayButtonStore";
import { useWidgetStore } from "../../../../store/useWidgetStore";
import { DraggableWidget } from "../2d/DraggableWidget";
import { useSelectedZoneStore } from "../../../../store/useZoneStore";
type Side = "top" | "bottom" | "left" | "right";
interface Widget {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}
interface PanelProps {
selectedZone: {
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: Widget[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
points: [];
zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
widgets: Widget[];
}>
>;
hiddenPanels: any;
setZonesData: React.Dispatch<React.SetStateAction<any>>;
}
const generateUniqueId = () =>`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const generateUniqueId = () =>
`${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
const Panel: React.FC<PanelProps> = ({
selectedZone,
setSelectedZone,
hiddenPanels,
setZonesData,
}) => {
const { widgetSelect, setWidgetSelect } = useAsset3dWidget();
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
const [panelDimensions, setPanelDimensions] = useState<{
[side in Side]?: { width: number; height: number };
}>({});
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
const Panel: React.FC<PanelProps> = ({hiddenPanels,setZonesData,}) => {
//zustand state
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { isPlaying } = usePlayButtonStore();
const { visualizationSocket } = useSocketStore();
const [canvasDimensions, setCanvasDimensions] = useState({
width: 0,
height: 0,
});
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
const [panelDimensions, setPanelDimensions] = useState<{ [side in Side]?: { width: number; height: number }; }>({});
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
const [canvasDimensions, setCanvasDimensions] = useState({ width: 0, height: 0, });
// Track canvas dimensions
useEffect(() => {
const canvas = document.getElementById("real-time-vis-canvas");
if (!canvas) return;
const updateCanvasDimensions = () => {
const rect = canvas.getBoundingClientRect();
setCanvasDimensions({
width: rect.width,
height: rect.height,
});
setCanvasDimensions({ width: rect.width, height: rect.height, });
};
updateCanvasDimensions();
const resizeObserver = new ResizeObserver(updateCanvasDimensions);
resizeObserver.observe(canvas);
return () => resizeObserver.unobserve(canvas);
}, []);
// Calculate panel size
const panelSize = Math.max(
Math.min(canvasDimensions.width * 0.25, canvasDimensions.height * 0.25),
170 // Min 170px
);
// Calculate panel size // Min 170px
const panelSize = Math.max(Math.min(canvasDimensions.width * 0.25, canvasDimensions.height * 0.25), 170);
// Check if panel is locked
const isPanelLocked = (panel: Side) => selectedZone.lockedPanels.includes(panel);
// Get current widget count in a panel
const getCurrentWidgetCount = (panel: Side) => selectedZone.widgets.filter((w) => w.panel === panel).length;
// Define getPanelStyle
const getPanelStyle = useMemo(
() => (side: Side) => {
@ -108,8 +60,7 @@ const Panel: React.FC<PanelProps> = ({
case "bottom":
return {
minWidth: "170px",
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
}px)`,
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)}px)`,
minHeight: "170px",
height: `${panelSize}px`,
left: leftActive ? `${panelSize}px` : "0",
@ -122,8 +73,7 @@ const Panel: React.FC<PanelProps> = ({
minWidth: "170px",
width: `${panelSize}px`,
minHeight: "170px",
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
}px)`,
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)}px)`,
top: topActive ? `${panelSize}px` : "0",
bottom: bottomActive ? `${panelSize}px` : "0",
[side]: "0",
@ -134,82 +84,54 @@ const Panel: React.FC<PanelProps> = ({
},
[selectedZone.panelOrder, panelSize]
);
// Handle drop event
const handleDrop = (e: React.DragEvent, panel: Side) => {
e.preventDefault();
const { draggedAsset } = useWidgetStore.getState();
if (
!draggedAsset ||
isPanelLocked(panel) ||
hiddenPanels[selectedZone.zoneId]?.includes(panel)
)
return;
if (!draggedAsset || isPanelLocked(panel) || hiddenPanels[selectedZone.zoneId]?.includes(panel)) return;
const currentWidgetsCount = getCurrentWidgetCount(panel);
const maxCapacity = calculatePanelCapacity(panel);
if (currentWidgetsCount < maxCapacity) {
addWidgetToPanel(draggedAsset, panel);
}
};
// Check if panel is locked
const isPanelLocked = (panel: Side) =>
selectedZone.lockedPanels.includes(panel);
// Get current widget count in a panel
const getCurrentWidgetCount = (panel: Side) =>
selectedZone.widgets.filter((w) => w.panel === panel).length;
// Calculate panel capacity
const calculatePanelCapacity = (panel: Side) => {
const CHART_WIDTH = panelSize - 10;
const CHART_HEIGHT = panelSize - 10;
const dimensions = panelDimensions[panel];
if (!dimensions) {
return panel === "top" || panel === "bottom" ? 5 : 3; // Fallback capacities
}
return panel === "top" || panel === "bottom"
? Math.max(1, Math.floor(dimensions.width / CHART_WIDTH))
: Math.max(1, Math.floor(dimensions.height / CHART_HEIGHT));
return panel === "top" || panel === "bottom" ? Math.max(1, Math.floor(dimensions.width / CHART_WIDTH)) : Math.max(1, Math.floor(dimensions.height / CHART_HEIGHT));
};
// Add widget to panel
const addWidgetToPanel = async (asset: any, panel: Side) => {
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
const newWidget = {
...asset,
id: generateUniqueId(),
panel,
};
let addWidget = {
organization: organization,
zoneId: selectedZone.zoneId,
widget: newWidget,
};
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-widget:add", addWidget);
}
setSelectedZone((prev) => ({
...prev,
widgets: [...prev.widgets, newWidget],
}));
};
// Observe panel dimensions
useEffect(() => {
const observers: ResizeObserver[] = [];
const currentPanelRefs = panelRefs.current;
selectedZone.activeSides.forEach((side) => {
const element = currentPanelRefs[side];
if (element) {
@ -232,24 +154,18 @@ const Panel: React.FC<PanelProps> = ({
observers.forEach((observer) => observer.disconnect());
};
}, [selectedZone.activeSides]);
// Handle widget reordering
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
setSelectedZone((prev) => {
const widgetsInPanel = prev.widgets.filter((w) => w.panel === panel);
const reorderedWidgets = arrayMove(widgetsInPanel, fromIndex, toIndex);
const updatedWidgets = prev.widgets
.filter((widget) => widget.panel !== panel)
.concat(reorderedWidgets);
const updatedWidgets = prev.widgets.filter((widget) => widget.panel !== panel).concat(reorderedWidgets);
return {
...prev,
widgets: updatedWidgets,
};
});
};
// Calculate capacities and dimensions
const topWidth = getPanelStyle("top").width;
const bottomWidth = getPanelStyle("bottom").height;
@ -283,41 +199,29 @@ const Panel: React.FC<PanelProps> = ({
<div
key={side}
id="panel-wrapper"
className={`panel ${side}-panel absolute ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""
}`}
className={`panel ${side}-panel absolute ${hiddenPanels[selectedZone.zoneId]?.includes(side) ? "hidePanel" : ""}`}
style={getPanelStyle(side)}
onDrop={(e) => handleDrop(e, side)}
onDragOver={(e) => e.preventDefault()}
ref={(el) => {
if (el) {
panelRefs.current[side] = el;
} else {
delete panelRefs.current[side];
}
if (el) { panelRefs.current[side] = el; }
else { delete panelRefs.current[side]; }
}}
>
<div
className={`panel-content ${isPlaying && "fullScreen"}`}
style={{
pointerEvents:
selectedZone.lockedPanels.includes(side) ||
hiddenPanels[selectedZone.zoneId]?.includes(side)
? "none"
: "auto",
pointerEvents:selectedZone.lockedPanels.includes(side) || hiddenPanels[selectedZone.zoneId]?.includes(side)? "none": "auto",
opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
}}
>
{selectedZone.widgets
.filter((w) => w.panel === side)
.map((widget, index) => (
{selectedZone.widgets.filter((w) => w.panel === side).map((widget, index) => (
<DraggableWidget
hiddenPanels={hiddenPanels}
widget={widget}
key={widget.id}
index={index}
onReorder={(fromIndex, toIndex) =>
handleReorder(fromIndex, toIndex, side)
}
onReorder={(fromIndex, toIndex) =>handleReorder(fromIndex, toIndex, side)}
openKebabId={openKebabId}
setOpenKebabId={setOpenKebabId}
selectedZone={selectedZone}

View File

@ -1,81 +1,59 @@
import React, { useEffect, useRef } from 'react'
import { useSelectedFloorItem, useZoneAssetId } from '../../store/store';
import { useSelectedFloorItem, useZoneAssetId, useToggleView } from '../../store/store';
import * as THREE from "three";
import { useThree } from '@react-three/fiber';
import * as Types from "../../types/world/worldTypes";
export default function ZoneAssets() {
const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
const { zoneAssetId } = useZoneAssetId();
const { setSelectedFloorItem } = useSelectedFloorItem();
const { raycaster, controls, scene }: any = useThree();
const { toggleView } = useToggleView();
const { controls, scene }: any = useThree();
function focusAsset(AssetMesh: any) {
console.log('AssetMesh: ', AssetMesh);
if (toggleView) return;
const bbox = new THREE.Box3().setFromObject(AssetMesh);
const size = bbox.getSize(new THREE.Vector3());
const center = bbox.getCenter(new THREE.Vector3());
const front = new THREE.Vector3(0, 0, 1);
AssetMesh.localToWorld(front);
front.sub(AssetMesh.position).normalize();
const distance = Math.max(size.x, size.y, size.z) * 2;
const newPosition = center.clone().addScaledVector(front, distance);
controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true);
controls.setTarget(center.x, center.y, center.z, true);
controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
setSelectedFloorItem(AssetMesh);
}
useEffect(() => {
// console.log('zoneAssetId: ', zoneAssetId);
if (!zoneAssetId) return
console.log('zoneAssetId: ', zoneAssetId);
let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id);
if (AssetMesh) {
const bbox = new THREE.Box3().setFromObject(AssetMesh);
const size = bbox.getSize(new THREE.Vector3());
const center = bbox.getCenter(new THREE.Vector3());
const front = new THREE.Vector3(0, 0, 1);
AssetMesh.localToWorld(front);
front.sub(AssetMesh.position).normalize();
const distance = Math.max(size.x, size.y, size.z) * 2;
const newPosition = center.clone().addScaledVector(front, distance);
controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true);
controls.setTarget(center.x, center.y, center.z, true);
controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
setSelectedFloorItem(AssetMesh);
focusAsset(AssetMesh)
} else {
console.log('zoneAssetId: ', zoneAssetId)
if (Array.isArray(zoneAssetId.position) && zoneAssetId.position.length >= 3) {
let selectedAssetPosition = [
zoneAssetId.position[0],
10,
zoneAssetId.position[2]
];
console.log('selectedAssetPosition: ', selectedAssetPosition);
let selectedAssetTarget = [
zoneAssetId.position[0],
zoneAssetId.position[1],
zoneAssetId.position[2]
];
console.log('selectedAssetTarget: ', selectedAssetTarget);
const setCam = async () => {
let selectedAssetPosition = [zoneAssetId.position[0], 10, zoneAssetId.position[2]];
let selectedAssetTarget = [zoneAssetId.position[0], zoneAssetId.position[1], zoneAssetId.position[2]];
const setCamera = async () => {
await controls?.setLookAt(...selectedAssetPosition, ...selectedAssetTarget, true);
setTimeout(() => {
let AssetMesh = scene.getObjectByProperty("uuid", zoneAssetId.id);
if (AssetMesh) {
const bbox = new THREE.Box3().setFromObject(AssetMesh);
const size = bbox.getSize(new THREE.Vector3());
const center = bbox.getCenter(new THREE.Vector3());
const front = new THREE.Vector3(0, 0, 1);
AssetMesh.localToWorld(front);
front.sub(AssetMesh.position).normalize();
const distance = Math.max(size.x, size.y, size.z) * 2;
const newPosition = center.clone().addScaledVector(front, distance);
controls.setPosition(newPosition.x, newPosition.y, newPosition.z, true);
controls.setTarget(center.x, center.y, center.z, true);
controls.fitToBox(AssetMesh, true, { cover: true, paddingTop: 5, paddingLeft: 5, paddingBottom: 5, paddingRight: 5, });
setSelectedFloorItem(AssetMesh);
focusAsset(AssetMesh)
}
}, 500)
};
setCam();
setCamera();
}
}
}, [zoneAssetId, scene, controls])
return (
<>
</>