socket added for 3d and floating Widget

This commit is contained in:
2025-04-02 18:49:18 +05:30
parent b828cb2437
commit 238f76cb4c
12 changed files with 401 additions and 134 deletions

View File

@@ -5,11 +5,13 @@ import { useSelectedZoneStore } from "../../../../store/useZoneStore";
import { getTemplateData } from "../../../../services/realTimeVisulization/zoneData/getTemplate";
import { deleteTemplateApi } from "../../../../services/realTimeVisulization/zoneData/deleteTemplate";
import { loadTempleteApi } from "../../../../services/realTimeVisulization/zoneData/loadTemplate";
import { useSocketStore } from "../../../../store/store";
const Templates = () => {
const { templates, removeTemplate } = useTemplateStore();
const { setTemplates } = useTemplateStore();
const { setSelectedZone, selectedZone } = useSelectedZoneStore();
const { visualizationSocket } = useSocketStore();
useEffect(() => {
async function templateData() {
@@ -30,12 +32,18 @@ const Templates = () => {
try {
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
let response = await deleteTemplateApi(id, organization);
if (response.message === "Template deleted successfully") {
removeTemplate(id);
let deleteTemplate = {
organization: organization,
templateID: id,
}
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-template:deleteTemplate", deleteTemplate)
}
removeTemplate(id);
// let response = await deleteTemplateApi(id, organization);
// if (response.message === "Template deleted successfully") {
// }
} catch (error) {
console.error("Error deleting template:", error);
}
@@ -48,9 +56,20 @@ const Templates = () => {
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
let response = await loadTempleteApi(template.id, selectedZone.zoneId, organization);
let loadingTemplate = {
organization: organization,
zoneId: selectedZone.zoneId,
templateID: template.id,
}
console.log('template: ', template);
console.log('loadingTemplate: ', loadingTemplate);
if (response.message === "Template placed in Zone") {
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-template:addToZone", loadingTemplate)
}
// let response = await loadTempleteApi(template.id, selectedZone.zoneId, organization);
// if (response.message === "Template placed in Zone") {
setSelectedZone({
panelOrder: template.panelOrder,
activeSides: Array.from(new Set(template.panelOrder)), // No merging with previous `activeSides`
@@ -64,7 +83,7 @@ const Templates = () => {
useDroppedObjectsStore.getState().addObject(selectedZone.zoneName, val);
});
}
}
// }
} catch (error) {
console.error("Error loading template:", error);
}

View File

@@ -27,6 +27,7 @@ import {
useMovePoint,
useRefTextUpdate,
useSelectedWallItem,
useSocketStore,
useToggleView,
useToolMode,
useTransformMode,
@@ -42,7 +43,7 @@ const Tools: React.FC = () => {
const dropdownRef = useRef<HTMLDivElement>(null);
const [openDrop, setOpenDrop] = useState(false);
const { visualizationSocket } = useSocketStore();
const { activeModule } = useModuleStore();
const { isPlaying, setIsPlaying } = usePlayButtonStore();
const { addTemplate } = useTemplateStore();
@@ -397,6 +398,7 @@ const Tools: React.FC = () => {
widgets3D,
selectedZone,
templates,
visualizationSocket
})
}
}

View File

@@ -92,6 +92,7 @@ export const DraggableWidget = ({
widgetID: widget.id,
organization: organization
}
console.log('deleteWidget: ', deleteWidget);
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-widget:delete", deleteWidget)
}
@@ -160,14 +161,27 @@ export const DraggableWidget = ({
id: `${widget.id}-copy-${Date.now()}`,
};
const response = await duplicateWidgetApi(selectedZone.zoneId, organization, duplicatedWidget);
if (response?.message === "Widget created successfully") {
setSelectedZone((prevZone: any) => ({
...prevZone,
widgets: [...prevZone.widgets, duplicatedWidget],
}));
let duplicateWidget = {
organization: organization,
zoneId: selectedZone.zoneId,
widget: duplicatedWidget
}
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-widget:add", duplicateWidget)
}
setSelectedZone((prevZone: any) => ({
...prevZone,
widgets: [...prevZone.widgets, duplicatedWidget],
}));
// const response = await duplicateWidgetApi(selectedZone.zoneId, organization, duplicatedWidget);
// if (response?.message === "Widget created successfully") {
// setSelectedZone((prevZone: any) => ({
// ...prevZone,
// widgets: [...prevZone.widgets, duplicatedWidget],
// }));
// }
} catch (error) {
} finally {

View File

@@ -1,7 +1,7 @@
import { useThree } from "@react-three/fiber";
import React, { useState, useEffect } from "react";
import { useAsset3dWidget, useWidgetSubOption } from "../../../store/store";
import { useAsset3dWidget, useSocketStore, useWidgetSubOption } from "../../../store/store";
import useModuleStore from "../../../store/useModuleStore";
import { ThreeState } from "../../../types/world/worldTypes";
import * as THREE from "three";
@@ -14,21 +14,23 @@ import { generateUniqueId } from "../../../functions/generateUniqueId";
import { adding3dWidgets } from "../../../services/realTimeVisulization/zoneData/add3dWidget";
import { get3dWidgetZoneData } from "../../../services/realTimeVisulization/zoneData/get3dWidgetData";
import { use3DWidget } from "../../../store/useDroppedObjectsStore";
import { useZoneWidgetStore } from "../../../store/useZone3DWidgetStore";
export default function Dropped3dWidgets() {
const { widgetSelect } = useAsset3dWidget();
const { activeModule } = useModuleStore();
const { raycaster, gl, scene }: ThreeState = useThree();
const { widgetSubOption, setWidgetSubOption } = useWidgetSubOption();
const { selectedZone } = useSelectedZoneStore(); // Get the currently active zone
// 🔥 Store widget data (id, type, position) based on the selected zone
const [zoneWidgetData, setZoneWidgetData] = useState<
Record<string, { id: string; type: string; position: [number, number, number] }[]>
>({});
const { setWidgets3D } = use3DWidget()
const { widgetSubOption } = useWidgetSubOption();
const { selectedZone } = useSelectedZoneStore();
// ✅ Use Zustand Store instead of useState
const { zoneWidgetData, setZoneWidgetData, addWidget } = useZoneWidgetStore();
const { setWidgets3D } = use3DWidget();
const { visualizationSocket } = useSocketStore();
useEffect(() => {
if (activeModule !== "visualization") return
if (selectedZone.zoneName === "") return;
if (activeModule !== "visualization") return;
if (!selectedZone.zoneId) return;
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
@@ -36,37 +38,36 @@ export default function Dropped3dWidgets() {
async function get3dWidgetData() {
let result = await get3dWidgetZoneData(selectedZone.zoneId, organization);
console.log('result: ', result);
setWidgets3D(result)
// Ensure the extracted data has id, type, and position correctly mapped
setWidgets3D(result);
const formattedWidgets = result.map((widget: any) => ({
id: widget.id,
type: widget.type,
position: widget.position,
}));
setZoneWidgetData((prev) => ({
...prev,
[selectedZone.zoneId]: formattedWidgets,
}));
setZoneWidgetData(selectedZone.zoneId, formattedWidgets);
}
get3dWidgetData();
}, [selectedZone.zoneId, activeModule]);
useEffect(() => {
if (activeModule !== "visualization") return;
if (widgetSubOption === "Floating") return;
if (widgetSubOption === "2D") return;
if (selectedZone.zoneName === "") return
if (widgetSubOption === "Floating" || widgetSubOption === "2D") return;
if (selectedZone.zoneName === "") return;
const canvasElement = gl.domElement;
const onDrop = async (event: DragEvent) => {
event.preventDefault(); // Prevent default browser behavior
event.preventDefault();
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
if (!widgetSelect.startsWith("ui")) return;
const group1 = scene.getObjectByName("itemsGroup");
if (!group1) return;
const intersects = raycaster.intersectObjects(scene.children, true).filter(
(intersect) =>
!intersect.object.name.includes("Roof") &&
@@ -75,40 +76,41 @@ export default function Dropped3dWidgets() {
!intersect.object.userData.isPathObject &&
!(intersect.object.type === "GridHelper")
);
if (intersects.length > 0) {
const { x, y, z } = intersects[0].point;
// ✅ Explicitly define position as a tuple
const newWidget: { id: string; type: string; position: [number, number, number] } = {
const newWidget = {
id: generateUniqueId(),
type: widgetSelect,
position: [x, y, z], // Ensures TypeScript recognizes it as a tuple
position: [x, y, z] as [number, number, number],
};
let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget)
console.log('response: ', response);
if (response.message === "Widget created successfully") {
// ✅ Store widgets uniquely for each zone
setZoneWidgetData((prev) => ({
...prev,
[selectedZone.zoneId]: [...(prev[selectedZone.zoneId] || []), newWidget],
}));
let add3dWidget = {
organization: organization,
widget: newWidget,
zoneId: selectedZone.zoneId
}
console.log('add3dWidget: ', add3dWidget);
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-3D-widget:add", add3dWidget)
}
// let response = await adding3dWidgets(selectedZone.zoneId, organization, newWidget);
// console.log('response: ', response);
// if (response.message === "Widget created successfully") {
addWidget(selectedZone.zoneId, newWidget);
// }
}
};
canvasElement.addEventListener("drop", onDrop);
return () => {
canvasElement.removeEventListener("drop", onDrop);
};
}, [widgetSelect, activeModule, selectedZone.zoneId, widgetSubOption]);
// Get widgets for the currently active zone
const activeZoneWidgets = zoneWidgetData[selectedZone.zoneId] || [];
console.log('activeZoneWidgets: ', activeZoneWidgets);
return (
<>
@@ -130,5 +132,3 @@ export default function Dropped3dWidgets() {
);
}

View File

@@ -21,6 +21,7 @@ import TotalCardComponent from "../realTimeVis/floating/TotalCardComponent";
import WarehouseThroughputComponent from "../realTimeVis/floating/WarehouseThroughputComponent";
import FleetEfficiencyComponent from "../realTimeVis/floating/FleetEfficiencyComponent";
import { useWidgetStore } from "../../../store/useWidgetStore";
import { useSocketStore } from "../../../store/store";
interface DraggingState {
zone: string;
index: number;
@@ -43,6 +44,7 @@ interface DraggingState {
};
}
const DroppedObjects: React.FC = () => {
const { visualizationSocket } = useSocketStore();
const zones = useDroppedObjectsStore((state) => state.zones);
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
const updateObjectPosition = useDroppedObjectsStore(
@@ -98,29 +100,41 @@ const DroppedObjects: React.FC = () => {
const zoneEntries = Object.entries(zones);
if (zoneEntries.length === 0) return null;
const [zoneName, zone] = zoneEntries[0];
function handleDuplicate(zoneName: string, index: number) {
setOpenKebabId(null)
duplicateObject(zoneName, index); // Call the duplicateObject method from the store
}
async function handleDelete(zoneName: string, id: string, index: number) {
async function handleDelete(zoneName: string, id: string) {
try {
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
let res = await deleteFloatingWidgetApi(id, organization);
console.log('res: ', res);
if (res.message === "FloatingWidget deleted successfully") {
deleteObject(zoneName, id, index); // Call the deleteObject method from the store
let deleteFloatingWidget = {
floatWidgetID: id,
organization: organization,
zoneId: zone.zoneId
}
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-float:delete", deleteFloatingWidget)
}
deleteObject(zoneName, id);
// let res = await deleteFloatingWidgetApi(id, organization);
// s
// if (res.message === "FloatingWidget deleted successfully") {
// deleteObject(zoneName, id, index); // Call the deleteObject method from the store
// }
} catch (error) {
console.error("Error deleting floating widget:", error);
}
}
const handlePointerDown = (event: React.PointerEvent, index: number) => {
if ((event.target as HTMLElement).closest(".kebab-options") || (event.target as HTMLElement).closest(".kebab")) {
return; // Prevent dragging when clicking on the kebab menu or its options
@@ -278,15 +292,30 @@ const DroppedObjects: React.FC = () => {
// Save to backend
const email = localStorage.getItem("email") || "";
const organization = email?.split("@")[1]?.split(".")[0];
const response = await addingFloatingWidgets(zone.zoneId, organization, {
...zone.objects[draggingIndex.index],
position: boundedPosition,
});
console.log('response: ', response);
// const response = await addingFloatingWidgets(zone.zoneId, organization, {
// ...zone.objects[draggingIndex.index],
// position: boundedPosition,
// });
if (response.message === "Widget updated successfully") {
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
let updateFloatingWidget = {
organization: organization,
widget: {
...zone.objects[draggingIndex.index],
position: boundedPosition,
},
index:draggingIndex.index,
zoneId: zone.zoneId
}
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-float:add", updateFloatingWidget)
}
// if (response.message === "Widget updated successfully") {
console.log('boundedPosition: ', boundedPosition);
updateObjectPosition(zoneName, draggingIndex.index, boundedPosition);
// }
// // Clean up
// setDraggingIndex(null);
@@ -298,7 +327,7 @@ const DroppedObjects: React.FC = () => {
// animationRef.current = null;
// }
} catch (error) {
console.error("Error in handlePointerUp:", error);
} finally {
// Clean up regardless of success or failure
setDraggingIndex(null);
@@ -390,7 +419,7 @@ const DroppedObjects: React.FC = () => {
</div>
<div className="edit btn" onClick={(event) => {
event.stopPropagation();
handleDelete(zoneName, obj.id, index); // Call the delete handler
handleDelete(zoneName, obj.id); // Call the delete handler
}}>
<div className="icon">
<DeleteIcon />

View File

@@ -153,8 +153,6 @@ const Panel: React.FC<PanelProps> = ({
zoneId: selectedZone.zoneId,
widget: newWidget
}
console.log('newWidget: ', newWidget);
console.log('addWidget: ', addWidget);
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-widget:add", addWidget)
}
@@ -163,18 +161,18 @@ const Panel: React.FC<PanelProps> = ({
widgets: [...prev.widgets, newWidget],
}));
// try {
// let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
try {
// let response = await addingWidgets(selectedZone.zoneId, organization, newWidget);
// if (response.message === "Widget created successfully") {
// setSelectedZone((prev) => ({
// ...prev,
// widgets: [...prev.widgets, newWidget],
// }));
// }
// } catch (error) {
// console.error("Error adding widget:", error);
// }
// if (response.message === "Widget created successfully") {
// setSelectedZone((prev) => ({
// ...prev,
// widgets: [...prev.widgets, newWidget],
// }));
// }
} catch (error) {
console.error("Error adding widget:", error);
}
};

View File

@@ -144,12 +144,6 @@ const RealTimeVisulization: React.FC = () => {
};
console.log('newObject: ', newObject);
let response = await addingFloatingWidgets(
selectedZone.zoneId,
organization,
newObject
);
// Only set zone if its not already in the store (prevents overwriting objects)
const existingZone =
useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
@@ -159,12 +153,28 @@ const RealTimeVisulization: React.FC = () => {
.setZone(selectedZone.zoneName, selectedZone.zoneId);
}
// Add the dropped object to the zone if the API call is successful
if (response.message === "FloatWidget created successfully") {
useDroppedObjectsStore
.getState()
.addObject(selectedZone.zoneName, newObject);
let addFloatingWidget = {
organization: organization,
widget: newObject,
zoneId: selectedZone.zoneId
}
console.log('newObject: ', newObject);
if (visualizationSocket) {
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget)
}
// let response = await addingFloatingWidgets(
// selectedZone.zoneId,
// organization,
// newObject
// );
// Add the dropped object to the zone if the API call is successful
// if (response.message === "FloatWidget created successfully") {
useDroppedObjectsStore
.getState()
.addObject(selectedZone.zoneName, newObject);
// }
// Update floating widgets state
setFloatingWidgets((prevWidgets) => ({
@@ -209,6 +219,11 @@ const RealTimeVisulization: React.FC = () => {
{activeModule === "visualization" && selectedZone.zoneName !== "" && <DroppedObjects />}
{activeModule === "visualization" && <SocketRealTimeViz />}
{/* <DroppedObjects /> */}
{/* <RenderOverlay>
<EditWidgetOption
options={["Dublicate", "Vertical Move", "Horizontal Move", "Delete"]}
/>
</RenderOverlay> */}
{activeModule === "visualization" && (
<>
<DisplayZone