added sockets and dynamic saving function

This commit is contained in:
gabriel 2025-03-24 18:24:28 +05:30
parent 3caab7aa36
commit b85820d410
7 changed files with 1021 additions and 390 deletions

138
app/package-lock.json generated
View File

@ -14,6 +14,7 @@
"react-chartjs-2": "^5.3.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.3.0",
"socket.io-client": "^4.8.1",
"zustand": "^5.0.3"
},
"devDependencies": {
@ -1655,6 +1656,12 @@
"win32"
]
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==",
"license": "MIT"
},
"node_modules/@types/axios": {
"version": "0.14.4",
"resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.4.tgz",
@ -2795,6 +2802,45 @@
"dev": true,
"license": "ISC"
},
"node_modules/engine.io-client": {
"version": "6.6.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.3.tgz",
"integrity": "sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.1.1"
}
},
"node_modules/engine.io-client/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/engine.io-parser": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz",
"integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@ -3708,7 +3754,6 @@
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/nanoid": {
@ -4607,6 +4652,68 @@
"node": ">=8"
}
},
"node_modules/socket.io-client": {
"version": "4.8.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.8.1.tgz",
"integrity": "sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.6.1",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-client/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"license": "MIT",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser/node_modules/debug": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@ -4996,6 +5103,35 @@
"node": ">=0.10.0"
}
},
"node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",
"integrity": "sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",

View File

@ -16,6 +16,7 @@
"react-chartjs-2": "^5.3.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.3.0",
"socket.io-client": "^4.8.1",
"zustand": "^5.0.3"
},
"devDependencies": {

View File

@ -1,3 +1,199 @@
// import React from "react";
// import {
// CleanPannel,
// EyeIcon,
// LockIcon,
// } from "../../icons/RealTimeVisulationIcons";
// // Define the type for `Side`
// type Side = "top" | "bottom" | "left" | "right";
// // Define the type for the props passed to the Buttons component
// interface ButtonsProps {
// selectedZone: {
// zoneName: string;
// activeSides: Side[];
// panelOrder: Side[];
// lockedPanels: Side[];
// widgets: {
// id: string;
// type: string;
// title: string;
// panel: Side;
// data: any;
// }[];
// };
// setSelectedZone: React.Dispatch<
// React.SetStateAction<{
// zoneName: string;
// activeSides: Side[];
// panelOrder: Side[];
// lockedPanels: Side[];
// widgets: {
// id: string;
// type: string;
// title: string;
// panel: Side;
// data: any;
// }[];
// }>
// >;
// hiddenPanels: Side[]; // Add this prop for hidden panels
// setHiddenPanels: React.Dispatch<React.SetStateAction<Side[]>>; // Add this prop for updating hidden panels
// }
// const AddButtons: React.FC<ButtonsProps> = ({
// selectedZone,
// setSelectedZone,
// setHiddenPanels,
// hiddenPanels,
// }) => {
// // Local state to track hidden panels
// // Function to toggle lock/unlock a panel
// const toggleLockPanel = (side: Side) => {
// const newLockedPanels = selectedZone.lockedPanels.includes(side)
// ? selectedZone.lockedPanels.filter((panel) => panel !== side)
// : [...selectedZone.lockedPanels, side];
// const updatedZone = {
// ...selectedZone,
// lockedPanels: newLockedPanels,
// };
// // Update the selectedZone state
// setSelectedZone(updatedZone);
// };
// // Function to toggle visibility of a panel
// const toggleVisibility = (side: Side) => {
// const isHidden = hiddenPanels.includes(side);
// if (isHidden) {
// // If the panel is already hidden, remove it from the hiddenPanels array
// setHiddenPanels(hiddenPanels.filter((panel) => panel !== side));
// } else {
// // If the panel is visible, add it to the hiddenPanels array
// setHiddenPanels([...hiddenPanels, side]);
// }
// };
// // Function to clean all widgets from a panel
// const cleanPanel = (side: Side) => {
// 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 = (side: Side) => {
// if (selectedZone.activeSides.includes(side)) {
// // If the panel is already active, remove all widgets and close the panel
// 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,
// };
// // Update the selectedZone state
// setSelectedZone(updatedZone);
// } else {
// // If the panel is not active, activate it
// const newActiveSides = [...selectedZone.activeSides, side];
// const updatedZone = {
// ...selectedZone,
// activeSides: newActiveSides,
// panelOrder: newActiveSides,
// };
// // Update the selectedZone state
// setSelectedZone(updatedZone);
// }
// };
// return (
// <div>
// {(["top", "right", "bottom", "left"] as Side[]).map((side) => (
// <div key={side} className={`side-button-container ${side}`}>
// {/* "+" Button */}
// <button
// className={`side-button ${side}`}
// onClick={() => handlePlusButtonClick(side)}
// title={
// selectedZone.activeSides.includes(side)
// ? `Remove all items and close ${side} panel`
// : `Activate ${side} panel`
// }
// >
// +
// </button>
// {/* Extra Buttons */}
// {selectedZone.activeSides.includes(side) && (
// <div className="extra-Bs">
// {/* Hide Panel */}
// <div
// className={`icon ${
// hiddenPanels.includes(side) ? "active" : ""
// }`}
// title={
// hiddenPanels.includes(side) ? "Show Panel" : "Hide Panel"
// }
// onClick={() => toggleVisibility(side)}
// >
// <EyeIcon />
// </div>
// {/* Clean Panel */}
// <div
// className="icon"
// title="Clean Panel"
// onClick={() => cleanPanel(side)}
// >
// <CleanPannel />
// </div>
// {/* Lock/Unlock Panel */}
// <div
// className={`icon ${
// selectedZone.lockedPanels.includes(side) ? "active" : ""
// }`}
// title={
// selectedZone.lockedPanels.includes(side)
// ? "Unlock Panel"
// : "Lock Panel"
// }
// onClick={() => toggleLockPanel(side)}
// >
// <LockIcon />
// </div>
// </div>
// )}
// </div>
// ))}
// </div>
// );
// };
// export default AddButtons;
import React from "react";
import {
CleanPannel,

View File

@ -1,188 +1,3 @@
import React, { useEffect, useRef } from "react";
import { Widget } from "../../../store/useWidgetStore";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
interface DisplayZoneProps {
zonesData: {
[key: string]: {
zoneId: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: Widget[];
};
};
selectedZone: {
zoneId: string;
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneId: string;
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
}>
>;
}
const DisplayZone: React.FC<DisplayZoneProps> = ({
zonesData,
selectedZone,
setSelectedZone,
}) => {
// Ref for the container element
const containerRef = useRef<HTMLDivElement | null>(null);
// Example state for selectedOption and options (adjust based on your actual use case)
const [selectedOption, setSelectedOption] = React.useState<string | null>(
null
);
console.log('setSelectedOption: ', setSelectedOption);
const [options, setOptions] = React.useState<string[]>([]);
console.log('setOptions: ', setOptions);
// Scroll to the selected option when it changes
useEffect(() => {
const container = containerRef.current;
if (container && selectedOption) {
// Handle scrolling to the selected option
const index = options.findIndex((option) => {
const formattedOption = formatOptionName(option);
const selectedFormattedOption =
selectedOption?.split("_")[1] || selectedOption;
return formattedOption === selectedFormattedOption;
});
if (index !== -1) {
const optionElement = container.children[index] as HTMLElement;
if (optionElement) {
optionElement.scrollIntoView({
behavior: "smooth",
block: "nearest",
inline: "center",
});
}
}
}
}, [selectedOption, options]);
useEffect(() => {
const container = containerRef.current;
const handleWheel = (event: WheelEvent) => {
event.preventDefault();
if (container) {
container.scrollBy({
left: event.deltaY * 2, // Adjust the multiplier for faster scrolling
behavior: "smooth",
});
}
};
let isDragging = false;
let startX: number;
let scrollLeft: number;
const handleMouseDown = (event: MouseEvent) => {
isDragging = true;
startX = event.pageX - (container?.offsetLeft || 0);
scrollLeft = container?.scrollLeft || 0;
};
const handleMouseMove = (event: MouseEvent) => {
if (!isDragging || !container) return;
event.preventDefault();
const x = event.pageX - (container.offsetLeft || 0);
const walk = (x - startX) * 2; // Adjust the multiplier for faster dragging
container.scrollLeft = scrollLeft - walk;
};
const handleMouseUp = () => {
isDragging = false;
};
const handleMouseLeave = () => {
isDragging = false;
};
if (container) {
container.addEventListener("wheel", handleWheel, { passive: false });
container.addEventListener("mousedown", handleMouseDown);
container.addEventListener("mousemove", handleMouseMove);
container.addEventListener("mouseup", handleMouseUp);
container.addEventListener("mouseleave", handleMouseLeave);
}
return () => {
if (container) {
container.removeEventListener("wheel", handleWheel);
container.removeEventListener("mousedown", handleMouseDown);
container.removeEventListener("mousemove", handleMouseMove);
container.removeEventListener("mouseup", handleMouseUp);
container.removeEventListener("mouseleave", handleMouseLeave);
}
};
}, []);
// Helper function to format option names (customize as needed)
const formatOptionName = (option: string): string => {
// Replace underscores with spaces and capitalize the first letter
return option.replace(/_/g, " ").replace(/^\w/, (c) => c.toUpperCase());
};
return (
<div
ref={containerRef}
className={`zoon-wrapper ${
selectedZone.activeSides.includes("bottom") && "bottom"
}`}
>
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${
selectedZone.zoneName === zoneName ? "active" : ""
}`}
onClick={() => {
setSelectedZone({
zoneName,
...zonesData[zoneName],
});
}}
>
{zoneName}
</div>
))}
</div>
);
};
export default DisplayZone;
// import React, { useEffect, useRef } from "react";
// import { Widget } from "../../../store/useWidgetStore";
@ -191,11 +6,13 @@ export default DisplayZone;
// interface DisplayZoneProps {
// zonesData: {
// _id: string;
// zoneName: string;
// zoneUUID: string;
// sceneID: string;
// }[];
// [key: string]: {
// activeSides: Side[];
// panelOrder: Side[];
// lockedPanels: Side[];
// widgets: Widget[];
// };
// };
// selectedZone: {
// zoneName: string;
// activeSides: Side[];
@ -339,24 +156,237 @@ export default DisplayZone;
// selectedZone.activeSides.includes("bottom") && "bottom"
// }`}
// >
// {zonesData && zonesData.length > 0 && zonesData?.map((zone, index) => (
// {Object.keys(zonesData).map((zoneName, index) => (
// <div
// key={index}
// className={`zone ${
// selectedZone.zoneName === zone._id ? "active" : ""
// selectedZone.zoneName === zoneName ? "active" : ""
// }`}
// // onClick={() => {
// // setSelectedZone({
// // zoneName,
// // ...zonesData[zoneName],
// // });
// // }}
// onClick={() => {
// setSelectedZone({
// zoneName,
// ...zonesData[zoneName],
// });
// }}
// >
// {zone.zoneName}
// {zoneName}
// </div>
// ))}
// </div>
// );
// };
// export default DisplayZone;
// export default DisplayZone;
import React, { useEffect, useRef } from "react";
import { Widget } from "../../../store/useWidgetStore";
import axios from "axios";
// Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right";
interface DisplayZoneProps {
zonesData: {
_id: string;
zoneName: string;
zoneUUID: string;
sceneID: string;
}[];
selectedZone: {
zoneId: string;
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}[];
};
setSelectedZone: React.Dispatch<
React.SetStateAction<{
zoneId: string;
zoneName: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: {
id: string;
type: string;
title: string;
panel: Side;
data: any
}[];
}>
>;
}
const DisplayZone: React.FC<DisplayZoneProps> = ({
zonesData,
selectedZone,
setSelectedZone,
}) => {
// Ref for the container element
const containerRef = useRef<HTMLDivElement | null>(null);
// Example state for selectedOption and options (adjust based on your actual use case)
const [selectedOption, setSelectedOption] = React.useState<string | null>(
null
);
console.log('setSelectedOption: ', setSelectedOption);
const [options, setOptions] = React.useState<string[]>([]);
console.log('setOptions: ', setOptions);
// Scroll to the selected option when it changes
useEffect(() => {
const container = containerRef.current;
if (container && selectedOption) {
// Handle scrolling to the selected option
const index = options.findIndex((option) => {
const formattedOption = formatOptionName(option);
const selectedFormattedOption =
selectedOption?.split("_")[1] || selectedOption;
return formattedOption === selectedFormattedOption;
});
if (index !== -1) {
const optionElement = container.children[index] as HTMLElement;
if (optionElement) {
optionElement.scrollIntoView({
behavior: "smooth",
block: "nearest",
inline: "center",
});
}
}
}
}, [selectedOption, options]);
useEffect(() => {
const container = containerRef.current;
const handleWheel = (event: WheelEvent) => {
event.preventDefault();
if (container) {
container.scrollBy({
left: event.deltaY * 2, // Adjust the multiplier for faster scrolling
behavior: "smooth",
});
}
};
let isDragging = false;
let startX: number;
let scrollLeft: number;
const handleMouseDown = (event: MouseEvent) => {
isDragging = true;
startX = event.pageX - (container?.offsetLeft || 0);
scrollLeft = container?.scrollLeft || 0;
};
const handleMouseMove = (event: MouseEvent) => {
if (!isDragging || !container) return;
event.preventDefault();
const x = event.pageX - (container.offsetLeft || 0);
const walk = (x - startX) * 2; // Adjust the multiplier for faster dragging
container.scrollLeft = scrollLeft - walk;
};
const handleMouseUp = () => {
isDragging = false;
};
const handleMouseLeave = () => {
isDragging = false;
};
if (container) {
container.addEventListener("wheel", handleWheel, { passive: false });
container.addEventListener("mousedown", handleMouseDown);
container.addEventListener("mousemove", handleMouseMove);
container.addEventListener("mouseup", handleMouseUp);
container.addEventListener("mouseleave", handleMouseLeave);
}
return () => {
if (container) {
container.removeEventListener("wheel", handleWheel);
container.removeEventListener("mousedown", handleMouseDown);
container.removeEventListener("mousemove", handleMouseMove);
container.removeEventListener("mouseup", handleMouseUp);
container.removeEventListener("mouseleave", handleMouseLeave);
}
};
}, []);
// Helper function to format option names (customize as needed)
const formatOptionName = (option: string): string => {
// Replace underscores with spaces and capitalize the first letter
return option.replace(/_/g, " ").replace(/^\w/, (c) => c.toUpperCase());
};
const fetchSelectedZone = async (selectedZoneId: string) => {
try {
// Send POST request to the server
const response = await axios.get('http://192.168.0.192:4000/fetchzonedetails',
{
params: {
zoneId: selectedZoneId
}
}
);
// Check the response and show a success message if needed
if (response.status === 200) {
console.log('broker details responce:', response.data);
setSelectedZone(response.data)
} else {
console.log('Unexpected response:', response);
}
} catch (error) {
console.error('There was an error!', error);
// setZonesData([])
}
};
console.log(zonesData);
return (
<div
ref={containerRef}
className={`zoon-wrapper ${selectedZone.activeSides.includes("bottom") && "bottom"
}`}
>
{zonesData && zonesData.length > 0 && zonesData?.map((zone, index) => (
<div
key={index}
className={`zone ${selectedZone.zoneId === zone._id ? "active" : ""
}`}
// onClick={() => {
// setSelectedZone({
// zoneName,
// ...zonesData[zoneName],
// });
// }}
onClick={() => {
fetchSelectedZone(zone._id)
}}
>
{zone.zoneName}
</div>
))}
</div>
);
};
export default DisplayZone;

View File

@ -1,3 +1,209 @@
// import React, { useEffect, useMemo, useRef, useState } from "react";
// import { useWidgetStore } from "../../../store/useWidgetStore";
// import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
// import { DraggableWidget } from "./DraggableWidget";
// 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[];
// widgets: Widget[];
// };
// setSelectedZone: React.Dispatch<
// React.SetStateAction<{
// zoneName: string;
// activeSides: Side[];
// panelOrder: Side[];
// lockedPanels: Side[];
// widgets: Widget[];
// }>
// >;
// }
// const generateUniqueId = () =>
// `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
// const Panel: React.FC<PanelProps> = ({ selectedZone, setSelectedZone }) => {
// const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
// const [panelDimensions, setPanelDimensions] = useState<{
// [side in Side]?: { width: number; height: number };
// }>({});
// const getPanelStyle = useMemo(
// () => (side: Side) => {
// const currentIndex = selectedZone.panelOrder.indexOf(side);
// const previousPanels = selectedZone.panelOrder.slice(0, currentIndex);
// const leftActive = previousPanels.includes("left");
// const rightActive = previousPanels.includes("right");
// const topActive = previousPanels.includes("top");
// const bottomActive = previousPanels.includes("bottom");
// switch (side) {
// case "top":
// case "bottom":
// return {
// width: `calc(100% - ${
// (leftActive ? 204 : 0) + (rightActive ? 204 : 0)
// }px)`,
// left: leftActive ? "204px" : "0",
// right: rightActive ? "204px" : "0",
// [side]: "0",
// height: "200px",
// };
// case "left":
// case "right":
// return {
// height: `calc(100% - ${
// (topActive ? 204 : 0) + (bottomActive ? 204 : 0)
// }px)`,
// top: topActive ? "204px" : "0",
// bottom: bottomActive ? "204px" : "0",
// [side]: "0",
// width: "200px",
// };
// default:
// return {};
// }
// },
// [selectedZone.panelOrder]
// );
// const handleDrop = (e: React.DragEvent, panel: Side) => {
// e.preventDefault();
// const { draggedAsset } = useWidgetStore.getState();
// if (!draggedAsset) return;
// if (isPanelLocked(panel)) return;
// const currentWidgetsCount = getCurrentWidgetCount(panel);
// const maxCapacity = calculatePanelCapacity(panel);
// if (currentWidgetsCount >= maxCapacity) return;
// addWidgetToPanel(draggedAsset, panel);
// };
// // Helper functions
// const isPanelLocked = (panel: Side) =>
// selectedZone.lockedPanels.includes(panel);
// const getCurrentWidgetCount = (panel: Side) =>
// selectedZone.widgets.filter(w => w.panel === panel).length;
// const calculatePanelCapacity = (panel: Side) => {
// const CHART_WIDTH = 200;
// const CHART_HEIGHT = 200;
// const FALLBACK_HORIZONTAL_CAPACITY = 5;
// const FALLBACK_VERTICAL_CAPACITY = 3;
// const dimensions = panelDimensions[panel];
// if (!dimensions) {
// return panel === "top" || panel === "bottom"
// ? FALLBACK_HORIZONTAL_CAPACITY
// : FALLBACK_VERTICAL_CAPACITY;
// }
// return panel === "top" || panel === "bottom"
// ? Math.floor(dimensions.width / CHART_WIDTH)
// : Math.floor(dimensions.height / CHART_HEIGHT);
// };
// const addWidgetToPanel = (asset: any, panel: Side) => {
// const newWidget = {
// ...asset,
// id: generateUniqueId(),
// panel,
// };
// setSelectedZone(prev => ({
// ...prev,
// widgets: [...prev.widgets, newWidget]
// }));
// };
// useEffect(() => {
// const observers: ResizeObserver[] = [];
// const currentPanelRefs = panelRefs.current;
// selectedZone.activeSides.forEach((side) => {
// const element = currentPanelRefs[side];
// if (element) {
// const observer = new ResizeObserver((entries) => {
// for (const entry of entries) {
// const { width, height } = entry.contentRect;
// setPanelDimensions((prev) => ({
// ...prev,
// [side]: { width, height },
// }));
// }
// });
// observer.observe(element);
// observers.push(observer);
// }
// });
// return () => {
// observers.forEach((observer) => observer.disconnect());
// };
// }, [selectedZone.activeSides]);
// const { isPlaying } = usePlayButtonStore();
// return (
// <>
// {selectedZone.activeSides.map((side) => (
// <div
// key={side}
// className={`panel ${side}-panel absolute ${isPlaying && ""}`}
// 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];
// }
// }}
// >
// <div
// className={`panel-content ${isPlaying && "fullScreen"}`}
// style={{
// pointerEvents: selectedZone.lockedPanels.includes(side)
// ? "none"
// : "auto",
// opacity: selectedZone.lockedPanels.includes(side) ? "0.8" : "1",
// }}
// >
// <>{}</>
// {selectedZone.widgets
// .filter((w) => w.panel === side)
// .map((widget) => (
// <DraggableWidget widget={widget} key={widget.id} />
// ))}
// </div>
// </div>
// ))}
// </>
// );
// };
// export default Panel;
import React, { useEffect, useMemo, useRef, useState } from "react";
import { useWidgetStore } from "../../../store/useWidgetStore";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
@ -203,3 +409,4 @@ const Panel: React.FC<PanelProps> = ({ selectedZone, setSelectedZone }) => {
};
export default Panel;

View File

@ -1,123 +1,9 @@
import React, { useEffect, useState, useRef } from "react";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import Panel from "./Panel";
import AddButtons from "./AddButtons";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
import DisplayZone from "./DisplayZone";
type Side = "top" | "bottom" | "left" | "right";
interface Widget {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}
const RealTimeVisulization: React.FC = () => {
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
const containerRef = useRef<HTMLDivElement>(null);
const [zonesData, setZonesData] = useState<{
[key: string]: {
zoneId: string;
activeSides: Side[];
panelOrder: Side[];
lockedPanels: Side[];
widgets: Widget[];
};
}>({
"Manufacturing unit": {
zoneId: "Manufacturing unit",
activeSides: [],
panelOrder: [],
lockedPanels: [],
widgets: [],
},
"Assembly unit": {
zoneId: "Assembly unit",
activeSides: [],
panelOrder: [],
lockedPanels: [],
widgets: [],
},
"Packing unit": {
zoneId: "Packing unit",
activeSides: [],
panelOrder: [],
lockedPanels: [],
widgets: [],
},
Warehouse: {
zoneId: "Warehouse",
activeSides: [],
panelOrder: [],
lockedPanels: [],
widgets: [],
},
Inventory: {
zoneId: "Inventory",
activeSides: [],
panelOrder: [],
lockedPanels: [],
widgets: [],
},
});
const { isPlaying } = usePlayButtonStore();
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
useEffect(() => {
setZonesData((prev) => ({
...prev,
[selectedZone.zoneName]: selectedZone,
}));
}, [selectedZone]);
return (
<div
ref={containerRef}
id="real-time-vis-canvas"
className="realTime-viz canvas"
style={{
height: isPlaying ? "100vh" : "",
width: isPlaying ? "100%" : "",
left: isPlaying ? "0%" : "",
}}
>
<DisplayZone
zonesData={zonesData}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
{!isPlaying && (
<AddButtons
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
)}
<Panel selectedZone={selectedZone} setSelectedZone={setSelectedZone} />
</div>
);
};
export default RealTimeVisulization;
// import React, { useEffect, useState, useRef } from "react";
// import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
// import Panel from "./Panel";
// import AddButtons from "./AddButtons";
// import { useSelectedZoneStore } from "../../../store/useZoneStore";
// import DisplayZone from "./DisplayZone";
// import axios from "axios";
// type Side = "top" | "bottom" | "left" | "right";
@ -132,80 +18,45 @@ export default RealTimeVisulization;
// const RealTimeVisulization: React.FC = () => {
// const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
// const containerRef = useRef<HTMLDivElement>(null);
// // const [zonesData, setZonesData] = useState<{
// // [key: string]: {
// // activeSides: Side[];
// // panelOrder: Side[];
// // lockedPanels: Side[];
// // widgets: Widget[];
// // };
// // }>({
// // "Manufacturing unit": {
// // activeSides: [],
// // panelOrder: [],
// // lockedPanels: [],
// // widgets: [],
// // },
// // "Assembly unit": {
// // activeSides: [],
// // panelOrder: [],
// // lockedPanels: [],
// // widgets: [],
// // },
// // "Packing unit": {
// // activeSides: [],
// // panelOrder: [],
// // lockedPanels: [],
// // widgets: [],
// // },
// // Warehouse: {
// // activeSides: [],
// // panelOrder: [],
// // lockedPanels: [],
// // widgets: [],
// // },
// // Inventory: {
// // activeSides: [],
// // panelOrder: [],
// // lockedPanels: [],
// // widgets: [],
// // },
// // });
// const [zonesData, setZonesData] = useState<{
// _id: string;
// zoneName: string;
// zoneUUID: string;
// sceneID: string;
// }[]>([]);
// useEffect(() => {
// const fetchZoneData = async () => {
// try {
// // Send POST request to the server
// const response = await axios.get('http://192.168.0.102:2000/zone_sets/6656cbf555be4ff11327fd7f?organization=organization',
// // {
// // params: {
// // sceneId:"123456789"
// // }
// // }
// );
// // Check the response and show a success message if needed
// if (response.status === 200) {
// console.log('broker details responce:', response.data);
// setZonesData(response.data)
// } else {
// console.log('Unexpected response:', response);
// }
// } catch (error) {
// console.error('There was an error!', error);
// setZonesData([])
// }
// [key: string]: {
// activeSides: Side[];
// panelOrder: Side[];
// lockedPanels: Side[];
// widgets: Widget[];
// };
// fetchZoneData();
// }, []);
// }>({
// "Manufacturing unit": {
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// "Assembly unit": {
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// "Packing unit": {
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// Warehouse: {
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// Inventory: {
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// });
// const { isPlaying } = usePlayButtonStore();
@ -250,3 +101,150 @@ export default RealTimeVisulization;
// export default RealTimeVisulization;
import React, { useEffect, useState, useRef } from "react";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import Panel from "./Panel";
import AddButtons from "./AddButtons";
import { useSelectedZoneStore } from "../../../store/useZoneStore";
import DisplayZone from "./DisplayZone";
import axios from "axios";
type Side = "top" | "bottom" | "left" | "right";
interface Widget {
id: string;
type: string;
title: string;
panel: Side;
data: any;
}
const RealTimeVisulization: React.FC = () => {
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
const containerRef = useRef<HTMLDivElement>(null);
const [zonesData, setZonesData] = useState<{
_id: string;
zoneName: string;
zoneUUID: string;
sceneID: string;
}[]>([]);
// const [zonesData, setZonesData] = useState<{
// [key: string]: {
// zoneId: string;
// activeSides: Side[];
// panelOrder: Side[];
// lockedPanels: Side[];
// widgets: Widget[];
// };
// }>({
// "Manufacturing unit": {
// zoneId: "Manufacturing unit",
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// "Assembly unit": {
// zoneId: "Assembly unit",
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// "Packing unit": {
// zoneId: "Packing unit",
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// Warehouse: {
// zoneId: "Warehouse",
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// Inventory: {
// zoneId: "Inventory",
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// });
useEffect(() => {
const fetchZoneData = async () => {
try {
// Send POST request to the server
const response = await axios.get('http://192.168.0.192:4000/fetchzone',
// {
// params: {
// sceneId:"123456789"
// }
// }
);
// Check the response and show a success message if needed
if (response.status === 200) {
console.log('broker details responce:', response.data);
setZonesData(response.data)
} else {
console.log('Unexpected response:', response);
}
} catch (error) {
console.error('There was an error!', error);
setZonesData([])
}
};
fetchZoneData();
}, []);
const { isPlaying } = usePlayButtonStore();
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
// useEffect(() => {
// setZonesData((prev) => ({
// ...prev,
// [selectedZone.zoneName]: selectedZone,
// }));
// }, [selectedZone]);
return (
<div
ref={containerRef}
id="real-time-vis-canvas"
className="realTime-viz canvas"
style={{
height: isPlaying ? "100vh" : "",
width: isPlaying ? "100%" : "",
left: isPlaying ? "0%" : "",
}}
>
<DisplayZone
zonesData={zonesData}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
{!isPlaying && (
<AddButtons
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
)}
<Panel selectedZone={selectedZone} setSelectedZone={setSelectedZone} />
</div>
);
};
export default RealTimeVisulization;

View File

@ -41,7 +41,60 @@
// }));
// import { create } from "zustand";
// type Side = "top" | "bottom" | "left" | "right";
// interface Widget {
// id: string;
// type: string;
// title: string;
// panel: Side;
// data: any;
// }
// interface SelectedZoneState {
// zoneId: string;
// zoneName: string;
// activeSides: Side[];
// panelOrder: Side[];
// lockedPanels: Side[];
// widgets: Widget[];
// }
// interface SelectedZoneStore {
// selectedZone: SelectedZoneState;
// setSelectedZone: (zone: Partial<SelectedZoneState> | ((prev: SelectedZoneState) => SelectedZoneState)) => void;
// }
// export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
// selectedZone: {
// zoneId:"",
// zoneName: "",
// activeSides: [],
// panelOrder: [],
// lockedPanels: [],
// widgets: [],
// },
// setSelectedZone: (zone) =>
// set((state) => {
// const newState =
// typeof zone === "function"
// ? zone(state.selectedZone) // Handle functional updates
// : { ...state.selectedZone, ...zone }; // Handle partial updates
// console.log("Previous state:", state.selectedZone);
// console.log("Updated state:", newState);
// return { selectedZone: newState };
// }),
// }));
import { create } from "zustand";
import { io } from "socket.io-client";
const socket = io("http://192.168.0.192:4000");
type Side = "top" | "bottom" | "left" | "right";
@ -69,7 +122,7 @@ interface SelectedZoneStore {
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
selectedZone: {
zoneId:"",
zoneId: "",
zoneName: "",
activeSides: [],
panelOrder: [],
@ -80,12 +133,22 @@ export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
set((state) => {
const newState =
typeof zone === "function"
? zone(state.selectedZone) // Handle functional updates
: { ...state.selectedZone, ...zone }; // Handle partial updates
? zone(state.selectedZone)
: { ...state.selectedZone, ...zone };
console.log("Previous state:", state.selectedZone);
console.log("Updated state:", newState);
// Send updates to the backend
socket.emit("updateZone", newState);
return { selectedZone: newState };
}),
}));
// Listen for backend updates
// socket.on("zoneUpdated", (updatedZone: SelectedZoneState) => {
// console.log("Received update from server:", updatedZone);
// useSelectedZoneStore.setState({ selectedZone: updatedZone });
// });