Merge pull request 'ui' (#12) from ui into main

Reviewed-on: http://185.100.212.76:7776/Dwinzo-Beta/Dwinzo_dev/pulls/12
This commit was merged in pull request #12.
This commit is contained in:
2025-03-27 10:47:46 +00:00
27 changed files with 1717 additions and 642 deletions

58
app/.gitignore vendored
View File

@@ -1,29 +1,29 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies # dependencies
/node_modules /node_modules
# /package-lock.json # /package-lock.json
/.pnp /.pnp
.pnp.js .pnp.js
# testing # testing
/coverage /coverage
# production # production
/build /build
# misc # misc
.DS_Store .DS_Store
.env.local .env.local
.env.development.local .env.development.local
.env.test.local .env.test.local
.env.production.local .env.production.local
npm-debug.log* npm-debug.log*
yarn-debug.log* yarn-debug.log*
yarn-error.log* yarn-error.log*
# remove zip # remove zip
*.zip *.zip
**/temp/ **/temp/

View File

@@ -8,8 +8,8 @@ export function ThroughputIcon() {
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path
fill-rule="evenodd" fillRule="evenodd"
clip-rule="evenodd" clipRule="evenodd"
d="M10.124 7.90083L10.4726 8.94104L10.7027 9.64579C11.3046 11.5148 11.5973 12.6497 11.5973 13.1545C11.5973 14.3435 10.6334 15.3073 9.44448 15.3073C8.25553 15.3073 7.2917 14.3435 7.2917 13.1545C7.2917 12.5891 7.65886 11.2334 8.41633 8.94104L8.76493 7.90083C8.98524 7.25142 9.90372 7.25142 10.124 7.90083ZM9.44448 2.39062C13.4076 2.39062 16.6204 5.6034 16.6204 9.56655C16.6204 11.0058 16.1951 12.3836 15.4109 13.5546C15.1904 13.884 14.7447 13.9722 14.4154 13.7516C14.0861 13.5311 13.9979 13.0854 14.2184 12.7561C14.8456 11.8196 15.1852 10.7193 15.1852 9.56655C15.1852 6.39603 12.615 3.82581 9.44448 3.82581C6.27396 3.82581 3.70374 6.39603 3.70374 9.56655C3.70374 10.7193 4.04341 11.8196 4.67054 12.7561C4.89104 13.0854 4.80285 13.5311 4.47354 13.7516C4.14423 13.9722 3.69852 13.884 3.47801 13.5546C2.69389 12.3836 2.26855 11.0058 2.26855 9.56655C2.26855 5.6034 5.48133 2.39062 9.44448 2.39062ZM9.44448 10.4269L9.20879 11.188L9.04587 11.7413C8.83445 12.4807 8.72689 12.9596 8.72689 13.1545C8.72689 13.5508 9.04817 13.8721 9.44448 13.8721C9.8408 13.8721 10.1621 13.5508 10.1621 13.1545C10.1621 12.9161 10.0013 12.2533 9.6864 11.2087L9.44448 10.4269Z" d="M10.124 7.90083L10.4726 8.94104L10.7027 9.64579C11.3046 11.5148 11.5973 12.6497 11.5973 13.1545C11.5973 14.3435 10.6334 15.3073 9.44448 15.3073C8.25553 15.3073 7.2917 14.3435 7.2917 13.1545C7.2917 12.5891 7.65886 11.2334 8.41633 8.94104L8.76493 7.90083C8.98524 7.25142 9.90372 7.25142 10.124 7.90083ZM9.44448 2.39062C13.4076 2.39062 16.6204 5.6034 16.6204 9.56655C16.6204 11.0058 16.1951 12.3836 15.4109 13.5546C15.1904 13.884 14.7447 13.9722 14.4154 13.7516C14.0861 13.5311 13.9979 13.0854 14.2184 12.7561C14.8456 11.8196 15.1852 10.7193 15.1852 9.56655C15.1852 6.39603 12.615 3.82581 9.44448 3.82581C6.27396 3.82581 3.70374 6.39603 3.70374 9.56655C3.70374 10.7193 4.04341 11.8196 4.67054 12.7561C4.89104 13.0854 4.80285 13.5311 4.47354 13.7516C4.14423 13.9722 3.69852 13.884 3.47801 13.5546C2.69389 12.3836 2.26855 11.0058 2.26855 9.56655C2.26855 5.6034 5.48133 2.39062 9.44448 2.39062ZM9.44448 10.4269L9.20879 11.188L9.04587 11.7413C8.83445 12.4807 8.72689 12.9596 8.72689 13.1545C8.72689 13.5508 9.04817 13.8721 9.44448 13.8721C9.8408 13.8721 10.1621 13.5508 10.1621 13.1545C10.1621 12.9161 10.0013 12.2533 9.6864 11.2087L9.44448 10.4269Z"
fill="#507BDC" fill="#507BDC"
/> />

View File

@@ -511,3 +511,99 @@ export function AI_Icon() {
</svg> </svg>
); );
} }
export const KebabIcon = () => {
return (
<svg
width="13"
height="3"
viewBox="0 0 13 3"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<ellipse
cx="1.54798"
cy="1.35112"
rx="1.4993"
ry="1.27477"
fill="#E1E1E1"
/>
<ellipse
cx="6.04868"
cy="1.35131"
rx="1.4993"
ry="1.27477"
fill="#E1E1E1"
/>
<ellipse
cx="10.5476"
cy="1.35131"
rx="1.4993"
ry="1.27477"
fill="#E1E1E1"
/>
</svg>
);
};
export const DublicateIcon = () => {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M14.3125 11.375C14.3125 11.7545 14.0045 12.0625 13.625 12.0625H8.125C7.7455 12.0625 7.4375 11.7545 7.4375 11.375V5.875C7.4375 5.4955 7.7455 5.1875 8.125 5.1875H13.625C14.0045 5.1875 14.3125 5.4955 14.3125 5.875V11.375ZM13.625 4.5H8.125C7.36566 4.5 6.75 5.11566 6.75 5.875V11.375C6.75 12.1343 7.36566 12.75 8.125 12.75H13.625C14.3843 12.75 15 12.1343 15 11.375V5.875C15 5.11566 14.3843 4.5 13.625 4.5ZM11.5625 14.125C11.5625 14.5045 11.2545 14.8125 10.875 14.8125H5.375C4.9955 14.8125 4.6875 14.5045 4.6875 14.125V8.625C4.6875 8.2455 4.9955 7.9375 5.375 7.9375H6.0625V7.25H5.375C4.61566 7.25 4 7.86566 4 8.625V14.125C4 14.8843 4.61566 15.5 5.375 15.5H10.875C11.6343 15.5 12.25 14.8843 12.25 14.125V13.4375H11.5625V14.125Z"
fill="#6F42C1"
/>
</svg>
);
};
export const DeleteIcon = () => {
return (
<svg
width="20"
height="20"
viewBox="0 0 20 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8.33301 10V13.3334"
stroke="#5D5F63"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M11 10V13.3334"
stroke="#5D5F63"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M4.33301 6.66406H15"
stroke="#5D5F63"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M5.66699 8.66406V13.9976C5.66699 15.1022 6.56245 15.9976 7.66705 15.9976H11.6672C12.7718 15.9976 13.6672 15.1022 13.6672 13.9976V8.66406"
stroke="#5D5F63"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M7.66699 5.33337C7.66699 4.59697 8.26396 4 9.00037 4H10.3337C11.0702 4 11.6671 4.59697 11.6671 5.33337V6.66675H7.66699V5.33337Z"
stroke="#5D5F63"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};

View File

@@ -93,3 +93,114 @@ export function SimulationIcon({ isActive }: { isActive: boolean }) {
</svg> </svg>
); );
} }
// simulation player icons
export function ResetIcon() {
return (
<svg
width="13"
height="13"
viewBox="0 0 13 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2.54182 4.09637C3.33333 2.73422 4.80832 1.81836 6.49721 1.81836C9.02194 1.81836 11.0686 3.86506 11.0686 6.38979C11.0686 8.91452 9.02194 10.9612 6.49721 10.9612C3.97248 10.9612 1.92578 8.91452 1.92578 6.38979"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M7.64118 6.38895C7.64118 7.02013 7.12951 7.53181 6.49833 7.53181C5.86714 7.53181 5.35547 7.02013 5.35547 6.38895C5.35547 5.75777 5.86714 5.24609 6.49833 5.24609C7.12951 5.24609 7.64118 5.75777 7.64118 6.38895Z"
fill="var(--text-color)"
stroke="var(--text-color)"
strokeWidth="0.571429"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M4.78125 4.10407H2.49554V1.81836"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
export function PlayStopIcon() {
return (
<svg
width="13"
height="13"
viewBox="0 0 13 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M8 2.88867V9.88867M11 2.88867V9.88867M2 3.99171V8.78562C2 9.28847 2 9.53987 2.09943 9.65627C2.1857 9.75732 2.31512 9.81092 2.44756 9.80047C2.60019 9.78847 2.77796 9.61072 3.13352 9.25517L5.5305 6.85817C5.69485 6.69382 5.777 6.61167 5.8078 6.51692C5.83485 6.43357 5.83485 6.34377 5.8078 6.26042C5.777 6.16567 5.69485 6.08352 5.5305 5.91917L3.13352 3.52219C2.77796 3.16664 2.60019 2.98886 2.44756 2.97685C2.31512 2.96643 2.1857 3.02004 2.09943 3.12105C2 3.23747 2 3.48888 2 3.99171Z"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
export function ExitIcon() {
return (
<svg
width="13"
height="13"
viewBox="0 0 13 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M2.08203 6.34311L5.03647 3.38867M2.08203 6.34311L5.03647 9.29755M2.08203 6.34311H5.9228C7.22276 6.34334 9.34995 7.05241 10.7681 9.88867"
stroke="var(--text-color)"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
export function MoveArrowRight() {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9.58363 6.16637L15.4173 12L9.58363 17.8336"
stroke="var(--accent-color)"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
}
export function MoveArrowLeft() {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.4164 6.16637L8.58274 12L14.4164 17.8336"
stroke="var(--accent-color)"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
}

View File

@@ -10,8 +10,8 @@ export function StarsIcon() {
<path <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" 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="#595965"
stroke-linecap="round" strokeLinecap="round"
stroke-linejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); );
@@ -26,14 +26,14 @@ export function DownloadIcon() {
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path
fill-rule="evenodd" fillRule="evenodd"
clip-rule="evenodd" clipRule="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" 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" fill="#FCFDFD"
/> />
<path <path
fill-rule="evenodd" fillRule="evenodd"
clip-rule="evenodd" clipRule="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" 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" fill="#FCFDFD"
/> />
@@ -53,14 +53,14 @@ export function EyeIconBig() {
<path <path
d="M2.75 11.918C6.05 4.58464 15.95 4.58464 19.25 11.918" d="M2.75 11.918C6.05 4.58464 15.95 4.58464 19.25 11.918"
stroke="#2B3344" stroke="#2B3344"
stroke-linecap="round" strokeLinecap="round"
stroke-linejoin="round" strokeLinejoin="round"
/> />
<path <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" 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="#2B3344"
stroke-linecap="round" strokeLinecap="round"
stroke-linejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); );
@@ -77,8 +77,8 @@ export function CommentsIcon() {
> >
<g clip-path="url(#clip0_2926_17620)"> <g clip-path="url(#clip0_2926_17620)">
<path <path
fill-rule="evenodd" fillRule="evenodd"
clip-rule="evenodd" clipRule="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" 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" fill="#2B3344"
/> />
@@ -102,8 +102,8 @@ export function VerifiedIcon() {
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
> >
<path <path
fill-rule="evenodd" fillRule="evenodd"
clip-rule="evenodd" clipRule="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" 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" fill="#6F42C1"
/> />
@@ -123,9 +123,9 @@ export function StarsIconSmall() {
<path <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" 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="#595965"
stroke-width="0.6" strokeWidth="0.6"
stroke-linecap="round" strokeLinecap="round"
stroke-linejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); );
@@ -144,9 +144,9 @@ export function FiileedStarsIconSmall() {
d="M5.07372 1.61354C5.20877 1.31056 5.27632 1.15908 5.37035 1.11243C5.45202 1.0719 5.54791 1.0719 5.62958 1.11243C5.72362 1.15908 5.79117 1.31056 5.92621 1.61354L7.00187 4.02675C7.04183 4.11631 7.06178 4.16109 7.0927 4.19539C7.12 4.22573 7.15342 4.25 7.1907 4.26662C7.23287 4.2854 7.28164 4.29055 7.37917 4.30084L10.0067 4.57816C10.3366 4.61297 10.5015 4.63038 10.5749 4.70539C10.6387 4.77054 10.6683 4.86177 10.655 4.95198C10.6397 5.05581 10.5165 5.16682 10.2701 5.3889L8.30737 7.15768C8.23457 7.22331 8.19811 7.25615 8.17507 7.29611C8.15466 7.33152 8.14188 7.37077 8.13762 7.41137C8.13278 7.45728 8.14293 7.50523 8.16329 7.60119L8.71151 10.1858C8.78034 10.5103 8.81476 10.6725 8.76611 10.7655C8.72381 10.8463 8.64623 10.9027 8.55634 10.9179C8.45286 10.9354 8.30918 10.8526 8.02183 10.6868L5.73312 9.36677C5.64819 9.31777 5.60572 9.29332 5.56057 9.2837C5.52062 9.27524 5.47931 9.27524 5.43936 9.2837C5.39421 9.29332 5.35174 9.31777 5.26681 9.36677L2.97811 10.6868C2.69077 10.8526 2.5471 10.9354 2.44361 10.9179C2.35372 10.9027 2.27611 10.8463 2.23385 10.7655C2.18521 10.6725 2.21962 10.5103 2.28845 10.1858L2.83664 7.60119C2.85699 7.50523 2.86716 7.45728 2.86233 7.41137C2.85805 7.37077 2.8453 7.33152 2.82488 7.29611C2.80181 7.25615 2.76539 7.22331 2.69254 7.15768L0.72985 5.3889C0.483444 5.16682 0.360238 5.05581 0.34492 4.95198C0.33162 4.86177 0.361259 4.77054 0.425041 4.70539C0.498471 4.63038 0.663408 4.61297 0.993283 4.57816L3.62079 4.30084C3.71831 4.29055 3.76706 4.2854 3.80923 4.26662C3.84653 4.25 3.87993 4.22573 3.90727 4.19539C3.93815 4.16109 3.95812 4.11631 3.99804 4.02675L5.07372 1.61354Z" d="M5.07372 1.61354C5.20877 1.31056 5.27632 1.15908 5.37035 1.11243C5.45202 1.0719 5.54791 1.0719 5.62958 1.11243C5.72362 1.15908 5.79117 1.31056 5.92621 1.61354L7.00187 4.02675C7.04183 4.11631 7.06178 4.16109 7.0927 4.19539C7.12 4.22573 7.15342 4.25 7.1907 4.26662C7.23287 4.2854 7.28164 4.29055 7.37917 4.30084L10.0067 4.57816C10.3366 4.61297 10.5015 4.63038 10.5749 4.70539C10.6387 4.77054 10.6683 4.86177 10.655 4.95198C10.6397 5.05581 10.5165 5.16682 10.2701 5.3889L8.30737 7.15768C8.23457 7.22331 8.19811 7.25615 8.17507 7.29611C8.15466 7.33152 8.14188 7.37077 8.13762 7.41137C8.13278 7.45728 8.14293 7.50523 8.16329 7.60119L8.71151 10.1858C8.78034 10.5103 8.81476 10.6725 8.76611 10.7655C8.72381 10.8463 8.64623 10.9027 8.55634 10.9179C8.45286 10.9354 8.30918 10.8526 8.02183 10.6868L5.73312 9.36677C5.64819 9.31777 5.60572 9.29332 5.56057 9.2837C5.52062 9.27524 5.47931 9.27524 5.43936 9.2837C5.39421 9.29332 5.35174 9.31777 5.26681 9.36677L2.97811 10.6868C2.69077 10.8526 2.5471 10.9354 2.44361 10.9179C2.35372 10.9027 2.27611 10.8463 2.23385 10.7655C2.18521 10.6725 2.21962 10.5103 2.28845 10.1858L2.83664 7.60119C2.85699 7.50523 2.86716 7.45728 2.86233 7.41137C2.85805 7.37077 2.8453 7.33152 2.82488 7.29611C2.80181 7.25615 2.76539 7.22331 2.69254 7.15768L0.72985 5.3889C0.483444 5.16682 0.360238 5.05581 0.34492 4.95198C0.33162 4.86177 0.361259 4.77054 0.425041 4.70539C0.498471 4.63038 0.663408 4.61297 0.993283 4.57816L3.62079 4.30084C3.71831 4.29055 3.76706 4.2854 3.80923 4.26662C3.84653 4.25 3.87993 4.22573 3.90727 4.19539C3.93815 4.16109 3.95812 4.11631 3.99804 4.02675L5.07372 1.61354Z"
fill="#F3A50C" fill="#F3A50C"
stroke="#F3A50C" stroke="#F3A50C"
stroke-width="0.7" strokeWidth="0.7"
stroke-linecap="round" strokeLinecap="round"
stroke-linejoin="round" strokeLinejoin="round"
/> />
</svg> </svg>
); );

View File

@@ -13,7 +13,7 @@ const Visualization = () => {
return ( return (
<div className="visualization-right-sideBar"> <div className="visualization-right-sideBar">
<ToggleHeader <ToggleHeader
options={["Data", "Design"]} options={["Data"]}
activeOption={activeOption} activeOption={activeOption}
handleClick={handleToggleClick} handleClick={handleToggleClick}
/> />

View File

@@ -285,9 +285,13 @@ const Tools: React.FC = () => {
</div> </div>
</> </>
) : ( ) : (
<div className="exitPlay" onClick={() => setIsPlaying(false)}> <>
X {activeModule !== "simulation" && (
</div> <div className="exitPlay" onClick={() => setIsPlaying(false)}>
X
</div>
)}
</>
)} )}
</> </>
); );

View File

@@ -53,7 +53,6 @@ const PieChartComponent = ({
.getPropertyValue("--accent-color") .getPropertyValue("--accent-color")
.trim(); .trim();
console.log("accentColor: ", accentColor);
const options = useMemo( const options = useMemo(
() => ({ () => ({
responsive: true, responsive: true,

View File

@@ -5,6 +5,7 @@ import {
LockIcon, LockIcon,
} from "../../icons/RealTimeVisulationIcons"; } from "../../icons/RealTimeVisulationIcons";
import { panelData } from "../../../services/realTimeVisulization/zoneData/panel"; import { panelData } from "../../../services/realTimeVisulization/zoneData/panel";
import { AddIcon } from "../../icons/ExportCommonIcons";
// Define the type for `Side` // Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
@@ -18,7 +19,7 @@ interface ButtonsProps {
lockedPanels: Side[]; lockedPanels: Side[];
zoneId: string; zoneId: string;
zoneViewPortTarget: number[]; zoneViewPortTarget: number[];
zoneViewPortPosition: number[] zoneViewPortPosition: number[];
widgets: { widgets: {
id: string; id: string;
type: string; type: string;
@@ -35,7 +36,7 @@ interface ButtonsProps {
lockedPanels: Side[]; lockedPanels: Side[];
zoneId: string; zoneId: string;
zoneViewPortTarget: number[]; zoneViewPortTarget: number[];
zoneViewPortPosition: number[] zoneViewPortPosition: number[];
widgets: { widgets: {
id: string; id: string;
type: string; type: string;
@@ -116,7 +117,7 @@ const AddButtons: React.FC<ButtonsProps> = ({
}; };
// Delete the selectedZone state // Delete the selectedZone state
console.log('updatedZone: ', updatedZone); console.log("updatedZone: ", updatedZone);
setSelectedZone(updatedZone); setSelectedZone(updatedZone);
} else { } else {
// If the panel is not active, activate it // If the panel is not active, activate it
@@ -127,8 +128,8 @@ const AddButtons: React.FC<ButtonsProps> = ({
activeSides: newActiveSides, activeSides: newActiveSides,
panelOrder: newActiveSides, panelOrder: newActiveSides,
}; };
const email = localStorage.getItem('email') const email = localStorage.getItem("email");
const organization = (email!.split("@")[1]).split(".")[0]; const organization = email!.split("@")[1].split(".")[0];
// let response = panelData(organization, selectedZone.zoneId, newActiveSides) // let response = panelData(organization, selectedZone.zoneId, newActiveSides)
// console.log('response: ', response); // console.log('response: ', response);
@@ -145,7 +146,9 @@ const AddButtons: React.FC<ButtonsProps> = ({
<div key={side} className={`side-button-container ${side}`}> <div key={side} className={`side-button-container ${side}`}>
{/* "+" Button */} {/* "+" Button */}
<button <button
className={`side-button ${side}`} className={`side-button ${side}${
selectedZone.activeSides.includes(side) ? " active" : ""
}`}
onClick={() => handlePlusButtonClick(side)} onClick={() => handlePlusButtonClick(side)}
title={ title={
selectedZone.activeSides.includes(side) selectedZone.activeSides.includes(side)
@@ -153,7 +156,9 @@ const AddButtons: React.FC<ButtonsProps> = ({
: `Activate ${side} panel` : `Activate ${side} panel`
} }
> >
+ <div className="add-icon">
<AddIcon />
</div>
</button> </button>
{/* Extra Buttons */} {/* Extra Buttons */}
@@ -161,19 +166,16 @@ const AddButtons: React.FC<ButtonsProps> = ({
<div className="extra-Bs"> <div className="extra-Bs">
{/* Hide Panel */} {/* Hide Panel */}
<div <div
className={`icon ${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) ? "var(--primary-color)" : "var(--text-color)"}
hiddenPanels.includes(side)
? "white"
: "#1D1E21"
}
/> />
</div> </div>
@@ -188,8 +190,9 @@ const AddButtons: React.FC<ButtonsProps> = ({
{/* Lock/Unlock Panel */} {/* Lock/Unlock Panel */}
<div <div
className={`icon ${selectedZone.lockedPanels.includes(side) ? "active" : "" className={`icon ${
}`} selectedZone.lockedPanels.includes(side) ? "active" : ""
}`}
title={ title={
selectedZone.lockedPanels.includes(side) selectedZone.lockedPanels.includes(side)
? "Unlock Panel" ? "Unlock Panel"
@@ -197,7 +200,13 @@ const AddButtons: React.FC<ButtonsProps> = ({
} }
onClick={() => toggleLockPanel(side)} onClick={() => toggleLockPanel(side)}
> >
<LockIcon fill={selectedZone.lockedPanels.includes(side) ? "#ffffff" : "#1D1E21"} /> <LockIcon
fill={
selectedZone.lockedPanels.includes(side)
? "var(--primary-color)"
: "var(--text-color)"
}
/>
</div> </div>
</div> </div>
)} )}

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef, useState, useCallback } from "react";
import { Widget } from "../../../store/useWidgetStore"; import { Widget } from "../../../store/useWidgetStore";
import { MoveArrowLeft, MoveArrowRight } from "../../icons/SimulationIcons";
// Define the type for `Side` // Define the type for `Side`
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
@@ -60,138 +61,128 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
// Ref for the container element // Ref for the container element
const containerRef = useRef<HTMLDivElement | null>(null); const containerRef = useRef<HTMLDivElement | null>(null);
// Example state for selectedOption and options (adjust based on your actual use case) // State to track overflow visibility
const [selectedOption, setSelectedOption] = React.useState<string | null>( const [showLeftArrow, setShowLeftArrow] = useState(false);
null const [showRightArrow, setShowRightArrow] = useState(false);
);
// console.log('setSelectedOption: ', setSelectedOption);
const [options, setOptions] = React.useState<string[]>([]);
// console.log('setOptions: ', setOptions);
// Scroll to the selected option when it changes // Function to calculate overflow state
useEffect(() => { const updateOverflowState = useCallback(() => {
const container = containerRef.current; const container = containerRef.current;
if (container && selectedOption) {
// Handle scrolling to the selected option
const index = options.findIndex((option) => {
const formattedOption = formatOptionName(option);
const selectedFormattedOption =
selectedOption?.split("_")[1] || selectedOption;
return formattedOption === selectedFormattedOption;
});
if (index !== -1) {
const optionElement = container.children[index] as HTMLElement;
if (optionElement) {
optionElement.scrollIntoView({
behavior: "smooth",
block: "nearest",
inline: "center",
});
}
}
}
}, [selectedOption, options]);
useEffect(() => {
const container = containerRef.current;
const handleWheel = (event: WheelEvent) => {
event.preventDefault();
if (container) {
container.scrollBy({
left: event.deltaY * 2, // Adjust the multiplier for faster scrolling
behavior: "smooth",
});
}
};
let isDragging = false;
let startX: number;
let scrollLeft: number;
const handleMouseDown = (event: MouseEvent) => {
isDragging = true;
startX = event.pageX - (container?.offsetLeft || 0);
scrollLeft = container?.scrollLeft || 0;
};
const handleMouseMove = (event: MouseEvent) => {
if (!isDragging || !container) return;
event.preventDefault();
const x = event.pageX - (container.offsetLeft || 0);
const walk = (x - startX) * 2; // Adjust the multiplier for faster dragging
container.scrollLeft = scrollLeft - walk;
};
const handleMouseUp = () => {
isDragging = false;
};
const handleMouseLeave = () => {
isDragging = false;
};
if (container) { if (container) {
container.addEventListener("wheel", handleWheel, { passive: false }); const isOverflowing = container.scrollWidth > container.clientWidth;
container.addEventListener("mousedown", handleMouseDown); const canScrollLeft = container.scrollLeft > 0;
container.addEventListener("mousemove", handleMouseMove); const canScrollRight =
container.addEventListener("mouseup", handleMouseUp); container.scrollLeft + container.clientWidth < container.scrollWidth;
container.addEventListener("mouseleave", handleMouseLeave);
}
return () => { setShowLeftArrow(isOverflowing && canScrollLeft);
if (container) { setShowRightArrow(isOverflowing && canScrollRight);
container.removeEventListener("wheel", handleWheel); }
container.removeEventListener("mousedown", handleMouseDown);
container.removeEventListener("mousemove", handleMouseMove);
container.removeEventListener("mouseup", handleMouseUp);
container.removeEventListener("mouseleave", handleMouseLeave);
}
};
}, []); }, []);
// Helper function to format option names (customize as needed) useEffect(() => {
const formatOptionName = (option: string): string => { const container = containerRef.current;
// Replace underscores with spaces and capitalize the first letter
return option.replace(/_/g, " ").replace(/^\w/, (c) => c.toUpperCase()); if (container) {
// Initial calculation after the DOM has been rendered
const handleInitialRender = () => {
requestAnimationFrame(updateOverflowState);
};
handleInitialRender();
// Update on window resize or scroll
const handleResize = () => updateOverflowState();
const handleScroll = () => updateOverflowState();
// Add mouse wheel listener for horizontal scrolling
const handleWheel = (event: WheelEvent) => {
event.preventDefault(); // Prevent default vertical scrolling
if (container) {
container.scrollBy({
left: event.deltaY * 2, // Translate vertical scroll to horizontal scroll
behavior: "smooth",
});
}
};
container.addEventListener("scroll", handleScroll);
window.addEventListener("resize", handleResize);
container.addEventListener("wheel", handleWheel, { passive: false });
return () => {
container.removeEventListener("scroll", handleScroll);
window.removeEventListener("resize", handleResize);
container.removeEventListener("wheel", handleWheel);
};
}
}, [updateOverflowState]);
// Handle scrolling with navigation arrows
const handleScrollLeft = () => {
const container = containerRef.current;
if (container) {
container.scrollBy({
left: -200, // Scroll left by 200px
behavior: "smooth",
});
}
};
const handleScrollRight = () => {
const container = containerRef.current;
if (container) {
container.scrollBy({
left: 200, // Scroll right by 200px
behavior: "smooth",
});
}
}; };
return ( return (
<div <div className="zone-wrapper">
ref={containerRef} {/* Left Arrow */}
className={`zoon-wrapper ${selectedZone?.activeSides?.includes("bottom") && "bottom" {showLeftArrow && (
}`} <button className="arrow left-arrow" onClick={handleScrollLeft}>
> <MoveArrowLeft />
{Object.keys(zonesData).map((zoneName, index) => ( </button>
<div )}
key={index}
className={`zone ${selectedZone.zoneName === zoneName ? "active" : "" {/* Zones Wrapper */}
<div ref={containerRef} className="zones-wrapper">
{Object.keys(zonesData).map((zoneName, index) => (
<div
key={index}
className={`zone ${
selectedZone.zoneName === zoneName ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
console.log("zoneName: ", zoneName);
setSelectedZone({
zoneName,
activeSides: zonesData[zoneName].activeSides || [],
panelOrder: zonesData[zoneName].panelOrder || [],
lockedPanels: zonesData[zoneName].lockedPanels || [],
widgets: zonesData[zoneName].widgets || [],
zoneId: zonesData[zoneName]?.zoneId || "",
zoneViewPortTarget:
zonesData[zoneName].zoneViewPortTarget || [],
zoneViewPortPosition:
zonesData[zoneName].zoneViewPortPosition || [],
});
}}
>
{zoneName}
</div>
))}
</div>
{/* Right Arrow */}
setSelectedZone({ {showRightArrow && (
zoneName, <button className="arrow right-arrow" onClick={handleScrollRight}>
activeSides: zonesData[zoneName].activeSides || [], <MoveArrowRight />
panelOrder: zonesData[zoneName].panelOrder || [], </button>
lockedPanels: zonesData[zoneName].lockedPanels || [], )}
widgets: zonesData[zoneName].widgets || [],
zoneId: zonesData[zoneName]?.zoneId || "",
zoneViewPortTarget: zonesData[zoneName].zoneViewPortTarget || [],
zoneViewPortPosition:
zonesData[zoneName].zoneViewPortPosition || [],
});
// setSelectedZone({
// zoneName,
// ...zonesData[zoneName],
// });
}}
>
{zoneName}
</div>
))}
</div> </div>
); );
}; };

View File

@@ -1,164 +1,317 @@
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 DoughnutGraphComponent from "../realTimeVis/charts/DoughnutGraphComponent";
import DoughnutGraphComponent from "../realTimeVis/charts/DoughnutGraphComponent"; import PolarAreaGraphComponent from "../realTimeVis/charts/PolarAreaGraphComponent";
import PolarAreaGraphComponent from "../realTimeVis/charts/PolarAreaGraphComponent"; import {
DeleteIcon,
export const DraggableWidget = ({ DublicateIcon,
widget, KebabIcon,
hiddenPanels, // Add this prop to track hidden panels } from "../../icons/ExportCommonIcons";
index, onReorder import { useEffect, useRef, useState } from "react";
}: {
widget: any; type Side = "top" | "bottom" | "left" | "right";
hiddenPanels: string[]; // Array of hidden panel names
index: number; onReorder: (fromIndex: number, toIndex: number) => void interface Widget {
}) => { id: string;
const { selectedChartId, setSelectedChartId } = useWidgetStore(); type: string;
title: string;
const handlePointerDown = () => { panel: Side;
if (selectedChartId?.id !== widget.id) { data: any;
setSelectedChartId(widget); }
}
}; export const DraggableWidget = ({
widget,
// Determine if the widget's panel is hidden hiddenPanels,
const isPanelHidden = hiddenPanels.includes(widget.panel); index,
onReorder,
const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => { openKebabId,
event.dataTransfer.setData('text/plain', index.toString()); // Store the index of the dragged widget setOpenKebabId,
}; selectedZone,
const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => { setSelectedZone,
event.preventDefault(); // Allow drop }: {
}; selectedZone: {
zoneName: string;
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => { activeSides: Side[];
event.preventDefault(); // Allow drop panelOrder: Side[];
}; lockedPanels: Side[];
widgets: Widget[];
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => { };
event.preventDefault(); setSelectedZone: React.Dispatch<
const fromIndex = parseInt(event.dataTransfer.getData('text/plain'), 10); // Get the dragged widget's index React.SetStateAction<{
const toIndex = index; // The index of the widget where the drop occurred zoneName: string;
if (fromIndex !== toIndex) { activeSides: Side[];
onReorder(fromIndex, toIndex); // Call the reorder function passed as a prop panelOrder: Side[];
} lockedPanels: Side[];
}; zoneId: string;
zoneViewPortTarget: number[];
zoneViewPortPosition: number[];
return ( widgets: {
<> id: string;
<div type: string;
draggable title: string;
key={widget.id} panel: Side;
className={`chart-container ${selectedChartId?.id === widget.id && "activeChart" data: any;
}`} }[];
onPointerDown={handlePointerDown} }>
onDragStart={handleDragStart} >;
onDragEnter={handleDragEnter}
onDragOver={handleDragOver} widget: any;
onDrop={handleDrop} hiddenPanels: string[];
style={{ index: number;
opacity: isPanelHidden ? 0 : 1, // Set opacity to 0 if the panel is hidden onReorder: (fromIndex: number, toIndex: number) => void;
pointerEvents: isPanelHidden ? "none" : "auto", // Disable interaction when hidden openKebabId: string | null;
}} setOpenKebabId: (id: string | null) => void;
> }) => {
{/* Render charts based on widget type */} const { selectedChartId, setSelectedChartId } = useWidgetStore();
{widget.type === "progress" && ( const [panelDimensions, setPanelDimensions] = useState<{
<ProgressCard title={widget.title} data={widget.data} /> [side in Side]?: { width: number; height: number };
)} }>({});
{widget.type === "line" && ( const handlePointerDown = () => {
<LineGraphComponent if (selectedChartId?.id !== widget.id) {
type={widget.type} setSelectedChartId(widget);
title={widget.title} }
fontSize={widget.fontSize} };
fontWeight={widget.fontWeight}
data={{ const isPanelHidden = hiddenPanels.includes(widget.panel);
measurements: [
{ name: "testDevice", fields: "powerConsumption" }, const deleteSelectedChart = () => {
{ name: "furnace", fields: "powerConsumption" }, const updatedWidgets = selectedZone.widgets.filter(
], (w: Widget) => w.id !== widget.id
interval: 1000, );
duration: "1h",
}} setSelectedZone((prevZone: any) => ({
/> ...prevZone,
)} widgets: updatedWidgets,
{widget.type === "bar" && ( }));
<BarGraphComponent
type={widget.type} setOpenKebabId(null);
title={widget.title} };
fontSize={widget.fontSize}
fontWeight={widget.fontWeight} const getCurrentWidgetCount = (panel: Side) =>
data={{ selectedZone.widgets.filter((w) => w.panel === panel).length;
measurements: [
{ name: "testDevice", fields: "powerConsumption" }, const calculatePanelCapacity = (panel: Side) => {
{ name: "furnace", fields: "powerConsumption" }, const CHART_WIDTH = 150;
], const CHART_HEIGHT = 150;
interval: 1000, const FALLBACK_HORIZONTAL_CAPACITY = 5;
duration: "1h", const FALLBACK_VERTICAL_CAPACITY = 3;
}}
/> const dimensions = panelDimensions[panel];
)} if (!dimensions) {
{/* {widget.type === "radar" && ( return panel === "top" || panel === "bottom"
<RadarGraphComponent ? FALLBACK_HORIZONTAL_CAPACITY
type={widget.type} : FALLBACK_VERTICAL_CAPACITY;
title={widget.title} }
fontSize={widget.fontSize}
fontWeight={widget.fontWeight} return panel === "top" || panel === "bottom"
data={widget.data.measurements.map((item: any) => item.fields)} ? Math.floor(dimensions.width / CHART_WIDTH)
/> : Math.floor(dimensions.height / CHART_HEIGHT);
)} */} };
{widget.type === "pie" && (
<PieGraphComponent const isPanelFull = (panel: Side) => {
type={widget.type} const currentWidgetCount = getCurrentWidgetCount(panel);
title={widget.title} const panelCapacity = calculatePanelCapacity(panel);
fontSize={widget.fontSize} return currentWidgetCount >= panelCapacity;
fontWeight={widget.fontWeight} };
data={{
measurements: [ const duplicateWidget = () => {
{ name: "testDevice", fields: "powerConsumption" }, const duplicatedWidget: Widget = {
{ name: "furnace", fields: "powerConsumption" }, ...widget,
], id: `${widget.id}-copy-${Date.now()}`,
interval: 1000, };
duration: "1h",
}} setSelectedZone((prevZone: any) => ({
/> ...prevZone,
)} widgets: [...prevZone.widgets, duplicatedWidget],
{widget.type === "doughnut" && ( }));
<DoughnutGraphComponent
type={widget.type} setOpenKebabId(null);
title={widget.title}
fontSize={widget.fontSize} console.log("Duplicated widget with ID:", duplicatedWidget.id);
fontWeight={widget.fontWeight} };
data={{
measurements: [ const handleKebabClick = (event: React.MouseEvent<HTMLDivElement>) => {
{ name: "testDevice", fields: "powerConsumption" }, event.stopPropagation();
{ name: "furnace", fields: "powerConsumption" }, if (openKebabId === widget.id) {
], setOpenKebabId(null);
interval: 1000, } else {
duration: "1h", setOpenKebabId(widget.id);
}} }
/> };
)}
{widget.type === "polarArea" && ( const widgetRef = useRef<HTMLDivElement | null>(null);
<PolarAreaGraphComponent
type={widget.type} useEffect(() => {
title={widget.title} const handleClickOutside = (event: MouseEvent) => {
fontSize={widget.fontSize} if (
fontWeight={widget.fontWeight} widgetRef.current &&
data={{ !widgetRef.current.contains(event.target as Node)
measurements: [ ) {
{ name: "testDevice", fields: "powerConsumption" }, setOpenKebabId(null);
{ name: "furnace", fields: "powerConsumption" }, }
], };
interval: 1000,
duration: "1h", document.addEventListener("mousedown", handleClickOutside);
}}
/> return () => {
)} document.removeEventListener("mousedown", handleClickOutside);
</div> };
</> }, [setOpenKebabId]);
);
}; const handleDragStart = (event: React.DragEvent<HTMLDivElement>) => {
event.dataTransfer.setData("text/plain", index.toString()); // Store the index of the dragged widget
};
const handleDragEnter = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault(); // Allow drop
};
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault(); // Allow drop
};
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
const fromIndex = parseInt(event.dataTransfer.getData("text/plain"), 10); // Get the dragged widget's index
const toIndex = index; // The index of the widget where the drop occurred
if (fromIndex !== toIndex) {
onReorder(fromIndex, toIndex); // Call the reorder function passed as a prop
}
};
return (
<>
<div
draggable
key={widget.id}
className={`chart-container ${
selectedChartId?.id === widget.id && "activeChart"
}`}
onPointerDown={handlePointerDown}
onDragStart={handleDragStart}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
onDrop={handleDrop}
style={{
opacity: isPanelHidden ? 0 : 1,
pointerEvents: isPanelHidden ? "none" : "auto",
}}
>
{/* Kebab Icon */}
<div className="icon kebab" onClick={handleKebabClick}>
<KebabIcon />
</div>
{/* Kebab Options */}
{openKebabId === widget.id && (
<div className="kebab-options" ref={widgetRef}>
<div
className={`edit btn ${
isPanelFull(widget.panel) ? "btn-blur" : ""
}`}
onClick={isPanelFull(widget.panel) ? undefined : duplicateWidget}
>
<div className="icon">
<DublicateIcon />
</div>
<div className="label">Duplicate</div>
</div>
<div className="edit btn" onClick={deleteSelectedChart}>
<div className="icon">
<DeleteIcon />
</div>
<div className="label">Delete</div>
</div>
</div>
)}
{/* Render charts based on widget type */}
{widget.type === "progress" && (
<ProgressCard title={widget.title} data={widget.data} />
)}
{widget.type === "line" && (
<LineGraphComponent
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",
}}
/>
)}
{widget.type === "bar" && (
<BarGraphComponent
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",
}}
/>
)}
{widget.type === "pie" && (
<PieGraphComponent
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",
}}
/>
)}
{widget.type === "doughnut" && (
<DoughnutGraphComponent
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",
}}
/>
)}
{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

@@ -38,6 +38,7 @@ interface PanelProps {
}> }>
>; >;
hiddenPanels: string[]; hiddenPanels: string[];
setZonesData: React.Dispatch<React.SetStateAction<any>>; // Add this line
} }
const generateUniqueId = () => const generateUniqueId = () =>
@@ -47,11 +48,13 @@ const Panel: React.FC<PanelProps> = ({
selectedZone, selectedZone,
setSelectedZone, setSelectedZone,
hiddenPanels, hiddenPanels,
setZonesData,
}) => { }) => {
const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({}); const panelRefs = useRef<{ [side in Side]?: HTMLDivElement }>({});
const [panelDimensions, setPanelDimensions] = useState<{ const [panelDimensions, setPanelDimensions] = useState<{
[side in Side]?: { width: number; height: number }; [side in Side]?: { width: number; height: number };
}>({}); }>({});
const [openKebabId, setOpenKebabId] = useState<string | null>(null);
const { isPlaying } = usePlayButtonStore(); const { isPlaying } = usePlayButtonStore();
@@ -69,8 +72,9 @@ const Panel: React.FC<PanelProps> = ({
case "top": case "top":
case "bottom": case "bottom":
return { return {
width: `calc(100% - ${(leftActive ? panelSize : 0) + (rightActive ? panelSize : 0) width: `calc(100% - ${
}px)`, (leftActive ? panelSize : 0) + (rightActive ? panelSize : 0)
}px)`,
height: `${panelSize - 2}px`, height: `${panelSize - 2}px`,
left: leftActive ? `${panelSize}px` : "0", left: leftActive ? `${panelSize}px` : "0",
right: rightActive ? `${panelSize}px` : "0", right: rightActive ? `${panelSize}px` : "0",
@@ -80,8 +84,9 @@ const Panel: React.FC<PanelProps> = ({
case "right": case "right":
return { return {
width: `${panelSize - 2}px`, width: `${panelSize - 2}px`,
height: `calc(100% - ${(topActive ? panelSize : 0) + (bottomActive ? panelSize : 0) height: `calc(100% - ${
}px)`, (topActive ? panelSize : 0) + (bottomActive ? panelSize : 0)
}px)`,
top: topActive ? `${panelSize}px` : "0", top: topActive ? `${panelSize}px` : "0",
bottom: bottomActive ? `${panelSize}px` : "0", bottom: bottomActive ? `${panelSize}px` : "0",
[side]: "0", [side]: "0",
@@ -104,8 +109,8 @@ const Panel: React.FC<PanelProps> = ({
if (currentWidgetsCount >= maxCapacity) return; if (currentWidgetsCount >= maxCapacity) return;
console.log('draggedAsset: ', draggedAsset); console.log("draggedAsset: ", draggedAsset);
console.log('panel: ', panel); console.log("panel: ", panel);
addWidgetToPanel(draggedAsset, panel); addWidgetToPanel(draggedAsset, panel);
}; };
@@ -133,6 +138,7 @@ const Panel: React.FC<PanelProps> = ({
: Math.floor(dimensions.height / CHART_HEIGHT); : Math.floor(dimensions.height / CHART_HEIGHT);
}; };
// while dublicate check this and add
const addWidgetToPanel = (asset: any, panel: Side) => { const addWidgetToPanel = (asset: any, panel: Side) => {
const newWidget = { const newWidget = {
...asset, ...asset,
@@ -174,7 +180,7 @@ const Panel: React.FC<PanelProps> = ({
const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => { const handleReorder = (fromIndex: number, toIndex: number, panel: Side) => {
if (!selectedZone) return; // Ensure selectedZone is not null if (!selectedZone) return; // Ensure selectedZone is not null
console.log('selectedZone: ', selectedZone); console.log("selectedZone: ", selectedZone);
setSelectedZone((prev) => { setSelectedZone((prev) => {
if (!prev) return prev; // Ensure prev is not null if (!prev) return prev; // Ensure prev is not null
@@ -197,9 +203,6 @@ const Panel: React.FC<PanelProps> = ({
}); });
}; };
return ( return (
<> <>
{selectedZone.activeSides.map((side) => ( {selectedZone.activeSides.map((side) => (
@@ -237,6 +240,10 @@ const Panel: React.FC<PanelProps> = ({
onReorder={(fromIndex, toIndex) => onReorder={(fromIndex, toIndex) =>
handleReorder(fromIndex, toIndex, side) handleReorder(fromIndex, toIndex, side)
} }
openKebabId={openKebabId}
setOpenKebabId={setOpenKebabId}
selectedZone={selectedZone}
setSelectedZone={setSelectedZone}
/> />
))} ))}
</div> </div>
@@ -247,5 +254,3 @@ const Panel: React.FC<PanelProps> = ({
}; };
export default Panel; export default Panel;

View File

@@ -10,7 +10,6 @@ import { useDroppedObjectsStore, useZones } from "../../../store/store";
import DroppedObjects from "./DroppedFloatingWidgets"; import DroppedObjects from "./DroppedFloatingWidgets";
type Side = "top" | "bottom" | "left" | "right"; type Side = "top" | "bottom" | "left" | "right";
type FormattedZoneData = Record< type FormattedZoneData = Record<
@@ -128,7 +127,8 @@ const RealTimeVisulization: React.FC = () => {
style={{ style={{
height: "100%", height: "100%",
width: "100%", width: "100%",
borderRadius: isPlaying || activeModule !== "visualization" ? "" : "6px", borderRadius:
isPlaying || activeModule !== "visualization" ? "" : "6px",
}} }}
onDrop={(event) => handleDrop(event)} onDrop={(event) => handleDrop(event)}
onDragOver={(event) => event.preventDefault()} onDragOver={(event) => event.preventDefault()}
@@ -154,10 +154,10 @@ const RealTimeVisulization: React.FC = () => {
)} )}
<Panel <Panel
hiddenPanels={hiddenPanels}
selectedZone={selectedZone} selectedZone={selectedZone}
setSelectedZone={setSelectedZone} setSelectedZone={setSelectedZone}
hiddenPanels={hiddenPanels}
setZonesData={setZonesData}
/> />
</> </>
)} )}

View File

@@ -141,6 +141,7 @@
// export default MultiLevelDropdown; // export default MultiLevelDropdown;
import React, { useState, useRef, useEffect } from "react"; import React, { useState, useRef, useEffect } from "react";
import { ArrowIcon } from "../../icons/ExportCommonIcons";
// Dropdown Item Component // Dropdown Item Component
const DropdownItem = ({ const DropdownItem = ({
@@ -173,7 +174,13 @@ const NestedDropdown = ({
className={`dropdown-trigger ${open ? "open" : ""}`} className={`dropdown-trigger ${open ? "open" : ""}`}
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
> >
{label} <span className="icon">{open ? "▼" : "▶"}</span> {label}
<div
className="arrow-container"
style={{ rotate: open ? "" : "-90deg" }}
>
<ArrowIcon />
</div>
</div> </div>
{open && ( {open && (
<div className="submenu"> <div className="submenu">
@@ -199,11 +206,11 @@ interface MultiLevelDropdownProps {
} }
// Main Multi-Level Dropdown Component // Main Multi-Level Dropdown Component
const MultiLevelDropdown = ({ const MultiLevelDropdown = ({
data, data,
onSelect, onSelect,
onUnselect, onUnselect,
selectedValue selectedValue,
}: MultiLevelDropdownProps) => { }: MultiLevelDropdownProps) => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null); const dropdownRef = useRef<HTMLDivElement>(null);
@@ -236,7 +243,7 @@ const MultiLevelDropdown = ({
}; };
// Determine the display label // Determine the display label
const displayLabel = selectedValue const displayLabel = selectedValue
? `${selectedValue.name} - ${selectedValue.fields}` ? `${selectedValue.name} - ${selectedValue.fields}`
: "Dropdown trigger"; : "Dropdown trigger";
@@ -270,4 +277,3 @@ const MultiLevelDropdown = ({
}; };
export default MultiLevelDropdown; export default MultiLevelDropdown;

View File

@@ -0,0 +1,133 @@
import React, { useState, useRef, useEffect } from "react";
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
const SimulationPlayer: React.FC = () => {
const [speed, setSpeed] = useState<number>(1);
const [playSimulation, setPlaySimulation] = useState(false);
const { setIsPlaying } = usePlayButtonStore();
const sliderRef = useRef<HTMLDivElement>(null);
const isDragging = useRef(false);
// Button functions
const handleReset = () => {
setSpeed(1);
};
const handlePlayStop = () => {
setPlaySimulation(!playSimulation);
};
const handleExit = () => {
setPlaySimulation(false);
setIsPlaying(false);
};
// Slider functions starts
const handleSpeedChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSpeed(parseFloat(event.target.value));
};
const calculateHandlePosition = () => {
return ((speed - 0.5) / (50 - 0.5)) * 100;
};
const handleMouseDown = () => {
isDragging.current = true;
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
};
const handleMouseMove = (e: MouseEvent) => {
if (!isDragging.current || !sliderRef.current) return;
const sliderRect = sliderRef.current.getBoundingClientRect();
const offsetX = e.clientX - sliderRect.left;
const percentage = Math.min(Math.max(offsetX / sliderRect.width, 0), 1);
const newValue = 0.5 + percentage * (50 - 0.5);
setSpeed(parseFloat(newValue.toFixed(1)));
};
const handleMouseUp = () => {
isDragging.current = false;
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
useEffect(() => {
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
};
}, []);
// Slider function ends
return (
<div className="simulation-player-wrapper">
<div className="simulation-player-container">
<div className="controls-container">
<div
className="simulation-button-container"
onClick={() => {
handleReset();
}}
>
<ResetIcon />
Reset
</div>
<div
className="simulation-button-container"
onClick={() => {
handlePlayStop();
}}
>
<PlayStopIcon />
{playSimulation ? "Play" : "Stop"}
</div>
<div
className="simulation-button-container"
onClick={() => {
handleExit();
}}
>
<ExitIcon />
Exit
</div>
</div>
<div className="speed-control-container">
<div className="min-value">0.5x</div>
<div className="slider-container" ref={sliderRef}>
<div className="marker marker-10"></div>
<div className="marker marker-20"></div>
<div className="marker marker-30"></div>
<div className="marker marker-40"></div>
<div className="marker marker-50"></div>
<div className="marker marker-60"></div>
<div className="marker marker-70"></div>
<div className="marker marker-80"></div>
<div className="marker marker-90"></div>
<div className="custom-slider">
<div
className={`slider-handle ${isDragging ? "dragging" : ""}`}
style={{ left: `${calculateHandlePosition()}%` }}
onMouseDown={handleMouseDown}
>
{speed.toFixed(1)}x
</div>
<input
type="range"
min="0.5"
max="50"
step="0.1"
value={speed}
onChange={handleSpeedChange}
className="slider-input"
/>
</div>
</div>
<div className="max-value">50x</div>
</div>
</div>
</div>
);
};
export default SimulationPlayer;

View File

@@ -37,6 +37,7 @@ const AssetPreview: React.FC<AssetPreviewProps> = ({
<div className="assetPreview"> <div className="assetPreview">
<div className="image-preview"> <div className="image-preview">
<img src={assetImage} alt="" /> <img src={assetImage} alt="" />
{/* Add canvas here */}
</div> </div>
<div className="asset-details-preview"> <div className="asset-details-preview">

View File

@@ -8,24 +8,51 @@ import {
} from "../../components/icons/marketPlaceIcons"; } from "../../components/icons/marketPlaceIcons";
import assetImage from "../../assets/image/image.png"; import assetImage from "../../assets/image/image.png";
const Card: React.FC = () => {
interface CardProps {
assetName: string;
uploadedOn: string;
price: number;
rating: number;
views: number;
onSelectCard: (cardData: {
assetName: string;
uploadedOn: string;
price: number;
rating: number;
views: number;
}) => void;
}
const Card: React.FC<CardProps> = ({
assetName,
uploadedOn,
price,
rating,
views,
onSelectCard,
}) => {
const handleCardSelect = () => {
onSelectCard({ assetName, uploadedOn, price, rating, views });
};
return ( return (
<div className="card-container"> <div className="card-container">
<div className="icon"> <div className="icon">
<DownloadIcon /> <DownloadIcon />
</div> </div>
<div className="image-container"> <div className="image-container">
<img src={assetImage} alt="" /> <img src={assetImage} alt={assetName} />
</div> </div>
<div className="assets-container"> <div className="assets-container">
<div className="name-container"> <div className="name-container">
<div className="asstes-container">Asset name</div> <div className="assets-name">{assetName}</div>
<div className="assets-date">Uploaded on-12 Jan 23</div> <div className="assets-date">{uploadedOn}</div>
</div> </div>
<div className="details"> <div className="details">
<div className="content"> <div className="content">
<EyeIconBig /> <EyeIconBig />
1.5k {views}
</div> </div>
<div className="content"> <div className="content">
<CommentsIcon /> <CommentsIcon />
@@ -39,17 +66,17 @@ const Card: React.FC = () => {
</div> </div>
<div className="stars-container"> <div className="stars-container">
<div className="stars-wrapper"> <div className="stars-wrapper">
<StarsIconSmall /> {[...Array(5)].map((_, index) => (
<StarsIconSmall /> <StarsIconSmall key={index} />
<StarsIconSmall /> ))}
<StarsIconSmall />
<StarsIconSmall />
</div> </div>
<div className="units"> <div className="units">
36,500/<span>unit</span> {price}/<span>unit</span>
</div> </div>
</div> </div>
<div className="buy-now-button">Buy now</div> <div className="buy-now-button" onClick={handleCardSelect}>
Buy now
</div>
</div> </div>
); );
}; };

View File

@@ -1,15 +1,149 @@
import React from "react"; import React, { useState } from "react";
import Card from "./Card"; import Card from "./Card";
import AssetPreview from "./AssetPreview";
import RenderOverlay from "../../components/templates/Overlay";
const CardsContainer: React.FC = () => { const CardsContainer: React.FC = () => {
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; const array = [
{
id: 1,
name: "Asset 1",
uploadedOn: "12 Jan 23",
price: 36500,
rating: 4.5,
views: 500,
},
{
id: 2,
name: "Asset 2",
uploadedOn: "14 Jan 23",
price: 45000,
rating: 4.0,
views: 500,
},
{
id: 3,
name: "Asset 3",
uploadedOn: "15 Jan 23",
price: 52000,
rating: 4.8,
views: 500,
},
{
id: 4,
name: "Asset 4",
uploadedOn: "18 Jan 23",
price: 37000,
rating: 3.9,
views: 500,
},
{
id: 5,
name: "Asset 5",
uploadedOn: "20 Jan 23",
price: 60000,
rating: 5.0,
views: 500,
},
{
id: 6,
name: "Asset 6",
uploadedOn: "22 Jan 23",
price: 46000,
rating: 4.2,
views: 500,
},
{
id: 7,
name: "Asset 7",
uploadedOn: "25 Jan 23",
price: 38000,
rating: 4.3,
views: 500,
},
{
id: 8,
name: "Asset 8",
uploadedOn: "27 Jan 23",
price: 41000,
rating: 4.1,
views: 500,
},
{
id: 9,
name: "Asset 9",
uploadedOn: "30 Jan 23",
price: 55000,
rating: 4.6,
views: 500,
},
{
id: 10,
name: "Asset 10",
uploadedOn: "2 Feb 23",
price: 49000,
rating: 4.4,
views: 500,
},
{
id: 11,
name: "Asset 11",
uploadedOn: "5 Feb 23",
price: 62000,
rating: 5.0,
views: 500,
},
{
id: 12,
name: "Asset 12",
uploadedOn: "7 Feb 23",
price: 53000,
rating: 4.7,
views: 500,
},
];
const [selectedCard, setSelectedCard] = useState<{
assetName: string;
uploadedOn: string;
price: number;
rating: number;
views: number;
} | null>(null);
const handleCardSelect = (cardData: {
assetName: string;
uploadedOn: string;
price: number;
rating: number;
views: number;
}) => {
setSelectedCard(cardData);
};
return ( return (
<div className="cards-container-container"> <div className="cards-container-container">
<div className="header">Products You May Like</div> <div className="header">Products You May Like</div>
<div className="cards-wrapper-container"> <div className="cards-wrapper-container">
{array.map((index) => ( {array.map((asset) => (
<Card key={index} /> <Card
key={asset.id}
assetName={asset.name}
uploadedOn={asset.uploadedOn}
price={asset.price}
rating={asset.rating}
views={asset.views}
onSelectCard={handleCardSelect}
/>
))} ))}
{/* <RenderOverlay> */}
{selectedCard && (
<AssetPreview
selectedCard={selectedCard}
setSelectedCard={setSelectedCard}
/>
)}
{/* </RenderOverlay> */}
</div> </div>
</div> </div>
); );

View File

@@ -18,6 +18,7 @@ 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"; import MarketPlace from "../modules/market/MarketPlace";
import SimulationPlayer from "../components/ui/simulation/simulationPlayer";
const Project: React.FC = () => { const Project: React.FC = () => {
let navigate = useNavigate(); let navigate = useNavigate();
@@ -61,6 +62,7 @@ const Project: React.FC = () => {
<RealTimeVisulization /> <RealTimeVisulization />
{activeModule !== "market" && <Tools />} {activeModule !== "market" && <Tools />}
{/* <SimulationUI /> */} {/* <SimulationUI /> */}
{isPlaying && activeModule === "simulation" && <SimulationPlayer />}
</div> </div>
); );
}; };

View File

@@ -1,7 +1,14 @@
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
box-sizing: border-box; box-sizing: border-box;
user-select: none; user-select: none;
font-size: var(--font-size-regular); font-size: var(--font-size-regular);
}
input[type="password"]::-ms-reveal, /* For Microsoft Edge */
input[type="password"]::-ms-clear, /* For Edge clear button */
input[type="password"]::-webkit-clear-button, /* For Chrome/Safari clear button */
input[type="password"]::-webkit-inner-spin-button { /* Just in case */
display: none;
} }

View File

@@ -280,28 +280,24 @@ input {
.dropdown-menu { .dropdown-menu {
position: absolute; position: absolute;
top: 100%; top: 110%;
left: 0; right: -16px;
background-color: #ffffff; background-color: var(--background-color);
border: 1px solid #cccccc; border: 1px solid var(--border-color);
border-radius: 5px; border-radius: 5px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); box-shadow: #{$box-shadow-medium};
z-index: 1000; z-index: 1000;
min-width: 200px; min-width: 200px;
overflow: auto; overflow: auto;
max-height: 600px; max-height: 400px;
.dropdown-content { .dropdown-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 6px;
.nested-dropdown { .nested-dropdown {
// &:first-child{
margin-left: 0; margin-left: 0;
// }
} }
padding: 10px; padding: 10px;
} }
@@ -309,13 +305,13 @@ input {
display: block; display: block;
padding: 5px 10px; padding: 5px 10px;
text-decoration: none; text-decoration: none;
color: #000000; color: var(--text-color);
font-size: 14px; font-size: 14px;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s ease; transition: background-color 0.3s ease;
&:hover { &:hover {
background-color: #f0f0f0; background-color: var(--background-color);
} }
} }
@@ -329,15 +325,20 @@ input {
padding: 5px 10px; padding: 5px 10px;
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 14px;
color: #000000; color: var(--text-color);
transition: background-color 0.3s ease; transition: background-color 0.3s ease;
border-radius: #{$border-radius-small};
.arrow-container{
@include flex-center;
}
&:hover { &:hover {
background-color: #f0f0f0; background-color: var(--background-color);
} }
&.open { &.open {
background-color: #e0e0e0; color: var(--accent-color);
background-color: var(--highlight-accent-color);
} }
.icon { .icon {
@@ -349,7 +350,7 @@ input {
.submenu { .submenu {
margin-top: 5px; margin-top: 5px;
padding-left: 20px; padding-left: 20px;
border-left: 2px solid #cccccc; border-left: 2px solid var(--border-color);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 6px; gap: 6px;
@@ -576,26 +577,26 @@ input {
color: var(--text-disabled); color: var(--text-disabled);
} }
} }
.entered-emails{ .entered-emails {
@include flex-center; @include flex-center;
gap: 2px; gap: 2px;
background: var(--background-color-gray); background: var(--background-color-gray);
padding: 0 4px; padding: 0 4px;
border-radius: #{$border-radius-large}; border-radius: #{$border-radius-large};
span{ span {
height: 14px; height: 14px;
width: 14px; width: 14px;
line-height: 12px; line-height: 12px;
text-align: center; text-align: center;
border-radius: #{$border-radius-small}; border-radius: #{$border-radius-small};
&:hover{ &:hover {
background: var(--accent-color); background: var(--accent-color);
color: var(--primary-color); color: var(--primary-color);
} }
} }
} }
} }
.invite-button{ .invite-button {
padding: 4px 12px; padding: 4px 12px;
border-radius: #{$border-radius-large}; border-radius: #{$border-radius-large};
background: var(--accent-color); background: var(--accent-color);

View File

@@ -2,186 +2,356 @@
@use "../../abstracts/mixins.scss" as *; @use "../../abstracts/mixins.scss" as *;
.marketplace-wrapper { .marketplace-wrapper {
height: 100vh; height: 100vh;
width: 100vw; width: 100vw;
z-index: #{$z-index-marketplace}; z-index: #{$z-index-marketplace};
background-color: var(--background-color-secondary); background-color: var(--background-color-secondary);
position: absolute; position: absolute;
left: 0; left: 0;
padding: 100px 50px; padding: 100px 50px;
padding-bottom: 32px;
backdrop-filter: blur(6px);
.marketplace-container { .marketplace-container {
padding: 20px 2px; position: relative;
height: calc(100vh - 120px); padding: 20px 2px;
background-color: var(--background-color); height: 100%;
box-shadow: #{$box-shadow-medium}; background-color: var(--background-color);
border-radius: #{$border-radius-extra-large}; 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;
}
}
} }
.marketPlace { .cards-container-container {
width: 100%; padding: 0px 20px;
height: 100%; display: flex;
overflow: auto; flex-direction: column;
left: calc(120px / 2); gap: 6px;
top: 100px;
padding: 14px;
padding-bottom: 60px;
display: flex;
flex-direction: column;
gap: 24px;
.filter-search-container { .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%; width: 100%;
display: flex; display: flex;
align-items: center; justify-content: center;
gap: 12px; }
.search-wrapper { .assets-container {
min-width: 60%; display: flex;
max-width: 684px; justify-content: space-between;
padding: 0;
border-radius: $border-radius-large ;
.search-container { .name-container {
border: none !important; display: flex;
box-shadow: $box-shadow-medium; flex-direction: column;
border-radius: $border-radius-large ; gap: 3px;
input { .asstes-container {
border: none !important; font-weight: #{$bold-weight};
outline: none; font-size: $regular;
}
} .assets-date {
} color: var(--accent-color);
font-size: $small;
}
} }
.regularDropdown-container { .details {
max-width: 159px; display: flex;
} align-items: center;
gap: 10px;
.button { .content {
padding: 5px 20px;
border: 1px solid var(--accent-color);
border-radius: 14px;
}
.rating-container {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 6px; gap: 6px;
}
.stars {
display: flex;
align-items: center;
}
} }
} }
.cards-container-container { .vendor-icon {
padding: 0px 20px; font-weight: #{$bold-weight};
font-size: $regular;
}
.stars-container {
display: flex; display: flex;
flex-direction: column; justify-content: space-between;
gap: 6px; }
.header { .buy-now-button {
color: var(--text-color); width: 100%;
font-weight: $medium-weight; background-color: var(--background-color-secondary);
font-size: $xlarge; border-radius: $border-radius-extra-large;
} padding: 8px 0;
@include flex-center;
.cards-wrapper-container { color: var(--accent-color);
display: flex;
flex-wrap: wrap; &:hover {
gap: 28px; cursor: pointer;
.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;
}
}
}
} }
}
} }
}
} }
}
}
.assetPreview-wrapper {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 3;
.assetPreview {
width: 100%;
height: 100%;
background-color: var(--background-color);
display: flex;
gap: 12px;
z-index: 100;
border-radius: 20px;
}
// Image Preview Section
.image-preview {
width: 50%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
// Asset Details Section
.asset-details-preview {
width: 50%;
padding: 50px 20px;
overflow-y: auto;
}
// Organization Section (Top part with image and details)
.organization {
display: flex;
align-items: center;
margin-bottom: 20px;
gap: 10px;
.image {
@include flex-center;
height: 30px;
width: 30px;
min-height: 26px;
min-width: 26px;
border-radius: 50%;
font-weight: var(--font-weight-bold);
color: var(--background-color);
background-color: var(--accent-color);
}
.organization-details {
display: flex;
flex-direction: column;
.organization-name {
font-weight: bold;
margin-bottom: 5px;
font-weight: #{$bold-weight};
font-size: $regular;
}
.follow {
color: var(--accent-color);
cursor: pointer;
}
}
}
// Asset Details
.asset-details {
margin-top: 20px;
.asset-name {
font-size: 1.5em;
font-weight: bold;
margin-bottom: 10px;
font-weight: #{$bold-weight};
font-size: $large;
}
.asset-description {
margin-bottom: 20px;
color: #666;
}
.asset-review {
width: fit-content;
padding: 5px 10px;
display: flex;
align-items: center;
margin-bottom: 20px;
outline: 1px solid #909090cc;
border-radius: 6px;
.asset-rating {
display: flex;
align-items: center;
gap: 4px;
margin-right: 10px;
font-weight: bold;
position: relative;
font-weight: #{$bold-weight};
font-size: $regular;
&::after {
margin-left: 5px;
content: "";
display: block;
width: 2px;
height: 12px;
background-color: #ccc;
}
}
.asset-view {
font-weight: #{$bold-weight};
font-size: $regular;
}
}
.asset-price {
font-size: $xxlarge;
font-weight: bold;
margin-bottom: 20px;
}
}
// Button Container and Button Styles
.button-container {
display: flex;
gap: 10px;
}
.button {
color: white;
padding: 10px 20px;
border-radius: 5px;
cursor: pointer;
text-align: center;
&:first-child {
outline: 1px solid var(--accent-color);
color: var(--accent-color);
}
&:last-child {
background-color: var(--accent-color);
color: var(--background-color);
}
}
.closeButton {
color: var(--accent-color);
position: absolute;
top: 18px;
left: 18px;
@include flex-center;
cursor: pointer;
font-size: var(--font-size-large);
}
} }

View File

@@ -0,0 +1,114 @@
@use "../../abstracts/variables" as *;
@use "../../abstracts/mixins" as *;
.simulation-player-wrapper {
position: fixed;
bottom: 32px;
left: 50%;
z-index: 2;
transform: translate(-50%, 0);
.simulation-player-container {
.controls-container {
@include flex-center;
gap: 12px;
margin-bottom: 4px;
.simulation-button-container {
@include flex-center;
gap: 2px;
padding: 6px 8px;
min-width: 64px;
background-color: var(--background-color);
border-radius: #{$border-radius-small};
cursor: pointer;
&:hover {
background-color: var(--highlight-accent-color);
color: var(--accent-color);
path {
stroke: var(--accent-color);
}
}
}
}
.speed-control-container {
@include flex-center;
gap: 18px;
padding: 5px 16px;
background: var(--background-color);
border-radius: #{$border-radius-medium};
box-sizing: #{$box-shadow-medium};
.min-value,
.max-value {
font-weight: var(--font-weight-bold);
}
.slider-container {
width: 580px;
max-width: 80vw;
height: 28px;
background: var(--background-color-gray);
border-radius: #{$border-radius-small};
position: relative;
padding: 4px 26px;
.custom-slider {
height: 100%;
width: 100%;
position: relative;
.slider-input {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
z-index: 3;
cursor: pointer;
}
.slider-handle {
position: absolute;
width: 42px;
line-height: 20px;
text-align: center;
background: var(--accent-color);
color: var(--primary-color);
border-radius: #{$border-radius-small};
transform: translateX(-50%);
cursor: pointer;
z-index: 2;
}
}
.marker{
position: absolute;
background-color: var(--text-disabled);
width: 2px;
height: 12px;
border-radius: 1px;
top: 8px;
}
.marker.marker-10{
left: 10%;
}
.marker.marker-20{
left: 20%;
}
.marker.marker-30{
left: 30%;
}
.marker.marker-40{
left: 40%;
}
.marker.marker-50{
left: 50%;
}
.marker.marker-60{
left: 60%;
}
.marker.marker-70{
left: 70%;
}
.marker.marker-80{
left: 80%;
}
.marker.marker-90{
left: 90%;
}
}
}
}
}

View File

@@ -8,7 +8,7 @@
flex-direction: column; flex-direction: column;
gap: 6px; gap: 6px;
width: 100%; width: 100%;
min-width: 250px; // min-width: 1450px;
.header { .header {
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@@ -20,8 +20,9 @@
@use 'components/tools'; @use 'components/tools';
@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'; @use 'components/marketPlace/marketPlace';
@use 'components/simulation/simulation';
// layout // layout
@use 'layout/loading'; @use 'layout/loading';

View File

@@ -1,4 +1,5 @@
@use "../abstracts/variables.scss" as *; @use "../abstracts/variables.scss" as *;
@use "../abstracts/mixins.scss" as *;
// Main Container // Main Container
.realTime-viz { .realTime-viz {
@@ -35,7 +36,7 @@
} }
} }
.zoon-wrapper { .zone-wrapper {
display: flex; display: flex;
background-color: var(--background-color); background-color: var(--background-color);
position: absolute; position: absolute;
@@ -43,15 +44,32 @@
left: 50%; left: 50%;
transform: translate(-50%, 0); transform: translate(-50%, 0);
gap: 6px; gap: 6px;
padding: 4px;
border-radius: 8px; border-radius: 8px;
max-width: 80%; max-width: 80%;
overflow: auto; overflow: auto;
max-width: calc(100% - 450px); // max-width: calc(100% - 450px);
&::-webkit-scrollbar { &::-webkit-scrollbar {
display: none; display: none;
} }
.arrow {
background-color: var(--highlight-accent-color);
color: var(--background-color);
}
.zones-wrapper {
padding: 6px;
display: flex;
gap: 6px;
border-radius: #{$border-radius-medium};
overflow-x: auto;
&::-webkit-scrollbar {
display: none;
}
}
.zone { .zone {
width: auto; width: auto;
background-color: var(--background-color); background-color: var(--background-color);
@@ -68,28 +86,10 @@
} }
} }
.zoon-wrapper.bottom { .zone-wrapper.bottom {
bottom: 210px; bottom: 210px;
} }
@media (max-width: 1024px) {
width: 80%; // Increase width to take more space on smaller screens
height: 500px; // Reduce height to fit smaller screens
left: 50%; // Center horizontally
.main-container {
margin: 0 15px; // Reduce margin for better spacing
}
.zoon-wrapper {
bottom: 5px; // Adjust position for smaller screens
&.bottom {
bottom: 150px; // Adjust for bottom placement
}
}
}
.content-container { .content-container {
display: flex; display: flex;
height: 100vh; height: 100vh;
@@ -104,7 +104,7 @@
margin: 0 30px; margin: 0 30px;
transition: height 0.3s ease, margin 0.3s ease; transition: height 0.3s ease, margin 0.3s ease;
.zoon-wrapper { .zone-wrapper {
display: flex; display: flex;
background-color: rgba(224, 223, 255, 0.5); background-color: rgba(224, 223, 255, 0.5);
position: absolute; position: absolute;
@@ -150,15 +150,15 @@
transition: all 0.3s ease; transition: all 0.3s ease;
border-radius: 6px; border-radius: 6px;
overflow: visible !important; overflow: visible !important;
z-index: $z-index-tools;
.panel-content { .panel-content {
position: relative; position: relative;
height: 100%; height: 100%;
padding: 10px; padding: 10px;
overflow: auto;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 6px;
background-color: var(--background-color); background-color: var(--background-color);
&::-webkit-scrollbar { &::-webkit-scrollbar {
@@ -167,8 +167,7 @@
.chart-container { .chart-container {
width: 100%; width: 100%;
height: 24% !important; height: 25% !important;
min-height: 150px; min-height: 150px;
max-height: 100%; max-height: 100%;
border: 1px dotted #a9a9a9; border: 1px dotted #a9a9a9;
@@ -176,6 +175,70 @@
box-shadow: 0px 2px 6px 0px rgba(60, 60, 67, 0.1); box-shadow: 0px 2px 6px 0px rgba(60, 60, 67, 0.1);
padding: 6px 0; padding: 6px 0;
background-color: white; background-color: white;
position: relative;
.kebab {
width: 30px;
height: 30px;
position: absolute;
top: 0px;
right: 0px;
z-index: 10;
cursor: pointer;
@include flex-center;
}
.kebab-options {
position: absolute;
top: 12px;
right: -100px;
transform: translate(0px, 0);
background-color: var(--background-color);
z-index: 10;
display: flex;
flex-direction: column;
gap: 6px;
border-radius: 4px;
box-shadow: var(--box-shadow-medium);
.btn {
display: flex;
gap: 6px;
align-items: center;
padding: 5px 10px;
color: var(--text-color);
&:hover {
.label {
color: var(--accent-color);
}
}
&:hover {
background-color: var(--highlight-accent-color);
width: 100%;
svg {
&:first-child {
fill: var(--accent-color);
}
&:last-child {
fill: auto;
stroke: var(--accent-color);
}
}
}
}
.btn-blur {
color: var(--text-disabled);
cursor: not-allowed;
pointer-events: none;
}
}
} }
.close-btn { .close-btn {
@@ -194,8 +257,6 @@
left: 0; left: 0;
right: 0; right: 0;
.panel-content { .panel-content {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -236,19 +297,21 @@
} }
} }
.playingFlase{ .playingFlase {
.zoon-wrapper{ .zone-wrapper.bottom {
bottom: 300px !important; bottom: 300px;
} }
} }
// Side Buttons // Side Buttons
.side-button-container { .side-button-container {
position: absolute; position: absolute;
display: flex; display: flex;
background-color: var(--background-color); background-color: var(--background-color);
padding: 5px; padding: 2px;
border-radius: 8px; border-radius: 2px;
transition: transform 0.3s ease; transition: transform 0.3s ease;
box-shadow: #{$box-shadow-medium};
.extra-Bs { .extra-Bs {
display: flex; display: flex;
@@ -285,6 +348,24 @@
border: none; border: none;
color: var(--background-color); color: var(--background-color);
border-radius: 4px; border-radius: 4px;
.add-icon {
@include flex-center;
transition: rotate 0.2s;
}
path {
stroke: var(--primary-color);
stroke-width: 2;
}
}
.active {
background: #ffe3e0;
.add-icon {
rotate: 45deg;
path {
stroke: #f65648;
stroke-width: 2;
}
}
} }
&.top { &.top {
@@ -401,3 +482,33 @@
} }
} }
} }
.arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
border: none;
cursor: pointer;
z-index: 10;
height: 100%;
}
.left-arrow {
left: 0;
}
.right-arrow {
right: 0;
}
.zone {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
cursor: pointer;
}
.zone.active {
background-color: #007bff;
color: white;
}

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