added api to fetch data

This commit is contained in:
gabriel 2025-03-26 18:40:00 +05:30
commit fee85f406c
40 changed files with 22588 additions and 21583 deletions

1
app/.gitignore vendored
View File

@ -2,6 +2,7 @@
# dependencies # dependencies
/node_modules /node_modules
# /package-lock.json
/.pnp /.pnp
.pnp.js .pnp.js

40331
app/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,8 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@react-three/csg": "^3.2.0", "@react-three/csg": "^3.2.0",
"@react-three/drei": "^9.113.0", "@react-three/drei": "^9.113.0",
"@react-three/fiber": "^8.17.7", "@react-three/fiber": "^8.17.7",

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -107,7 +107,7 @@ export function StockIncreseIcon() {
fill="none" fill="none"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<g clip-path="url(#clip0_3050_69519)"> <g clipPath="url(#clip0_3050_69519)">
<path <path
d="M7.80766 6.99219H1.17811C0.752382 6.99219 0.407227 7.33734 0.407227 7.76307C0.407227 8.18879 0.752382 8.53395 1.17811 8.53395H7.80766C8.23339 8.53395 8.57854 8.18879 8.57854 7.76307C8.57854 7.33733 8.23339 6.99219 7.80766 6.99219Z" d="M7.80766 6.99219H1.17811C0.752382 6.99219 0.407227 7.33734 0.407227 7.76307C0.407227 8.18879 0.752382 8.53395 1.17811 8.53395H7.80766C8.23339 8.53395 8.57854 8.18879 8.57854 7.76307C8.57854 7.33733 8.23339 6.99219 7.80766 6.99219Z"
fill="white" fill="white"
@ -142,8 +142,8 @@ export function StockIncreseIcon() {
y2="8.53122" y2="8.53122"
gradientUnits="userSpaceOnUse" gradientUnits="userSpaceOnUse"
> >
<stop stop-color="#31B2B9" /> <stop stopColor="#31B2B9" />
<stop offset="1" stop-color="#FBD8B8" /> <stop offset="1" stopColor="#FBD8B8" />
</linearGradient> </linearGradient>
<clipPath id="clip0_3050_69519"> <clipPath id="clip0_3050_69519">
<rect <rect

View File

@ -0,0 +1,132 @@
export function StarsIcon() {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.39075 3.67726C9.58367 3.24444 9.68017 3.02804 9.8145 2.96139C9.93117 2.90349 10.0682 2.90349 10.1848 2.96139C10.3192 3.02804 10.4157 3.24444 10.6086 3.67726L12.1453 7.1247C12.2023 7.25265 12.2308 7.31663 12.275 7.36562C12.314 7.40897 12.3618 7.44364 12.415 7.46738C12.4753 7.49421 12.5449 7.50156 12.6843 7.51626L16.4378 7.91244C16.9091 7.96217 17.1447 7.98704 17.2496 8.09419C17.3407 8.18727 17.383 8.3176 17.364 8.44647C17.3422 8.5948 17.1662 8.75339 16.8142 9.07064L14.0103 11.5975C13.9063 11.6912 13.8542 11.7381 13.8213 11.7952C13.7921 11.8458 13.7738 11.9019 13.7678 11.9599C13.7608 12.0255 13.7753 12.094 13.8044 12.2311L14.5876 15.9233C14.6859 16.3869 14.7351 16.6186 14.6656 16.7515C14.6052 16.867 14.4943 16.9475 14.3659 16.9692C14.2181 16.9942 14.0128 16.8759 13.6023 16.6391L10.3328 14.7533C10.2114 14.6833 10.1508 14.6484 10.0863 14.6346C10.0292 14.6226 9.97017 14.6226 9.91309 14.6346C9.84859 14.6484 9.78792 14.6833 9.66659 14.7533L6.39702 16.6391C5.98654 16.8759 5.7813 16.9942 5.63345 16.9692C5.50503 16.9475 5.39416 16.867 5.3338 16.7515C5.2643 16.6186 5.31346 16.3869 5.41179 15.9233L6.19492 12.2311C6.22399 12.094 6.23852 12.0255 6.23162 11.9599C6.22551 11.9019 6.20729 11.8458 6.17812 11.7952C6.14516 11.7381 6.09313 11.6912 5.98907 11.5975L3.18522 9.07064C2.83321 8.75339 2.6572 8.5948 2.63532 8.44647C2.61632 8.3176 2.65866 8.18727 2.74978 8.09419C2.85468 7.98704 3.0903 7.96217 3.56155 7.91244L7.31513 7.51626C7.45445 7.50156 7.5241 7.49421 7.58433 7.46738C7.63762 7.44364 7.68534 7.40897 7.72439 7.36562C7.76851 7.31663 7.79703 7.25265 7.85407 7.1247L9.39075 3.67726Z"
stroke="#595965"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
}
export function DownloadIcon() {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M2.5 11.875C2.84518 11.875 3.125 12.1548 3.125 12.5C3.125 13.6962 3.12633 14.5304 3.21096 15.1599C3.29317 15.7714 3.44354 16.0952 3.67418 16.3258C3.90481 16.5565 4.22863 16.7068 4.8401 16.7891C5.46956 16.8737 6.30383 16.875 7.5 16.875H12.5C13.6962 16.875 14.5304 16.8737 15.1599 16.7891C15.7714 16.7068 16.0952 16.5565 16.3258 16.3258C16.5565 16.0952 16.7068 15.7714 16.7891 15.1599C16.8737 14.5304 16.875 13.6962 16.875 12.5C16.875 12.1548 17.1548 11.875 17.5 11.875C17.8452 11.875 18.125 12.1548 18.125 12.5V12.5458C18.125 13.6854 18.125 14.604 18.0279 15.3265C17.9271 16.0766 17.7113 16.7081 17.2097 17.2097C16.7081 17.7113 16.0766 17.9271 15.3265 18.0279C14.604 18.125 13.6854 18.125 12.5458 18.125H7.45428C6.31462 18.125 5.39602 18.125 4.67354 18.0279C3.92345 17.9271 3.29189 17.7113 2.79029 17.2097C2.28869 16.7081 2.07295 16.0766 1.9721 15.3265C1.87497 14.604 1.87498 13.6854 1.875 12.5458C1.875 12.5305 1.875 12.5152 1.875 12.5C1.875 12.1548 2.15483 11.875 2.5 11.875Z"
fill="#FCFDFD"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M10.0003 13.9583C10.1758 13.9583 10.3432 13.8846 10.4616 13.7551L13.7949 10.1093C14.0278 9.8545 14.0102 9.45917 13.7554 9.22625C13.5007 8.99333 13.1053 9.011 12.8724 9.26575L10.6253 11.7235V2.5C10.6253 2.15483 10.3455 1.875 10.0003 1.875C9.65516 1.875 9.37533 2.15483 9.37533 2.5V11.7235L7.12827 9.26575C6.89535 9.011 6.50002 8.99333 6.24527 9.22625C5.99052 9.45917 5.97281 9.8545 6.20573 10.1093L9.53908 13.7551C9.65749 13.8846 9.82483 13.9583 10.0003 13.9583Z"
fill="#FCFDFD"
/>
</svg>
);
}
export function EyeIconBig() {
return (
<svg
width="22"
height="22"
viewBox="0 0 22 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2.75 11.918C6.05 4.58464 15.95 4.58464 19.25 11.918"
stroke="#2B3344"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M11 15.5859C10.6389 15.5859 10.2813 15.5148 9.94762 15.3766C9.61398 15.2384 9.31082 15.0358 9.05546 14.7805C8.80009 14.5251 8.59753 14.222 8.45933 13.8883C8.32113 13.5547 8.25 13.1971 8.25 12.8359C8.25 12.4748 8.32113 12.1172 8.45933 11.7836C8.59753 11.4499 8.80009 11.1468 9.05546 10.8914C9.31082 10.636 9.61398 10.4335 9.94762 10.2953C10.2813 10.1571 10.6389 10.0859 11 10.0859C11.7293 10.0859 12.4288 10.3757 12.9445 10.8914C13.4603 11.4071 13.75 12.1066 13.75 12.8359C13.75 13.5653 13.4603 14.2648 12.9445 14.7805C12.4288 15.2962 11.7293 15.5859 11 15.5859Z"
stroke="#2B3344"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
}
export function CommentsIcon() {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_2926_17620)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8 13C7.416 13 6.852 12.932 6.31 12.8165L3.956 14.2315L3.9875 11.912C2.183 10.827 1 9.033 1 7C1 3.6865 4.134 1 8 1C11.866 1 15 3.6865 15 7C15 10.314 11.866 13 8 13ZM8 0C3.582 0 0 3.1345 0 7C0 9.2095 1.1725 11.177 3 12.4595V16L6.5045 13.8735C6.9895 13.9535 7.4885 14 8 14C12.418 14 16 10.866 16 7C16 3.1345 12.418 0 8 0ZM11.5 5.5H4.5C4.224 5.5 4 5.724 4 6C4 6.2765 4.224 6.5 4.5 6.5H11.5C11.776 6.5 12 6.2765 12 6C12 5.724 11.776 5.5 11.5 5.5ZM10.5 8.5H5.5C5.224 8.5 5 8.7235 5 9C5 9.2765 5.224 9.5 5.5 9.5H10.5C10.776 9.5 11 9.2765 11 9C11 8.7235 10.776 8.5 10.5 8.5Z"
fill="#2B3344"
/>
</g>
<defs>
<clipPath id="clip0_2926_17620">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
);
}
export function VerifiedIcon() {
return (
<svg
width="12"
height="13"
viewBox="0 0 12 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M4.7962 2.10014C4.67444 2.2039 4.61356 2.25579 4.54853 2.29937C4.39948 2.39927 4.23209 2.46861 4.05605 2.50336C3.97926 2.51853 3.89952 2.52489 3.74004 2.53761C3.33935 2.56959 3.139 2.58558 2.97186 2.64462C2.58526 2.78117 2.28117 3.08526 2.14462 3.47186C2.08558 3.639 2.06959 3.83935 2.03761 4.24004C2.02489 4.39952 2.01853 4.47926 2.00336 4.55605C1.96861 4.73209 1.89927 4.89948 1.79937 5.04853C1.75579 5.11356 1.70391 5.17444 1.60014 5.2962C1.33942 5.60215 1.20905 5.7551 1.13261 5.91505C0.955796 6.285 0.955796 6.715 1.13261 7.08495C1.20906 7.2449 1.33942 7.39785 1.60014 7.7038C1.70389 7.82555 1.75579 7.88645 1.79937 7.95145C1.89927 8.1005 1.96861 8.2679 2.00336 8.44395C2.01853 8.52075 2.02489 8.6005 2.03761 8.75995C2.06959 9.16065 2.08558 9.361 2.14462 9.52815C2.28117 9.91475 2.58526 10.2189 2.97186 10.3554C3.139 10.4144 3.33935 10.4304 3.74004 10.4624C3.89952 10.4751 3.97926 10.4815 4.05605 10.4966C4.23209 10.5314 4.39948 10.6007 4.54853 10.7007C4.61356 10.7442 4.67444 10.7961 4.7962 10.8998C5.10215 11.1606 5.2551 11.2909 5.41505 11.3674C5.785 11.5442 6.215 11.5442 6.58495 11.3674C6.7449 11.2909 6.89785 11.1606 7.2038 10.8998C7.32555 10.7961 7.38645 10.7442 7.45145 10.7007C7.6005 10.6007 7.7679 10.5314 7.94395 10.4966C8.02075 10.4815 8.1005 10.4751 8.25995 10.4624C8.66065 10.4304 8.861 10.4144 9.02815 10.3554C9.41475 10.2189 9.71885 9.91475 9.8554 9.52815C9.9144 9.361 9.9304 9.16065 9.9624 8.75995C9.9751 8.6005 9.9815 8.52075 9.99665 8.44395C10.0314 8.2679 10.1007 8.1005 10.2007 7.95145C10.2442 7.88645 10.2961 7.82555 10.3998 7.7038C10.6606 7.39785 10.7909 7.2449 10.8674 7.08495C11.0442 6.715 11.0442 6.285 10.8674 5.91505C10.7909 5.7551 10.6606 5.60215 10.3998 5.2962C10.2961 5.17444 10.2442 5.11356 10.2007 5.04853C10.1007 4.89948 10.0314 4.73209 9.99665 4.55605C9.9815 4.47926 9.9751 4.39952 9.9624 4.24004C9.9304 3.83935 9.9144 3.639 9.8554 3.47186C9.71885 3.08526 9.41475 2.78117 9.02815 2.64462C8.861 2.58558 8.66065 2.56959 8.25995 2.53761C8.1005 2.52489 8.02075 2.51853 7.94395 2.50336C7.7679 2.46861 7.6005 2.39927 7.45145 2.29937C7.38645 2.25579 7.32555 2.20391 7.2038 2.10014C6.89785 1.83942 6.7449 1.70906 6.58495 1.63261C6.215 1.4558 5.785 1.4558 5.41505 1.63261C5.2551 1.70905 5.10215 1.83942 4.7962 2.10014ZM8.18675 5.43157C8.34565 5.27265 8.34565 5.015 8.18675 4.85608C8.02785 4.69717 7.77015 4.69717 7.61125 4.85608L5.18615 7.2812L4.38873 6.4838C4.22982 6.3249 3.97216 6.3249 3.81325 6.4838C3.65433 6.6427 3.65433 6.90035 3.81325 7.0593L4.89839 8.14445C5.0573 8.30335 5.31495 8.30335 5.4739 8.14445L8.18675 5.43157Z"
fill="#6F42C1"
/>
</svg>
);
}
export function StarsIconSmall() {
return (
<svg
width="13"
height="13"
viewBox="0 0 13 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M6.43387 2.70558C6.54962 2.44589 6.60752 2.31604 6.68812 2.27606C6.75812 2.24131 6.84032 2.24131 6.91032 2.27606C6.99092 2.31604 7.04882 2.44589 7.16457 2.70558L8.08657 4.77404C8.12082 4.85081 8.13792 4.8892 8.16442 4.91859C8.18782 4.9446 8.21647 4.96541 8.24842 4.97965C8.28457 4.99575 8.32637 5.00016 8.40997 5.00898L10.6621 5.24668C10.9449 5.27652 11.0862 5.29144 11.1492 5.35574C11.2038 5.41158 11.2292 5.48978 11.2178 5.5671C11.2047 5.6561 11.0991 5.75125 10.8879 5.9416L9.20557 7.4577C9.14317 7.51395 9.11192 7.5421 9.09217 7.57635C9.07467 7.6067 9.06372 7.64035 9.06007 7.67515C9.05592 7.7145 9.06462 7.7556 9.08207 7.83785L9.55197 10.0532C9.61097 10.3314 9.64047 10.4704 9.59877 10.5501C9.56252 10.6194 9.49602 10.6677 9.41897 10.6808C9.33027 10.6958 9.20712 10.6248 8.96082 10.4827L6.99907 9.3512C6.92627 9.3092 6.88987 9.28825 6.85117 9.28C6.81692 9.27275 6.78152 9.27275 6.74727 9.28C6.70857 9.28825 6.67217 9.3092 6.59937 9.3512L4.63763 10.4827C4.39134 10.6248 4.26819 10.6958 4.17949 10.6808C4.10243 10.6677 4.03591 10.6194 3.99969 10.5501C3.958 10.4704 3.98749 10.3314 4.04649 10.0532L4.51637 7.83785C4.53381 7.7556 4.54253 7.7145 4.53839 7.67515C4.53472 7.64035 4.52379 7.6067 4.50629 7.57635C4.48651 7.5421 4.45529 7.51395 4.39286 7.4577L2.71055 5.9416C2.49934 5.75125 2.39374 5.6561 2.38061 5.5671C2.36921 5.48978 2.39461 5.41158 2.44928 5.35574C2.51222 5.29144 2.6536 5.27652 2.93635 5.24668L5.18849 5.00898C5.27208 5.00016 5.31387 4.99575 5.35001 4.97965C5.38199 4.96541 5.41062 4.9446 5.43405 4.91859C5.46052 4.8892 5.47763 4.85081 5.51186 4.77404L6.43387 2.70558Z"
stroke="#595965"
stroke-width="0.6"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
}

View File

@ -3,9 +3,12 @@ import { ToggleSidebarIcon } from "../../icons/HeaderIcons";
import { LogoIcon } from "../../icons/Logo"; import { LogoIcon } from "../../icons/Logo";
import FileMenu from "../../ui/FileMenu"; import FileMenu from "../../ui/FileMenu";
import useToggleStore from "../../../store/useUIToggleStore"; import useToggleStore from "../../../store/useUIToggleStore";
import useModuleStore from "../../../store/useModuleStore";
const Header: React.FC = () => { const Header: React.FC = () => {
const { toggleUI, setToggleUI } = useToggleStore(); const { toggleUI, setToggleUI } = useToggleStore();
const { activeModule } = useModuleStore();
return ( return (
<div className="header-container"> <div className="header-container">
<div className="header-content"> <div className="header-content">
@ -19,7 +22,7 @@ const Header: React.FC = () => {
<div <div
className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`} className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`}
onClick={() => { onClick={() => {
setToggleUI(!toggleUI); if (activeModule !== "market") setToggleUI(!toggleUI);
}} }}
> >
<ToggleSidebarIcon /> <ToggleSidebarIcon />

View File

@ -1,6 +1,8 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Header from "./Header"; import Header from "./Header";
import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore"; import useModuleStore, {
useSubModuleStore,
} from "../../../store/useModuleStore";
import { import {
AnalysisIcon, AnalysisIcon,
MechanicsIcon, MechanicsIcon,
@ -15,16 +17,18 @@ import AsstePropertiies from "./properties/AssetProperties";
import Analysis from "./analysis/Analysis"; import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations"; import Simulations from "./simulation/Simulations";
import { useSelectedActionSphere } from "../../../store/store"; import { useSelectedActionSphere } from "../../../store/store";
import ZoneProperties from "./properties/ZoneProperties";
const SideBarRight: React.FC = () => { const SideBarRight: React.FC = () => {
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const [activeList] = useState("properties");
const { toggleUI } = useToggleStore();
const { selectedActionSphere } = useSelectedActionSphere(); const { selectedActionSphere } = useSelectedActionSphere();
const { subModule, setSubModule } = useSubModuleStore(); const { subModule, setSubModule } = useSubModuleStore();
const { toggleUI } = useToggleStore(); // Reset activeList whenever activeModule changes
// Reset subModule whenever activeModule changes
useEffect(() => { useEffect(() => {
setSubModule("properties"); if (activeModule !== "simulation") setSubModule("properties");
if (activeModule === "simulation") setSubModule("mechanics");
}, [activeModule]); }, [activeModule]);
return ( return (
@ -32,35 +36,41 @@ const SideBarRight: React.FC = () => {
<Header /> <Header />
{toggleUI && ( {toggleUI && (
<div className="sidebar-actions-container"> <div className="sidebar-actions-container">
{/* {activeModule === "builder" && ( */}
<div <div
className={`sidebar-action-list ${subModule === "properties" ? "active" : "" className={`sidebar-action-list ${
}`} subModule === "properties" ? "active" : ""
}`}
onClick={() => setSubModule("properties")} onClick={() => setSubModule("properties")}
> >
<PropertiesIcon isActive={subModule === "properties"} /> <PropertiesIcon isActive={subModule === "properties"} />
</div> </div>
{/* )} */}
{activeModule === "simulation" && ( {activeModule === "simulation" && (
<> <>
<div <div
className={`sidebar-action-list ${subModule === "mechanics" ? "active" : "" className={`sidebar-action-list ${
}`} subModule === "mechanics" ? "active" : ""
}`}
onClick={() => setSubModule("mechanics")} onClick={() => setSubModule("mechanics")}
> >
<MechanicsIcon isActive={subModule === "mechanics"} /> <MechanicsIcon isActive={activeList === "mechanics"} />
</div> </div>
<div <div
className={`sidebar-action-list ${subModule === "simulations" ? "active" : "" className={`sidebar-action-list ${
}`} subModule === "simulations" ? "active" : ""
}`}
onClick={() => setSubModule("simulations")} onClick={() => setSubModule("simulations")}
> >
<SimulationIcon isActive={subModule === "simulations"} /> <SimulationIcon isActive={activeList === "simulations"} />
</div> </div>
<div <div
className={`sidebar-action-list ${subModule === "analysis" ? "active" : "" className={`sidebar-action-list ${
}`} subModule === "analysis" ? "active" : ""
}`}
onClick={() => setSubModule("analysis")} onClick={() => setSubModule("analysis")}
> >
<AnalysisIcon isActive={subModule === "analysis"} /> <AnalysisIcon isActive={activeList === "analysis"} />
</div> </div>
</> </>
)} )}
@ -68,11 +78,12 @@ const SideBarRight: React.FC = () => {
)} )}
{/* process builder */} {/* process builder */}
{toggleUI && {toggleUI &&
subModule === "properties" && activeList === "properties" &&
activeModule !== "visualization" && ( activeModule !== "visualization" && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<GlobalProperties /> <GlobalProperties />
{/* <ZoneProperties /> */}
{/* <AsstePropertiies /> */} {/* <AsstePropertiies /> */}
</div> </div>
</div> </div>
@ -82,17 +93,17 @@ const SideBarRight: React.FC = () => {
{toggleUI && activeModule === "simulation" && ( {toggleUI && activeModule === "simulation" && (
<> <>
{(subModule === "mechanics" && selectedActionSphere) && ( {subModule === "mechanics" && selectedActionSphere && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<MachineMechanics /> <MachineMechanics />
</div> </div>
</div> </div>
)} )}
{(subModule === "mechanics" && !selectedActionSphere) && ( {subModule === "mechanics" && !selectedActionSphere && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
{/* <MachineMechanics /> */} <MachineMechanics />
</div> </div>
</div> </div>
)} )}
@ -103,7 +114,7 @@ const SideBarRight: React.FC = () => {
</div> </div>
</div> </div>
)} )}
{subModule === "simulations" && ( {activeList === "simulations" && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<Simulations /> <Simulations />

View File

@ -0,0 +1,62 @@
import React from "react";
import { EyeDroperIcon } from "../../../icons/ExportCommonIcons";
interface PositionInputProps {
onChange: (value: string) => void; // Callback for value change
header: string;
placeholder?: string; // Optional placeholder
type?: string; // Input type (e.g., text, number, email)
}
const Vector3Input: React.FC<PositionInputProps> = ({
onChange,
header,
placeholder = "Enter value", // Default placeholder
type = "number", // Default type
}) => {
return (
<div className="custom-input-container">
<div className="header">
{header}{" "}
<div className="eyedrop-button">
<EyeDroperIcon isActive={false} />
</div>
</div>
<div className="inputs-container">
<div className="input-container">
<div className="custom-input-label">X : </div>
<input
className="custom-input-field"
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
disabled
/>
</div>
<div className="input-container">
<div className="custom-input-label">Y : </div>
<input
className="custom-input-field"
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
disabled
min={0}
/>
</div>
<div className="input-container">
<div className="custom-input-label">Z : </div>
<input
className="custom-input-field"
type={type}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
disabled
/>
</div>
</div>
</div>
);
};
export default Vector3Input;

View File

@ -14,8 +14,8 @@ import EyeDropInput from "../../../ui/inputs/EyeDropInput";
import { useSelectedActionSphere } from "../../../../store/store"; import { useSelectedActionSphere } from "../../../../store/store";
const MachineMechanics: React.FC = () => { const MachineMechanics: React.FC = () => {
const { selectedActionSphere, setSelectedActionSphere } = useSelectedActionSphere(); const { selectedActionSphere } = useSelectedActionSphere();
console.log('selectedActionSphere: ', selectedActionSphere); console.log("selectedActionSphere: ", selectedActionSphere);
const [actionList, setActionList] = useState<string[]>([]); const [actionList, setActionList] = useState<string[]>([]);
const [triggerList, setTriggerList] = useState<string[]>([]); const [triggerList, setTriggerList] = useState<string[]>([]);
const [selectedItem, setSelectedItem] = useState<{ const [selectedItem, setSelectedItem] = useState<{
@ -71,7 +71,9 @@ const MachineMechanics: React.FC = () => {
return ( return (
<div className="machine-mechanics-container"> <div className="machine-mechanics-container">
<div className="machine-mechanics-header">{selectedActionSphere.path.modelName}</div> <div className="machine-mechanics-header">
{selectedActionSphere?.path?.modelName || "path name not found"}
</div>
{/* <div className="process-list-container"> {/* <div className="process-list-container">
<div className="label">Process:</div> <div className="label">Process:</div>
<RegularDropDown <RegularDropDown
@ -100,11 +102,12 @@ const MachineMechanics: React.FC = () => {
{actionList.map((action, index) => ( {actionList.map((action, index) => (
<div <div
key={index} key={index}
className={`list-item ${selectedItem?.type === "action" && className={`list-item ${
selectedItem?.type === "action" &&
selectedItem.name === action selectedItem.name === action
? "active" ? "active"
: "" : ""
}`} }`}
> >
<div <div
className="value" className="value"
@ -146,11 +149,12 @@ const MachineMechanics: React.FC = () => {
{triggerList.map((trigger, index) => ( {triggerList.map((trigger, index) => (
<div <div
key={index} key={index}
className={`list-item ${selectedItem?.type === "trigger" && className={`list-item ${
selectedItem?.type === "trigger" &&
selectedItem.name === trigger selectedItem.name === trigger
? "active" ? "active"
: "" : ""
}`} }`}
> >
<div <div
className="value" className="value"
@ -188,7 +192,7 @@ const MachineMechanics: React.FC = () => {
label="Speed" label="Speed"
value="" value=""
activeOption=".mm" activeOption=".mm"
onChange={() => { }} onChange={() => {}}
/> />
<EyeDropInput /> <EyeDropInput />
</> </>

View File

@ -0,0 +1,39 @@
import React, { useState } from "react";
import RenameInput from "../../../ui/inputs/RenameInput";
import Vector3Input from "../customInput/Vector3Input";
const ZoneProperties: React.FC = () => {
const [Edit, setEdit] = useState(false);
function handleSetView() {
setEdit(false);
}
function handleEditView() {
if (Edit) {
setEdit(false);
} else {
setEdit(true);
}
}
return (
<div className="zone-properties-container">
<div className="header">
<RenameInput value="Selected Zone Name" />
<div className="button" onClick={handleEditView}>
{Edit ? "Cancel" : "Edit"}
</div>
</div>
<Vector3Input onChange={() => {}} header="Viewport Target" />
<Vector3Input onChange={() => {}} header="Viewport Position" />
{Edit && (
<div className="button-save" onClick={handleSetView}>
Set View
</div>
)}
</div>
);
};
export default ZoneProperties;

View File

@ -28,7 +28,7 @@ const DropList: React.FC<DropListProps> = ({ val }) => {
}} }}
> >
{val.pathName} {val.pathName}
<div className="arrow-container"> <div className={`arrow-container${openDrop ? " active" : ""}`}>
<ArrowIcon /> <ArrowIcon />
</div> </div>
</div> </div>
@ -87,8 +87,9 @@ const Simulations: React.FC = () => {
{productsList.map((action, index) => ( {productsList.map((action, index) => (
<div <div
key={index} key={index}
className={`list-item ${selectedItem === action ? "active" : "" className={`list-item ${
}`} selectedItem === action ? "active" : ""
}`}
> >
<div <div
className="value" className="value"

View File

@ -1,115 +1,115 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown' import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown'
import { AddIcon } from '../../../../icons/ExportCommonIcons' import { AddIcon } from '../../../../icons/ExportCommonIcons'
import RegularDropDown from '../../../../ui/inputs/RegularDropDown' import RegularDropDown from '../../../../ui/inputs/RegularDropDown'
import useChartStore from '../../../../../store/useChartStore' import useChartStore from '../../../../../store/useChartStore'
import axios from 'axios' import axios from 'axios'
type Props = {} type Props = {}
const LineGrapInput = (props: Props) => { const LineGrapInput = (props: Props) => {
const [dropDowndata, setDropDownData] = useState({}) const [dropDowndata, setDropDownData] = useState({})
const [selections, setSelections] = useState<Record<string, { name: string, fields: string }>>({}) const [selections, setSelections] = useState<Record<string, { name: string, fields: string }>>({})
const [selectedOption, setSelectedOption] = useState('1h') const [selectedOption, setSelectedOption] = useState('1h')
const { measurements, setMeasurements, updateDuration, duration } = useChartStore(); const { measurements, setMeasurements, updateDuration, duration } = useChartStore();
const handleSelectDuration = (option: string) => { const handleSelectDuration = (option: string) => {
updateDuration(option); // Normalize for key matching updateDuration(option); // Normalize for key matching
}; };
useEffect(() => { useEffect(() => {
const fetchZoneData = async () => { const fetchZoneData = async () => {
try { try {
const response = await axios.get('http://192.168.0.192:5010/getinput'); const response = await axios.get('http://192.168.0.192:5010/getinput');
if (response.status === 200) { if (response.status === 200) {
console.log('dropdown data:', response.data); console.log('dropdown data:', response.data);
setDropDownData(response.data) setDropDownData(response.data)
} else { } else {
console.log('Unexpected response:', response); console.log('Unexpected response:', response);
} }
} catch (error) { } catch (error) {
console.error('There was an error!', error); console.error('There was an error!', error);
} }
}; };
fetchZoneData(); fetchZoneData();
}, []); }, []);
useEffect(() => { useEffect(() => {
console.log(selections); console.log(selections);
}, [selections]) }, [selections])
const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => { const handleSelect = (inputKey: string, selectedData: { name: string, fields: string } | null) => {
setSelections(prev => { setSelections(prev => {
if (selectedData === null) { if (selectedData === null) {
const newSelections = { ...prev }; const newSelections = { ...prev };
delete newSelections[inputKey]; delete newSelections[inputKey];
return newSelections; return newSelections;
} else { } else {
return { return {
...prev, ...prev,
[inputKey]: selectedData [inputKey]: selectedData
}; };
} }
}); });
}; };
interface Measurement { interface Measurement {
name: string; name: string;
fields: string; fields: string;
} }
interface InputData { interface InputData {
[key: string]: Measurement; [key: string]: Measurement;
} }
const extractMeasurements = (input: InputData): Measurement[] => { const extractMeasurements = (input: InputData): Measurement[] => {
return Object.values(input); return Object.values(input);
}; };
useEffect(() => { useEffect(() => {
const measurementsData = extractMeasurements(selections); const measurementsData = extractMeasurements(selections);
setMeasurements(measurementsData); setMeasurements(measurementsData);
}, [selections]); }, [selections]);
return ( return (
<> <>
<div className="inputs-wrapper"> <div className="inputs-wrapper">
{[...Array(6)].map((_, index) => { {[...Array(6)].map((_, index) => {
const inputKey = `input${index + 1}`; const inputKey = `input${index + 1}`;
return ( return (
<div key={index} className="datas"> <div key={index} className="datas">
<div className="datas__label">Input {index + 1}</div> <div className="datas__label">Input {index + 1}</div>
<div className="datas__class"> <div className="datas__class">
<MultiLevelDropdown <MultiLevelDropdown
data={dropDowndata} data={dropDowndata}
onSelect={(selectedData) => handleSelect(inputKey, selectedData)} onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
onUnselect={() => handleSelect(inputKey, null)} onUnselect={() => handleSelect(inputKey, null)}
selectedValue={selections[inputKey]} selectedValue={selections[inputKey]}
/> />
<div className="icon"> <div className="icon">
<AddIcon /> <AddIcon />
</div> </div>
</div> </div>
</div> </div>
); );
})} })}
</div> </div>
<div> <div>
<div className="datas"> <div className="datas">
<div className="datas__label">duration</div> <div className="datas__label">duration</div>
<div className="datas__class"> <div className="datas__class">
<RegularDropDown <RegularDropDown
header={duration} header={duration}
options={["1h", "2h", "12h"]} options={["1h", "2h", "12h"]}
onSelect={handleSelectDuration} onSelect={handleSelectDuration}
search={false} search={false}
/> />
</div> </div>
</div> </div>
</div> </div>
</> </>
) )
} }
export default LineGrapInput export default LineGrapInput

View File

@ -1,77 +1,77 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown' import MultiLevelDropdown from '../../../../ui/inputs/MultiLevelDropDown'
import { AddIcon } from '../../../../icons/ExportCommonIcons' import { AddIcon } from '../../../../icons/ExportCommonIcons'
import axios from 'axios' import axios from 'axios'
type Props = {} type Props = {}
const PieChartInput = (props: Props) => { const PieChartInput = (props: Props) => {
const [dropDowndata, setDropDownData] = useState({}) const [dropDowndata, setDropDownData] = useState({})
const [selections, setSelections] = useState<Record<string, {name: string, fields: string}>>({}) const [selections, setSelections] = useState<Record<string, {name: string, fields: string}>>({})
useEffect(() => { useEffect(() => {
const fetchZoneData = async () => { const fetchZoneData = async () => {
try { try {
const response = await axios.get('http://192.168.0.192:5010/getinput'); const response = await axios.get('http://192.168.0.192:5010/getinput');
if (response.status === 200) { if (response.status === 200) {
console.log('dropdown data:', response.data); console.log('dropdown data:', response.data);
setDropDownData(response.data) setDropDownData(response.data)
} else { } else {
console.log('Unexpected response:', response); console.log('Unexpected response:', response);
} }
} catch (error) { } catch (error) {
console.error('There was an error!', error); console.error('There was an error!', error);
} }
}; };
fetchZoneData(); fetchZoneData();
}, []); }, []);
useEffect(() => {console.log(selections); useEffect(() => {console.log(selections);
},[selections]) },[selections])
const handleSelect = (inputKey: string, selectedData: {name: string, fields: string} | null) => { const handleSelect = (inputKey: string, selectedData: {name: string, fields: string} | null) => {
setSelections(prev => { setSelections(prev => {
if (selectedData === null) { if (selectedData === null) {
const newSelections = {...prev}; const newSelections = {...prev};
delete newSelections[inputKey]; delete newSelections[inputKey];
return newSelections; return newSelections;
} else { } else {
return { return {
...prev, ...prev,
[inputKey]: selectedData [inputKey]: selectedData
}; };
} }
}); });
}; };
return ( return (
<> <>
<div className="inputs-wrapper"> <div className="inputs-wrapper">
{[...Array(3)].map((_, index) => { {[...Array(3)].map((_, index) => {
const inputKey = `input${index+1}`; const inputKey = `input${index+1}`;
return ( return (
<div key={index} className="datas"> <div key={index} className="datas">
<div className="datas__label">Input {index+1}</div> <div className="datas__label">Input {index+1}</div>
<div className="datas__class"> <div className="datas__class">
<MultiLevelDropdown <MultiLevelDropdown
data={dropDowndata} data={dropDowndata}
onSelect={(selectedData) => handleSelect(inputKey, selectedData)} onSelect={(selectedData) => handleSelect(inputKey, selectedData)}
onUnselect={() => handleSelect(inputKey, null)} onUnselect={() => handleSelect(inputKey, null)}
selectedValue={selections[inputKey]} selectedValue={selections[inputKey]}
/> />
<div className="icon"> <div className="icon">
<AddIcon /> <AddIcon />
</div> </div>
</div> </div>
</div> </div>
); );
})} })}
</div> </div>
<div> <div>
</div> </div>
</> </>
) )
} }
export default PieChartInput export default PieChartInput

View File

@ -6,15 +6,20 @@ import {
SimulationIcon, SimulationIcon,
VisualizationIcon, VisualizationIcon,
} from "../icons/ExportModuleIcons"; } from "../icons/ExportModuleIcons";
import useToggleStore from "../../store/useUIToggleStore";
const ModuleToggle: React.FC = () => { const ModuleToggle: React.FC = () => {
const { activeModule, setActiveModule } = useModuleStore(); const { activeModule, setActiveModule } = useModuleStore();
const { setToggleUI } = useToggleStore();
return ( return (
<div className="module-toggle-container"> <div className="module-toggle-container">
<div <div
className={`module-list ${activeModule === "builder" && "active"}`} className={`module-list ${activeModule === "builder" && "active"}`}
onClick={() => setActiveModule("builder")} onClick={() => {
setActiveModule("builder");
setToggleUI(true);
}}
> >
<div className="icon"> <div className="icon">
<BuilderIcon isActive={activeModule === "builder"} /> <BuilderIcon isActive={activeModule === "builder"} />
@ -23,7 +28,10 @@ const ModuleToggle: React.FC = () => {
</div> </div>
<div <div
className={`module-list ${activeModule === "simulation" && "active"}`} className={`module-list ${activeModule === "simulation" && "active"}`}
onClick={() => setActiveModule("simulation")} onClick={() => {
setActiveModule("simulation");
setToggleUI(true);
}}
> >
<div className="icon"> <div className="icon">
<SimulationIcon isActive={activeModule === "simulation"} /> <SimulationIcon isActive={activeModule === "simulation"} />
@ -34,7 +42,10 @@ const ModuleToggle: React.FC = () => {
className={`module-list ${ className={`module-list ${
activeModule === "visualization" && "active" activeModule === "visualization" && "active"
}`} }`}
onClick={() => setActiveModule("visualization")} onClick={() => {
setActiveModule("visualization");
setToggleUI(true);
}}
> >
<div className="icon"> <div className="icon">
<VisualizationIcon isActive={activeModule === "visualization"} /> <VisualizationIcon isActive={activeModule === "visualization"} />
@ -42,10 +53,11 @@ const ModuleToggle: React.FC = () => {
<div className="module">Visualization</div> <div className="module">Visualization</div>
</div> </div>
<div <div
className={`module-list ${ className={`module-list ${activeModule === "market" && "active"}`}
activeModule === "market" && "active" onClick={() => {
}`} setActiveModule("market");
onClick={() => setActiveModule("market")} setToggleUI(false);
}}
> >
<div className="icon"> <div className="icon">
<CartIcon isActive={activeModule === "market"} /> <CartIcon isActive={activeModule === "market"} />

View File

@ -17,7 +17,12 @@ import { handleSaveTemplate } from "../../modules/visualization/handleSaveTempla
import { usePlayButtonStore } from "../../store/usePlayButtonStore"; import { usePlayButtonStore } from "../../store/usePlayButtonStore";
import useTemplateStore from "../../store/useTemplateStore"; import useTemplateStore from "../../store/useTemplateStore";
import { useSelectedZoneStore } from "../../store/useZoneStore"; import { useSelectedZoneStore } from "../../store/useZoneStore";
import { useAddAction, useDeleteModels, useSelectedWallItem, useToggleView } from "../../store/store"; import {
useAddAction,
useDeleteModels,
useSelectedWallItem,
useToggleView,
} from "../../store/store";
const Tools: React.FC = () => { const Tools: React.FC = () => {
const { templates } = useTemplateStore(); const { templates } = useTemplateStore();
@ -39,7 +44,6 @@ const Tools: React.FC = () => {
const { setAddAction } = useAddAction(); const { setAddAction } = useAddAction();
const { setSelectedWallItem } = useSelectedWallItem(); const { setSelectedWallItem } = useSelectedWallItem();
// Reset activeTool whenever activeModule changes // Reset activeTool whenever activeModule changes
useEffect(() => { useEffect(() => {
setActiveTool(activeSubTool); setActiveTool(activeSubTool);
@ -52,8 +56,7 @@ const Tools: React.FC = () => {
setDeleteModels(false); setDeleteModels(false);
setAddAction(null); setAddAction(null);
setToggleView(true); setToggleView(true);
} } else {
else {
setToggleView(false); setToggleView(false);
} }
setToggleThreeD(!toggleThreeD); setToggleThreeD(!toggleThreeD);
@ -68,196 +71,225 @@ const Tools: React.FC = () => {
setOpenDrop(false); // Close the dropdown setOpenDrop(false); // Close the dropdown
} }
}; };
const handleEscKeyPress = (event: KeyboardEvent) => {
if (event.key === "Escape") {
setIsPlaying(false); // Set isPlaying to false when Escape key is pressed
}
};
document.addEventListener("mousedown", handleOutsideClick); document.addEventListener("mousedown", handleOutsideClick);
document.addEventListener("keydown", handleEscKeyPress); // Listen for ESC key
return () => { return () => {
document.removeEventListener("mousedown", handleOutsideClick); document.removeEventListener("mousedown", handleOutsideClick);
document.removeEventListener("keydown", handleEscKeyPress); // Clean up the event listener
}; };
}, []); }, []);
return ( return (
<div className="tools-container"> <>
<div className="drop-down-icons"> {!isPlaying ? (
<div className="activeDropicon"> <>
{activeSubTool == "cursor" && ( <div className="tools-container">
<div <div className="drop-down-icons">
className={`tool-button ${activeTool === "cursor" ? "active" : "" <div className="activeDropicon">
}`} {activeSubTool == "cursor" && (
onClick={() => {
setActiveTool("cursor");
}}
>
<CursorIcon isActive={activeTool === "cursor"} />
</div>
)}
{activeSubTool == "free-hand" && (
<div
className={`tool-button ${activeTool === "free-hand" ? "active" : ""
}`}
onClick={() => {
setActiveTool("free-hand");
}}
>
<FreeMoveIcon isActive={activeTool === "free-hand"} />
</div>
)}
{activeModule !== "visualization" && (
<div
className="drop-down-option-button"
ref={dropdownRef}
onClick={() => {
setOpenDrop(!openDrop);
console.log(openDrop);
}}
>
<ArrowIcon />
{openDrop && (
<div className="drop-down-container">
<div <div
className="option-list" className={`tool-button ${
activeTool === "cursor" ? "active" : ""
}`}
onClick={() => { onClick={() => {
setOpenDrop(false);
setActiveTool("cursor"); setActiveTool("cursor");
setActiveSubTool("cursor");
}} }}
> >
<div className="active-option"> <CursorIcon isActive={activeTool === "cursor"} />
{activeSubTool === "cursor" && <TickIcon />} </div>
</div> )}
<CursorIcon isActive={false} /> {activeSubTool == "free-hand" && (
<div className="option">Cursor</div> <div
className={`tool-button ${
activeTool === "free-hand" ? "active" : ""
}`}
onClick={() => {
setActiveTool("free-hand");
}}
>
<FreeMoveIcon isActive={activeTool === "free-hand"} />
</div>
)}
{activeModule !== "visualization" && (
<div
className="drop-down-option-button"
ref={dropdownRef}
onClick={() => {
setOpenDrop(!openDrop);
console.log(openDrop);
}}
>
<ArrowIcon />
{openDrop && (
<div className="drop-down-container">
<div
className="option-list"
onClick={() => {
setOpenDrop(false);
setActiveTool("cursor");
setActiveSubTool("cursor");
}}
>
<div className="active-option">
{activeSubTool === "cursor" && <TickIcon />}
</div>
<CursorIcon isActive={false} />
<div className="option">Cursor</div>
</div>
<div
className="option-list"
onClick={() => {
setOpenDrop(false);
setActiveTool("free-hand");
setActiveSubTool("free-hand");
}}
>
<div className="active-option">
{activeSubTool === "free-hand" && <TickIcon />}
</div>
<FreeMoveIcon isActive={false} />
<div className="option">Free Hand</div>
</div>
</div>
)}
</div>
)}
</div>
</div>
{!toggleThreeD && activeModule === "builder" && (
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button ${
activeTool === "draw-wall" ? "active" : ""
}`}
onClick={() => {
setActiveTool("draw-wall");
}}
>
<WallIcon isActive={activeTool === "draw-wall"} />
</div> </div>
<div <div
className="option-list" className={`tool-button ${
activeTool === "draw-zone" ? "active" : ""
}`}
onClick={() => { onClick={() => {
setOpenDrop(false); setActiveTool("draw-zone");
setActiveTool("free-hand");
setActiveSubTool("free-hand");
}} }}
> >
<div className="active-option"> <ZoneIcon isActive={activeTool === "draw-zone"} />
{activeSubTool === "free-hand" && <TickIcon />} </div>
</div> <div
<FreeMoveIcon isActive={false} /> className={`tool-button ${
<div className="option">Free Hand</div> activeTool === "draw-aisle" ? "active" : ""
}`}
onClick={() => {
setActiveTool("draw-aisle");
}}
>
<AsileIcon isActive={activeTool === "draw-aisle"} />
</div>
<div
className={`tool-button ${
activeTool === "draw-floor" ? "active" : ""
}`}
onClick={() => {
setActiveTool("draw-floor");
}}
>
<FloorIcon isActive={activeTool === "draw-floor"} />
</div> </div>
</div> </div>
)} </>
</div> )}
)} {activeModule === "simulation" && (
</div> <>
</div> <div className="split"></div>
{!toggleThreeD && activeModule === "builder" && ( <div className="draw-tools">
<> <div
<div className="split"></div> className={`tool-button ${
<div className="draw-tools"> activeTool === "pen" ? "active" : ""
<div }`}
className={`tool-button ${activeTool === "draw-wall" ? "active" : "" onClick={() => {
setActiveTool("pen");
}}
>
<PenIcon isActive={activeTool === "pen"} />
</div>
</div>
</>
)}
{activeModule === "visualization" && (
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button`}
onClick={() =>
handleSaveTemplate({
addTemplate,
selectedZone,
templates,
})
}
>
<SaveTemplateIcon isActive={false} />
</div>
</div>
</>
)}
<div className="split"></div>
<div className="general-options">
<div
className={`tool-button ${
activeTool === "comment" ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
setActiveTool("draw-wall"); setActiveTool("comment");
}} }}
> >
<WallIcon isActive={activeTool === "draw-wall"} /> <CommentIcon isActive={activeTool === "comment"} />
</div> </div>
<div <div
className={`tool-button ${activeTool === "draw-zone" ? "active" : "" className={`tool-button ${
activeTool === "play" ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
setActiveTool("draw-zone"); setIsPlaying(!isPlaying);
}} }}
> >
<ZoneIcon isActive={activeTool === "draw-zone"} /> <PlayIcon isActive={activeTool === "play"} />
</div>
</div> </div>
<div className="split"></div>
<div <div
className={`tool-button ${activeTool === "draw-aisle" ? "active" : "" className={`toggle-threed-button${
}`} toggleThreeD ? " toggled" : ""
onClick={() => { }`}
setActiveTool("draw-aisle"); onClick={toggleSwitch}
}}
> >
<AsileIcon isActive={activeTool === "draw-aisle"} /> <div className={`toggle-option${!toggleThreeD ? " active" : ""}`}>
</div> 2d
<div </div>
className={`tool-button ${activeTool === "draw-floor" ? "active" : "" <div className={`toggle-option${toggleThreeD ? " active" : ""}`}>
}`} 3d
onClick={() => { </div>
setActiveTool("draw-floor");
}}
>
<FloorIcon isActive={activeTool === "draw-floor"} />
</div> </div>
</div> </div>
</> </>
) : (
<div className="exitPlay" onClick={() => setIsPlaying(false)}>
X
</div>
)} )}
{activeModule === "simulation" && ( </>
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button ${activeTool === "pen" ? "active" : ""}`}
onClick={() => {
setActiveTool("pen");
}}
>
<PenIcon isActive={activeTool === "pen"} />
</div>
</div>
</>
)}
{activeModule === "visualization" && (
<>
<div className="split"></div>
<div className="draw-tools">
<div
className={`tool-button`}
onClick={() =>
handleSaveTemplate({
addTemplate,
selectedZone,
templates,
})
}
>
<SaveTemplateIcon isActive={false} />
</div>
</div>
</>
)}
<div className="split"></div>
<div className="general-options">
<div
className={`tool-button ${activeTool === "comment" ? "active" : ""}`}
onClick={() => {
setActiveTool("comment");
}}
>
<CommentIcon isActive={activeTool === "comment"} />
</div>
<div
className={`tool-button ${activeTool === "play" ? "active" : ""}`}
onClick={() => {
setActiveTool("play");
setIsPlaying(!isPlaying);
}}
>
<PlayIcon isActive={activeTool === "play"} />
</div>
</div>
<div className="split"></div>
<div
className={`toggle-threed-button${toggleThreeD ? " toggled" : ""}`}
onClick={toggleSwitch}
>
<div className={`toggle-option${!toggleThreeD ? " active" : ""}`}>
2d
</div>
<div className={`toggle-option${toggleThreeD ? " active" : ""}`}>
3d
</div>
</div>
</div>
); );
}; };

View File

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

View File

@ -152,21 +152,29 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
return ( return (
<div <div
ref={containerRef} ref={containerRef}
className={`zoon-wrapper ${ className={`zoon-wrapper ${selectedZone.activeSides.includes("bottom") && "bottom"
selectedZone.activeSides.includes("bottom") && "bottom" }`}
}`}
> >
{Object.keys(zonesData).map((zoneName, index) => ( {Object.keys(zonesData).map((zoneName, index) => (
<div <div
key={index} key={index}
className={`zone ${ className={`zone ${selectedZone.zoneName === zoneName ? "active" : ""
selectedZone.zoneName === zoneName ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
console.log('zoneName: ', zoneName);
setSelectedZone({ setSelectedZone({
zoneName, zoneName,
...zonesData[zoneName], activeSides: zonesData[zoneName].activeSides || [],
}); panelOrder: zonesData[zoneName].panelOrder || [],
lockedPanels: zonesData[zoneName].lockedPanels || [],
widgets: zonesData[zoneName].widgets || [],
})
// setSelectedZone({
// zoneName,
// ...zonesData[zoneName],
// });
console.log(selectedZone);
}} }}
> >
{zoneName} {zoneName}

View File

@ -1,138 +1,164 @@
import { useWidgetStore } from "../../../store/useWidgetStore"; import { useWidgetStore } from "../../../store/useWidgetStore";
import ProgressCard from "../realTimeVis/charts/ProgressCard"; import ProgressCard from "../realTimeVis/charts/ProgressCard";
import PieGraphComponent from "../realTimeVis/charts/PieGraphComponent"; import PieGraphComponent from "../realTimeVis/charts/PieGraphComponent";
import BarGraphComponent from "../realTimeVis/charts/BarGraphComponent"; import BarGraphComponent from "../realTimeVis/charts/BarGraphComponent";
import LineGraphComponent from "../realTimeVis/charts/LineGraphComponent"; import LineGraphComponent from "../realTimeVis/charts/LineGraphComponent";
import RadarGraphComponent from "../realTimeVis/charts/RadarGraphComponent"; import RadarGraphComponent from "../realTimeVis/charts/RadarGraphComponent";
import DoughnutGraphComponent from "../realTimeVis/charts/DoughnutGraphComponent"; import DoughnutGraphComponent from "../realTimeVis/charts/DoughnutGraphComponent";
import PolarAreaGraphComponent from "../realTimeVis/charts/PolarAreaGraphComponent"; import PolarAreaGraphComponent from "../realTimeVis/charts/PolarAreaGraphComponent";
export const DraggableWidget = ({ export const DraggableWidget = ({
widget, widget,
hiddenPanels, // Add this prop to track hidden panels hiddenPanels, // Add this prop to track hidden panels
}: { index, onReorder
widget: any; }: {
hiddenPanels: string[]; // Array of hidden panel names widget: any;
}) => { hiddenPanels: string[]; // Array of hidden panel names
// console.log("widget: ", widget.type); index: number; onReorder: (fromIndex: number, toIndex: number) => void
const { selectedChartId, setSelectedChartId } = useWidgetStore(); }) => {
const { selectedChartId, setSelectedChartId } = useWidgetStore();
const handlePointerDown = () => {
if (selectedChartId?.id !== widget.id) { const handlePointerDown = () => {
setSelectedChartId(widget); if (selectedChartId?.id !== widget.id) {
} setSelectedChartId(widget);
}; }
};
// Determine if the widget's panel is hidden
const isPanelHidden = hiddenPanels.includes(widget.panel); // Determine if the widget's panel is hidden
const isPanelHidden = hiddenPanels.includes(widget.panel);
return (
<> const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => {
<div event.dataTransfer.setData('text/plain', index.toString()); // Store the index of the dragged widget
key={widget.id} };
className={`chart-container ${ const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
selectedChartId?.id === widget.id && "activeChart" event.preventDefault(); // Allow drop
}`} };
onPointerDown={handlePointerDown}
style={{ const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
opacity: isPanelHidden ? 0 : 1, // Set opacity to 0 if the panel is hidden event.preventDefault(); // Allow drop
pointerEvents: isPanelHidden ? "none" : "auto", // Disable interaction when hidden };
}}
> const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
{/* Render charts based on widget type */} event.preventDefault();
{widget.type === "progress" && ( const fromIndex = parseInt(event.dataTransfer.getData('text/plain'), 10); // Get the dragged widget's index
<ProgressCard title={widget.title} data={widget.data} /> const toIndex = index; // The index of the widget where the drop occurred
)} if (fromIndex !== toIndex) {
{widget.type === "line" && ( onReorder(fromIndex, toIndex); // Call the reorder function passed as a prop
<LineGraphComponent }
type={widget.type} };
title={widget.title}
fontSize={widget.fontSize}
fontWeight={widget.fontWeight} return (
data={{ <>
measurements: [ <div
{ name: "testDevice", fields: "powerConsumption" }, draggable
{ name: "furnace", fields: "powerConsumption" }, key={widget.id}
], className={`chart-container ${selectedChartId?.id === widget.id && "activeChart"
interval: 1000, }`}
duration: "1h", onPointerDown={handlePointerDown}
}} onDragStart={handleDragStart}
/> onDragEnter={handleDragEnter}
)} onDragOver={handleDragOver}
{widget.type === "bar" && ( onDrop={handleDrop}
<BarGraphComponent style={{
type={widget.type} opacity: isPanelHidden ? 0 : 1, // Set opacity to 0 if the panel is hidden
title={widget.title} pointerEvents: isPanelHidden ? "none" : "auto", // Disable interaction when hidden
fontSize={widget.fontSize} }}
fontWeight={widget.fontWeight} >
data={{ {/* Render charts based on widget type */}
measurements: [ {widget.type === "progress" && (
{ name: "testDevice", fields: "powerConsumption" }, <ProgressCard title={widget.title} data={widget.data} />
{ name: "furnace", fields: "powerConsumption" }, )}
], {widget.type === "line" && (
interval: 1000, <LineGraphComponent
duration: "1h", type={widget.type}
}} title={widget.title}
/> fontSize={widget.fontSize}
)} fontWeight={widget.fontWeight}
{/* {widget.type === "radar" && ( data={{
<RadarGraphComponent measurements: [
type={widget.type} { name: "testDevice", fields: "powerConsumption" },
title={widget.title} { name: "furnace", fields: "powerConsumption" },
fontSize={widget.fontSize} ],
fontWeight={widget.fontWeight} interval: 1000,
data={widget.data.measurements.map((item: any) => item.fields)} duration: "1h",
/> }}
)} */} />
{widget.type === "pie" && ( )}
<PieGraphComponent {widget.type === "bar" && (
type={widget.type} <BarGraphComponent
title={widget.title} type={widget.type}
fontSize={widget.fontSize} title={widget.title}
fontWeight={widget.fontWeight} fontSize={widget.fontSize}
data={{ fontWeight={widget.fontWeight}
measurements: [ data={{
{ name: "testDevice", fields: "powerConsumption" }, measurements: [
{ name: "furnace", fields: "powerConsumption" }, { name: "testDevice", fields: "powerConsumption" },
], { name: "furnace", fields: "powerConsumption" },
interval: 1000, ],
duration: "1h", interval: 1000,
}} duration: "1h",
/> }}
)} />
{widget.type === "doughnut" && ( )}
<DoughnutGraphComponent {/* {widget.type === "radar" && (
type={widget.type} <RadarGraphComponent
title={widget.title} type={widget.type}
fontSize={widget.fontSize} title={widget.title}
fontWeight={widget.fontWeight} fontSize={widget.fontSize}
data={{ fontWeight={widget.fontWeight}
measurements: [ data={widget.data.measurements.map((item: any) => item.fields)}
{ name: "testDevice", fields: "powerConsumption" }, />
{ name: "furnace", fields: "powerConsumption" }, )} */}
], {widget.type === "pie" && (
interval: 1000, <PieGraphComponent
duration: "1h", type={widget.type}
}} title={widget.title}
/> fontSize={widget.fontSize}
)} fontWeight={widget.fontWeight}
{widget.type === "polarArea" && ( data={{
<PolarAreaGraphComponent measurements: [
type={widget.type} { name: "testDevice", fields: "powerConsumption" },
title={widget.title} { name: "furnace", fields: "powerConsumption" },
fontSize={widget.fontSize} ],
fontWeight={widget.fontWeight} interval: 1000,
data={{ duration: "1h",
measurements: [ }}
{ name: "testDevice", fields: "powerConsumption" }, />
{ name: "furnace", fields: "powerConsumption" }, )}
], {widget.type === "doughnut" && (
interval: 1000, <DoughnutGraphComponent
duration: "1h", type={widget.type}
}} title={widget.title}
/> fontSize={widget.fontSize}
)} fontWeight={widget.fontWeight}
</div> data={{
</> measurements: [
); { name: "testDevice", fields: "powerConsumption" },
}; { name: "furnace", fields: "powerConsumption" },
],
interval: 1000,
duration: "1h",
}}
/>
)}
{widget.type === "polarArea" && (
<PolarAreaGraphComponent
type={widget.type}
title={widget.title}
fontSize={widget.fontSize}
fontWeight={widget.fontWeight}
data={{
measurements: [
{ name: "testDevice", fields: "powerConsumption" },
{ name: "furnace", fields: "powerConsumption" },
],
interval: 1000,
duration: "1h",
}}
/>
)}
</div>
</>
);
};

View File

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

View File

@ -1,110 +1,147 @@
import React, { useEffect, useState, useRef } from "react"; import React, { useEffect, useState, useRef } from "react";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore"; import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
import Panel from "./Panel"; import Panel from "./Panel";
import AddButtons from "./AddButtons"; import AddButtons from "./AddButtons";
import { useSelectedZoneStore } from "../../../store/useZoneStore"; import { useSelectedZoneStore } from "../../../store/useZoneStore";
import DisplayZone from "./DisplayZone"; import DisplayZone from "./DisplayZone";
import Scene from "../../../modules/scene/scene"; import Scene from "../../../modules/scene/scene";
import useModuleStore from "../../../store/useModuleStore";
type Side = "top" | "bottom" | "left" | "right"; import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones";
interface Widget {
id: string; type Side = "top" | "bottom" | "left" | "right";
type: string;
title: string; type FormattedZoneData = Record<
panel: Side; string,
data: any; {
} activeSides: Side[];
panelOrder: Side[];
const RealTimeVisulization: React.FC = () => { lockedPanels: Side[];
const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]); zoneCentrePoint: number[];
const containerRef = useRef<HTMLDivElement>(null); widgets: Widget[];
const [zonesData, setZonesData] = useState<{ }
[key: string]: { >;
activeSides: Side[]; type Widget = {
panelOrder: Side[]; id: string;
lockedPanels: Side[]; type: string;
widgets: Widget[]; title: string;
}; panel: Side;
}>({ data: any;
"Manufacturing unit": { };
activeSides: [], type Zone = {
panelOrder: [], zoneId: string;
lockedPanels: [], zoneName: string;
widgets: [], points: number[][];
}, layer: number;
"Assembly unit": { };
activeSides: [],
panelOrder: [], const RealTimeVisulization: React.FC = () => {
lockedPanels: [], const [hiddenPanels, setHiddenPanels] = React.useState<Side[]>([]);
widgets: [], const containerRef = useRef<HTMLDivElement>(null);
}, const { isPlaying } = usePlayButtonStore();
"Packing unit": { const { activeModule } = useModuleStore();
activeSides: [],
panelOrder: [], const [zonesData, setZonesData] = useState<FormattedZoneData>({});
lockedPanels: [], const { selectedZone, setSelectedZone } = useSelectedZoneStore();
widgets: [],
}, useEffect(() => {
Warehouse: { async function GetZoneData() {
activeSides: [], try {
panelOrder: [], const response: { data: Zone[] } | undefined = await getZonesApi(
lockedPanels: [], "hexrfactory"
widgets: [], );
},
Inventory: { if (!response || !response.data) {
activeSides: [], return;
panelOrder: [], }
lockedPanels: [], const formattedData = response?.data?.reduce<FormattedZoneData>(
widgets: [], (acc, zone) => {
}, acc[zone.zoneName] = {
}); activeSides: [],
panelOrder: [],
const { isPlaying } = usePlayButtonStore(); lockedPanels: [],
zoneCentrePoint: [],
const { selectedZone, setSelectedZone } = useSelectedZoneStore(); widgets: [],
useEffect(() => { };
setZonesData((prev) => ({ return acc;
...prev, },
[selectedZone.zoneName]: selectedZone, {}
})); );
}, [selectedZone]); setZonesData(formattedData);
} catch (error) { }
return ( }
<div GetZoneData();
ref={containerRef} }, []);
id="real-time-vis-canvas"
className={`realTime-viz canvas ${!isPlaying ? "playActiveFalse" : ""}`} useEffect(() => {
style={{
height: isPlaying ? "100vh" : "", console.log('zonesData: ', zonesData);
left: isPlaying ? "0%" : "", }, [zonesData]);
}}
> useEffect(() => {
<div setZonesData((prev) => {
className="scene-container" if (!selectedZone) return prev;
style={{ height: "100%", width: "100%" }}
> return {
<Scene /> ...prev,
</div> [selectedZone.zoneName]: {
{!isPlaying && ( ...prev[selectedZone.zoneName], // Keep existing properties
<AddButtons activeSides: selectedZone.activeSides || [],
hiddenPanels={hiddenPanels} panelOrder: selectedZone.panelOrder || [],
setHiddenPanels={setHiddenPanels} lockedPanels: selectedZone.lockedPanels || [],
selectedZone={selectedZone} widgets: selectedZone.widgets || [],
setSelectedZone={setSelectedZone} },
/> };
)} });
<DisplayZone }, [selectedZone]);
zonesData={zonesData}
selectedZone={selectedZone} return (
setSelectedZone={setSelectedZone} <div
/> ref={containerRef}
<Panel id="real-time-vis-canvas"
selectedZone={selectedZone} className={`realTime-viz canvas ${isPlaying ? "playingFlase" : ""}`}
hiddenPanels={hiddenPanels} style={{
setSelectedZone={setSelectedZone} height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
/>{" "} width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
</div> left: isPlaying || activeModule !== "visualization" ? "0%" : "",
); }}
}; >
<div
export default RealTimeVisulization; className="scene-container"
style={{
height: "100%",
width: "100%",
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px",
}}
>
<Scene />
</div>
{activeModule === "visualization" && (
<>
<DisplayZone
zonesData={zonesData}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
{!isPlaying && (
<AddButtons
hiddenPanels={hiddenPanels}
setHiddenPanels={setHiddenPanels}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/>
)}
<Panel
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
hiddenPanels={hiddenPanels}
/>
</>
)}
</div>
);
};
export default RealTimeVisulization;

View File

@ -1,7 +1,8 @@
import React, { useState } from "react"; import React, { useEffect, useState } from "react";
import List from "./List"; import List from "./List";
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons"; import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect"; import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
import { getZonesApi } from "../../../services/realTimeVisulization/zoneData/getZones";
interface DropDownListProps { interface DropDownListProps {
value?: string; // Value to display in the DropDownList value?: string; // Value to display in the DropDownList
@ -33,6 +34,19 @@ const DropDownList: React.FC<DropDownListProps> = ({
const handleToggle = () => { const handleToggle = () => {
setIsOpen((prev) => !prev); // Toggle the state setIsOpen((prev) => !prev); // Toggle the state
}; };
const [zoneDataList, setZoneDataList] = useState<{ id: string; name: string }[]>([]);
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()
}, [])
return ( return (
<div className="dropdown-list-container"> <div className="dropdown-list-container">
@ -79,7 +93,7 @@ const DropDownList: React.FC<DropDownListProps> = ({
value="Zones" value="Zones"
showKebabMenu={false} showKebabMenu={false}
showAddIcon={false} showAddIcon={false}
items={[]} items={zoneDataList}
/> />
</> </>
)} )}

View File

@ -8,6 +8,7 @@ interface ListProps {
} }
const List: React.FC<ListProps> = ({ items = [] }) => { const List: React.FC<ListProps> = ({ items = [] }) => {
console.log('items: ', items);
return ( return (
<> <>
{items.length > 0 ? ( {items.length > 0 ? (

View File

@ -128,6 +128,25 @@ const ZoneGroup: React.FC = () => {
const userId = localStorage.getItem('userId'); const userId = localStorage.getItem('userId');
const organization = (email!.split("@")[1]).split(".")[0]; const organization = (email!.split("@")[1]).split(".")[0];
const calculateCenter = (points: number[][]) => {
if (!points || points.length === 0) return null;
let sumX = 0, sumY = 0, sumZ = 0;
const numPoints = points.length;
points.forEach(([x, y, z]) => {
sumX += x;
sumY += y;
sumZ += z;
});
return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
};
const target: [number, number, number] | null = calculateCenter(zone.points);
if (!target) return;
const position = [target[0], 75, target[2]];
const input = { const input = {
userId: userId, userId: userId,
organization: organization, organization: organization,
@ -135,6 +154,8 @@ const ZoneGroup: React.FC = () => {
zoneName: zone.zoneName, zoneName: zone.zoneName,
zoneId: zone.zoneId, zoneId: zone.zoneId,
points: zone.points, points: zone.points,
viewPortCenter: target,
viewPortposition: position,
layer: zone.layer layer: zone.layer
} }
} }
@ -148,6 +169,25 @@ const ZoneGroup: React.FC = () => {
const userId = localStorage.getItem('userId'); const userId = localStorage.getItem('userId');
const organization = (email!.split("@")[1]).split(".")[0]; const organization = (email!.split("@")[1]).split(".")[0];
const calculateCenter = (points: number[][]) => {
if (!points || points.length === 0) return null;
let sumX = 0, sumY = 0, sumZ = 0;
const numPoints = points.length;
points.forEach(([x, y, z]) => {
sumX += x;
sumY += y;
sumZ += z;
});
return [sumX / numPoints, sumY / numPoints, sumZ / numPoints] as [number, number, number];
};
const target: [number, number, number] | null = calculateCenter(zone.points);
if (!target) return;
const position = [target[0], 75, target[2]];
const input = { const input = {
userId: userId, userId: userId,
organization: organization, organization: organization,
@ -155,6 +195,8 @@ const ZoneGroup: React.FC = () => {
zoneName: zone.zoneName, zoneName: zone.zoneName,
zoneId: zone.zoneId, zoneId: zone.zoneId,
points: zone.points, points: zone.points,
viewPortCenter: target,
viewPortposition: position,
layer: zone.layer layer: zone.layer
} }
} }
@ -162,6 +204,7 @@ const ZoneGroup: React.FC = () => {
socket.emit('v2:zone:set', input); socket.emit('v2:zone:set', input);
}; };
const deleteZoneFromBackend = async (zoneId: string) => { const deleteZoneFromBackend = async (zoneId: string) => {
const email = localStorage.getItem('email'); const email = localStorage.getItem('email');

View File

@ -0,0 +1,57 @@
import React from "react";
import {
CommentsIcon,
DownloadIcon,
EyeIconBig,
StarsIconSmall,
VerifiedIcon,
} from "../../components/icons/marketPlaceIcons";
import assetImage from "../../assets/image/image.png";
const Card: React.FC = () => {
return (
<div className="card-container">
<div className="icon">
<DownloadIcon />
</div>
<div className="image-container">
<img src={assetImage} alt="" />
</div>
<div className="assets-container">
<div className="name-container">
<div className="asstes-container">Asset name</div>
<div className="assets-date">Uploaded on-12 Jan 23</div>
</div>
<div className="details">
<div className="content">
<EyeIconBig />
1.5k
</div>
<div className="content">
<CommentsIcon />
32
</div>
</div>
</div>
<div className="vendor-icon">
HEXR FACTORY <VerifiedIcon />
</div>
<div className="stars-container">
<div className="stars-wrapper">
<StarsIconSmall />
<StarsIconSmall />
<StarsIconSmall />
<StarsIconSmall />
<StarsIconSmall />
</div>
<div className="units">
36,500/<span>unit</span>
</div>
</div>
<div className="buy-now-button">Buy now</div>
</div>
);
};
export default Card;

View File

@ -0,0 +1,18 @@
import React from "react";
import Card from "./Card";
const CardsContainer: React.FC = () => {
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
return (
<div className="cards-container-container">
<div className="header">Products You May Like</div>
<div className="cards-wrapper-container">
{array.map((index) => (
<Card key={index} />
))}
</div>
</div>
);
};
export default CardsContainer;

View File

@ -0,0 +1,39 @@
import React, { useState } from "react";
// import RegularDropDown from "./ui/inputs/RegularDropDown";
import Search from "../../components/ui/inputs/Search";
import { StarsIcon } from "../../components/icons/marketPlaceIcons";
import RegularDropDown from "../../components/ui/inputs/RegularDropDown";
const FilterSearch: React.FC = () => {
const [activeOption, setActiveOption] = useState("Sort by"); // State for active option
const handleSelect = (option: string) => {
setActiveOption(option);
};
return (
<div className="filter-search-container">
<Search onChange={() => {}} />
<RegularDropDown
header={activeOption}
options={["Alphabet ascending", "Alphabet descending", ""]}
onSelect={handleSelect}
search={false}
/>
<div className="button">Free</div>
<div className="button">Animated</div>
<div className="rating-container">
<div className="label">Rating</div>
<div className="stars">
<StarsIcon />
<StarsIcon />
<StarsIcon />
<StarsIcon />
<StarsIcon />
</div>
</div>
</div>
);
};
export default FilterSearch;

View File

@ -0,0 +1,18 @@
import React from "react";
import FilterSearch from "./FilterSearch";
import CardsContainer from "./CardsContainer";
const MarketPlace = () => {
return (
<div className="marketplace-wrapper">
<div className="marketplace-container">
<div className="marketPlace">
<FilterSearch />
<CardsContainer />
</div>
</div>
</div>
);
};
export default MarketPlace;

View File

@ -17,13 +17,14 @@ import {
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { usePlayButtonStore } from "../store/usePlayButtonStore"; import { usePlayButtonStore } from "../store/usePlayButtonStore";
import SimulationUI from "../modules/simulation/simulationUI"; import SimulationUI from "../modules/simulation/simulationUI";
import MarketPlace from "../modules/market/MarketPlace";
const Project: React.FC = () => { const Project: React.FC = () => {
let navigate = useNavigate(); let navigate = useNavigate();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { userName, setUserName } = useUserName(); const { setUserName } = useUserName();
const { organization, setOrganization } = useOrganization(); const { setOrganization } = useOrganization();
const { setFloorItems } = useFloorItems(); const { setFloorItems } = useFloorItems();
const { setWallItems } = useWallItems(); const { setWallItems } = useWallItems();
const { setZones } = useZones(); const { setZones } = useZones();
@ -49,22 +50,17 @@ const Project: React.FC = () => {
return ( return (
<div className="project-main"> <div className="project-main">
<ModuleToggle /> {!isPlaying && (
<>
{!isPlaying && <SideBarLeft />} <ModuleToggle />
{!isPlaying && <SideBarRight />} <SideBarLeft />
{activeModule === "visualization" && <RealTimeVisulization />} <SideBarRight />
{/* {activeModule !== "visualization" && <Scene />} */} </>
<Tools /> )}
{activeModule === "market" && <MarketPlace />}
{/* <Scene /> */} <RealTimeVisulization />
{activeModule !== "market" && <Tools />}
{/* <SimulationUI /> */} {/* <SimulationUI /> */}
<div
className="canvas-container"
style={{ height: "100vh", width: "100vw" }}
>
{activeModule !== "visualization" && <Scene />}
</div>
</div> </div>
); );
}; };

View File

@ -141,7 +141,7 @@ const UserAuth: React.FC = () => {
</div> </div>
{!isSignIn && ( {!isSignIn && (
<div className="policy-checkbox"> <div className="policy-checkbox">
<input type="checkbox" name="" id="" /> <input type="checkbox" name="" id="" required/>
<div className="label"> <div className="label">
I have read and agree to the terms of service I have read and agree to the terms of service
</div> </div>

View File

@ -0,0 +1,25 @@
let url_Backend_dwinzo = `http://185.100.212.76:5000`;
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",
},
});
// 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");
}
}
};

View File

@ -1,28 +1,28 @@
import { create } from "zustand"; import { create } from "zustand";
interface Measurement { interface Measurement {
name: string; name: string;
fields: string; fields: string;
} }
interface MeasurementStore { interface MeasurementStore {
measurements: Measurement[]; measurements: Measurement[];
interval: number; interval: number;
duration: string; duration: string;
setMeasurements: (newMeasurements: Measurement[]) => void; setMeasurements: (newMeasurements: Measurement[]) => void;
updateDuration: (newDuration: string) => void; updateDuration: (newDuration: string) => void;
} }
const useChartStore = create<MeasurementStore>((set) => ({ const useChartStore = create<MeasurementStore>((set) => ({
measurements: [], measurements: [],
interval: 1000, interval: 1000,
duration: "1h", duration: "1h",
setMeasurements: (newMeasurements) => setMeasurements: (newMeasurements) =>
set(() => ({ measurements: newMeasurements })), set(() => ({ measurements: newMeasurements })),
updateDuration: (newDuration) => updateDuration: (newDuration) =>
set(() => ({ duration: newDuration })), set(() => ({ duration: newDuration })),
})); }));
export default useChartStore; export default useChartStore;

View File

@ -6,7 +6,7 @@ interface ModuleStore {
} }
const useModuleStore = create<ModuleStore>((set) => ({ const useModuleStore = create<ModuleStore>((set) => ({
activeModule: "visualization", // Initial state activeModule: "builder", // Initial state
setActiveModule: (module) => set({ activeModule: module }), // Update state setActiveModule: (module) => set({ activeModule: module }), // Update state
})); }));

View File

@ -25,7 +25,7 @@ interface SelectedZoneStore {
export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({ export const useSelectedZoneStore = create<SelectedZoneStore>((set) => ({
selectedZone: { selectedZone: {
zoneName: "Manufacturing unit", zoneName: "",
activeSides: [], activeSides: [],
panelOrder: [], panelOrder: [],
lockedPanels: [], lockedPanels: [],

View File

@ -0,0 +1,187 @@
@use "../../abstracts/variables" as *;
@use "../../abstracts/mixins.scss" as *;
.marketplace-wrapper {
height: 100vh;
width: 100vw;
z-index: #{$z-index-marketplace};
background-color: var(--background-color-secondary);
position: absolute;
left: 0;
padding: 100px 50px;
.marketplace-container {
padding: 20px 2px;
height: calc(100vh - 120px);
background-color: var(--background-color);
box-shadow: #{$box-shadow-medium};
border-radius: #{$border-radius-extra-large};
}
.marketPlace {
width: 100%;
height: 100%;
overflow: auto;
left: calc(120px / 2);
top: 100px;
padding: 14px;
padding-bottom: 60px;
display: flex;
flex-direction: column;
gap: 24px;
.filter-search-container {
width: 100%;
display: flex;
align-items: center;
gap: 12px;
.search-wrapper {
min-width: 60%;
max-width: 684px;
padding: 0;
border-radius: $border-radius-large ;
.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;
}
.button {
padding: 5px 20px;
border: 1px solid var(--accent-color);
border-radius: 14px;
}
.rating-container {
display: flex;
align-items: center;
gap: 6px;
.stars {
display: flex;
align-items: center;
}
}
}
.cards-container-container {
padding: 0px 20px;
display: flex;
flex-direction: column;
gap: 6px;
.header {
color: var(--text-color);
font-weight: $medium-weight;
font-size: $xlarge;
}
.cards-wrapper-container {
display: flex;
flex-wrap: wrap;
gap: 28px;
.card-container {
width: calc(25% - 23px);
border-radius: 18px;
padding: 12px;
box-shadow: 0px 2px 10.5px 0px #0000000D;
border: 1px solid var(--background-accent-transparent, #E0DFFF80);
position: relative;
display: flex;
flex-direction: column;
justify-content: center;
gap: 6px;
.icon {
position: absolute;
top: 12px;
left: 12px;
width: 30px;
height: 30px;
border-radius: 10px;
padding: 5px;
background-color: var(--accent-color);
}
.image-container {
width: 100%;
display: flex;
justify-content: center;
}
.assets-container {
display: flex;
justify-content: space-between;
.name-container {
display: flex;
flex-direction: column;
gap: 3px;
.asstes-container {
font-weight: #{$bold-weight};
font-size: $regular ;
}
.assets-date {
color: var(--accent-color);
font-size: $small;
}
}
.details {
display: flex;
align-items: center;
gap: 10px;
.content {
display: flex;
align-items: center;
gap: 6px;
}
}
}
.vendor-icon {
font-weight: #{$bold-weight};
font-size: $regular ;
}
.stars-container {
display: flex;
justify-content: space-between;
}
.buy-now-button {
width: 100%;
background-color: var(--background-color-secondary);
border-radius: $border-radius-extra-large ;
padding: 8px 0;
@include flex-center;
color: var(--accent-color);
&:hover {
cursor: pointer;
}
}
}
}
}
}
}

View File

@ -14,7 +14,8 @@
width: fit-content; width: fit-content;
transition: width 0.2s; transition: width 0.2s;
background-color: var(--background-color); background-color: var(--background-color);
z-index: #{$z-index-tools}; z-index: #{$z-index-default};
.split { .split {
height: 20px; height: 20px;
width: 2px; width: 2px;
@ -79,6 +80,7 @@
padding: 8px; padding: 8px;
border-radius: #{$border-radius-large}; border-radius: #{$border-radius-large};
background: var(--background-color); background: var(--background-color);
.option-list { .option-list {
margin: 4px 0; margin: 4px 0;
display: flex; display: flex;
@ -149,28 +151,36 @@
} }
} }
.exitPlay {
width: 30px;
height: 30px;
border-radius: 50%;
background-color: var(--accent-color);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
position: relative;
transition: background-color 0.3s, transform 0.3s;
color: var(--background-color);
}
.exitPlay:hover {
background-color: var(--accent-color);
transform: scale(1.1);
}
} }
.exitPlay {
width: 30px;
height: 30px;
border-radius: 50%;
background-color: var(--accent-color);
cursor: pointer;
@include flex-center;
position: fixed;
bottom: 60px;
left: 50%;
transform: translate(-50%, 0);
transition: background-color 0.3s, transform 0.3s;
color: var(--background-color);
// transform: none;
z-index: 100;
&:hover {
background-color: var(--accent-color);
}
}
@keyframes expandWidth { @keyframes expandWidth {
from { from {
width: 0; width: 0;

View File

@ -662,16 +662,30 @@
.collapse-header-container { .collapse-header-container {
@include flex-space-between; @include flex-space-between;
padding-right: 12px; padding-right: 12px;
margin-top: 8px;
border-top: 1px solid var(--border-color);
border-bottom: 1px solid var(--border-color);
.header {
color: var(--accent-color);
}
} }
.process-container { .process-container {
padding: 0 12px;
margin: 6px 0;
.value { .value {
@include flex-space-between;
.arrow-container { .arrow-container {
height: 16px;
width: 16px;
} }
.active { .active {
rotate: 90deg;
} }
} }
.children-drop { .children-drop {
.value { .value {
padding: 6px;
border-left: 1px solid var(--border-color);
} }
} }
} }
@ -716,12 +730,17 @@
} }
.global-properties-container, .global-properties-container,
.analysis-main-container, .analysis-main-container,
.asset-properties-container { .asset-properties-container,
.zone-properties-container {
.header { .header {
@include flex-space-between;
padding: 8px 12px; padding: 8px 12px;
border-top: 1px solid var(--highlight-accent-color); border-top: 1px solid var(--highlight-accent-color);
border-bottom: 1px solid var(--highlight-accent-color); border-bottom: 1px solid var(--highlight-accent-color);
color: var(--accent-color); color: var(--accent-color);
.input-value {
color: inherit;
}
} }
.input-container { .input-container {
@include flex-center; @include flex-center;
@ -740,7 +759,8 @@
} }
} }
.optimize-button, .optimize-button,
.generate-report-button { .generate-report-button,
.button-save {
@include flex-center; @include flex-center;
background-color: var(--accent-color); background-color: var(--accent-color);
color: var(--primary-color); color: var(--primary-color);
@ -759,7 +779,11 @@
} }
.custom-input-container { .custom-input-container {
.header { .header {
@include flex-space-between;
border: none; border: none;
.eyedrop-button {
@include flex-center;
}
} }
.inputs-container { .inputs-container {
@include flex-space-between; @include flex-space-between;

View File

@ -21,6 +21,7 @@
@use 'components/visualization/floating/energyConsumed'; @use 'components/visualization/floating/energyConsumed';
@use 'components/visualization/ui/styledWidgets'; @use 'components/visualization/ui/styledWidgets';
@use './components/visualization/floating/common'; @use './components/visualization/floating/common';
@use './components/marketPlace/marketPlace.scss';
// layout // layout
@use 'layout/loading'; @use 'layout/loading';

View File

@ -1,284 +1,403 @@
@use "../abstracts/variables.scss" as *; @use "../abstracts/variables.scss" as *;
@use "../abstracts/mixins.scss" as *;
// Main Container
// Main Container .realTime-viz {
.realTime-viz { background-color: var(--background-color);
background-color: var(--background-color); border-radius: 20px;
border-radius: 20px; box-shadow: $box-shadow-medium;
box-shadow: $box-shadow-medium; width: calc(100% - (320px + 270px + 90px));
width: 100%; height: calc(100% - (200px + 80px));
height: 100%; position: absolute;
position: absolute; top: 50%;
top: 0; left: calc(270px + 45px);
left: 0; transform: translate(0, -50%);
transform: scale(1); border-radius: #{$border-radius-medium};
.scene-container { transition: all 0.2s;
width: 100%; z-index: #{$z-index-default};
height: 100%;
.scene-container {
canvas { overflow: hidden;
width: 100vw !important; }
height: 100% !important;
.icon {
} display: flex;
} align-items: center;
// Panels position: relative;
.panel { }
position: absolute;
background: white; .icons-container {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); .icon {
transition: all 0.3s ease; &:first-child {
border-radius: 6px; &::after {
overflow: hidden; display: none;
}
.panel-content { }
position: relative; }
height: 100%; }
padding: 10px;
overflow: auto; .zoon-wrapper {
display: flex; display: flex;
flex-direction: column; background-color: var(--background-color);
gap: 10px; position: absolute;
background-color: var(--background-color); bottom: 10px;
left: 50%;
&::-webkit-scrollbar { transform: translate(-50%, 0);
display: none; gap: 6px;
} padding: 4px;
border-radius: 8px;
.chart-container { max-width: 80%;
width: 229px; overflow: auto;
height: 200px; max-width: calc(100% - 450px);
max-height: 100%; &::-webkit-scrollbar {
border: 1px dotted #a9a9a9; display: none;
border-radius: 8px; }
box-shadow: 0px 2px 6px 0px rgba(60, 60, 67, 0.1);
padding: 6px 0; .zone {
background-color: white; width: auto;
} background-color: var(--background-color);
border-radius: 6px;
.close-btn { padding: 4px 8px;
position: absolute; white-space: nowrap;
top: 5px; font-size: $small;
right: 5px; }
background: none;
border: none; .active {
cursor: pointer; background-color: var(--accent-color);
color: var(--primary-color); color: var(--background-color);
} // color: #FCFDFD !important;
} }
} }
// Panels for each side .zoon-wrapper.bottom {
.left-panel, bottom: 210px;
.right-panel { }
.chart-container {
padding: 10px; @media (max-width: 1024px) {
width: 100% !important; width: 80%; // Increase width to take more space on smaller screens
height: 250px !important; height: 500px; // Reduce height to fit smaller screens
left: 50%; // Center horizontally
}
} .main-container {
margin: 0 15px; // Reduce margin for better spacing
.top-panel, }
.bottom-panel {
.chart-container { .zoon-wrapper {
padding: 10px; bottom: 5px; // Adjust position for smaller screens
width: 300px !important;
height: 100% !important; &.bottom {
} bottom: 150px; // Adjust for bottom placement
} }
}
// Zone Wrapper }
.zoon-wrapper {
display: flex; .content-container {
background-color: var(--background-color); display: flex;
position: absolute; height: 100vh;
bottom: 10px; transition: all 0.3s ease;
left: 50%; }
transform: translate(-50%, 0);
gap: 6px; .main-container {
padding: 4px; position: relative;
border-radius: 8px; flex: 1;
max-width: 80%; height: 600px;
overflow: auto; background-color: rgb(235, 235, 235);
max-width: calc(100% - 450px); margin: 0 30px;
z-index: 11000000000; transition: height 0.3s ease, margin 0.3s ease;
&::-webkit-scrollbar { .zoon-wrapper {
display: none; display: flex;
} background-color: rgba(224, 223, 255, 0.5);
position: absolute;
.zone { bottom: 10px;
width: auto; left: 50%;
background-color: var(--background-color); transform: translate(-50%, 0);
border-radius: 6px; gap: 6px;
padding: 4px 8px; padding: 4px;
white-space: nowrap; border-radius: 8px;
font-size: $small; max-width: 80%;
} overflow: auto;
transition: transform 0.3s ease;
.active {
background-color: var(--accent-color); &::-webkit-scrollbar {
color: var(--background-color); display: none;
} }
}
.zone {
.zoon-wrapper.bottom { width: auto;
bottom: 250px; background-color: $background-color;
} border-radius: 6px;
padding: 4px 8px;
.content-container { white-space: nowrap;
display: flex; cursor: pointer;
height: 100vh; transition: background-color 0.3s ease;
transition: all 0.3s ease;
} &.active {
background-color: var(--primary-color);
.main-container { color: var(--accent-color);
position: relative; }
flex: 1; }
height: 600px;
background-color: rgb(235, 235, 235); &.bottom {
margin: 0 30px; bottom: 210px;
transition: height 0.3s ease, margin 0.3s ease; }
} }
} }
.playActiveFalse { .panel {
position: absolute; position: absolute;
top: 50%; background: white;
left: calc(270px + 45px); box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
transform-origin: left; transition: all 0.3s ease;
transform: translate(0, -50%) scaleX(0.6) scaleY(0.65); border-radius: 6px;
width: calc((100vw * 1.65) - (320px + 270px + 70px) / 0.6); overflow: visible !important;
z-index: 100;
.panel-content {
.scene-container { position: relative;
width: 100%; height: 100%;
height: 100%; padding: 10px;
overflow: auto;
canvas { display: flex;
width: calc((100vw * 1.65) - (320px + 270px + 70px) / 0.6) !important; flex-direction: column;
height: 100% !important; gap: 10px;
background-color: var(--background-color);
}
} &::-webkit-scrollbar {
display: none;
&.top { }
transform: scale(1.5);
} .chart-container {
width: 100%;
&.right { height: 24% !important;
transform: scale(1.5);
} min-height: 150px;
max-height: 100%;
&.bottom { border: 1px dotted #a9a9a9;
transform: scale(1.5); border-radius: 8px;
} box-shadow: 0px 2px 6px 0px rgba(60, 60, 67, 0.1);
padding: 6px 0;
&.left { background-color: white;
transform: scale(1.5); }
}
.close-btn {
.zoon-wrapper { position: absolute;
transform: translate(-50%, 0) scale(1.5); top: 5px;
} right: 5px;
} background: none;
border: none;
cursor: pointer;
// Side Buttons color: var(--primary-color);
.side-button-container { }
position: absolute; }
display: flex;
background-color: var(--background-color); &.top-panel,
padding: 5px; &.bottom-panel {
border-radius: 8px; left: 0;
transition: transform 0.3s ease; right: 0;
.extra-Bs {
display: flex;
align-items: center; .panel-content {
gap: 12px; display: flex;
flex-direction: row;
.icon { height: 100%;
display: flex;
align-items: center; .chart-container {
justify-content: center; height: 100% !important;
width: 18px; width: 20%;
height: 18px; min-width: 150px;
border-radius: 4px; }
} }
}
.active {
background-color: var(--accent-color); &.top-panel {
} top: 0;
}
&:hover {
cursor: pointer; &.bottom-panel {
} bottom: 0;
} }
.side-button { &.left-panel {
cursor: pointer; left: 0;
transition: background-color 0.3s ease; top: 0;
width: 18px; bottom: 0;
height: 18px;
display: flex; .chart-container {
justify-content: center; width: 100%;
background-color: var(--accent-color); height: 180px;
border: none; }
color: var(--background-color); }
border-radius: 4px;
} &.right-panel {
right: 0;
&.top { top: 0;
top: -35px; bottom: 0;
left: 50%; }
transform: translateX(-50%); }
flex-direction: row; }
gap: 6px;
transform: scale(1.5); .playingFlase{
} .zoon-wrapper{
bottom: 300px !important;
&.right { }
right: -35px; }
top: 50%; // Side Buttons
transform: translateY(-50%); .side-button-container {
flex-direction: column; position: absolute;
gap: 6px; display: flex;
transform: scale(1.5); background-color: var(--background-color);
} padding: 5px;
border-radius: 8px;
&.bottom { transition: transform 0.3s ease;
bottom: -35px;
left: 50%; .extra-Bs {
transform: translateX(-50%); display: flex;
flex-direction: row; align-items: center;
gap: 6px; gap: 12px;
transform: scale(1.5);
} .icon {
display: flex;
&.left { align-items: center;
left: -35px; justify-content: center;
top: 50%; width: 18px;
transform: translateY(-50%); height: 18px;
flex-direction: column; border-radius: 4px;
gap: 6px; }
transform: scale(1.5);
} .active {
} background-color: var(--accent-color);
}
.right.side-button-container,
.left.side-button-container { &:hover {
.extra-Bs { cursor: pointer;
flex-direction: column; }
} }
}
.side-button {
.top-panel, cursor: pointer;
.bottom-panel { transition: background-color 0.3s ease;
.panel-content { width: 18px;
height: 18px;
display: flex; display: flex;
flex-direction: row !important; justify-content: center;
} // align-items: center;
} background-color: var(--accent-color);
border: none;
color: var(--background-color);
border-radius: 4px;
}
&.top {
top: -30px;
left: 50%;
transform: translateX(-50%);
flex-direction: row;
gap: 6px;
}
&.right {
right: -30px;
top: 50%;
transform: translateY(-50%);
flex-direction: column;
gap: 6px;
}
&.bottom {
bottom: -30px;
left: 50%;
transform: translateX(-50%);
flex-direction: row;
gap: 6px;
}
&.left {
left: -30px;
top: 50%;
transform: translateY(-50%);
flex-direction: column;
gap: 6px;
}
}
.right.side-button-container {
.extra-Bs {
flex-direction: column;
}
}
.left.side-button-container {
.extra-Bs {
flex-direction: column;
}
}
// Theme Container
.theme-container {
width: 250px;
padding: 12px;
box-shadow: 1px -3px 4px 0px rgba(0, 0, 0, 0.11);
border-radius: 8px;
background-color: white;
position: absolute;
top: 20px;
right: -100%;
transform: translate(-0%, 0);
h2 {
font-size: 12px;
margin-bottom: 8px;
color: #2b3344;
}
.theme-preset-wrapper {
display: flex;
gap: 5px;
flex-wrap: wrap;
.theme-preset {
display: flex;
gap: 2px;
margin-bottom: 10px;
border: 1px solid $border-color;
padding: 5px 10px;
border-radius: 4px;
transition: border 0.3s ease;
&.active {
border: 1px solid var(--primary-color);
&::after {
content: "";
position: absolute;
top: 1px;
left: 1px;
width: 10px;
height: 10px;
background-color: var(--primary-color);
border-radius: 50%;
}
}
}
}
.custom-color {
display: flex;
justify-content: space-between;
.color-displayer {
display: flex;
gap: 5px;
align-items: center;
border: 1px solid var(--accent-color);
border-radius: 4px;
padding: 0 5px;
input {
border: none;
outline: none;
border-radius: 50%;
}
}
}
}

View File

@ -1,24 +1,24 @@
services: services:
frontend: frontend:
build: build:
context: ./app context: ./app
dockerfile: Dockerfile dockerfile: Dockerfile
args: args:
- REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000 - REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000
- REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000 - REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000
- REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011 - REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011
container_name: dwinzo-beta container_name: dwinzo-beta
stdin_open: true stdin_open: true
tty: true tty: true
ports: ports:
- "8200:3000" - "8200:3000"
environment: environment:
- WDS_SOCKET_PORT=0 - WDS_SOCKET_PORT=0
- PORT=3000 - PORT=3000
- DOCSIFY_PORT=8201 - DOCSIFY_PORT=8201
volumes: volumes:
- ./app:/app - ./app:/app
volumes: volumes:
frontend: frontend:
driver: local driver: local