diff --git a/app/package-lock.json b/app/package-lock.json index dbeaf5c..0abd22a 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -45,6 +45,7 @@ "devDependencies": { "@types/node": "^22.9.1", "@types/three": "^0.169.0", + "axios": "^1.8.4", "cypress": "^13.14.2", "dotenv": "^16.4.5", "husky": "^9.1.6", @@ -7599,6 +7600,25 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, "node_modules/axobject-query": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", diff --git a/app/package.json b/app/package.json index 39b8663..ba0ec79 100644 --- a/app/package.json +++ b/app/package.json @@ -67,6 +67,7 @@ "devDependencies": { "@types/node": "^22.9.1", "@types/three": "^0.169.0", + "axios": "^1.8.4", "cypress": "^13.14.2", "dotenv": "^16.4.5", "husky": "^9.1.6", diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index 9c18cd3..b37630b 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -37,9 +37,8 @@ const SideBarRight: React.FC = () => {
{/* {activeModule === "builder" && ( */}
setSubModule("properties")} > @@ -48,25 +47,22 @@ const SideBarRight: React.FC = () => { {activeModule === "simulation" && ( <>
setSubModule("mechanics")} >
setSubModule("simulations")} >
setSubModule("analysis")} > @@ -87,7 +83,17 @@ const SideBarRight: React.FC = () => {
)} - + {toggleUI && + subModule === "zoneProperties" && + activeModule === "builder" && ( +
+
+ {/* */} + + {/* */} +
+
+ )} {/* simulation */} {toggleUI && activeModule === "simulation" && ( diff --git a/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx b/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx index 05b7041..38fae4e 100644 --- a/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx +++ b/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx @@ -1,62 +1,57 @@ import React from "react"; import { EyeDroperIcon } from "../../../icons/ExportCommonIcons"; +// import { useThree } from "@react-three/fiber"; interface PositionInputProps { - onChange: (value: string) => void; // Callback for value change + onChange: (value: [number, number, number]) => void; // Callback for value change header: string; placeholder?: string; // Optional placeholder type?: string; // Input type (e.g., text, number, email) + value: [number, number, number] | null; + disabled?: boolean; // To enable/disable editing } const Vector3Input: React.FC = ({ onChange, header, placeholder = "Enter value", // Default placeholder - type = "number", // Default type + type = "string", // Default type + value, + disabled = false, // Default to disabled }) => { + + const handleChange = (index: number, newValue: string) => { + if (!value) return; + const updatedValue = [...value] as [number, number, number]; + updatedValue[index] = parseFloat(newValue) || 0; + console.log('updatedValue: ', updatedValue); + onChange(updatedValue); + }; + + + return (
- {header}{" "} -
- -
+ {header}
-
-
X :
- onChange(e.target.value)} - placeholder={placeholder} - disabled - /> -
-
-
Y :
- onChange(e.target.value)} - placeholder={placeholder} - disabled - min={0} - /> -
-
-
Z :
- onChange(e.target.value)} - placeholder={placeholder} - disabled - /> -
+ {["X", "Y", "Z"].map((axis, i) => ( +
+
{axis}:
+ handleChange(i, e.target.value)} + placeholder={placeholder} + disabled={disabled} + /> +
+ ))}
); }; -export default Vector3Input; +export default Vector3Input; \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx index 65dd55f..c707f14 100644 --- a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx @@ -1,32 +1,65 @@ -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import RenameInput from "../../../ui/inputs/RenameInput"; import Vector3Input from "../customInput/Vector3Input"; +import { useSelectedZoneStore } from "../../../../store/useZoneStore"; +import { useEditPosition, usezonePosition, usezoneTarget } from "../../../../store/store"; const ZoneProperties: React.FC = () => { - const [Edit, setEdit] = useState(false); + const { Edit, setEdit } = useEditPosition(); + const { selectedZone, setSelectedZone } = useSelectedZoneStore(); + const { zonePosition, setZonePosition } = usezonePosition(); + const { zoneTarget, setZoneTarget } = usezoneTarget(); + + useEffect(() => { + setZonePosition(selectedZone.zoneViewPortPosition) + setZoneTarget(selectedZone.zoneViewPortTarget) + }, [selectedZone?.zoneViewPortPosition, selectedZone?.zoneViewPortTarget]) function handleSetView() { + console.log("setApi"); + + console.log('zoneTarget: ', zoneTarget); + console.log('zonePosition: ', zonePosition); setEdit(false); } function handleEditView() { - if (Edit) { - setEdit(false); - } else { - setEdit(true); - } + setEdit(!Edit); // This will toggle the `Edit` state correctly } + function handleZoneNameChange(newName: string) { + setSelectedZone((prev) => ({ ...prev, zoneName: newName })); + } + + function handleVectorChange(key: "zoneViewPortTarget" | "zoneViewPortPosition", newValue: [number, number, number]) { + setSelectedZone((prev) => ({ ...prev, [key]: newValue })); + } + + useEffect(() => { + console.log("Updated selectedZone: ", selectedZone); + }, [selectedZone]); + return (
- +
{Edit ? "Cancel" : "Edit"}
- {}} header="Viewport Target" /> - {}} header="Viewport Position" /> + handleVectorChange("zoneViewPortTarget", value)} + header="Viewport Target" + value={zoneTarget as [number, number, number]} + disabled={!Edit} + /> + handleVectorChange("zoneViewPortPosition", value)} + header="Viewport Position" + value={zonePosition as [number, number, number]} + disabled={!Edit} + /> + {Edit && (
Set View @@ -37,3 +70,4 @@ const ZoneProperties: React.FC = () => { }; export default ZoneProperties; + diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx new file mode 100644 index 0000000..c223c67 --- /dev/null +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/LineGrapInput.tsx @@ -0,0 +1,115 @@ +import React, { useEffect, useState } from 'react' +import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown' +import { AddIcon } from '../../../../icons/ExportCommonIcons' +import RegularDropDown from '../../../../ui/inputs/RegularDropDown' +import useChartStore from '../../../../../store/useChartStore' +import axios from 'axios' + +type Props = {} + +const LineGrapInput = (props: Props) => { + const [dropDowndata, setDropDownData] = useState({}) + const [selections, setSelections] = useState>({}) + const [selectedOption, setSelectedOption] = useState('1h') + const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); + + const handleSelectDuration = (option: string) => { + updateDuration(option); // Normalize for key matching + }; + + useEffect(() => { + const fetchZoneData = async () => { + try { + const response = await axios.get('http://192.168.0.192:5010/getinput'); + if (response.status === 200) { + console.log('dropdown data:', response.data); + setDropDownData(response.data) + } else { + console.log('Unexpected response:', response); + } + } catch (error) { + console.error('There was an error!', error); + } + }; + fetchZoneData(); + }, []); + + useEffect(() => { + console.log(selections); + }, [selections]) + + const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => { + setSelections(prev => { + if (selectedData === null) { + const newSelections = { ...prev }; + delete newSelections[inputKey]; + return newSelections; + } else { + return { + ...prev, + [inputKey]: selectedData + }; + } + }); + }; + + interface Measurement { + name: string; + fields: string; + } + + interface InputData { + [key: string]: Measurement; + } + + const extractMeasurements = (input: InputData): Measurement[] => { + return Object.values(input); + }; + + useEffect(() => { + const measurementsData = extractMeasurements(selections); + setMeasurements(measurementsData); + }, [selections]); + + + return ( + <> +
+ {[...Array(6)].map((_, index) => { + const inputKey = `input${index + 1}`; + return ( +
+
Input {index + 1}
+
+ handleSelect(inputKey, selectedData)} + onUnselect={() => handleSelect(inputKey, null)} + selectedValue={selections[inputKey]} + /> +
+ +
+
+
+ ); + })} +
+
+
+
duration
+
+ +
+
+
+ + ) +} + +export default LineGrapInput \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx new file mode 100644 index 0000000..5b056a5 --- /dev/null +++ b/app/src/components/layout/sidebarRight/visualization/IotInputCards/PieChartInput.tsx @@ -0,0 +1,77 @@ +import React, { useEffect, useState } from 'react' +import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown' +import { AddIcon } from '../../../../icons/ExportCommonIcons' +import axios from 'axios' + +type Props = {} + +const PieChartInput = (props: Props) => { + const [dropDowndata, setDropDownData] = useState({}) + const [selections, setSelections] = useState>({}) + + useEffect(() => { + const fetchZoneData = async () => { + try { + const response = await axios.get('http://192.168.0.192:5010/getinput'); + if (response.status === 200) { + console.log('dropdown data:', response.data); + setDropDownData(response.data) + } else { + console.log('Unexpected response:', response); + } + } catch (error) { + console.error('There was an error!', error); + } + }; + fetchZoneData(); + }, []); + + useEffect(() => {console.log(selections); + },[selections]) + + const handleSelect = (inputKey: string, selectedData: {name: string, fields: string} | null) => { + setSelections(prev => { + if (selectedData === null) { + const newSelections = {...prev}; + delete newSelections[inputKey]; + return newSelections; + } else { + return { + ...prev, + [inputKey]: selectedData + }; + } + }); + }; + + return ( + <> +
+ {[...Array(3)].map((_, index) => { + const inputKey = `input${index+1}`; + return ( +
+
Input {index+1}
+
+ handleSelect(inputKey, selectedData)} + onUnselect={() => handleSelect(inputKey, null)} + selectedValue={selections[inputKey]} + /> +
+ +
+
+
+ ); + })} +
+
+ +
+ + ) +} + +export default PieChartInput \ No newline at end of file diff --git a/app/src/components/layout/sidebarRight/visualization/data/Data.tsx b/app/src/components/layout/sidebarRight/visualization/data/Data.tsx index 039ad1e..71847c7 100644 --- a/app/src/components/layout/sidebarRight/visualization/data/Data.tsx +++ b/app/src/components/layout/sidebarRight/visualization/data/Data.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import { useWidgetStore } from "../../../../../store/useWidgetStore"; import { AddIcon, RemoveIcon } from "../../../../icons/ExportCommonIcons"; import MultiLevelDropDown from "../../../../ui/inputs/MultiLevelDropDown"; +import LineGrapInput from "../IotInputCards/LineGrapInput"; // Define the data structure for demonstration purposes const DATA_STRUCTURE = { @@ -123,41 +124,10 @@ const Data = () => {
{selectedChartId?.title}
)} {/* Render groups dynamically */} - {chartDataGroups[selectedChartId?.id]?.map((group) => ( -
- {group.children.map((child, index) => ( -
-
Input {index + 1}
-
- - {/* Add Icon */} - {group.children.length < 7 && ( -
handleAddClick(group.id)} // Pass groupId to handleAddClick - > - -
- )} - {/* Remove Icon */} - - 1 ? "" : "disable" - }`} - onClick={(e) => { - e.stopPropagation(); // Prevent event bubbling - removeChild(group.id, child.id); // Pass groupId and childId to removeChild - }} - > - - -
-
- ))} -
- ))} - + { + chartDataGroups[selectedChartId?.id] && + } + {/* Info Box */}
i @@ -173,3 +143,40 @@ const Data = () => { }; export default Data; + + + +// {chartDataGroups[selectedChartId?.id]?.map((group) => ( +//
+// {group.children.map((child, index) => ( +//
+//
Input {index + 1}
+//
+// +// {/* Add Icon */} +// {group.children.length < 7 && ( +//
handleAddClick(group.id)} // Pass groupId to handleAddClick +// > +// +//
+// )} +// {/* Remove Icon */} + +// 1 ? "" : "disable" +// }`} +// onClick={(e) => { +// e.stopPropagation(); // Prevent event bubbling +// removeChild(group.id, child.id); // Pass groupId and childId to removeChild +// }} +// > +// +// +//
+//
+// ))} +//
+// ))} diff --git a/app/src/components/ui/componets/AddButtons.tsx b/app/src/components/ui/componets/AddButtons.tsx index 5943d6a..7185fc6 100644 --- a/app/src/components/ui/componets/AddButtons.tsx +++ b/app/src/components/ui/componets/AddButtons.tsx @@ -4,6 +4,7 @@ import { EyeIcon, LockIcon, } from "../../icons/RealTimeVisulationIcons"; +import { panelData } from "../../../services/realTimeVisulization/zoneData/panel"; import { AddIcon } from "../../icons/ExportCommonIcons"; // Define the type for `Side` @@ -16,6 +17,9 @@ interface ButtonsProps { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; + zoneId: string; + zoneViewPortTarget: number[]; + zoneViewPortPosition: number[]; widgets: { id: string; type: string; @@ -30,6 +34,9 @@ interface ButtonsProps { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; + zoneId: string; + zoneViewPortTarget: number[]; + zoneViewPortPosition: number[]; widgets: { id: string; type: string; @@ -109,7 +116,7 @@ const AddButtons: React.FC = ({ panelOrder: newActiveSides, }; - // Update the selectedZone state + // Delete the selectedZone state console.log("updatedZone: ", updatedZone); setSelectedZone(updatedZone); } else { @@ -121,6 +128,10 @@ const AddButtons: React.FC = ({ activeSides: newActiveSides, panelOrder: newActiveSides, }; + const email = localStorage.getItem("email"); + const organization = email!.split("@")[1].split(".")[0]; + // let response = panelData(organization, selectedZone.zoneId, newActiveSides) + // console.log('response: ', response); // Update the selectedZone state console.log("updatedZone: ", updatedZone); @@ -129,77 +140,80 @@ const AddButtons: React.FC = ({ }; return ( -
- {(["top", "right", "bottom", "left"] as Side[]).map((side) => ( -
- - - {/* Extra Buttons */} - {selectedZone.activeSides.includes(side) && ( -
- {/* Hide Panel */} -
toggleVisibility(side)} - > - + <> +
+ {(["top", "right", "bottom", "left"] as Side[]).map((side) => ( +
+ {/* "+" Button */} + - {/* Clean Panel */} -
cleanPanel(side)} - > - -
- - {/* Lock/Unlock Panel */} -
toggleLockPanel(side)} - > - + {/* Hide Panel */} +
+ onClick={() => toggleVisibility(side)} + > + +
+ + {/* Clean Panel */} +
cleanPanel(side)} + > + +
+ + {/* Lock/Unlock Panel */} +
toggleLockPanel(side)} + > + +
-
- )} -
- ))} -
+ )} +
+ ))} +
+ ); }; diff --git a/app/src/components/ui/componets/DisplayZone.tsx b/app/src/components/ui/componets/DisplayZone.tsx index a84c30c..9f1028f 100644 --- a/app/src/components/ui/componets/DisplayZone.tsx +++ b/app/src/components/ui/componets/DisplayZone.tsx @@ -12,6 +12,9 @@ interface DisplayZoneProps { panelOrder: Side[]; lockedPanels: Side[]; widgets: Widget[]; + zoneId: string; + zoneViewPortTarget: number[]; + zoneViewPortPosition: number[]; }; }; selectedZone: { @@ -19,6 +22,9 @@ interface DisplayZoneProps { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; + zoneId: string; + zoneViewPortTarget: number[]; + zoneViewPortPosition: number[]; widgets: { id: string; type: string; @@ -33,6 +39,9 @@ interface DisplayZoneProps { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; + zoneId: string; + zoneViewPortTarget: number[]; + zoneViewPortPosition: number[]; widgets: { id: string; type: string; @@ -66,10 +75,6 @@ const DisplayZone: React.FC = ({ const canScrollRight = container.scrollLeft + container.clientWidth < container.scrollWidth; - console.log("isOverflowing:", isOverflowing); - console.log("canScrollLeft:", canScrollLeft); - console.log("canScrollRight:", canScrollRight); - setShowLeftArrow(isOverflowing && canScrollLeft); setShowRightArrow(isOverflowing && canScrollRight); } @@ -135,11 +140,7 @@ const DisplayZone: React.FC = ({ }; return ( -
+
{/* Left Arrow */} {showLeftArrow && ( + +// {/* Dropdown Menu */} +// {open && ( +//
+//
+// {renderNestedData(data, handleSelect)} +//
+//
+// )} +//
+// ); +// }; + +// export default MultiLevelDropdown; + import React, { useState, useRef, useEffect } from "react"; +import { ArrowIcon } from "../../icons/ExportCommonIcons"; // Dropdown Item Component const DropdownItem = ({ label, - href, onClick, }: { label: string; - href?: string; - onClick?: () => void; + onClick: () => void; }) => ( - { - e.preventDefault(); - onClick?.(); - }} - > + ); // Nested Dropdown Component const NestedDropdown = ({ label, - children, + fields, onSelect, }: { label: string; - children: React.ReactNode; - onSelect: (selectedLabel: string) => void; + fields: string[]; + onSelect: (selectedData: { name: string; fields: string }) => void; }) => { const [open, setOpen] = useState(false); return (
- {/* Dropdown Trigger */}
setOpen(!open)} // Toggle submenu on click + onClick={() => setOpen(!open)} > - {label} {open ? "▼" : "▶"} + {label} +
+ +
- - {/* Submenu */} {open && (
- {React.Children.map(children, (child) => { - if (React.isValidElement(child)) { - // Clone the element and pass the `onSelect` prop only if it's expected - return React.cloneElement(child as React.ReactElement, { onSelect }); - } - return child; // Return non-element children as-is - })} + {fields.map((field) => ( + onSelect({ name: label, fields: field })} + /> + ))}
)}
); }; -// Recursive Function to Render Nested Data -const renderNestedData = ( - data: Record, - onSelect: (selectedLabel: string) => void -) => { - return Object.entries(data).map(([key, value]) => { - if (typeof value === "object" && !Array.isArray(value)) { - // If the value is an object, render it as a nested dropdown - return ( - - {renderNestedData(value, onSelect)} - - ); - } else if (Array.isArray(value)) { - // If the value is an array, render each item as a dropdown item - return value.map((item, index) => ( - onSelect(item)} /> - )); - } else { - // If the value is a simple string, render it as a dropdown item - return ( - onSelect(value)} /> - ); - } - }); -}; +// Props type for MultiLevelDropdown +interface MultiLevelDropdownProps { + data: Record; + onSelect: (selectedData: { name: string; fields: string }) => void; + onUnselect: () => void; + selectedValue?: { name: string; fields: string }; +} // Main Multi-Level Dropdown Component -const MultiLevelDropdown = ({ data }: { data: Record }) => { +const MultiLevelDropdown = ({ + data, + onSelect, + onUnselect, + selectedValue, +}: MultiLevelDropdownProps) => { const [open, setOpen] = useState(false); - const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger"); const dropdownRef = useRef(null); - // Handle outer click to close the dropdown useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if ( @@ -103,34 +224,51 @@ const MultiLevelDropdown = ({ data }: { data: Record }) => { setOpen(false); } }; - document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, []); - // Handle selection of an item - const handleSelect = (selectedLabel: string) => { - setSelectedLabel(selectedLabel); // Update the dropdown trigger text - setOpen(false); // Close the dropdown + // Handle item selection + const handleItemSelect = (selectedData: { name: string; fields: string }) => { + onSelect(selectedData); + setOpen(false); }; + // Handle unselect + const handleItemUnselect = () => { + onUnselect(); + setOpen(false); + }; + + // Determine the display label + const displayLabel = selectedValue + ? `${selectedValue.name} - ${selectedValue.fields}` + : "Dropdown trigger"; + return (
- {/* Dropdown Trigger Button */} - - {/* Dropdown Menu */} {open && (
- {renderNestedData(data, handleSelect)} + {/* Unselect Option */} + + {/* Nested Dropdown Items */} + {Object.entries(data).map(([key, value]) => ( + + ))}
)} @@ -138,4 +276,4 @@ const MultiLevelDropdown = ({ data }: { data: Record }) => { ); }; -export default MultiLevelDropdown; \ No newline at end of file +export default MultiLevelDropdown; diff --git a/app/src/components/ui/inputs/RenameInput.tsx b/app/src/components/ui/inputs/RenameInput.tsx index cae54f3..d197dd4 100644 --- a/app/src/components/ui/inputs/RenameInput.tsx +++ b/app/src/components/ui/inputs/RenameInput.tsx @@ -1,4 +1,4 @@ -import React, { useState, useRef } from "react"; +import React, { useState, useRef, useEffect } from "react"; interface RenameInputProps { value: string; @@ -9,6 +9,9 @@ const RenameInput: React.FC = ({ value, onRename }) => { const [isEditing, setIsEditing] = useState(false); const [text, setText] = useState(value); const inputRef = useRef(null); + useEffect(() => { + setText(value); // Ensure state updates when parent value changes + }, [value]); const handleDoubleClick = () => { setIsEditing(true); diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx index d6c35a9..4ff51ca 100644 --- a/app/src/components/ui/list/DropDownList.tsx +++ b/app/src/components/ui/list/DropDownList.tsx @@ -2,7 +2,8 @@ import React, { useEffect, useState } from "react"; import List from "./List"; import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons"; import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect"; -import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones"; +import { useZones } from "../../../store/store"; +import { useSelectedZoneStore } from "../../../store/useZoneStore"; interface DropDownListProps { value?: string; // Value to display in the DropDownList @@ -31,27 +32,23 @@ const DropDownList: React.FC = ({ listType = "default", remove, }) => { + const [isOpen, setIsOpen] = useState(defaultOpen); + const { zones, setZones } = useZones() const handleToggle = () => { setIsOpen((prev) => !prev); // Toggle the state }; - const [zoneDataList, setZoneDataList] = useState< - { id: string; name: string }[] - >([]); + const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]); + const { selectedZone, setSelectedZone } = useSelectedZoneStore(); useEffect(() => { - async function GetZoneData() { - const response = await getZonesApi("hexrfactory"); - console.log("response: ", response.data); - setZoneDataList([ - { id: "1", name: "zone1" }, - { id: "2", name: "Zone 2" }, - ]); - } - - GetZoneData(); - }, []); + const value = (zones || []).map((val: { zoneId: string; zoneName: string }) => ({ + id: val.zoneId, + name: val.zoneName + })); + setZoneDataList(prev => (JSON.stringify(prev) !== JSON.stringify(value) ? value : prev)); + }, [zones]); return (
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 54b710d..7a7da8d 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -1,6 +1,9 @@ import React from "react"; import RenameInput from "../inputs/RenameInput"; import { EyeIcon, LockIcon, RmoveIcon } from "../../icons/ExportCommonIcons"; +import { useSelectedZoneStore } from "../../../store/useZoneStore"; +import { getZoneData } from "../../../services/realTimeVisulization/zoneData/getZones"; +import { useSubModuleStore } from "../../../store/useModuleStore"; interface ListProps { items?: { id: string; name: string }[]; // Optional array of items to render @@ -9,6 +12,27 @@ interface ListProps { } const List: React.FC = ({ items = [], remove }) => { + const { setSelectedZone } = useSelectedZoneStore(); + const { setSubModule } = useSubModuleStore(); + + async function handleSelectZone(id: string) { + setSubModule("zoneProperties") + const email = localStorage.getItem('email') + const organization = (email!.split("@")[1]).split(".")[0]; + let response = await getZoneData(id, organization) + setSelectedZone({ + zoneName: response?.zoneName, + activeSides: response?.activeSides || [], + panelOrder: response?.panelOrder || [], + lockedPanels: response?.lockedPanels || [], + widgets: response?.widgets || [], + zoneId: response?.zoneId, + zoneViewPortTarget: response?.viewPortCenter || [], + zoneViewPortPosition: + response?.viewPortposition || [], + }); + + } return ( <> {items.length > 0 ? ( @@ -16,7 +40,7 @@ const List: React.FC = ({ items = [], remove }) => { {items.map((item, index) => (
  • -
    +
    handleSelectZone(item.id)}>
    diff --git a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx index 5911842..07a387f 100644 --- a/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx +++ b/app/src/components/ui/realTimeVis/charts/LineGraphComponent.tsx @@ -1,5 +1,107 @@ -import { useMemo } from "react"; -import { Line } from "react-chartjs-2"; +// import { useMemo } from "react"; +// import { Line } from "react-chartjs-2"; + +// interface ChartComponentProps { +// type: any; +// title: string; +// fontFamily?: string; +// fontSize?: string; +// fontWeight?: "Light" | "Regular" | "Bold"; +// data: any; +// } + +// const LineGraphComponent = ({ +// title, +// fontFamily, +// fontSize, +// fontWeight = "Regular", +// }: ChartComponentProps) => { +// // Memoize Font Weight Mapping +// const chartFontWeightMap = useMemo( +// () => ({ +// Light: "lighter" as const, +// Regular: "normal" as const, +// Bold: "bold" as const, +// }), +// [] +// ); + +// // Parse and Memoize Font Size +// const fontSizeValue = useMemo( +// () => (fontSize ? parseInt(fontSize) : 12), +// [fontSize] +// ); + +// // Determine and Memoize Font Weight +// const fontWeightValue = useMemo( +// () => chartFontWeightMap[fontWeight], +// [fontWeight, chartFontWeightMap] +// ); + +// // Memoize Chart Font Style +// const chartFontStyle = useMemo( +// () => ({ +// family: fontFamily || "Arial", +// size: fontSizeValue, +// weight: fontWeightValue, +// }), +// [fontFamily, fontSizeValue, fontWeightValue] +// ); + +// const options = useMemo( +// () => ({ +// responsive: true, +// maintainAspectRatio: false, +// plugins: { +// title: { +// display: true, +// text: title, +// font: chartFontStyle, +// }, +// legend: { +// display: false, +// }, +// }, +// scales: { +// x: { +// ticks: { +// display: true, // This hides the x-axis labels +// }, +// }, +// }, +// }), +// [title, chartFontStyle] +// ); + +// const chartData = { +// labels: ["January", "February", "March", "April", "May", "June", "July"], +// datasets: [ +// { +// label: "My First Dataset", +// data: [65, 59, 80, 81, 56, 55, 40], +// backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple) +// borderColor: "#ffffff", // Keeping border color white +// borderWidth: 2, +// fill: false, +// }, +// ], +// }; + +// return ; +// }; + +// export default LineGraphComponent; + + +import React, { useEffect, useRef, useMemo, useState } from "react"; +import { Chart } from "chart.js/auto"; +import { useThemeStore } from "../../../../store/useThemeStore"; +import io from "socket.io-client"; +import { Line } from 'react-chartjs-2'; +import useChartStore from "../../../../store/useChartStore"; + +// WebSocket Connection +// const socket = io("http://localhost:5000"); // Adjust to your backend URL interface ChartComponentProps { type: any; @@ -11,86 +113,153 @@ interface ChartComponentProps { } const LineGraphComponent = ({ + type, title, fontFamily, fontSize, fontWeight = "Regular", + data, }: ChartComponentProps) => { - // Memoize Font Weight Mapping - const chartFontWeightMap = useMemo( - () => ({ - Light: "lighter" as const, - Regular: "normal" as const, - Bold: "bold" as const, - }), - [] - ); + const canvasRef = useRef(null); + const { themeColor } = useThemeStore(); + const [chartData, setChartData] = useState<{ labels: string[]; datasets: any[] }>({ + labels: [], + datasets: [], + }); - // Parse and Memoize Font Size - const fontSizeValue = useMemo( - () => (fontSize ? parseInt(fontSize) : 12), - [fontSize] - ); - - // Determine and Memoize Font Weight - const fontWeightValue = useMemo( - () => chartFontWeightMap[fontWeight], - [fontWeight, chartFontWeightMap] - ); - - // Memoize Chart Font Style - const chartFontStyle = useMemo( - () => ({ - family: fontFamily || "Arial", - size: fontSizeValue, - weight: fontWeightValue, - }), - [fontFamily, fontSizeValue, fontWeightValue] - ); - - const options = useMemo( - () => ({ - responsive: true, - maintainAspectRatio: false, - plugins: { - title: { - display: true, - text: title, - font: chartFontStyle, - }, - legend: { - display: false, - }, - }, - scales: { - x: { - ticks: { - display: true, // This hides the x-axis labels + // Memoize Theme Colors to Prevent Unnecessary Recalculations + const buttonActionColor = useMemo( + () => themeColor[0] || "#5c87df", + [themeColor] + ); + const buttonAbortColor = useMemo( + () => themeColor[1] || "#ffffff", + [themeColor] + ); + + // Memoize Font Weight Mapping + const chartFontWeightMap = useMemo( + () => ({ + Light: "lighter" as const, + Regular: "normal" as const, + Bold: "bold" as const, + }), + [] + ); + + // Parse and Memoize Font Size + const fontSizeValue = useMemo( + () => (fontSize ? parseInt(fontSize) : 12), + [fontSize] + ); + + // Determine and Memoize Font Weight + const fontWeightValue = useMemo( + () => chartFontWeightMap[fontWeight], + [fontWeight, chartFontWeightMap] + ); + + // Memoize Chart Font Style + const chartFontStyle = useMemo( + () => ({ + family: fontFamily || "Arial", + size: fontSizeValue, + weight: fontWeightValue, + }), + [fontFamily, fontSizeValue, fontWeightValue] + ); + + // Memoize Chart Data + // const data = useMemo(() => propsData, [propsData]); + + // Memoize Chart Options + const options = useMemo( + () => ({ + responsive: true, + maintainAspectRatio: false, + plugins: { + title: { + display: true, + text: title, + font: chartFontStyle, + }, + legend: { + display: false, }, }, - }, - }), - [title, chartFontStyle] - ); + scales: { + x: { + ticks: { + display: true, // This hides the x-axis labels + }, + }, + }, + }), + [title, chartFontStyle] + ); - const chartData = { - labels: ["January", "February", "March", "April", "May", "June", "July"], - datasets: [ - { - label: "My First Dataset", - data: [65, 59, 80, 81, 56, 55, 40], - backgroundColor: "#6f42c1", // Updated to #6f42c1 (Purple) - borderColor: "#ffffff", // Keeping border color white + const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); + + useEffect(() => { + if ( measurements.length > 0 ) { + const socket = io("http://192.168.0.192:5010"); + + var inputes = { + measurements: measurements, + duration: duration, + interval: 1000, + } + + console.log('graphHHHHHHHHHHHHHHHHHHHHHHHHHHHHH',inputes); + + + // Start stream + const startStream = () => { + socket.emit("lineInput", inputes); + } + + socket.on('connect', startStream); + + socket.on("lineOutput", (response) => { + const responceData = response.data; + console.log("Received data:", responceData); + + // Extract timestamps and values + const labels = responceData.time; + const datasets = data.measurements.map((measurement: any) => ({ + label: `${measurement.name}.${measurement.fields}`, + data: responceData[`${measurement.name}.${measurement.fields}`]?.values || [], + backgroundColor: themeColor[0] || "#5c87df", + borderColor: themeColor[1] || "#ffffff", borderWidth: 2, - fill: false, - }, - ], - }; + // fill: false, + })); + + setChartData({ labels, datasets }); + }); + + return () => { + socket.off("lineOutput"); + socket.emit("stop_stream"); // Stop streaming when component unmounts + }; + } + }, [measurements, duration]); + + // useEffect(() => { + // if (!canvasRef.current) return; + // const ctx = canvasRef.current.getContext("2d"); + // if (!ctx) return; + + // const chart = new Chart(ctx, { + // type, + // data: chartData, + // options: options, + // }); + + // return () => chart.destroy(); + // }, [chartData, type, title]); return ; }; -export default LineGraphComponent; - - -// like this \ No newline at end of file +export default LineGraphComponent; \ No newline at end of file diff --git a/app/src/components/ui/realTimeVis/floating/SimpleCard.tsx b/app/src/components/ui/realTimeVis/floating/SimpleCard.tsx index d67e87f..ef3d85c 100644 --- a/app/src/components/ui/realTimeVis/floating/SimpleCard.tsx +++ b/app/src/components/ui/realTimeVis/floating/SimpleCard.tsx @@ -13,8 +13,22 @@ const SimpleCard: React.FC = ({ value, per, }) => { + + const handleDragStart = (event: React.DragEvent) => { + const cardData = JSON.stringify({ + header, + value, + per, + className: event.currentTarget.className, + }); + + console.log("Dragging Data:", cardData); // ✅ Debugging log + + event.dataTransfer.setData("text/plain", cardData); + }; + return ( -
    +
    {header}
    diff --git a/app/src/modules/builder/geomentries/assets/assetManager.ts b/app/src/modules/builder/geomentries/assets/assetManager.ts index f083395..38d0721 100644 --- a/app/src/modules/builder/geomentries/assets/assetManager.ts +++ b/app/src/modules/builder/geomentries/assets/assetManager.ts @@ -112,7 +112,7 @@ export default async function assetManager( ) { if (!activePromises.get(taskId)) return; // Stop processing if task is canceled - const existingModel = itemsGroup.current.getObjectByProperty("uuid", item.modeluuid); + const existingModel = itemsGroup?.current?.getObjectByProperty("uuid", item.modeluuid); if (existingModel) { // console.log(`Model ${item.modelname} already exists in the scene.`); resolve(); diff --git a/app/src/modules/builder/groups/zoneGroup.tsx b/app/src/modules/builder/groups/zoneGroup.tsx index 9e0bc15..3d47a7e 100644 --- a/app/src/modules/builder/groups/zoneGroup.tsx +++ b/app/src/modules/builder/groups/zoneGroup.tsx @@ -65,6 +65,8 @@ const ZoneGroup: React.FC = () => { zoneId: zone.zoneId, zoneName: zone.zoneName, points: zone.points, + viewPortCenter: zone.viewPortCenter, + viewPortposition: zone.viewPortposition, layer: zone.layer })); @@ -145,7 +147,7 @@ const ZoneGroup: React.FC = () => { const target: [number, number, number] | null = calculateCenter(zone.points); if (!target) return; - const position = [target[0], 75, target[2]]; + const position = [target[0], 10, target[2]]; const input = { userId: userId, @@ -186,7 +188,7 @@ const ZoneGroup: React.FC = () => { const target: [number, number, number] | null = calculateCenter(zone.points); if (!target) return; - const position = [target[0], 75, target[2]]; + const position = [target[0], 10, target[2]]; const input = { userId: userId, diff --git a/app/src/modules/collaboration/socketResponses.dev.tsx b/app/src/modules/collaboration/socketResponses.dev.tsx index e9ca9e0..031629f 100644 --- a/app/src/modules/collaboration/socketResponses.dev.tsx +++ b/app/src/modules/collaboration/socketResponses.dev.tsx @@ -745,6 +745,7 @@ export default function SocketResponses({ return } if (data.message === "zone deleted") { + console.log('data: ', data); const updatedZones = zones.filter((zone: any) => zone.zoneId !== data.data.zoneId); setZones(updatedZones); diff --git a/app/src/modules/market/AssetPreview.tsx b/app/src/modules/market/AssetPreview.tsx index a3c1cb0..be474a2 100644 --- a/app/src/modules/market/AssetPreview.tsx +++ b/app/src/modules/market/AssetPreview.tsx @@ -37,6 +37,7 @@ const AssetPreview: React.FC = ({
    + {/* Add canvas here */}
    diff --git a/app/src/modules/market/Card.tsx b/app/src/modules/market/Card.tsx index d0596a5..646fe39 100644 --- a/app/src/modules/market/Card.tsx +++ b/app/src/modules/market/Card.tsx @@ -1,4 +1,3 @@ -// Card.tsx import React from "react"; import { CommentsIcon, diff --git a/app/src/modules/market/FilterSearch.tsx b/app/src/modules/market/FilterSearch.tsx index 163eed3..11a2cbf 100644 --- a/app/src/modules/market/FilterSearch.tsx +++ b/app/src/modules/market/FilterSearch.tsx @@ -13,12 +13,10 @@ const FilterSearch: React.FC = () => { }; return (
    -
    - {}} /> -
    + {}} /> diff --git a/app/src/modules/market/MarketPlace.tsx b/app/src/modules/market/MarketPlace.tsx index 71dc0a5..a68bfc3 100644 --- a/app/src/modules/market/MarketPlace.tsx +++ b/app/src/modules/market/MarketPlace.tsx @@ -1,18 +1,18 @@ -import React from "react"; -import FilterSearch from "./FilterSearch"; -import CardsContainer from "./CardsContainer"; - -const MarketPlace = () => { - return ( -
    -
    -
    - - -
    -
    -
    - ); -}; - -export default MarketPlace; +import React from "react"; +import FilterSearch from "./FilterSearch"; +import CardsContainer from "./CardsContainer"; + +const MarketPlace = () => { + return ( +
    +
    +
    + + +
    +
    +
    + ); +}; + +export default MarketPlace; diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 3aaff94..0b8987f 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -1,4 +1,4 @@ -import { useMemo } from "react"; +import { useMemo, useState } from "react"; import { Canvas } from "@react-three/fiber"; import { Environment, KeyboardControls } from "@react-three/drei"; @@ -15,6 +15,12 @@ import background from "../../assets/textures/hdr/mudroadpuresky2k.hdr"; import SelectionControls from "./controls/selection/selectionControls"; import MeasurementTool from "./tools/measurementTool"; import Simulation from "../simulation/simulation"; +import ZoneCentreTarget from "../../components/ui/componets/zoneCameraTarget"; + +import { useThree } from "@react-three/fiber"; +import * as THREE from "three"; +import DroppedObjects from "../../components/ui/componets/DroppedFloatingWidgets"; + // import Simulation from "./simulationtemp/simulation"; export default function Scene() { @@ -27,6 +33,9 @@ export default function Scene() { // { name: "jump", keys: ["Space"] }, ], []) + + + return ( { e.preventDefault(); }} + > + + {/* */} diff --git a/app/src/services/realTimeVisulization/zoneData/getZones.ts b/app/src/services/realTimeVisulization/zoneData/getZones.ts index b5e8147..39031d8 100644 --- a/app/src/services/realTimeVisulization/zoneData/getZones.ts +++ b/app/src/services/realTimeVisulization/zoneData/getZones.ts @@ -1,25 +1,23 @@ -let url_Backend_dwinzo = `http://185.100.212.76:5000`; +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const getZonesApi = async (organization: string) => { - try { - const response = await fetch(`${url_Backend_dwinzo}/api/v2/findZones/${organization}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }); +export const getZoneData = async (zoneId: string, organization: string) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v2/A_zone/${zoneId}/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); - // if (!response.ok) { - // throw new Error("Failed to get Zones"); - // } - - const result = await response.json(); - return result; - } catch (error) { - if (error instanceof Error) { - throw new Error(error.message); - } else { - throw new Error("An unknown error occurred"); - } + if (!response.ok) { + throw new Error("Failed to fetch zoneData"); } -}; \ No newline at end of file + + return await response.json(); + } catch (error: any) { + throw new Error(error.message); + } +}; diff --git a/app/src/services/realTimeVisulization/zoneData/panel.ts b/app/src/services/realTimeVisulization/zoneData/panel.ts new file mode 100644 index 0000000..5e0b5ac --- /dev/null +++ b/app/src/services/realTimeVisulization/zoneData/panel.ts @@ -0,0 +1,31 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_BACKEND_URL}`; + +type Side = "top" | "bottom" | "left" | "right"; + +export const panelData = async (organization: string, zoneID: string, panelOrder: Side[]) => { + console.log('panelOrder: ', panelOrder); + console.log('zoneID: ', zoneID); + console.log('organization: ', organization); + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/panel/save`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ organization, zoneID, panelOrder }), + }); + + if (!response.ok) { + throw new Error("Failed to add panelOrder for Zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; \ No newline at end of file diff --git a/app/src/store/store.ts b/app/src/store/store.ts index 0cca1fe..86c6dee 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -1,324 +1,344 @@ import * as THREE from "three"; -import * as Types from '../types/world/worldTypes'; +import * as Types from "../types/world/worldTypes"; import { create } from "zustand"; import { io } from "socket.io-client"; export const useSocketStore = create((set: any, get: any) => ({ - socket: null, - initializeSocket: (email: any) => { - const existingSocket = get().socket; - if (existingSocket) { - return; - } - - const socket = io(`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`, { - reconnection: false, - auth: { email } - }); - - set({ socket }); - }, - disconnectSocket: () => { - set((state: any) => { - state.socket?.disconnect(); - return { socket: null }; - }); + socket: null, + initializeSocket: (email: any) => { + const existingSocket = get().socket; + if (existingSocket) { + return; } + + const socket = io( + `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/`, + { + reconnection: false, + auth: { email }, + } + ); + + set({ socket }); + }, + disconnectSocket: () => { + set((state: any) => { + state.socket?.disconnect(); + return { socket: null }; + }); + }, })); export const useOrganization = create((set: any) => ({ - organization: "", - setOrganization: (x: any) => set(() => ({ organization: x })), + organization: "", + setOrganization: (x: any) => set(() => ({ organization: x })), })); export const useToggleView = create((set: any) => ({ - toggleView: false, - setToggleView: (x: any) => set(() => ({ toggleView: x })), + toggleView: false, + setToggleView: (x: any) => set(() => ({ toggleView: x })), })); export const useUpdateScene = create((set: any) => ({ - updateScene: false, - setUpdateScene: (x: any) => set(() => ({ updateScene: x })), + updateScene: false, + setUpdateScene: (x: any) => set(() => ({ updateScene: x })), })); export const useWalls = create((set: any) => ({ - walls: [], - setWalls: (x: any) => set(() => ({ walls: x })), + walls: [], + setWalls: (x: any) => set(() => ({ walls: x })), })); export const useZones = create((set: any) => ({ - zones: [], - setZones: (x: any) => set(() => ({ zones: x })), + zones: [], + setZones: (x: any) => set(() => ({ zones: x })), })); interface ZonePointsState { - zonePoints: THREE.Vector3[]; - setZonePoints: (points: THREE.Vector3[]) => void; + zonePoints: THREE.Vector3[]; + setZonePoints: (points: THREE.Vector3[]) => void; } export const useZonePoints = create((set) => ({ - zonePoints: [], - setZonePoints: (points) => set({ zonePoints: points }), + zonePoints: [], + setZonePoints: (points) => set({ zonePoints: points }), })); export const useSelectedItem = create((set: any) => ({ - selectedItem: { name: "", id: "" }, - setSelectedItem: (x: any) => set(() => ({ selectedItem: x })), + selectedItem: { name: "", id: "" }, + setSelectedItem: (x: any) => set(() => ({ selectedItem: x })), })); export const useSelectedAssets = create((set: any) => ({ - selectedAssets: [], - setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })), + selectedAssets: [], + setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })), })); export const useLayers = create((set: any) => ({ - Layers: 1, - setLayers: (x: any) => set(() => ({ Layers: x })), + Layers: 1, + setLayers: (x: any) => set(() => ({ Layers: x })), })); export const useCamPosition = create((set: any) => ({ - camPosition: { x: undefined, y: undefined, z: undefined }, - setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }), + camPosition: { x: undefined, y: undefined, z: undefined }, + setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }), })); export const useMenuVisible = create((set: any) => ({ - menuVisible: false, - setMenuVisible: (x: any) => set(() => ({ menuVisible: x })), + menuVisible: false, + setMenuVisible: (x: any) => set(() => ({ menuVisible: x })), })); export const useDeleteModels = create((set: any) => ({ - deleteModels: false, - setDeleteModels: (x: any) => set(() => ({ deleteModels: x })), + deleteModels: false, + setDeleteModels: (x: any) => set(() => ({ deleteModels: x })), })); export const useToolMode = create((set: any) => ({ - toolMode: null, - setToolMode: (x: any) => set(() => ({ toolMode: x })), + toolMode: null, + setToolMode: (x: any) => set(() => ({ toolMode: x })), })); export const useNewLines = create((set: any) => ({ - newLines: [], - setNewLines: (x: any) => set(() => ({ newLines: x })), + newLines: [], + setNewLines: (x: any) => set(() => ({ newLines: x })), })); export const useDeletedLines = create((set: any) => ({ - deletedLines: [], - setDeletedLines: (x: any) => set(() => ({ deletedLines: x })), + deletedLines: [], + setDeletedLines: (x: any) => set(() => ({ deletedLines: x })), })); export const useMovePoint = create((set: any) => ({ - movePoint: false, - setMovePoint: (x: any) => set(() => ({ movePoint: x })), + movePoint: false, + setMovePoint: (x: any) => set(() => ({ movePoint: x })), })); export const useTransformMode = create((set: any) => ({ - transformMode: null, - setTransformMode: (x: any) => set(() => ({ transformMode: x })), + transformMode: null, + setTransformMode: (x: any) => set(() => ({ transformMode: x })), })); export const useDeletePointOrLine = create((set: any) => ({ - deletePointOrLine: false, - setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })), + deletePointOrLine: false, + setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })), })); export const useFloorItems = create((set: any) => ({ - floorItems: null, - setFloorItems: (callback: any) => - set((state: any) => ({ - floorItems: - typeof callback === "function" - ? callback(state.floorItems) - : callback, - })), + floorItems: null, + setFloorItems: (callback: any) => + set((state: any) => ({ + floorItems: + typeof callback === "function" ? callback(state.floorItems) : callback, + })), })); export const useWallItems = create((set: any) => ({ - wallItems: [], - setWallItems: (callback: any) => - set((state: any) => ({ - wallItems: - typeof callback === "function" - ? callback(state.wallItems) - : callback, - })), + wallItems: [], + setWallItems: (callback: any) => + set((state: any) => ({ + wallItems: + typeof callback === "function" ? callback(state.wallItems) : callback, + })), })); export const useSelectedWallItem = create((set: any) => ({ - selectedWallItem: null, - setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })), + selectedWallItem: null, + setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })), })); export const useselectedFloorItem = create((set: any) => ({ - selectedFloorItem: null, - setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })), + selectedFloorItem: null, + setselectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })), })); export const useDeletableFloorItem = create((set: any) => ({ - deletableFloorItem: null, - setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })), + deletableFloorItem: null, + setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })), })); export const useSetScale = create((set: any) => ({ - scale: null, - setScale: (x: any) => set(() => ({ scale: x })), + scale: null, + setScale: (x: any) => set(() => ({ scale: x })), })); export const useRoofVisibility = create((set: any) => ({ - roofVisibility: false, - setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })), + roofVisibility: false, + setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })), })); export const useWallVisibility = create((set: any) => ({ - wallVisibility: false, - setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })), + wallVisibility: false, + setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })), })); export const useShadows = create((set: any) => ({ - shadows: false, - setShadows: (x: any) => set(() => ({ shadows: x })), + shadows: false, + setShadows: (x: any) => set(() => ({ shadows: x })), })); export const useSunPosition = create((set: any) => ({ - sunPosition: { x: undefined, y: undefined, z: undefined }, - setSunPosition: (newSuntPosition: any) => set({ sunPosition: newSuntPosition }), + sunPosition: { x: undefined, y: undefined, z: undefined }, + setSunPosition: (newSuntPosition: any) => + set({ sunPosition: newSuntPosition }), })); export const useRemoveLayer = create((set: any) => ({ - removeLayer: false, - setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })), + removeLayer: false, + setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })), })); export const useRemovedLayer = create((set: any) => ({ - removedLayer: null, - setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })), + removedLayer: null, + setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })), })); export const useActiveLayer = create((set: any) => ({ - activeLayer: 1, - setActiveLayer: (x: any) => set({ activeLayer: x }), + activeLayer: 1, + setActiveLayer: (x: any) => set({ activeLayer: x }), })); export const useResetCamera = create((set: any) => ({ - resetCamera: false, - setResetCamera: (x: any) => set({ resetCamera: x }), + resetCamera: false, + setResetCamera: (x: any) => set({ resetCamera: x }), })); export const useAddAction = create((set: any) => ({ - addAction: null, - setAddAction: (x: any) => set({ addAction: x }), + addAction: null, + setAddAction: (x: any) => set({ addAction: x }), })); export const useActiveTool = create((set: any) => ({ - activeTool: "Cursor", - setActiveTool: (x: any) => set({ activeTool: x }), + activeTool: "Cursor", + setActiveTool: (x: any) => set({ activeTool: x }), })); export const use2DUndoRedo = create((set: any) => ({ - is2DUndoRedo: null, - set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }), -})) + is2DUndoRedo: null, + set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }), +})); export const useElevation = create((set: any) => ({ - elevation: 45, - setElevation: (x: any) => set({ elevation: x }), + elevation: 45, + setElevation: (x: any) => set({ elevation: x }), })); export const useAzimuth = create((set: any) => ({ - azimuth: -160, - setAzimuth: (x: any) => set({ azimuth: x }), + azimuth: -160, + setAzimuth: (x: any) => set({ azimuth: x }), })); export const useRenderDistance = create((set: any) => ({ - renderDistance: 50, - setRenderDistance: (x: any) => set({ renderDistance: x }), + renderDistance: 50, + setRenderDistance: (x: any) => set({ renderDistance: x }), })); export const useCamMode = create((set: any) => ({ - camMode: "ThirdPerson", - setCamMode: (x: any) => set({ camMode: x }), + camMode: "ThirdPerson", + setCamMode: (x: any) => set({ camMode: x }), })); export const useUserName = create((set: any) => ({ - userName: "", - setUserName: (x: any) => set({ userName: x }), + userName: "", + setUserName: (x: any) => set({ userName: x }), })); export const useObjectPosition = create((set: any) => ({ - objectPosition: { x: undefined, y: undefined, z: undefined }, - setObjectPosition: (newObjectPosition: any) => set({ objectPosition: newObjectPosition }), + objectPosition: { x: undefined, y: undefined, z: undefined }, + setObjectPosition: (newObjectPosition: any) => + set({ objectPosition: newObjectPosition }), })); export const useObjectScale = create((set: any) => ({ - objectScale: { x: undefined, y: undefined, z: undefined }, - setObjectScale: (newObjectScale: any) => set({ objectScale: newObjectScale }), + objectScale: { x: undefined, y: undefined, z: undefined }, + setObjectScale: (newObjectScale: any) => set({ objectScale: newObjectScale }), })); export const useObjectRotation = create((set: any) => ({ - objectRotation: { x: undefined, y: undefined, z: undefined }, - setObjectRotation: (newObjectRotation: any) => set({ objectRotation: newObjectRotation }), + objectRotation: { x: undefined, y: undefined, z: undefined }, + setObjectRotation: (newObjectRotation: any) => + set({ objectRotation: newObjectRotation }), })); export const useDrieTemp = create((set: any) => ({ - drieTemp: undefined, - setDrieTemp: (x: any) => set({ drieTemp: x }), + drieTemp: undefined, + setDrieTemp: (x: any) => set({ drieTemp: x }), })); export const useActiveUsers = create((set: any) => ({ - activeUsers: [], - setActiveUsers: (x: any) => set({ activeUsers: x }), + activeUsers: [], + setActiveUsers: (x: any) => set({ activeUsers: x }), })); export const useDrieUIValue = create((set: any) => ({ - drieUIValue: { touch: null, temperature: null, humidity: null }, + drieUIValue: { touch: null, temperature: null, humidity: null }, - setDrieUIValue: (x: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })), + setDrieUIValue: (x: any) => + set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })), - setTouch: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, touch: value } })), - setTemperature: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, temperature: value } })), - setHumidity: (value: any) => set((state: any) => ({ drieUIValue: { ...state.drieUIValue, humidity: value } })), + setTouch: (value: any) => + set((state: any) => ({ + drieUIValue: { ...state.drieUIValue, touch: value }, + })), + setTemperature: (value: any) => + set((state: any) => ({ + drieUIValue: { ...state.drieUIValue, temperature: value }, + })), + setHumidity: (value: any) => + set((state: any) => ({ + drieUIValue: { ...state.drieUIValue, humidity: value }, + })), })); export const useDrawMaterialPath = create((set: any) => ({ - drawMaterialPath: false, - setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }), + drawMaterialPath: false, + setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }), })); export const useSelectedActionSphere = create((set: any) => ({ - selectedActionSphere: undefined, - setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }), + selectedActionSphere: undefined, + setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }), })); export const useSelectedPath = create((set: any) => ({ - selectedPath: undefined, - setSelectedPath: (x: any) => set({ selectedPath: x }), + selectedPath: undefined, + setSelectedPath: (x: any) => set({ selectedPath: x }), })); interface Path { - modeluuid: string; - modelName: string; - points: { - uuid: string; - position: [number, number, number]; - rotation: [number, number, number]; - actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; - triggers: { uuid: string; type: string; isUsed: boolean }[] | []; - }[]; - pathPosition: [number, number, number]; - pathRotation: [number, number, number]; - speed: number; + modeluuid: string; + modelName: string; + points: { + uuid: string; + position: [number, number, number]; + rotation: [number, number, number]; + actions: + | { + uuid: string; + type: string; + material: string; + delay: number | string; + spawnInterval: number | string; + isUsed: boolean; + }[] + | []; + triggers: { uuid: string; type: string; isUsed: boolean }[] | []; + }[]; + pathPosition: [number, number, number]; + pathRotation: [number, number, number]; + speed: number; } interface SimulationPathsStore { - simulationPaths: Path[]; - setSimulationPaths: (paths: Path[]) => void; + simulationPaths: Path[]; + setSimulationPaths: (paths: Path[]) => void; } export const useSimulationPaths = create((set) => ({ - simulationPaths: [], - setSimulationPaths: (paths) => set({ simulationPaths: paths }), + simulationPaths: [], + setSimulationPaths: (paths) => set({ simulationPaths: paths }), })); - // interface Point { // uuid: string; // position: [number, number, number]; @@ -363,40 +383,75 @@ export const useSimulationPaths = create((set) => ({ // setSimulationPaths: (paths) => set({ simulationPaths: paths }), // })); - export const useConnections = create((set) => ({ - connections: [], + connections: [], - setConnections: (connections) => set({ connections }), + setConnections: (connections) => set({ connections }), - addConnection: (newConnection) => - set((state) => ({ - connections: [...state.connections, newConnection], - })), + addConnection: (newConnection) => + set((state) => ({ + connections: [...state.connections, newConnection], + })), - removeConnection: (fromUUID, toUUID) => - set((state) => ({ - connections: state.connections - .map((connection) => - connection.fromUUID === fromUUID - ? { - ...connection, - toConnections: connection.toConnections.filter( - (to) => to.toUUID !== toUUID - ), - } - : connection - ) - .filter((connection) => connection.toConnections.length > 0), - })), + removeConnection: (fromUUID, toUUID) => + set((state) => ({ + connections: state.connections + .map((connection) => + connection.fromUUID === fromUUID + ? { + ...connection, + toConnections: connection.toConnections.filter( + (to) => to.toUUID !== toUUID + ), + } + : connection + ) + .filter((connection) => connection.toConnections.length > 0), + })), })); export const useIsConnecting = create((set: any) => ({ - isConnecting: false, - setIsConnecting: (x: any) => set({ isConnecting: x }), + isConnecting: false, + setIsConnecting: (x: any) => set({ isConnecting: x }), })); export const useStartSimulation = create((set: any) => ({ - startSimulation: false, - setStartSimulation: (x: any) => set({ startSimulation: x }), -})); \ No newline at end of file + startSimulation: false, + setStartSimulation: (x: any) => set({ startSimulation: x }), +})); +export const usezoneTarget = create((set: any) => ({ + zoneTarget: [], + setZoneTarget: (x: any) => set({ zoneTarget: x }), +})); +export const usezonePosition = create((set: any) => ({ + zonePosition: [], + setZonePosition: (x: any) => set({ zonePosition: x }), +})); + + +interface EditPositionState { + Edit: boolean; + setEdit: (value: boolean) => void; + } + + export const useEditPosition = create((set) => ({ + Edit: false, + setEdit: (value) => set({ Edit: value }), // Properly updating the state + })); + + interface DroppedObject { + header: string; + value: string; + per: string; + className: string; + } + + interface DroppedObjectsState { + objects: DroppedObject[]; + addObject: (obj: DroppedObject) => void; + } + + export const useDroppedObjectsStore = create((set) => ({ + objects: [], + addObject: (obj) => set((state) => ({ objects: [...state.objects, obj] })), + })); \ No newline at end of file diff --git a/app/src/store/useChartStore.ts b/app/src/store/useChartStore.ts new file mode 100644 index 0000000..ee9da29 --- /dev/null +++ b/app/src/store/useChartStore.ts @@ -0,0 +1,28 @@ +import { create } from "zustand"; + +interface Measurement { + name: string; + fields: string; +} + +interface MeasurementStore { + measurements: Measurement[]; + interval: number; + duration: string; + setMeasurements: (newMeasurements: Measurement[]) => void; + updateDuration: (newDuration: string) => void; +} + +const useChartStore = create((set) => ({ + measurements: [], + interval: 1000, + duration: "1h", + + setMeasurements: (newMeasurements) => + set(() => ({ measurements: newMeasurements })), + + updateDuration: (newDuration) => + set(() => ({ duration: newDuration })), +})); + +export default useChartStore; diff --git a/app/src/store/useZoneStore.ts b/app/src/store/useZoneStore.ts index e0a66f0..007a1c6 100644 --- a/app/src/store/useZoneStore.ts +++ b/app/src/store/useZoneStore.ts @@ -15,21 +15,31 @@ interface SelectedZoneState { activeSides: Side[]; panelOrder: Side[]; lockedPanels: Side[]; + zoneId: string; + zoneViewPortTarget: number[]; + zoneViewPortPosition: number[]; widgets: Widget[]; } interface SelectedZoneStore { selectedZone: SelectedZoneState; - setSelectedZone: (zone: Partial | ((prev: SelectedZoneState) => SelectedZoneState)) => void; + setSelectedZone: ( + zone: + | Partial + | ((prev: SelectedZoneState) => SelectedZoneState) + ) => void; } export const useSelectedZoneStore = create((set) => ({ selectedZone: { - zoneName: "", - activeSides: [], - panelOrder: [], - lockedPanels: [], - widgets: [], + zoneName: "", // Empty string initially + activeSides: [], // Empty array + panelOrder: [], // Empty array + lockedPanels: [], // Empty array + zoneId: "", + zoneViewPortTarget: [], + zoneViewPortPosition: [], + widgets: [], // Empty array }, setSelectedZone: (zone) => set((state) => ({ @@ -38,4 +48,4 @@ export const useSelectedZoneStore = create((set) => ({ ? zone(state.selectedZone) // Handle functional updates : { ...state.selectedZone, ...zone }, // Handle partial updates })), -})); \ No newline at end of file +})); diff --git a/app/src/styles/components/input.scss b/app/src/styles/components/input.scss index 3020c7d..36ac8ff 100644 --- a/app/src/styles/components/input.scss +++ b/app/src/styles/components/input.scss @@ -280,28 +280,24 @@ input { .dropdown-menu { position: absolute; - top: 100%; - left: 0; - background-color: #ffffff; - border: 1px solid #cccccc; + top: 110%; + right: -16px; + background-color: var(--background-color); + border: 1px solid var(--border-color); border-radius: 5px; - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + box-shadow: #{$box-shadow-medium}; z-index: 1000; min-width: 200px; overflow: auto; - max-height: 600px; + max-height: 400px; .dropdown-content { display: flex; flex-direction: column; gap: 6px; - .nested-dropdown { - // &:first-child{ margin-left: 0; - // } } - padding: 10px; } @@ -309,13 +305,13 @@ input { display: block; padding: 5px 10px; text-decoration: none; - color: #000000; + color: var(--text-color); font-size: 14px; cursor: pointer; transition: background-color 0.3s ease; &:hover { - background-color: #f0f0f0; + background-color: var(--background-color); } } @@ -329,15 +325,20 @@ input { padding: 5px 10px; cursor: pointer; font-size: 14px; - color: #000000; + color: var(--text-color); transition: background-color 0.3s ease; + border-radius: #{$border-radius-small}; + .arrow-container{ + @include flex-center; + } &:hover { - background-color: #f0f0f0; + background-color: var(--background-color); } &.open { - background-color: #e0e0e0; + color: var(--accent-color); + background-color: var(--highlight-accent-color); } .icon { @@ -349,7 +350,7 @@ input { .submenu { margin-top: 5px; padding-left: 20px; - border-left: 2px solid #cccccc; + border-left: 2px solid var(--border-color); display: flex; flex-direction: column; gap: 6px; @@ -576,26 +577,26 @@ input { color: var(--text-disabled); } } - .entered-emails{ + .entered-emails { @include flex-center; gap: 2px; background: var(--background-color-gray); padding: 0 4px; border-radius: #{$border-radius-large}; - span{ + span { height: 14px; width: 14px; line-height: 12px; text-align: center; border-radius: #{$border-radius-small}; - &:hover{ + &:hover { background: var(--accent-color); color: var(--primary-color); } } } } - .invite-button{ + .invite-button { padding: 4px 12px; border-radius: #{$border-radius-large}; background: var(--accent-color); diff --git a/app/src/styles/components/marketPlace/marketPlace.scss b/app/src/styles/components/marketPlace/marketPlace.scss index 3c9fb1a..cac366e 100644 --- a/app/src/styles/components/marketPlace/marketPlace.scss +++ b/app/src/styles/components/marketPlace/marketPlace.scss @@ -8,17 +8,17 @@ background-color: var(--background-color-secondary); position: absolute; left: 0; - padding: 95px 8px; + padding: 100px 50px; padding-bottom: 32px; + backdrop-filter: blur(6px); .marketplace-container { + position: relative; padding: 20px 2px; - // height: calc(100vh - 120px); height: 100%; background-color: var(--background-color); box-shadow: #{$box-shadow-medium}; border-radius: #{$border-radius-extra-large}; - position: relative; } .marketPlace { @@ -37,47 +37,34 @@ width: 100%; display: flex; align-items: center; - gap: 20px; + gap: 12px; - .asset-search-wrapper { + .search-wrapper { min-width: 60%; max-width: 684px; padding: 0; border-radius: $border-radius-large; - .search-wrapper { - padding: 0 12px; - .search-container { - display: flex; - align-items: center; - width: 100%; - border: none !important; - border-radius: $border-radius-large; - overflow: hidden; - padding: 6px 12px; - outline: 1px solid var(--border-color); - input { - border: none !important; - outline: none; - } + .search-container { + border: none !important; + box-shadow: $box-shadow-medium; + border-radius: $border-radius-large; + + input { + border: none !important; + outline: none; } } } .regularDropdown-container { max-width: 159px; - max-height: 30px; - height: 100%; - .dropdown-header { - align-items: center; - } } .button { padding: 5px 20px; border: 1px solid var(--accent-color); border-radius: 14px; - color: var(--accent-color); } .rating-container { @@ -102,7 +89,6 @@ color: var(--text-color); font-weight: $medium-weight; font-size: $xlarge; - margin: 10px 0; } .cards-wrapper-container { @@ -131,7 +117,6 @@ border-radius: 10px; padding: 5px; background-color: var(--accent-color); - cursor: pointer; } .image-container { diff --git a/app/src/styles/pages/realTimeViz.scss b/app/src/styles/pages/realTimeViz.scss index 3969880..4c4c9ae 100644 --- a/app/src/styles/pages/realTimeViz.scss +++ b/app/src/styles/pages/realTimeViz.scss @@ -1,5 +1,5 @@ @use "../abstracts/variables.scss" as *; -@use "../abstracts/mixins" as *; +@use "../abstracts/mixins.scss" as *; // Main Container .realTime-viz { @@ -68,7 +68,6 @@ &::-webkit-scrollbar { display: none; } - } .zone { @@ -149,6 +148,7 @@ background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); transition: all 0.3s ease; + border-radius: 6px; overflow: visible !important; z-index: $z-index-tools; @@ -156,13 +156,10 @@ position: relative; height: 100%; padding: 10px; - - display: flex; flex-direction: column; - gap: 10px; + gap: 6px; background-color: var(--background-color); - border-radius: #{$border-radius-small}; &::-webkit-scrollbar { display: none; @@ -170,8 +167,7 @@ .chart-container { width: 100%; - height: 24% !important; - + height: 25% !important; min-height: 150px; max-height: 100%; border: 1px dotted #a9a9a9; @@ -188,7 +184,7 @@ top: 0px; right: 0px; z-index: 10; - + cursor: pointer; @include flex-center; } @@ -207,8 +203,6 @@ box-shadow: var(--box-shadow-medium); - - .btn { display: flex; gap: 6px; @@ -318,7 +312,6 @@ border-radius: 2px; transition: transform 0.3s ease; box-shadow: #{$box-shadow-medium}; - // outline: 1px solid var(--border-color); .extra-Bs { display: flex; @@ -348,7 +341,9 @@ transition: background-color 0.3s ease; width: 18px; height: 18px; - @include flex-center; + display: flex; + justify-content: center; + // align-items: center; background-color: var(--accent-color); border: none; color: var(--background-color); @@ -488,10 +483,6 @@ } } - - - - .arrow { position: absolute; top: 50%; @@ -520,4 +511,4 @@ .zone.active { background-color: #007bff; color: white; -} \ No newline at end of file +}