Merge remote-tracking branch 'origin/v2-ui' into v2
This commit is contained in:
commit
8b0daa3305
|
@ -3,23 +3,20 @@ import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
|
||||||
import Dashboard from "./pages/Dashboard";
|
import Dashboard from "./pages/Dashboard";
|
||||||
import Project from "./pages/Project";
|
import Project from "./pages/Project";
|
||||||
import UserAuth from "./pages/UserAuth";
|
import UserAuth from "./pages/UserAuth";
|
||||||
import ToastProvider from "./components/templates/ToastProvider";
|
import "./styles/main.scss";
|
||||||
import "./styles/main.scss"
|
import { LoggerProvider } from "./components/ui/log/LoggerContext";
|
||||||
|
|
||||||
const App: React.FC = () => {
|
const App: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<ToastProvider>
|
<LoggerProvider>
|
||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route path="/" element={<UserAuth />} />
|
||||||
path="/"
|
|
||||||
element={<UserAuth />}
|
|
||||||
/>
|
|
||||||
<Route path="/dashboard" element={<Dashboard />} />
|
<Route path="/dashboard" element={<Dashboard />} />
|
||||||
<Route path="/project" element={<Project />} />
|
<Route path="/project" element={<Project />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
</ToastProvider>
|
</LoggerProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
import React from "react";
|
||||||
|
import { HelpIcon } from "../icons/DashboardIcon";
|
||||||
|
import {
|
||||||
|
LogInfoIcon,
|
||||||
|
ErrorIcon,
|
||||||
|
WarningIcon,
|
||||||
|
} from "../icons/ExportCommonIcons"; // Adjust path as needed
|
||||||
|
import { useLogger } from "../ui/log/LoggerContext";
|
||||||
|
|
||||||
|
const getLogIcon = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case "info":
|
||||||
|
return <LogInfoIcon />;
|
||||||
|
case "error":
|
||||||
|
return <ErrorIcon />;
|
||||||
|
case "warning":
|
||||||
|
return <WarningIcon />;
|
||||||
|
case "log":
|
||||||
|
default:
|
||||||
|
return <LogInfoIcon />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Footer: React.FC = () => {
|
||||||
|
const { logs, setIsLogListVisible } = useLogger();
|
||||||
|
const lastLog = logs.length > 0 ? logs[logs.length - 1] : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="footer-wrapper">
|
||||||
|
<div className="selection-wrapper">
|
||||||
|
<div className="selector-wrapper">
|
||||||
|
<div className="icon"></div>
|
||||||
|
<div className="selector">Selection</div>
|
||||||
|
</div>
|
||||||
|
<div className="selector-wrapper">
|
||||||
|
<div className="icon"></div>
|
||||||
|
<div className="selector">Rotate/Zoom</div>
|
||||||
|
</div>
|
||||||
|
<div className="selector-wrapper">
|
||||||
|
<div className="icon"></div>
|
||||||
|
<div className="selector">Pan/Context Menu</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="logs-wrapper">
|
||||||
|
<div className="logs-detail" onClick={() => setIsLogListVisible(true)}>
|
||||||
|
{lastLog ? (
|
||||||
|
<>
|
||||||
|
<span className="log-icon">{getLogIcon(lastLog.type)}</span>
|
||||||
|
<span className="log-message">{lastLog.message}</span>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"No logs yet."
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="version">
|
||||||
|
V 0.01
|
||||||
|
<div className="icon">
|
||||||
|
<HelpIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Footer;
|
|
@ -458,7 +458,7 @@ export function InfoIcon() {
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
d="M5.46289 7.75441C5.46289 7.68342 5.47691 7.6131 5.50422 7.54758C5.53158 7.48201 5.57156 7.42254 5.62201 7.37257C5.67246 7.3226 5.73231 7.2831 5.79807 7.25636C5.86388 7.22963 5.93425 7.21619 6.00529 7.21681C6.11003 7.21873 6.21188 7.25142 6.29814 7.31089C6.38435 7.37036 6.45121 7.45398 6.49019 7.55118C6.52921 7.64843 6.53862 7.75499 6.5174 7.85757C6.49614 7.96014 6.44511 8.05417 6.37071 8.12795C6.29631 8.20168 6.20185 8.25184 6.09908 8.27219C5.99631 8.29254 5.8898 8.28212 5.79294 8.24224C5.69603 8.2024 5.61308 8.13486 5.55438 8.04808C5.49567 7.96134 5.46385 7.8592 5.46289 7.75441ZM5.63564 6.44401L5.56844 3.93842C5.56206 3.87819 5.56844 3.81729 5.58716 3.75968C5.60583 3.70207 5.63641 3.64902 5.67692 3.604C5.71743 3.55897 5.76697 3.52297 5.82227 3.49832C5.87761 3.47368 5.93751 3.46094 5.99804 3.46094C6.05862 3.46094 6.11852 3.47368 6.17387 3.49832C6.22916 3.52297 6.2787 3.55897 6.31921 3.604C6.35972 3.64902 6.3903 3.70207 6.40897 3.75968C6.42769 3.81729 6.43407 3.87819 6.42769 3.93842L6.36529 6.44401C6.36529 6.54073 6.32689 6.63356 6.25844 6.70196C6.19004 6.77036 6.09721 6.80881 6.00049 6.80881C5.90372 6.80881 5.81094 6.77036 5.74254 6.70196C5.67414 6.63356 5.63564 6.54073 5.63564 6.44401Z"
|
d="M5.46289 7.75441C5.46289 7.68342 5.47691 7.6131 5.50422 7.54758C5.53158 7.48201 5.57156 7.42254 5.62201 7.37257C5.67246 7.3226 5.73231 7.2831 5.79807 7.25636C5.86388 7.22963 5.93425 7.21619 6.00529 7.21681C6.11003 7.21873 6.21188 7.25142 6.29814 7.31089C6.38435 7.37036 6.45121 7.45398 6.49019 7.55118C6.52921 7.64843 6.53862 7.75499 6.5174 7.85757C6.49614 7.96014 6.44511 8.05417 6.37071 8.12795C6.29631 8.20168 6.20185 8.25184 6.09908 8.27219C5.99631 8.29254 5.8898 8.28212 5.79294 8.24224C5.69603 8.2024 5.61308 8.13486 5.55438 8.04808C5.49567 7.96134 5.46385 7.8592 5.46289 7.75441ZM5.63564 6.44401L5.56844 3.93842C5.56206 3.87819 5.56844 3.81729 5.58716 3.75968C5.60583 3.70207 5.63641 3.64902 5.67692 3.604C5.71743 3.55897 5.76697 3.52297 5.82227 3.49832C5.87761 3.47368 5.93751 3.46094 5.99804 3.46094C6.05862 3.46094 6.11852 3.47368 6.17387 3.49832C6.22916 3.52297 6.2787 3.55897 6.31921 3.604C6.35972 3.64902 6.3903 3.70207 6.40897 3.75968C6.42769 3.81729 6.43407 3.87819 6.42769 3.93842L6.36529 6.44401C6.36529 6.54073 6.32689 6.63356 6.25844 6.70196C6.19004 6.77036 6.09721 6.80881 6.00049 6.80881C5.90372 6.80881 5.81094 6.77036 5.74254 6.70196C5.67414 6.63356 5.63564 6.54073 5.63564 6.44401Z"
|
||||||
fill="var(--icon-default-color)"
|
fill="var(--text-color)"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
d="M6.00006 10.3175C8.45219 10.3175 10.4401 8.32963 10.4401 5.8775C10.4401 3.42536 8.45219 1.4375 6.00006 1.4375C3.54792 1.4375 1.56006 3.42536 1.56006 5.8775C1.56006 8.32963 3.54792 10.3175 6.00006 10.3175Z"
|
d="M6.00006 10.3175C8.45219 10.3175 10.4401 8.32963 10.4401 5.8775C10.4401 3.42536 8.45219 1.4375 6.00006 1.4375C3.54792 1.4375 1.56006 3.42536 1.56006 5.8775C1.56006 8.32963 3.54792 10.3175 6.00006 10.3175Z"
|
||||||
|
@ -471,7 +471,7 @@ export function InfoIcon() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AI_Icon() {
|
export function AIIcon() {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
width="20"
|
width="20"
|
||||||
|
@ -814,3 +814,136 @@ export const SpeedIcon = () => {
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const LogListIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="24"
|
||||||
|
height="25"
|
||||||
|
viewBox="0 0 24 25"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.5 18.25H5.5M18.5 21.7272V19.3568H17.3829C16.8245 19.3568 16.375 18.9072 16.375 18.3489V18.08C16.375 17.5216 16.8246 17.0721 17.3829 17.0721H18.5V13.7318H17.2579C16.6995 13.7318 16.25 13.2822 16.25 12.7239V12.4551C16.25 11.8967 16.6996 11.4472 17.2579 11.4472H18.5V7.98185H17.2579C16.6995 7.98185 16.25 7.5323 16.25 6.97395V6.70515C16.25 6.14675 16.6996 5.69725 17.2579 5.69725H18.5V3.27065M14.5 12.75H5.5M12 7.24995H5.5M20.25 3.25H3.75C3.1977 3.25 2.75 3.6977 2.75 4.25V20.75C2.75 21.3023 3.1977 21.75 3.75 21.75H20.25C20.8023 21.75 21.25 21.3023 21.25 20.75V4.25C21.25 3.6977 20.8023 3.25 20.25 3.25Z"
|
||||||
|
stroke="#2B3344"
|
||||||
|
strokeWidth="1.2"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LogTickIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="10"
|
||||||
|
height="10"
|
||||||
|
viewBox="0 0 10 10"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<g clip-path="url(#clip0_3962_4223)">
|
||||||
|
<path
|
||||||
|
d="M5.00065 0.835938C2.70482 0.835938 0.833984 2.70677 0.833984 5.0026C0.833984 7.29844 2.70482 9.16927 5.00065 9.16927C7.29648 9.16927 9.16732 7.29844 9.16732 5.0026C9.16732 2.70677 7.29648 0.835938 5.00065 0.835938ZM6.99232 4.04427L4.62982 6.40677C4.57148 6.4651 4.49232 6.49844 4.40898 6.49844C4.32565 6.49844 4.24648 6.4651 4.18815 6.40677L3.00898 5.2276C2.88815 5.10677 2.88815 4.90677 3.00898 4.78594C3.12982 4.6651 3.32982 4.6651 3.45065 4.78594L4.40898 5.74427L6.55065 3.6026C6.67148 3.48177 6.87148 3.48177 6.99232 3.6026C7.11315 3.72344 7.11315 3.91927 6.99232 4.04427Z"
|
||||||
|
fill="#49B841"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_3962_4223">
|
||||||
|
<rect width="10" height="10" fill="white" />
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LogInfoIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="12"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M0.75 2.64438V7.41438C0.75 7.92094 0.951232 8.40675 1.30943 8.76495C1.66762 9.12314 2.15344 9.32438 2.66 9.32438H3.615V10.7544L6.5 9.32438H9.365C9.87156 9.32438 10.3574 9.12314 10.7156 8.76495C11.0738 8.40675 11.275 7.92094 11.275 7.41438V2.64438C11.275 2.13781 11.0738 1.652 10.7156 1.2938C10.3574 0.935607 9.87156 0.734375 9.365 0.734375H2.66C2.15344 0.734375 1.66762 0.935607 1.30943 1.2938C0.951232 1.652 0.75 2.13781 0.75 2.64438Z"
|
||||||
|
fill="#8E8E93"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5.04492 6.94531H6.95492"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="0.955"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5.04492 4.07812H5.99992V6.94313"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="0.955"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5.52539 2.65625H6.47539"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="0.955"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WarningIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="12"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M0.75 2.64438V7.41438C0.75 7.92094 0.951232 8.40675 1.30943 8.76495C1.66762 9.12314 2.15344 9.32438 2.66 9.32438H3.615V10.7544L6.5 9.32438H9.365C9.87156 9.32438 10.3574 9.12314 10.7156 8.76495C11.0738 8.40675 11.275 7.92094 11.275 7.41438V2.64438C11.275 2.13781 11.0738 1.652 10.7156 1.2938C10.3574 0.935607 9.87156 0.734375 9.365 0.734375H2.66C2.15344 0.734375 1.66762 0.935607 1.30943 1.2938C0.951232 1.652 0.75 2.13781 0.75 2.64438Z"
|
||||||
|
fill="#8E8E93"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5.04492 6.94531H6.95492"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="0.955"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5.04492 4.07812H5.99992V6.94313"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="0.955"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M5.52539 2.65625H6.47539"
|
||||||
|
stroke="white"
|
||||||
|
strokeWidth="0.955"
|
||||||
|
strokeMiterlimit="10"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ErrorIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="12"
|
||||||
|
height="12"
|
||||||
|
viewBox="0 0 12 12"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
d="M11 6C11 8.7614 8.7614 11 6 11C3.23857 11 1 8.7614 1 6C1 3.23857 3.23857 1 6 1C8.7614 1 11 3.23857 11 6ZM4.48482 4.48483C4.63126 4.33838 4.8687 4.33838 5.01515 4.48483L6 5.46965L6.9848 4.48484C7.13125 4.33839 7.3687 4.33839 7.51515 4.48484C7.6616 4.63128 7.6616 4.86872 7.51515 5.01515L6.5303 6L7.51515 6.9848C7.6616 7.13125 7.6616 7.3687 7.51515 7.51515C7.3687 7.6616 7.13125 7.6616 6.9848 7.51515L6 6.53035L5.01515 7.51515C4.86871 7.6616 4.63127 7.6616 4.48483 7.51515C4.33838 7.3687 4.33838 7.13125 4.48483 6.98485L5.46965 6L4.48482 5.01515C4.33837 4.86871 4.33837 4.63127 4.48482 4.48483Z"
|
||||||
|
fill="#ED5342"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -125,21 +125,21 @@ export function ResetIcon() {
|
||||||
>
|
>
|
||||||
<path
|
<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"
|
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(--icon-default-color-active)"
|
stroke="var(--text-color)"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
<path
|
<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"
|
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(--icon-default-color-active)"
|
fill="var(--text-color)"
|
||||||
stroke="var(--icon-default-color-active)"
|
stroke="var(--text-color)"
|
||||||
strokeWidth="0.571429"
|
strokeWidth="0.571429"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
<path
|
<path
|
||||||
d="M4.78125 4.10407H2.49554V1.81836"
|
d="M4.78125 4.10407H2.49554V1.81836"
|
||||||
stroke="var(--icon-default-color-active)"
|
stroke="var(--text-color)"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
|
@ -158,7 +158,7 @@ export function PlayStopIcon() {
|
||||||
>
|
>
|
||||||
<path
|
<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"
|
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(--icon-default-color-active)"
|
stroke="var(--text-color)"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
|
@ -177,7 +177,7 @@ export function ExitIcon() {
|
||||||
>
|
>
|
||||||
<path
|
<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"
|
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(--icon-default-color-active)"
|
stroke="var(--text-color)"
|
||||||
strokeLinecap="round"
|
strokeLinecap="round"
|
||||||
strokeLinejoin="round"
|
strokeLinejoin="round"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -19,7 +19,7 @@ const Header: React.FC = () => {
|
||||||
<FileMenu />
|
<FileMenu />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<button
|
||||||
className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`}
|
className={`toggle-sidebar-ui-button ${!toggleUI ? "active" : ""}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (activeModule !== "market") {
|
if (activeModule !== "market") {
|
||||||
|
@ -29,7 +29,7 @@ const Header: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ToggleSidebarIcon />
|
<ToggleSidebarIcon />
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { AI_Icon } from "../../../icons/ExportCommonIcons";
|
import { AIIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import RegularDropDown from "../../../ui/inputs/RegularDropDown";
|
import RegularDropDown from "../../../ui/inputs/RegularDropDown";
|
||||||
import { AnalysisPresetsType } from "../../../../types/analysis";
|
import { AnalysisPresetsType } from "../../../../types/analysis";
|
||||||
import RenderAnalysisInputs from "./RenderAnalysisInputs";
|
import RenderAnalysisInputs from "./RenderAnalysisInputs";
|
||||||
|
@ -13,53 +13,24 @@ const Analysis: React.FC = () => {
|
||||||
|
|
||||||
const AnalysisPresets: AnalysisPresetsType = {
|
const AnalysisPresets: AnalysisPresetsType = {
|
||||||
"Throughput time": [
|
"Throughput time": [
|
||||||
{ type: "default", inputs: { label: "Height", activeOption: "mm" } },
|
{ type: "default", inputs: { label: "Cycle time", activeOption: "s" } },
|
||||||
{ type: "default", inputs: { label: "Width", activeOption: "mm" } },
|
{ type: "default", inputs: { label: "machines / lines", activeOption: "item" } },
|
||||||
{ type: "default", inputs: { label: "Length", activeOption: "mtr" } },
|
{ type: "default", inputs: { label: "Machine uptime", activeOption: "%" } },
|
||||||
{ type: "default", inputs: { label: "Thickness", activeOption: "mm" } },
|
|
||||||
{
|
|
||||||
type: "default",
|
|
||||||
inputs: { label: "Raw Material", activeOption: "mm" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "range",
|
|
||||||
inputs: { label: "Material flow", activeOption: "m/min" },
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
"Production capacity": [
|
"Production capacity": [
|
||||||
{ type: "default", inputs: { label: "Height", activeOption: "mm" } },
|
{ type: "default", inputs: { label: "Shift length", activeOption: "hr" } },
|
||||||
{ type: "default", inputs: { label: "Width", activeOption: "mm" } },
|
{ type: "default", inputs: { label: "Shifts / day", activeOption: "unit" } },
|
||||||
{ type: "default", inputs: { label: "Length", activeOption: "mtr" } },
|
{ type: "default", inputs: { label: "Working days / year", activeOption: "days" } },
|
||||||
{ type: "default", inputs: { label: "Thickness", activeOption: "mm" } },
|
{ type: "default", inputs: { label: "Yield rate", activeOption: "%" } },
|
||||||
{
|
|
||||||
type: "default",
|
|
||||||
inputs: { label: "Raw Material", activeOption: "mm" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "range",
|
|
||||||
inputs: { label: "Material flow", activeOption: "m/min" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "range",
|
|
||||||
inputs: { label: "Shift 1", activeOption: "hr(s)" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "range",
|
|
||||||
inputs: { label: "Shift 2", activeOption: "hr(s)" },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "range",
|
|
||||||
inputs: { label: "Over time", activeOption: "hr(s)" },
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
ROI: [
|
ROI: [
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Equipment Cost", activeOption: "INR" },
|
inputs: { label: "Selling price", activeOption: "INR" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Employee Salary", activeOption: "INR" },
|
inputs: { label: "Material cost", activeOption: "INR" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
|
@ -67,7 +38,7 @@ const Analysis: React.FC = () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Cost per unit", activeOption: "INR" },
|
inputs: { label: "Maintenance cost", activeOption: "INR" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
|
@ -75,20 +46,19 @@ const Analysis: React.FC = () => {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Upkeep Cost", activeOption: "INR" },
|
inputs: { label: "Fixed costs", activeOption: "INR" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Working Hours", activeOption: "Hrs" },
|
inputs: { label: "Salvage value", activeOption: "Hrs" },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Power Usage", activeOption: "KWH" },
|
inputs: { label: "Production period", activeOption: "yrs" },
|
||||||
},
|
},
|
||||||
{ type: "default", inputs: { label: "KWH", activeOption: "Mos" } },
|
|
||||||
{
|
{
|
||||||
type: "default",
|
type: "default",
|
||||||
inputs: { label: "Man Power", activeOption: "Person" },
|
inputs: { label: "Tax rate", activeOption: "%" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@ -98,7 +68,7 @@ const Analysis: React.FC = () => {
|
||||||
<div className="analysis-main-container">
|
<div className="analysis-main-container">
|
||||||
<div className="header">Object</div>
|
<div className="header">Object</div>
|
||||||
<div className="generate-report-button">
|
<div className="generate-report-button">
|
||||||
<AI_Icon /> Generate Report
|
<AIIcon /> Generate Report
|
||||||
</div>
|
</div>
|
||||||
<div className="analysis-content-container section">
|
<div className="analysis-content-container section">
|
||||||
<div className="dropdown-header-container">
|
<div className="dropdown-header-container">
|
||||||
|
@ -121,7 +91,7 @@ const Analysis: React.FC = () => {
|
||||||
/>
|
/>
|
||||||
<div className="buttons-container">
|
<div className="buttons-container">
|
||||||
<input type="button" value={"Clear"} className="cancel" />
|
<input type="button" value={"Clear"} className="cancel" />
|
||||||
<input type="button" value={"Calculate"} className="submit" />
|
<input type="button" value={"Update"} className="submit" />
|
||||||
</div>
|
</div>
|
||||||
<div className="create-custom-analysis-container">
|
<div className="create-custom-analysis-container">
|
||||||
<div className="custom-analysis-header">Create Custom Analysis</div>
|
<div className="custom-analysis-header">Create Custom Analysis</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import InputRange from "../../../ui/inputs/InputRange";
|
import InputRange from "../../../ui/inputs/InputRange";
|
||||||
import InputToggle from "../../../ui/inputs/InputToggle";
|
import InputToggle from "../../../ui/inputs/InputToggle";
|
||||||
import { AI_Icon } from "../../../icons/ExportCommonIcons";
|
import { AIIcon } from "../../../icons/ExportCommonIcons";
|
||||||
import LabeledButton from "../../../ui/inputs/LabledButton";
|
import LabeledButton from "../../../ui/inputs/LabledButton";
|
||||||
import {
|
import {
|
||||||
useAzimuth,
|
useAzimuth,
|
||||||
|
@ -225,7 +225,7 @@ const GlobalProperties: React.FC = () => {
|
||||||
<section>
|
<section>
|
||||||
<div className="header">Environment</div>
|
<div className="header">Environment</div>
|
||||||
<div className="optimize-button" onClick={optimizeScene}>
|
<div className="optimize-button" onClick={optimizeScene}>
|
||||||
<AI_Icon />
|
<AIIcon />
|
||||||
Optimize
|
Optimize
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,9 @@ const EventProperties: React.FC = () => {
|
||||||
const { selectedEventData } = useSelectedEventData();
|
const { selectedEventData } = useSelectedEventData();
|
||||||
const { getEventByModelUuid } = useProductStore();
|
const { getEventByModelUuid } = useProductStore();
|
||||||
const { selectedProduct } = useSelectedProduct();
|
const { selectedProduct } = useSelectedProduct();
|
||||||
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(null);
|
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
const [assetType, setAssetType] = useState<string | null>(null);
|
const [assetType, setAssetType] = useState<string | null>(null);
|
||||||
const { products, addEvent } = useProductStore();
|
const { products, addEvent } = useProductStore();
|
||||||
const { selectedEventSphere } = useSelectedEventSphere();
|
const { selectedEventSphere } = useSelectedEventSphere();
|
||||||
|
@ -89,30 +91,32 @@ const EventProperties: React.FC = () => {
|
||||||
<p>
|
<p>
|
||||||
<strong>Here are some products you can add it to:</strong>
|
<strong>Here are some products you can add it to:</strong>
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<div className="product-item">
|
||||||
{products.map((product) => (
|
{products.map((product) => (
|
||||||
<li key={product.productId}>
|
|
||||||
<button
|
<button
|
||||||
|
key={product.productId}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (selectedEventData) {
|
if (selectedEventData) {
|
||||||
handleAddEventToProduct({
|
handleAddEventToProduct({
|
||||||
event: useEventsStore.getState().getEventByModelUuid(selectedEventData?.data.modelUuid),
|
event: useEventsStore
|
||||||
|
.getState()
|
||||||
|
.getEventByModelUuid(
|
||||||
|
selectedEventData?.data.modelUuid
|
||||||
|
),
|
||||||
addEvent,
|
addEvent,
|
||||||
selectedProduct,
|
selectedProduct,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AddIcon />
|
<AddIcon />
|
||||||
{product.productName}
|
{product.productName}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
|
||||||
))}
|
))}
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
}
|
)}
|
||||||
{!selectedEventSphere && (
|
{!selectedEventSphere && (
|
||||||
<div className="no-event-selected">
|
<div className="no-event-selected">
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -36,7 +36,6 @@ import {
|
||||||
import useToggleStore from "../../store/useUIToggleStore";
|
import useToggleStore from "../../store/useUIToggleStore";
|
||||||
import {
|
import {
|
||||||
use3DWidget,
|
use3DWidget,
|
||||||
useDroppedObjectsStore,
|
|
||||||
useFloatingWidget,
|
useFloatingWidget,
|
||||||
} from "../../store/visualization/useDroppedObjectsStore";
|
} from "../../store/visualization/useDroppedObjectsStore";
|
||||||
|
|
||||||
|
@ -57,20 +56,18 @@ const Tools: React.FC = () => {
|
||||||
|
|
||||||
const { widgets3D } = use3DWidget();
|
const { widgets3D } = use3DWidget();
|
||||||
|
|
||||||
const zones = useDroppedObjectsStore((state) => state.zones);
|
|
||||||
|
|
||||||
// wall options
|
// wall options
|
||||||
const { toggleView, setToggleView } = useToggleView();
|
const { toggleView, setToggleView } = useToggleView();
|
||||||
const { setDeleteTool } = useDeleteTool();
|
const { setDeleteTool } = useDeleteTool();
|
||||||
const { setAddAction } = useAddAction();
|
const { setAddAction } = useAddAction();
|
||||||
const { setSelectedWallItem } = useSelectedWallItem();
|
const { setSelectedWallItem } = useSelectedWallItem();
|
||||||
|
|
||||||
const { transformMode, setTransformMode } = useTransformMode();
|
const { setTransformMode } = useTransformMode();
|
||||||
const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine();
|
const { setDeletePointOrLine } = useDeletePointOrLine();
|
||||||
const { movePoint, setMovePoint } = useMovePoint();
|
const { setMovePoint } = useMovePoint();
|
||||||
const { toolMode, setToolMode } = useToolMode();
|
const { setToolMode } = useToolMode();
|
||||||
const { activeTool, setActiveTool } = useActiveTool();
|
const { activeTool, setActiveTool } = useActiveTool();
|
||||||
const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
|
const { setRefTextUpdate } = useRefTextUpdate();
|
||||||
|
|
||||||
// Reset activeTool whenever activeModule changes
|
// Reset activeTool whenever activeModule changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -209,7 +206,6 @@ const Tools: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isPlaying ? (
|
{!isPlaying ? (
|
||||||
<>
|
|
||||||
<div className="tools-container">
|
<div className="tools-container">
|
||||||
<div className="drop-down-icons">
|
<div className="drop-down-icons">
|
||||||
<div className="activeDropicon">
|
<div className="activeDropicon">
|
||||||
|
@ -464,13 +460,12 @@ const Tools: React.FC = () => {
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{activeModule !== "simulation" && (
|
{activeModule !== "simulation" && (
|
||||||
<div className="exitPlay" onClick={() => setIsPlaying(false)}>
|
<button className="exitPlay" onClick={() => setIsPlaying(false)}>
|
||||||
X
|
X
|
||||||
</div>
|
</button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { ROISummaryIcon } from "../../icons/analysis";
|
import { ROISummaryIcon } from "../../icons/analysis";
|
||||||
import SemiCircleProgress from "./SemiCircleProgress";
|
import SemiCircleProgress from "./SemiCircleProgress";
|
||||||
|
import { ArrowIcon } from "../../icons/ExportCommonIcons";
|
||||||
|
|
||||||
const ROISummary = ({
|
const ROISummary = ({
|
||||||
roiSummaryData = {
|
roiSummaryData = {
|
||||||
|
@ -121,7 +122,7 @@ const ROISummary = ({
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span className={`expand-icon ${isTableOpen ? "open" : ""}`}>
|
<span className={`expand-icon ${isTableOpen ? "open" : ""}`}>
|
||||||
{isTableOpen ? "⌵" : "⌵"}
|
<ArrowIcon />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
// LogList.tsx
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
LogListIcon,
|
||||||
|
LogInfoIcon,
|
||||||
|
WarningIcon,
|
||||||
|
ErrorIcon,
|
||||||
|
CloseIcon,
|
||||||
|
} from "../../icons/ExportCommonIcons"; // Adjust path as needed
|
||||||
|
import { useLogger } from "./LoggerContext";
|
||||||
|
|
||||||
|
const LogList: React.FC = () => {
|
||||||
|
const { logs, clear, setIsLogListVisible } = useLogger();
|
||||||
|
const [selectedTab, setSelectedTab] = useState<
|
||||||
|
"all" | "info" | "warning" | "error" | "log"
|
||||||
|
>("all");
|
||||||
|
|
||||||
|
const getLogIcon = (type: string) => {
|
||||||
|
switch (type) {
|
||||||
|
case "info":
|
||||||
|
return <LogInfoIcon />;
|
||||||
|
case "error":
|
||||||
|
return <ErrorIcon />;
|
||||||
|
case "warning":
|
||||||
|
return <WarningIcon />;
|
||||||
|
case "log":
|
||||||
|
default:
|
||||||
|
return <LogInfoIcon />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatTimestamp = (date: Date) => new Date(date).toLocaleTimeString();
|
||||||
|
|
||||||
|
const filteredLogs =
|
||||||
|
selectedTab === "all"
|
||||||
|
? [...logs].reverse()
|
||||||
|
: [...logs].filter((log) => log.type === selectedTab).reverse();
|
||||||
|
|
||||||
|
return (
|
||||||
|
// eslint-disable-next-line
|
||||||
|
<div
|
||||||
|
className="log-list-container"
|
||||||
|
onClick={() => setIsLogListVisible(false)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="log-list-wrapper"
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="log-header">
|
||||||
|
<div className="log-header-wrapper">
|
||||||
|
<div className="icon">
|
||||||
|
<LogListIcon />
|
||||||
|
</div>
|
||||||
|
<div className="head">Log List</div>
|
||||||
|
</div>
|
||||||
|
<button className="close" onClick={() => setIsLogListVisible(false)}>
|
||||||
|
<CloseIcon />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tabs */}
|
||||||
|
<div className="log-nav-wrapper">
|
||||||
|
{["all", "info", "warning", "error"].map((type) => (
|
||||||
|
<div
|
||||||
|
key={type}
|
||||||
|
className={`log-nav ${selectedTab === type ? "active" : ""}`}
|
||||||
|
onClick={() => setSelectedTab(type as any)}
|
||||||
|
>
|
||||||
|
{`${type.charAt(0).toUpperCase() + type.slice(1)} Logs`}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Log Entries */}
|
||||||
|
<div className="log-entry-wrapper">
|
||||||
|
{filteredLogs.map((log) => (
|
||||||
|
<div key={log.id} className={`log-entry ${log.type}`}>
|
||||||
|
<div className="log-icon">{getLogIcon(log.type)}</div>
|
||||||
|
<div className="log-entry-message-container">
|
||||||
|
<div className="log-entry-message">{log.message}</div>
|
||||||
|
<div className="message-time">
|
||||||
|
{formatTimestamp(log.timestamp)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LogList;
|
|
@ -0,0 +1,77 @@
|
||||||
|
import React, { createContext, useContext, useState, useCallback } from "react";
|
||||||
|
|
||||||
|
export type LogType = "log" | "info" | "warning" | "error";
|
||||||
|
|
||||||
|
export interface LogEntry {
|
||||||
|
id: string;
|
||||||
|
type: LogType;
|
||||||
|
message: string;
|
||||||
|
timestamp: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LoggerContextValue {
|
||||||
|
logs: LogEntry[];
|
||||||
|
setLogs: React.Dispatch<React.SetStateAction<LogEntry[]>>;
|
||||||
|
isLogListVisible: boolean;
|
||||||
|
setIsLogListVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
log: (message: string) => void;
|
||||||
|
info: (message: string) => void;
|
||||||
|
warn: (message: string) => void;
|
||||||
|
error: (message: string) => void;
|
||||||
|
clear: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LoggerContext = createContext<LoggerContextValue | undefined>(undefined);
|
||||||
|
|
||||||
|
export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const [logs, setLogs] = useState<LogEntry[]>([]);
|
||||||
|
const [isLogListVisible, setIsLogListVisible] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const generateId = useCallback(
|
||||||
|
() => Math.random().toString(36).substring(2, 9),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const addLog = useCallback(
|
||||||
|
(type: LogType, message: string) => {
|
||||||
|
const newLog: LogEntry = {
|
||||||
|
id: generateId(),
|
||||||
|
type,
|
||||||
|
message,
|
||||||
|
timestamp: new Date(),
|
||||||
|
};
|
||||||
|
setLogs((prevLogs) => [...prevLogs, newLog]);
|
||||||
|
},
|
||||||
|
[generateId]
|
||||||
|
);
|
||||||
|
|
||||||
|
const loggerMethods: LoggerContextValue = {
|
||||||
|
logs,
|
||||||
|
setLogs,
|
||||||
|
isLogListVisible,
|
||||||
|
setIsLogListVisible,
|
||||||
|
log: (message: string) => addLog("log", message),
|
||||||
|
info: (message: string) => addLog("info", message),
|
||||||
|
warn: (message: string) => addLog("warning", message),
|
||||||
|
error: (message: string) => addLog("error", message),
|
||||||
|
clear: () => {
|
||||||
|
setLogs([]);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoggerContext.Provider value={loggerMethods}>
|
||||||
|
{children}
|
||||||
|
</LoggerContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useLogger = () => {
|
||||||
|
const context = useContext(LoggerContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error("useLogger must be used within a LoggerProvider");
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
|
@ -0,0 +1,71 @@
|
||||||
|
type LogType = 'log' | 'info' | 'warning' | 'error';
|
||||||
|
|
||||||
|
interface LogEntry {
|
||||||
|
type: LogType;
|
||||||
|
message: string;
|
||||||
|
timestamp: Date;
|
||||||
|
context?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
private static instance: Logger;
|
||||||
|
private logs: LogEntry[] = [];
|
||||||
|
private subscribers: Array<(log: LogEntry) => void> = [];
|
||||||
|
|
||||||
|
private constructor() {}
|
||||||
|
|
||||||
|
public static getInstance(): Logger {
|
||||||
|
if (!Logger.instance) {
|
||||||
|
Logger.instance = new Logger();
|
||||||
|
}
|
||||||
|
return Logger.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private notifySubscribers(log: LogEntry) {
|
||||||
|
this.subscribers.forEach(callback => callback(log));
|
||||||
|
}
|
||||||
|
|
||||||
|
private addLog(type: LogType, message: string, context?: string) {
|
||||||
|
const log: LogEntry = { type, message, timestamp: new Date(), context };
|
||||||
|
this.logs.push(log);
|
||||||
|
this.notifySubscribers(log);
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
const logMessage = context ? `[${context}] ${message}` : message;
|
||||||
|
console[type === 'warning' ? 'warn' : type](logMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public log(message: string, context?: string) {
|
||||||
|
this.addLog('log', message, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public info(message: string, context?: string) {
|
||||||
|
this.addLog('info', message, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public warning(message: string, context?: string) {
|
||||||
|
this.addLog('warning', message, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public error(message: string, context?: string) {
|
||||||
|
this.addLog('error', message, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getLogs(): LogEntry[] {
|
||||||
|
return [...this.logs];
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.logs = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public subscribe(callback: (log: LogEntry) => void) {
|
||||||
|
this.subscribers.push(callback);
|
||||||
|
return () => {
|
||||||
|
this.subscribers = this.subscribers.filter(sub => sub !== callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const logger = Logger.getInstance();
|
|
@ -12,25 +12,31 @@ import {
|
||||||
EndIcon,
|
EndIcon,
|
||||||
ExpandIcon,
|
ExpandIcon,
|
||||||
HourlySimulationIcon,
|
HourlySimulationIcon,
|
||||||
|
InfoIcon,
|
||||||
MonthlyROI,
|
MonthlyROI,
|
||||||
SpeedIcon,
|
SpeedIcon,
|
||||||
StartIcon,
|
StartIcon,
|
||||||
} from "../../icons/ExportCommonIcons";
|
} from "../../icons/ExportCommonIcons";
|
||||||
import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
|
import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
|
||||||
|
import { useSubModuleStore } from "../../../store/useModuleStore";
|
||||||
|
import ProductionCapacity from "../analysis/ProductionCapacity";
|
||||||
|
import ThroughputSummary from "../analysis/ThroughputSummary";
|
||||||
|
import ROISummary from "../analysis/ROISummary";
|
||||||
|
|
||||||
const SimulationPlayer: React.FC = () => {
|
const SimulationPlayer: React.FC = () => {
|
||||||
const MAX_SPEED = 8; // Maximum speed
|
const MAX_SPEED = 8; // Maximum speed
|
||||||
|
|
||||||
|
const isDragging = useRef(false);
|
||||||
|
const sliderRef = useRef<HTMLDivElement>(null);
|
||||||
const [expand, setExpand] = useState(true);
|
const [expand, setExpand] = useState(true);
|
||||||
|
const [playSimulation, setPlaySimulation] = useState(false);
|
||||||
|
|
||||||
const { speed, setSpeed } = useAnimationPlaySpeed();
|
const { speed, setSpeed } = useAnimationPlaySpeed();
|
||||||
const [playSimulation, setPlaySimulation] = useState(false);
|
|
||||||
const { setIsPlaying } = usePlayButtonStore();
|
const { setIsPlaying } = usePlayButtonStore();
|
||||||
const sliderRef = useRef<HTMLDivElement>(null);
|
|
||||||
const isDragging = useRef(false);
|
|
||||||
const { setActiveTool } = useActiveTool();
|
const { setActiveTool } = useActiveTool();
|
||||||
const { isPaused, setIsPaused } = usePauseButtonStore();
|
const { isPaused, setIsPaused } = usePauseButtonStore();
|
||||||
const { isReset, setReset } = useResetButtonStore();
|
const { isReset, setReset } = useResetButtonStore();
|
||||||
|
const { subModule } = useSubModuleStore();
|
||||||
|
|
||||||
// Button functions
|
// Button functions
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
|
@ -114,7 +120,7 @@ const SimulationPlayer: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store colors for each process item
|
// Store colors for each process item
|
||||||
const [processColors, setProcessColors] = useState<string[]>([]);
|
const [_, setProcessColors] = useState<string[]>([]);
|
||||||
|
|
||||||
// Generate colors on mount or when process changes
|
// Generate colors on mount or when process changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -159,9 +165,11 @@ const SimulationPlayer: React.FC = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<div className="simulation-player-wrapper">
|
<div className="simulation-player-wrapper">
|
||||||
<div className={`simulation-player-container ${expand ? "open" : ""}`}>
|
<div className={`simulation-player-container ${expand ? "open" : ""}`}>
|
||||||
<div className="controls-container">
|
<div className="controls-container">
|
||||||
|
{subModule === "analysis" && (
|
||||||
<div className="production-details">
|
<div className="production-details">
|
||||||
{/* hourlySimulation */}
|
{/* hourlySimulation */}
|
||||||
<div className="hourly-wrapper production-wrapper">
|
<div className="hourly-wrapper production-wrapper">
|
||||||
|
@ -202,10 +210,22 @@ const SimulationPlayer: React.FC = () => {
|
||||||
<div className="label">Monthly ROI</div>
|
<div className="label">Monthly ROI</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="progress-wrapper">
|
<div className="progress-wrapper">
|
||||||
<div className="progress" style={{ width: monthlyROI }}></div>
|
<div
|
||||||
|
className="progress"
|
||||||
|
style={{ width: monthlyROI }}
|
||||||
|
></div>
|
||||||
</div>{" "}
|
</div>{" "}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
{subModule === "simulations" && (
|
||||||
|
<div className="header">
|
||||||
|
<InfoIcon />
|
||||||
|
{playSimulation
|
||||||
|
? "Paused - system idle."
|
||||||
|
: "Running simulation..."}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="controls-wrapper">
|
<div className="controls-wrapper">
|
||||||
<button
|
<button
|
||||||
className="simulation-button-container"
|
className="simulation-button-container"
|
||||||
|
@ -234,12 +254,14 @@ const SimulationPlayer: React.FC = () => {
|
||||||
<ExitIcon />
|
<ExitIcon />
|
||||||
Exit
|
Exit
|
||||||
</button>
|
</button>
|
||||||
|
{subModule === "analysis" && (
|
||||||
<button
|
<button
|
||||||
className="expand-icon-container"
|
className="expand-icon-container"
|
||||||
onClick={() => setExpand(!expand)}
|
onClick={() => setExpand(!expand)}
|
||||||
>
|
>
|
||||||
<ExpandIcon isActive={!expand} />
|
<ExpandIcon isActive={!expand} />
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="progresser-wrapper">
|
<div className="progresser-wrapper">
|
||||||
|
@ -330,6 +352,7 @@ const SimulationPlayer: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{subModule === "analysis" && (
|
||||||
<div className="processDisplayer">
|
<div className="processDisplayer">
|
||||||
<div className="start-displayer timmer">00:00</div>
|
<div className="start-displayer timmer">00:00</div>
|
||||||
<div className="end-displayer timmer">24:00</div>
|
<div className="end-displayer timmer">24:00</div>
|
||||||
|
@ -361,8 +384,17 @@ const SimulationPlayer: React.FC = () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="analysis">
|
||||||
|
<div className="analysis-wrapper">
|
||||||
|
<ProductionCapacity />
|
||||||
|
<ThroughputSummary />
|
||||||
|
</div>
|
||||||
|
<ROISummary />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -142,109 +142,109 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
});
|
});
|
||||||
}, [selectedZone]);
|
}, [selectedZone]);
|
||||||
|
|
||||||
const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
|
// const handleDrop = async (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
event.preventDefault();
|
// event.preventDefault();
|
||||||
try {
|
// try {
|
||||||
const email = localStorage.getItem("email") ?? "";
|
// const email = localStorage.getItem("email") ?? "";
|
||||||
const organization = email?.split("@")[1]?.split(".")[0];
|
// const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
|
||||||
const data = event.dataTransfer.getData("text/plain");
|
// const data = event.dataTransfer.getData("text/plain");
|
||||||
if (widgetSubOption === "3D") return;
|
// if (widgetSubOption === "3D") return;
|
||||||
if (!data || selectedZone.zoneName === "") return;
|
// if (!data || selectedZone.zoneName === "") return;
|
||||||
|
|
||||||
const droppedData = JSON.parse(data);
|
// const droppedData = JSON.parse(data);
|
||||||
const canvasElement = document.getElementById("real-time-vis-canvas");
|
// const canvasElement = document.getElementById("real-time-vis-canvas");
|
||||||
if (!canvasElement) throw new Error("Canvas element not found");
|
// if (!canvasElement) throw new Error("Canvas element not found");
|
||||||
|
|
||||||
const rect = canvasElement.getBoundingClientRect();
|
// const rect = canvasElement.getBoundingClientRect();
|
||||||
const relativeX = event.clientX - rect.left;
|
// const relativeX = event.clientX - rect.left;
|
||||||
const relativeY = event.clientY - rect.top;
|
// const relativeY = event.clientY - rect.top;
|
||||||
|
|
||||||
// Widget dimensions
|
// // Widget dimensions
|
||||||
const widgetWidth = droppedData.width ?? 125;
|
// const widgetWidth = droppedData.width ?? 125;
|
||||||
const widgetHeight = droppedData.height ?? 100;
|
// const widgetHeight = droppedData.height ?? 100;
|
||||||
|
|
||||||
// Center the widget at cursor
|
// // Center the widget at cursor
|
||||||
const centerOffsetX = widgetWidth / 2;
|
// const centerOffsetX = widgetWidth / 2;
|
||||||
const centerOffsetY = widgetHeight / 2;
|
// const centerOffsetY = widgetHeight / 2;
|
||||||
|
|
||||||
const adjustedX = relativeX - centerOffsetX;
|
// const adjustedX = relativeX - centerOffsetX;
|
||||||
const adjustedY = relativeY - centerOffsetY;
|
// const adjustedY = relativeY - centerOffsetY;
|
||||||
|
|
||||||
const finalPosition = determinePosition(rect, adjustedX, adjustedY);
|
// const finalPosition = determinePosition(rect, adjustedX, adjustedY);
|
||||||
const [activeProp1, activeProp2] = getActiveProperties(finalPosition);
|
// const [activeProp1, activeProp2] = getActiveProperties(finalPosition);
|
||||||
|
|
||||||
let finalY = 0;
|
// let finalY = 0;
|
||||||
let finalX = 0;
|
// let finalX = 0;
|
||||||
|
|
||||||
if (activeProp1 === "top") {
|
// if (activeProp1 === "top") {
|
||||||
finalY = adjustedY;
|
// finalY = adjustedY;
|
||||||
} else {
|
// } else {
|
||||||
finalY = rect.height - (adjustedY + widgetHeight);
|
// finalY = rect.height - (adjustedY + widgetHeight);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (activeProp2 === "left") {
|
// if (activeProp2 === "left") {
|
||||||
finalX = adjustedX;
|
// finalX = adjustedX;
|
||||||
} else {
|
// } else {
|
||||||
finalX = rect.width - (adjustedX + widgetWidth);
|
// finalX = rect.width - (adjustedX + widgetWidth);
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Clamp to boundaries
|
// // Clamp to boundaries
|
||||||
finalX = Math.max(0, Math.min(rect.width - widgetWidth, finalX));
|
// finalX = Math.max(0, Math.min(rect.width - widgetWidth, finalX));
|
||||||
finalY = Math.max(0, Math.min(rect.height - widgetHeight, finalY));
|
// finalY = Math.max(0, Math.min(rect.height - widgetHeight, finalY));
|
||||||
|
|
||||||
const boundedPosition = {
|
// const boundedPosition = {
|
||||||
...finalPosition,
|
// ...finalPosition,
|
||||||
[activeProp1]: finalY,
|
// [activeProp1]: finalY,
|
||||||
[activeProp2]: finalX,
|
// [activeProp2]: finalX,
|
||||||
[activeProp1 === "top" ? "bottom" : "top"]: "auto",
|
// [activeProp1 === "top" ? "bottom" : "top"]: "auto",
|
||||||
[activeProp2 === "left" ? "right" : "left"]: "auto",
|
// [activeProp2 === "left" ? "right" : "left"]: "auto",
|
||||||
};
|
// };
|
||||||
|
|
||||||
const newObject = {
|
// const newObject = {
|
||||||
...droppedData,
|
// ...droppedData,
|
||||||
id: generateUniqueId(),
|
// id: generateUniqueId(),
|
||||||
position: boundedPosition,
|
// position: boundedPosition,
|
||||||
};
|
// };
|
||||||
|
|
||||||
const existingZone =
|
// const existingZone =
|
||||||
useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
|
// useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
|
||||||
if (!existingZone) {
|
// if (!existingZone) {
|
||||||
useDroppedObjectsStore
|
// useDroppedObjectsStore
|
||||||
.getState()
|
// .getState()
|
||||||
.setZone(selectedZone.zoneName, selectedZone.zoneId);
|
// .setZone(selectedZone.zoneName, selectedZone.zoneId);
|
||||||
}
|
// }
|
||||||
|
|
||||||
const addFloatingWidget = {
|
// const addFloatingWidget = {
|
||||||
organization,
|
// organization,
|
||||||
widget: newObject,
|
// widget: newObject,
|
||||||
zoneId: selectedZone.zoneId,
|
// zoneId: selectedZone.zoneId,
|
||||||
};
|
// };
|
||||||
|
|
||||||
if (visualizationSocket) {
|
// if (visualizationSocket) {
|
||||||
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget);
|
// visualizationSocket.emit("v2:viz-float:add", addFloatingWidget);
|
||||||
}
|
// }
|
||||||
|
|
||||||
useDroppedObjectsStore
|
// useDroppedObjectsStore
|
||||||
.getState()
|
// .getState()
|
||||||
.addObject(selectedZone.zoneName, newObject);
|
// .addObject(selectedZone.zoneName, newObject);
|
||||||
|
|
||||||
const droppedObjectsStore = useDroppedObjectsStore.getState();
|
// const droppedObjectsStore = useDroppedObjectsStore.getState();
|
||||||
const currentZone = droppedObjectsStore.zones[selectedZone.zoneName];
|
// const currentZone = droppedObjectsStore.zones[selectedZone.zoneName];
|
||||||
|
|
||||||
if (currentZone && currentZone.zoneId === selectedZone.zoneId) {
|
// if (currentZone && currentZone.zoneId === selectedZone.zoneId) {
|
||||||
console.log(
|
// console.log(
|
||||||
`Objects for Zone ${selectedZone.zoneId}:`,
|
// `Objects for Zone ${selectedZone.zoneId}:`,
|
||||||
currentZone.objects
|
// currentZone.objects
|
||||||
);
|
// );
|
||||||
setFloatingWidget(currentZone.objects);
|
// setFloatingWidget(currentZone.objects);
|
||||||
} else {
|
// } else {
|
||||||
console.warn("Zone not found or zoneId mismatch");
|
// console.warn("Zone not found or zoneId mismatch");
|
||||||
}
|
// }
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error("Error in handleDrop:", error);
|
// console.error("Error in handleDrop:", error);
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleClickOutside = (event: MouseEvent) => {
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
@ -301,16 +301,7 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
</style>
|
</style>
|
||||||
<div
|
<div ref={containerRef} className="realTime-viz">
|
||||||
ref={containerRef}
|
|
||||||
id="real-time-vis-canvas"
|
|
||||||
className={`realTime-viz canvas ${isPlaying ? "playingFlase" : ""}`}
|
|
||||||
style={{
|
|
||||||
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
|
|
||||||
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
|
||||||
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="realTime-viz-wrapper">
|
<div className="realTime-viz-wrapper">
|
||||||
{openConfirmationPopup && (
|
{openConfirmationPopup && (
|
||||||
<RenderOverlay>
|
<RenderOverlay>
|
||||||
|
@ -321,20 +312,6 @@ const RealTimeVisulization: React.FC = () => {
|
||||||
/>
|
/>
|
||||||
</RenderOverlay>
|
</RenderOverlay>
|
||||||
)}
|
)}
|
||||||
<div
|
|
||||||
className="scene-container"
|
|
||||||
style={{
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
borderRadius:
|
|
||||||
isPlaying || activeModule !== "visualization" ? "" : "6px",
|
|
||||||
}}
|
|
||||||
role="application"
|
|
||||||
onDrop={(event) => handleDrop(event)}
|
|
||||||
onDragOver={(event) => event.preventDefault()}
|
|
||||||
>
|
|
||||||
<Scene />
|
|
||||||
</div>
|
|
||||||
{activeModule === "visualization" && selectedZone.zoneName !== "" && (
|
{activeModule === "visualization" && selectedZone.zoneName !== "" && (
|
||||||
<DroppedObjects />
|
<DroppedObjects />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
import { generateUniqueId } from "../../../functions/generateUniqueId";
|
||||||
|
import { useDroppedObjectsStore } from "../../../store/visualization/useDroppedObjectsStore";
|
||||||
|
import { determinePosition } from "./determinePosition";
|
||||||
|
import { getActiveProperties } from "./getActiveProperties";
|
||||||
|
|
||||||
|
interface HandleDropProps {
|
||||||
|
widgetSubOption: any;
|
||||||
|
visualizationSocket: any;
|
||||||
|
selectedZone: any;
|
||||||
|
setFloatingWidget: (value: any) => void;
|
||||||
|
event: React.DragEvent<HTMLDivElement>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createHandleDrop = ({
|
||||||
|
widgetSubOption,
|
||||||
|
visualizationSocket,
|
||||||
|
selectedZone,
|
||||||
|
setFloatingWidget,
|
||||||
|
event,
|
||||||
|
}: HandleDropProps) => {
|
||||||
|
event.preventDefault();
|
||||||
|
try {
|
||||||
|
const email = localStorage.getItem("email") ?? "";
|
||||||
|
const organization = email?.split("@")[1]?.split(".")[0];
|
||||||
|
|
||||||
|
const data = event.dataTransfer.getData("text/plain");
|
||||||
|
if (widgetSubOption === "3D") return;
|
||||||
|
if (!data || selectedZone.zoneName === "") return;
|
||||||
|
|
||||||
|
const droppedData = JSON.parse(data);
|
||||||
|
const canvasElement = document.getElementById("real-time-vis-canvas");
|
||||||
|
if (!canvasElement) throw new Error("Canvas element not found");
|
||||||
|
|
||||||
|
const rect = canvasElement.getBoundingClientRect();
|
||||||
|
const relativeX = event.clientX - rect.left;
|
||||||
|
const relativeY = event.clientY - rect.top;
|
||||||
|
|
||||||
|
// Widget dimensions
|
||||||
|
const widgetWidth = droppedData.width ?? 125;
|
||||||
|
const widgetHeight = droppedData.height ?? 100;
|
||||||
|
|
||||||
|
// Center the widget at cursor
|
||||||
|
const centerOffsetX = widgetWidth / 2;
|
||||||
|
const centerOffsetY = widgetHeight / 2;
|
||||||
|
|
||||||
|
const adjustedX = relativeX - centerOffsetX;
|
||||||
|
const adjustedY = relativeY - centerOffsetY;
|
||||||
|
|
||||||
|
const finalPosition = determinePosition(rect, adjustedX, adjustedY);
|
||||||
|
const [activeProp1, activeProp2] = getActiveProperties(finalPosition);
|
||||||
|
|
||||||
|
let finalY = 0;
|
||||||
|
let finalX = 0;
|
||||||
|
|
||||||
|
if (activeProp1 === "top") {
|
||||||
|
finalY = adjustedY;
|
||||||
|
} else {
|
||||||
|
finalY = rect.height - (adjustedY + widgetHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeProp2 === "left") {
|
||||||
|
finalX = adjustedX;
|
||||||
|
} else {
|
||||||
|
finalX = rect.width - (adjustedX + widgetWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clamp to boundaries
|
||||||
|
finalX = Math.max(0, Math.min(rect.width - widgetWidth, finalX));
|
||||||
|
finalY = Math.max(0, Math.min(rect.height - widgetHeight, finalY));
|
||||||
|
|
||||||
|
const boundedPosition = {
|
||||||
|
...finalPosition,
|
||||||
|
[activeProp1]: finalY,
|
||||||
|
[activeProp2]: finalX,
|
||||||
|
[activeProp1 === "top" ? "bottom" : "top"]: "auto",
|
||||||
|
[activeProp2 === "left" ? "right" : "left"]: "auto",
|
||||||
|
};
|
||||||
|
|
||||||
|
const newObject = {
|
||||||
|
...droppedData,
|
||||||
|
id: generateUniqueId(),
|
||||||
|
position: boundedPosition,
|
||||||
|
};
|
||||||
|
|
||||||
|
const existingZone =
|
||||||
|
useDroppedObjectsStore.getState().zones[selectedZone.zoneName];
|
||||||
|
if (!existingZone) {
|
||||||
|
useDroppedObjectsStore
|
||||||
|
.getState()
|
||||||
|
.setZone(selectedZone.zoneName, selectedZone.zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addFloatingWidget = {
|
||||||
|
organization,
|
||||||
|
widget: newObject,
|
||||||
|
zoneId: selectedZone.zoneId,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (visualizationSocket) {
|
||||||
|
visualizationSocket.emit("v2:viz-float:add", addFloatingWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
useDroppedObjectsStore
|
||||||
|
.getState()
|
||||||
|
.addObject(selectedZone.zoneName, newObject);
|
||||||
|
|
||||||
|
const droppedObjectsStore = useDroppedObjectsStore.getState();
|
||||||
|
const currentZone = droppedObjectsStore.zones[selectedZone.zoneName];
|
||||||
|
|
||||||
|
if (currentZone && currentZone.zoneId === selectedZone.zoneId) {
|
||||||
|
console.log(
|
||||||
|
`Objects for Zone ${selectedZone.zoneId}:`,
|
||||||
|
currentZone.objects
|
||||||
|
);
|
||||||
|
setFloatingWidget(currentZone.objects);
|
||||||
|
} else {
|
||||||
|
console.warn("Zone not found or zoneId mismatch");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in handleDrop:", error);
|
||||||
|
}
|
||||||
|
};
|
|
@ -13,6 +13,7 @@ import {
|
||||||
useWallItems,
|
useWallItems,
|
||||||
useZones,
|
useZones,
|
||||||
useLoadingProgress,
|
useLoadingProgress,
|
||||||
|
useWidgetSubOption,
|
||||||
} from "../store/store";
|
} from "../store/store";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { usePlayButtonStore } from "../store/usePlayButtonStore";
|
import { usePlayButtonStore } from "../store/usePlayButtonStore";
|
||||||
|
@ -22,12 +23,19 @@ import SimulationPlayer from "../components/ui/simulation/simulationPlayer";
|
||||||
import KeyPressListener from "../utils/shortcutkeys/handleShortcutKeys";
|
import KeyPressListener from "../utils/shortcutkeys/handleShortcutKeys";
|
||||||
import { useSelectedUserStore } from "../store/useCollabStore";
|
import { useSelectedUserStore } from "../store/useCollabStore";
|
||||||
import FollowPerson from "../components/templates/FollowPerson";
|
import FollowPerson from "../components/templates/FollowPerson";
|
||||||
import ProductionCapacity from "../components/ui/analysis/ProductionCapacity";
|
import Scene from "../modules/scene/scene";
|
||||||
import ThroughputSummary from "../components/ui/analysis/ThroughputSummary";
|
import { createHandleDrop } from "../modules/visualization/functions/handleUiDrop";
|
||||||
import ROISummary from "../components/ui/analysis/ROISummary";
|
import { useSelectedZoneStore } from "../store/visualization/useZoneStore";
|
||||||
|
import { useFloatingWidget } from "../store/visualization/useDroppedObjectsStore";
|
||||||
|
import { useLogger } from "../components/ui/log/LoggerContext";
|
||||||
|
import RenderOverlay from "../components/templates/Overlay";
|
||||||
|
import LogList from "../components/ui/log/LogList";
|
||||||
|
import Footer from "../components/footer/Footer";
|
||||||
|
|
||||||
const Project: React.FC = () => {
|
const Project: React.FC = () => {
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
|
const echo = useLogger();
|
||||||
|
|
||||||
const { activeModule, setActiveModule } = useModuleStore();
|
const { activeModule, setActiveModule } = useModuleStore();
|
||||||
const { loadingProgress } = useLoadingProgress();
|
const { loadingProgress } = useLoadingProgress();
|
||||||
const { setUserName } = useUserName();
|
const { setUserName } = useUserName();
|
||||||
|
@ -50,24 +58,33 @@ const Project: React.FC = () => {
|
||||||
setOrganization(Organization);
|
setOrganization(Organization);
|
||||||
setUserName(name);
|
setUserName(name);
|
||||||
}
|
}
|
||||||
|
echo.info("Log in success full");
|
||||||
} else {
|
} else {
|
||||||
navigate("/");
|
navigate("/");
|
||||||
}
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const { isPlaying } = usePlayButtonStore();
|
// global store
|
||||||
const { toggleThreeD } = useThreeDStore();
|
const { toggleThreeD } = useThreeDStore();
|
||||||
|
|
||||||
|
// simulation store
|
||||||
|
const { isPlaying } = usePlayButtonStore();
|
||||||
|
|
||||||
|
// collaboration store
|
||||||
const { selectedUser } = useSelectedUserStore();
|
const { selectedUser } = useSelectedUserStore();
|
||||||
|
const { isLogListVisible } = useLogger();
|
||||||
|
|
||||||
|
// real-time visualization store
|
||||||
|
const { widgetSubOption } = useWidgetSubOption();
|
||||||
|
const { visualizationSocket } = useSocketStore();
|
||||||
|
const { selectedZone } = useSelectedZoneStore();
|
||||||
|
const { setFloatingWidget } = useFloatingWidget();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="project-main">
|
<div className="project-main">
|
||||||
{/* <div className="analysis">
|
{!selectedUser && (
|
||||||
<div className="analysis-wrapper">
|
<>
|
||||||
<ProductionCapacity />
|
|
||||||
<ThroughputSummary />
|
|
||||||
</div>
|
|
||||||
<ROISummary />
|
|
||||||
</div> */}
|
|
||||||
<KeyPressListener />
|
<KeyPressListener />
|
||||||
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
|
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
|
||||||
{!isPlaying && (
|
{!isPlaying && (
|
||||||
|
@ -77,15 +94,43 @@ const Project: React.FC = () => {
|
||||||
<SideBarRight />
|
<SideBarRight />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* <RenderOverlay>
|
|
||||||
<MenuBar setOpenMenu={setOpenMenu} />
|
|
||||||
</RenderOverlay> */}
|
|
||||||
{activeModule === "market" && <MarketPlace />}
|
|
||||||
<RealTimeVisulization />
|
<RealTimeVisulization />
|
||||||
|
{activeModule === "market" && <MarketPlace />}
|
||||||
{activeModule !== "market" && <Tools />}
|
{activeModule !== "market" && <Tools />}
|
||||||
{isPlaying && activeModule === "simulation" && <SimulationPlayer />}
|
{isPlaying && activeModule === "simulation" && <SimulationPlayer />}
|
||||||
{/* {<SimulationPlayer />} */}
|
</>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
className="scene-container"
|
||||||
|
id="real-time-vis-canvas"
|
||||||
|
style={{
|
||||||
|
height: isPlaying || activeModule !== "visualization" ? "100vh" : "",
|
||||||
|
width: isPlaying || activeModule !== "visualization" ? "100vw" : "",
|
||||||
|
left: isPlaying || activeModule !== "visualization" ? "0%" : "",
|
||||||
|
borderRadius:
|
||||||
|
isPlaying || activeModule !== "visualization" ? "" : "6px",
|
||||||
|
}}
|
||||||
|
role="application"
|
||||||
|
onDrop={(event) =>
|
||||||
|
createHandleDrop({
|
||||||
|
widgetSubOption,
|
||||||
|
visualizationSocket,
|
||||||
|
selectedZone,
|
||||||
|
setFloatingWidget,
|
||||||
|
event,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onDragOver={(event) => event.preventDefault()}
|
||||||
|
>
|
||||||
|
<Scene />
|
||||||
|
</div>
|
||||||
{selectedUser && <FollowPerson />}
|
{selectedUser && <FollowPerson />}
|
||||||
|
{isLogListVisible && (
|
||||||
|
<RenderOverlay>
|
||||||
|
<LogList />
|
||||||
|
</RenderOverlay>
|
||||||
|
)}
|
||||||
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { addingFloatingWidgets } from "../../services/visulization/zone/addFloatingWidgets";
|
|
||||||
import { useSocketStore } from "../store";
|
import { useSocketStore } from "../store";
|
||||||
import useChartStore from "./useChartStore";
|
import useChartStore from "./useChartStore";
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,11 @@ $text-button-color-dark: #f3f3fd;
|
||||||
// background colors
|
// background colors
|
||||||
// ---------- light mode ----------
|
// ---------- light mode ----------
|
||||||
$background-color: linear-gradient(-45deg, #fcfdfd71 0%, #fcfdfd79 100%);
|
$background-color: linear-gradient(-45deg, #fcfdfd71 0%, #fcfdfd79 100%);
|
||||||
$background-color-solid-gradient: linear-gradient(-45deg, #fcfdfd 0%, #fcfdfd 100%);
|
$background-color-solid-gradient: linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
#fcfdfd 0%,
|
||||||
|
#fcfdfd 100%
|
||||||
|
);
|
||||||
$background-color-solid: #fcfdfd;
|
$background-color-solid: #fcfdfd;
|
||||||
$background-color-secondary: #fcfdfd4d;
|
$background-color-secondary: #fcfdfd4d;
|
||||||
$background-color-accent: #6f42c1;
|
$background-color-accent: #6f42c1;
|
||||||
|
@ -45,7 +49,11 @@ $background-radial-gray-gradient: radial-gradient(
|
||||||
|
|
||||||
// ---------- dark mode ----------
|
// ---------- dark mode ----------
|
||||||
$background-color-dark: linear-gradient(-45deg, #333333b3 0%, #2d2437b3 100%);
|
$background-color-dark: linear-gradient(-45deg, #333333b3 0%, #2d2437b3 100%);
|
||||||
$background-color-solid-gradient-dark: linear-gradient(-45deg, #333333 0%, #2d2437 100%);
|
$background-color-solid-gradient-dark: linear-gradient(
|
||||||
|
-45deg,
|
||||||
|
#333333 0%,
|
||||||
|
#2d2437 100%
|
||||||
|
);
|
||||||
$background-color-solid-dark: #19191d;
|
$background-color-solid-dark: #19191d;
|
||||||
$background-color-secondary-dark: #19191d99;
|
$background-color-secondary-dark: #19191d99;
|
||||||
$background-color-accent-dark: #6f42c1;
|
$background-color-accent-dark: #6f42c1;
|
||||||
|
@ -104,6 +112,21 @@ $color3: #b186ff;
|
||||||
$color4: #8752e8;
|
$color4: #8752e8;
|
||||||
$color5: #c7a8ff;
|
$color5: #c7a8ff;
|
||||||
|
|
||||||
|
// log indication colors
|
||||||
|
// ------------ text -------------
|
||||||
|
$log-default-text-color: #6f42c1;
|
||||||
|
$log-info-text-color: #488ef6;
|
||||||
|
$log-warn-text-color: #f3a50c;
|
||||||
|
$log-error-text-color: #f65648;
|
||||||
|
$log-success-text-color: #43c06d;
|
||||||
|
|
||||||
|
// ------------ background -------------
|
||||||
|
$log-default-backgroung-color: #6e42c133;
|
||||||
|
$log-info-background-color: #488ef633;
|
||||||
|
$log-warn-background-color: #f3a50c33;
|
||||||
|
$log-error-background-color: #f6564833;
|
||||||
|
$log-success-background-color: #43c06d33;
|
||||||
|
|
||||||
// old variables
|
// old variables
|
||||||
$accent-color: #6f42c1;
|
$accent-color: #6f42c1;
|
||||||
$accent-color-dark: #c4abf1;
|
$accent-color-dark: #c4abf1;
|
||||||
|
|
|
@ -37,11 +37,9 @@
|
||||||
|
|
||||||
// old colors
|
// old colors
|
||||||
--accent-color: #{$accent-color};
|
--accent-color: #{$accent-color};
|
||||||
--highlight-accent-color: #{$highlight-accent-color};
|
|
||||||
--accent-gradient-color: #{$acent-gradient};
|
--accent-gradient-color: #{$acent-gradient};
|
||||||
--faint-gradient-color: #{$faint-gradient};
|
--faint-gradient-color: #{$faint-gradient};
|
||||||
--background-color-gray: #{$background-color-gray};
|
--background-color-gray: #{$background-color-gray};
|
||||||
--border-color: #{$border-color};
|
|
||||||
--shadow-main-light: #{$shadow-color};
|
--shadow-main-light: #{$shadow-color};
|
||||||
--box-shadow-light: 0px 2px 4px var(--shadow-main-light);
|
--box-shadow-light: 0px 2px 4px var(--shadow-main-light);
|
||||||
--box-shadow-medium: 0px 4px 8px var(--shadow-main-light);
|
--box-shadow-medium: 0px 4px 8px var(--shadow-main-light);
|
||||||
|
@ -75,7 +73,7 @@
|
||||||
--background-radial-gray-gradient: #{$background-radial-gray-gradient-dark};
|
--background-radial-gray-gradient: #{$background-radial-gray-gradient-dark};
|
||||||
|
|
||||||
// border colors
|
// border colors
|
||||||
--border-color: #{$border-color};
|
--border-color: #{$border-color-dark};
|
||||||
--input-border-color: #{$input-border-color-dark};
|
--input-border-color: #{$input-border-color-dark};
|
||||||
--border-color-accent: #{$border-color-accent-dark};
|
--border-color-accent: #{$border-color-accent-dark};
|
||||||
|
|
||||||
|
@ -89,11 +87,9 @@
|
||||||
|
|
||||||
// old colors
|
// old colors
|
||||||
--accent-color: #{$accent-color-dark};
|
--accent-color: #{$accent-color-dark};
|
||||||
--highlight-accent-color: #{$highlight-accent-color-dark};
|
|
||||||
--accent-gradient-color: #{$acent-gradient-dark};
|
--accent-gradient-color: #{$acent-gradient-dark};
|
||||||
--faint-gradient-color: #{$faint-gradient-dark};
|
--faint-gradient-color: #{$faint-gradient-dark};
|
||||||
--background-color-gray: #{$background-color-gray-dark};
|
--background-color-gray: #{$background-color-gray-dark};
|
||||||
--border-color: #{$border-color-dark};
|
|
||||||
--shadow-main-dark: #{$shadow-color};
|
--shadow-main-dark: #{$shadow-color};
|
||||||
--box-shadow-light: 0px 2px 4px var(--shadow-main-dark);
|
--box-shadow-light: 0px 2px 4px var(--shadow-main-dark);
|
||||||
--box-shadow-medium: 0px 4px 8px var(--shadow-main-dark);
|
--box-shadow-medium: 0px 4px 8px var(--shadow-main-dark);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
@use "../abstracts/variables" as *;
|
@use "../abstracts/variables" as *;
|
||||||
@use "../abstracts/mixins" as *;
|
@use "../abstracts/mixins" as *;
|
||||||
|
|
||||||
section, .section{
|
section,
|
||||||
|
.section {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
outline: 1px solid var(--border-color);
|
outline: 1px solid var(--border-color);
|
||||||
outline-offset: -1px;
|
outline-offset: -1px;
|
||||||
|
@ -9,3 +10,21 @@ section, .section{
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scene-container {
|
||||||
|
width: calc(100% - (320px + 270px + 90px));
|
||||||
|
height: calc(100% - (250px));
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: calc(270px + 45px);
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 1;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
transition: all 0.2s;
|
||||||
|
box-shadow: $box-shadow-medium;
|
||||||
|
background: var(--background-color-solid);
|
||||||
|
canvas {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -12,10 +12,3 @@ input[type="password"]::-webkit-clear-button, /* For Chrome/Safari clear button
|
||||||
input[type="password"]::-webkit-inner-spin-button { /* Just in case */
|
input[type="password"]::-webkit-inner-spin-button { /* Just in case */
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
button{
|
|
||||||
border: none;
|
|
||||||
outline: none;
|
|
||||||
background: none;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
|
@ -1,311 +0,0 @@
|
||||||
.roiSummary-container {
|
|
||||||
.roiSummary-wrapper {
|
|
||||||
background-color: var(--background-color);
|
|
||||||
|
|
||||||
.product-info {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.playBack {
|
|
||||||
display: flex;
|
|
||||||
background-color: var(--background-color);
|
|
||||||
border-radius: 12px;
|
|
||||||
padding: 6px;
|
|
||||||
|
|
||||||
.info {
|
|
||||||
span {
|
|
||||||
font-size: var(--font-size-xlarge);
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
color: #31C756;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.roi-details {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
|
|
||||||
.progress-wrapper {
|
|
||||||
width: 250px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
.content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 3px;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.key {
|
|
||||||
font-size: var(--font-size-xlarge);
|
|
||||||
color: var(--accent-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.roi-progress {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metrics {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
.metric-item {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 6px;
|
|
||||||
border: 1px solid #00FF56;
|
|
||||||
background: #436D51;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 4px 6px;
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-label {
|
|
||||||
font-size: 10px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-value {
|
|
||||||
text-align: center;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.metric-wrapper {
|
|
||||||
display: flex;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
.metric-item {
|
|
||||||
background-color: var(--background-color);
|
|
||||||
border: 1px solid var(--Grays-Gray-6, #F2F2F7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.cost-breakdown {
|
|
||||||
background-color: var(--background-color);
|
|
||||||
border: 1px solid var(--text-disabled);
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
.breakdown-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
|
|
||||||
.section-wrapper {
|
|
||||||
display: flex;
|
|
||||||
gap: 4px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-number {
|
|
||||||
font-size: 20px;
|
|
||||||
color: #00aaff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
font-size: var(--font-size-regular);
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.expand-icon {
|
|
||||||
font-size: 16px;
|
|
||||||
color: var(--text-color);
|
|
||||||
cursor: pointer;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
transition: transform 0.2s linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
.expand-icon.open {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.breakdown-table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 8px;
|
|
||||||
text-align: left;
|
|
||||||
border-top: 1px solid var(--text-disabled);
|
|
||||||
border-bottom: 1px solid var(--text-disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
th:first-child,
|
|
||||||
td:first-child {
|
|
||||||
border-left: 1px solid var(--text-disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
th:last-child,
|
|
||||||
td:last-child {
|
|
||||||
border-right: 1px solid var(--text-disabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
background-color: var(--background-color);
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.total-row,
|
|
||||||
.net-profit-row {
|
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tips-section {
|
|
||||||
background-color: var(--background-color);
|
|
||||||
border-radius: 8px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 6px;
|
|
||||||
padding: 12px;
|
|
||||||
|
|
||||||
.tip-header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.tip-title {
|
|
||||||
color: var(--text-color);
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.tip-description {
|
|
||||||
span {
|
|
||||||
font-size: var(--font-size-xlarge);
|
|
||||||
color: #34C759;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
color: #34C759;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
color: #488EF6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.get-tips-button {
|
|
||||||
border: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-top: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
background: none;
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
background-color: var(--accent-color);
|
|
||||||
color: var(--background-color);
|
|
||||||
padding: 4px 6px;
|
|
||||||
border-radius: 5px;
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 14px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.semi-circle-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
height: 125px;
|
|
||||||
overflow-y: hidden;
|
|
||||||
position: relative;
|
|
||||||
.semi-circle {
|
|
||||||
width: 100%;
|
|
||||||
height: 250px;
|
|
||||||
border-radius: 50%;
|
|
||||||
position: relative;
|
|
||||||
transition: background 0.5s ease;
|
|
||||||
}
|
|
||||||
.progress-cover {
|
|
||||||
position: absolute;
|
|
||||||
width: 75%;
|
|
||||||
height: 75%;
|
|
||||||
top: 12.5%;
|
|
||||||
left: 12.5%;
|
|
||||||
background: #000000cc;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.label-wrapper {
|
|
||||||
.label {
|
|
||||||
font-size: var(--font-size-xxxlarge);
|
|
||||||
}
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, 0%);
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
color: #333;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Breakdown Table Open/Close Logic
|
|
||||||
|
|
||||||
.breakdown-table-wrapper {
|
|
||||||
&.closed {
|
|
||||||
max-height: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.open {
|
|
||||||
max-height: 500px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.breakdown-table {
|
|
||||||
width: 100%;
|
|
||||||
border-collapse: collapse;
|
|
||||||
|
|
||||||
th,
|
|
||||||
td {
|
|
||||||
padding: 10px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,279 +0,0 @@
|
||||||
.analysis {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: start;
|
|
||||||
width: 100%;
|
|
||||||
height: 100vh;
|
|
||||||
// pointer-events: none;
|
|
||||||
z-index: 10000;
|
|
||||||
|
|
||||||
.analysis-wrapper {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.analysis-card {
|
|
||||||
min-width: 333px;
|
|
||||||
background: var(--background-color);
|
|
||||||
border-radius: 20px;
|
|
||||||
|
|
||||||
padding: 8px;
|
|
||||||
|
|
||||||
.analysis-card-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
background: var(--background-color);
|
|
||||||
border-radius: 14px;
|
|
||||||
padding: 16px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 14px;
|
|
||||||
|
|
||||||
.card-header {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.main-header {
|
|
||||||
line-height: 20px;
|
|
||||||
font-size: var(--font-size-regular);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.process-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.throughput-value {
|
|
||||||
font-size: 1rem;
|
|
||||||
|
|
||||||
.value {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar-wrapper {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-bar {
|
|
||||||
position: relative;
|
|
||||||
// width: 36px;
|
|
||||||
width: 100%;
|
|
||||||
height: 4px;
|
|
||||||
border-radius: 13px;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #FBEBD7;
|
|
||||||
|
|
||||||
.bar-fill {
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
background: #FC9D2F;
|
|
||||||
border-radius: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-fill.full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bar-fill.partial {
|
|
||||||
width: 0; // inline style will override this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.metrics-section {
|
|
||||||
padding-top: 16px;
|
|
||||||
border-top: 1px solid var(--background-color-gray);
|
|
||||||
|
|
||||||
.metric {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 14px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
|
|
||||||
.label {
|
|
||||||
color: var(--text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.throughoutSummary {
|
|
||||||
.throughoutSummary-wrapper {
|
|
||||||
.process-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 16px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
.throughput-value {
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.value {
|
|
||||||
color: var(--accent-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Let the text take available space */
|
|
||||||
}
|
|
||||||
|
|
||||||
.lineChart {
|
|
||||||
max-width: 200px;
|
|
||||||
height: 100px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.assetUsage {
|
|
||||||
text-align: right;
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas {
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
display: flex;
|
|
||||||
gap: 16px; // Space between cards
|
|
||||||
margin-top: 24px;
|
|
||||||
|
|
||||||
.footer-card {
|
|
||||||
width: 100%;
|
|
||||||
background: var(--background-color-gray);
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 8px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
width: 85%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
font-size: var(--font-size-regular);
|
|
||||||
}
|
|
||||||
|
|
||||||
.value-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: end;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.shiftUtilization {
|
|
||||||
.value-container {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
.value {
|
|
||||||
font-size: var(--font-size-xlarge);
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
border-radius: 6px;
|
|
||||||
height: 5px;
|
|
||||||
|
|
||||||
&:nth-child(1) {
|
|
||||||
background: #F3C64D;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
background: #67B3F4;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) {
|
|
||||||
background: #7981F5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.progress-indicator {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
gap: 6px;
|
|
||||||
|
|
||||||
.shift-wrapper {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 5px;
|
|
||||||
|
|
||||||
/* Align items vertically */
|
|
||||||
&:nth-child(1) {
|
|
||||||
.indicator {
|
|
||||||
|
|
||||||
background: #F3C64D;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(2) {
|
|
||||||
.indicator {
|
|
||||||
|
|
||||||
background: #67B3F4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(3) {
|
|
||||||
.indicator {
|
|
||||||
|
|
||||||
background: #7981F5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
font-size: var(--font-size-small);
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.indicator {
|
|
||||||
display: inline-block;
|
|
||||||
width: 5px;
|
|
||||||
height: 5px;
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
@use "../abstracts/variables" as *;
|
||||||
|
@use "../abstracts/mixins" as *;
|
||||||
|
|
||||||
|
.labeled-button-container {
|
||||||
|
@include flex-space-between;
|
||||||
|
padding: 6px 12px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
padding: 2px 32px;
|
||||||
|
border: none;
|
||||||
|
border-radius: #{$border-radius-large};
|
||||||
|
color: var(--text-button-color);
|
||||||
|
background: var(--background-color-button);
|
||||||
|
transition: all 0.2s;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
@use "../../abstracts/variables" as *;
|
||||||
|
@use "../../abstracts/mixins" as *;
|
||||||
|
|
||||||
|
.footer-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 2px 12px;
|
||||||
|
|
||||||
|
.selection-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.selector-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
align-items: center;
|
||||||
|
background: var(--background-color);
|
||||||
|
padding: 3px 6px;
|
||||||
|
border-radius: 12px;
|
||||||
|
color: var(--text-color);
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.logs-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.logs-detail,
|
||||||
|
.version {
|
||||||
|
border-radius: 12px;
|
||||||
|
background: var(--background-color);
|
||||||
|
padding: 3px 6px;
|
||||||
|
color: var(--text-color);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logs-detail {
|
||||||
|
padding: 2px 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
.log-icon {
|
||||||
|
@include flex-center;
|
||||||
|
}
|
||||||
|
.log-message {
|
||||||
|
max-width: 40vw;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.version {
|
||||||
|
font-size: var(--font-size-tiny);
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
.icon{
|
||||||
|
@include flex-center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -639,21 +639,6 @@ input[type="number"] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.labeled-button-container {
|
|
||||||
@include flex-space-between;
|
|
||||||
padding: 6px 12px;
|
|
||||||
|
|
||||||
button {
|
|
||||||
padding: 2px 32px;
|
|
||||||
border: none;
|
|
||||||
border-radius: #{$border-radius-large};
|
|
||||||
color: var(--text-button-color);
|
|
||||||
background: var(--background-color-button);
|
|
||||||
transition: all 0.2s;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.value-field-container {
|
.value-field-container {
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
@use "../../abstracts/variables" as *;
|
||||||
|
@use "../../abstracts/mixins" as *;
|
||||||
|
|
||||||
|
.log-list-container {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background: var(--background-color-secondary);
|
||||||
|
|
||||||
|
.log-list-wrapper {
|
||||||
|
height: 50%;
|
||||||
|
min-width: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 5;
|
||||||
|
background: var(--background-color);
|
||||||
|
padding: 14px 12px;
|
||||||
|
border-radius: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
backdrop-filter: blur(50px);
|
||||||
|
outline: 1px solid var(--border-color);
|
||||||
|
|
||||||
|
.log-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
.log-header-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
@include flex-center;
|
||||||
|
height: 28px;
|
||||||
|
width: 28px;
|
||||||
|
cursor: pointer;
|
||||||
|
svg {
|
||||||
|
scale: 1.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-nav-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.log-nav {
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-nav.active {
|
||||||
|
background-color: var(--background-color-accent);
|
||||||
|
color: var(--text-button-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-entry-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
background: var(--background-color);
|
||||||
|
padding: 18px 10px;
|
||||||
|
border-radius: 16px;
|
||||||
|
outline: 1px solid var(--border-color);
|
||||||
|
outline-offset: -1px;
|
||||||
|
|
||||||
|
.log-entry {
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.log-icon {
|
||||||
|
@include flex-center;
|
||||||
|
}
|
||||||
|
.log-entry-message-container {
|
||||||
|
@include flex-space-between;
|
||||||
|
gap: 12px;
|
||||||
|
width: 100%;
|
||||||
|
.message-time {
|
||||||
|
font-size: var(--font-size-tiny);
|
||||||
|
font-weight: 300;
|
||||||
|
opacity: 0.8;
|
||||||
|
text-wrap: nowrap;
|
||||||
|
}
|
||||||
|
.log-entry-message{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(odd) {
|
||||||
|
background: var(--background-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,557 @@
|
||||||
|
@use "../../abstracts/variables" as *;
|
||||||
|
@use "../../abstracts/mixins" as *;
|
||||||
|
|
||||||
|
.analysis {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: start;
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
pointer-events: none;
|
||||||
|
padding: 10px;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.analysis-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.analysis-card {
|
||||||
|
min-width: 333px;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 8px;
|
||||||
|
pointer-events: all;
|
||||||
|
|
||||||
|
.analysis-card-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
background: var(--background-color);
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 14px;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
outline: 1px solid var(--border-color);
|
||||||
|
outline-offset: -1px;
|
||||||
|
|
||||||
|
.card-header {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.main-header {
|
||||||
|
line-height: 20px;
|
||||||
|
font-size: var(--font-size-regular);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.process-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.throughput-value {
|
||||||
|
font-size: 1rem;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 13px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #fbebd7;
|
||||||
|
|
||||||
|
.bar-fill {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background: #fc9d2f;
|
||||||
|
border-radius: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar-fill.full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bar-fill.partial {
|
||||||
|
width: 0; // inline style will override this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.metrics-section {
|
||||||
|
padding-top: 16px;
|
||||||
|
border-top: 1px solid var(--background-color-gray);
|
||||||
|
|
||||||
|
.metric {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.throughoutSummary-wrapper {
|
||||||
|
.process-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 16px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.throughput-value {
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Let the text take available space */
|
||||||
|
}
|
||||||
|
|
||||||
|
.lineChart {
|
||||||
|
max-width: 200px;
|
||||||
|
height: 100px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.assetUsage {
|
||||||
|
text-align: right;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px; // Space between cards
|
||||||
|
margin-top: 24px;
|
||||||
|
|
||||||
|
.footer-card {
|
||||||
|
width: 100%;
|
||||||
|
background: var(--background-color-gray);
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-size: var(--font-size-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
.value-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: end;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.shiftUtilization {
|
||||||
|
.value-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: var(--font-size-xlarge);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
border-radius: 6px;
|
||||||
|
height: 5px;
|
||||||
|
|
||||||
|
&:nth-child(1) {
|
||||||
|
background: #f3c64d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
background: #67b3f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
background: #7981f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-indicator {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.shift-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
/* Align items vertically */
|
||||||
|
&:nth-child(1) {
|
||||||
|
.indicator {
|
||||||
|
background: #f3c64d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
.indicator {
|
||||||
|
background: #67b3f4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(3) {
|
||||||
|
.indicator {
|
||||||
|
background: #7981f5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: var(--font-size-small);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indicator {
|
||||||
|
display: inline-block;
|
||||||
|
width: 5px;
|
||||||
|
height: 5px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.roiSummary-wrapper {
|
||||||
|
max-width: 470px;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
|
||||||
|
.product-info {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.playBack {
|
||||||
|
display: flex;
|
||||||
|
background-color: var(--background-color);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 6px;
|
||||||
|
|
||||||
|
.info {
|
||||||
|
span {
|
||||||
|
font-size: var(--font-size-xlarge);
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
color: #31c756;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.roi-details {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.progress-wrapper {
|
||||||
|
width: 250px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 3px;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.key {
|
||||||
|
font-size: var(--font-size-xlarge);
|
||||||
|
color: var(--accent-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.roi-progress {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metrics {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.metric-item {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: #{$border-radius-xxx};
|
||||||
|
border: 1px solid #00ff56;
|
||||||
|
background: #17eb5e42;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 4px 8px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-label {
|
||||||
|
opacity: 0.8;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 300;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value {
|
||||||
|
text-align: center;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
.metric-item {
|
||||||
|
border-radius: #{$border-radius-large};
|
||||||
|
background-color: var(--background-color);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cost-breakdown {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: #{$border-radius-extra-large};
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
|
.breakdown-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.section-wrapper {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-number {
|
||||||
|
color: #00aaff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: var(--font-size-regular);
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--text-color);
|
||||||
|
cursor: pointer;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
transition: transform 0.2s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-icon.open {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakdown-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
outline: 1px solid var(--border-color);
|
||||||
|
outline-offset: -1px;
|
||||||
|
margin-top: 12px;
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
color: var(--text-color);
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tips-section {
|
||||||
|
background-color: var(--background-color);
|
||||||
|
border-radius: #{$border-radius-large};
|
||||||
|
outline: 1px solid var(--border-color);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 12px;
|
||||||
|
|
||||||
|
.tip-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.tip-title {
|
||||||
|
color: var(--text-color);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tip-description {
|
||||||
|
span {
|
||||||
|
font-size: var(--font-size-xlarge);
|
||||||
|
color: #34c759;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
color: #34c759;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(2) {
|
||||||
|
color: #488ef6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.get-tips-button {
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 8px;
|
||||||
|
display: inline-block;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
color: var(--text-button-color);
|
||||||
|
background: var(--background-color-button);
|
||||||
|
padding: 4px 12px;
|
||||||
|
border-radius: #{$border-radius-large};
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.semi-circle-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
height: 125px;
|
||||||
|
overflow-y: hidden;
|
||||||
|
position: relative;
|
||||||
|
.semi-circle {
|
||||||
|
width: 100%;
|
||||||
|
height: 250px;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.progress-cover {
|
||||||
|
position: absolute;
|
||||||
|
width: 75%;
|
||||||
|
height: 75%;
|
||||||
|
top: 12.5%;
|
||||||
|
left: 12.5%;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-wrapper {
|
||||||
|
.label {
|
||||||
|
font-size: var(--font-size-xxxlarge);
|
||||||
|
}
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0%);
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #333;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakdown-table-wrapper {
|
||||||
|
&.closed {
|
||||||
|
max-height: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
max-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breakdown-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
|
||||||
|
th,
|
||||||
|
td {
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Breakdown Table Open/Close Logic
|
||||||
|
|
|
@ -32,10 +32,17 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls-container {
|
.controls-container {
|
||||||
@include flex-center;
|
@include flex-space-between;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
.header{
|
||||||
|
@include flex-center;
|
||||||
|
gap: 6px;
|
||||||
|
padding: 0 8px;
|
||||||
|
svg{
|
||||||
|
scale: 1.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
.production-details,
|
.production-details,
|
||||||
.controls-wrapper {
|
.controls-wrapper {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
|
@ -72,7 +79,7 @@
|
||||||
|
|
||||||
.expand-icon-container {
|
.expand-icon-container {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
padding: 6px 8px;
|
padding: 0 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,6 +314,22 @@
|
||||||
font-size: var(--font-size-tiny);
|
font-size: var(--font-size-tiny);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.timmer {
|
||||||
|
width: auto;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
font-size: var(--font-size-tiny);
|
||||||
|
}
|
||||||
|
|
||||||
|
.start-displayer {
|
||||||
|
left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.end-displayer {
|
||||||
|
width: auto;
|
||||||
|
right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.start-displayer {
|
.start-displayer {
|
||||||
bottom: 4px;
|
bottom: 4px;
|
||||||
left: 16px;
|
left: 16px;
|
||||||
|
@ -347,6 +370,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.simulation-player-container.open {
|
.simulation-player-container.open {
|
||||||
|
|
||||||
|
.start-displayer,
|
||||||
|
.end-displayer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.timmer {
|
.timmer {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
transition: width 0.2s;
|
transition: width 0.2s;
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
backdrop-filter: blur(8px);
|
backdrop-filter: blur(8px);
|
||||||
z-index: #{$z-index-default};
|
z-index: 2;
|
||||||
outline: 1px solid var(--border-color);
|
outline: 1px solid var(--border-color);
|
||||||
outline-offset: -1px;
|
outline-offset: -1px;
|
||||||
|
|
||||||
|
@ -124,6 +124,8 @@
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
border-radius: #{$border-radius-medium};
|
border-radius: #{$border-radius-medium};
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
|
outline: 1px solid var(--border-color);
|
||||||
|
outline-offset: -1px;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
|
|
@ -58,12 +58,8 @@
|
||||||
fill: var(--icon-default-color-active);
|
fill: var(--icon-default-color-active);
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
rect {
|
filter: saturate(0.8);
|
||||||
stroke: var(--icon-default-color);
|
background: var(--background-color-accent);
|
||||||
}
|
|
||||||
circle {
|
|
||||||
fill: var(--icon-default-color);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,7 +416,7 @@
|
||||||
outline: none;
|
outline: none;
|
||||||
path {
|
path {
|
||||||
stroke: var(--text-button-color);
|
stroke: var(--text-button-color);
|
||||||
stroke-width: 1.3;
|
strokeWidth: 1.3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,7 +682,7 @@
|
||||||
|
|
||||||
path {
|
path {
|
||||||
stroke: var(--accent-color);
|
stroke: var(--accent-color);
|
||||||
stroke-width: 1.5px;
|
strokeWidth: 1.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -714,10 +710,10 @@
|
||||||
|
|
||||||
.add-button {
|
.add-button {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
padding: 2px 4px;
|
padding: 4px 8px;
|
||||||
background: var(--background-color-button);
|
background: var(--background-color-button);
|
||||||
color: var(--text-button-color);
|
color: var(--text-button-color);
|
||||||
border-radius: #{$border-radius-small};
|
border-radius: #{$border-radius-large};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -832,10 +828,10 @@
|
||||||
transform: translateX(4px);
|
transform: translateX(4px);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--accent-color);
|
background: var(--background-color-accent);
|
||||||
|
|
||||||
path {
|
path {
|
||||||
stroke: var(--primary-color);
|
stroke: var(--text-button-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1003,10 +999,10 @@
|
||||||
border-radius: 8px 0 0 8px;
|
border-radius: 8px 0 0 8px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--accent-color);
|
background: var(--background-color-accent);
|
||||||
|
|
||||||
path {
|
path {
|
||||||
stroke: var(--primary-color);
|
stroke: var(--text-button-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1067,7 +1063,13 @@
|
||||||
.dropdown-content-container {
|
.dropdown-content-container {
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
}
|
}
|
||||||
|
.value-field-container {
|
||||||
|
padding: 6px;
|
||||||
|
.dropdown {
|
||||||
|
min-width: 44px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
.input-range-container {
|
.input-range-container {
|
||||||
.input-container {
|
.input-container {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
@use 'components/button';
|
@use 'components/button';
|
||||||
@use 'components/form';
|
@use 'components/form';
|
||||||
@use 'components/input';
|
@use 'components/input';
|
||||||
@use 'components/layouts';
|
|
||||||
@use 'components/lists';
|
@use 'components/lists';
|
||||||
@use 'components/moduleToggle';
|
@use 'components/moduleToggle';
|
||||||
@use 'components/templates';
|
@use 'components/templates';
|
||||||
|
@ -22,11 +21,12 @@
|
||||||
@use 'components/visualization/ui/styledWidgets';
|
@use 'components/visualization/ui/styledWidgets';
|
||||||
@use 'components/visualization/floating/common';
|
@use 'components/visualization/floating/common';
|
||||||
@use 'components/marketPlace/marketPlace';
|
@use 'components/marketPlace/marketPlace';
|
||||||
@use 'components/simulation/simulation';
|
|
||||||
@use 'components/menu/menu';
|
@use 'components/menu/menu';
|
||||||
@use 'components/confirmationPopUp';
|
@use 'components/confirmationPopUp';
|
||||||
@use 'components/analysis/analysis';
|
@use 'components/simulation/simulation';
|
||||||
@use 'components/analysis/ROISummary.scss';
|
@use 'components/simulation/analysis';
|
||||||
|
@use 'components/logs/logs';
|
||||||
|
@use 'components/footer/footer.scss';
|
||||||
|
|
||||||
// layout
|
// layout
|
||||||
@use 'layout/loading';
|
@use 'layout/loading';
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
// Main Container
|
// Main Container
|
||||||
.realTime-viz {
|
.realTime-viz {
|
||||||
background: #131313;
|
|
||||||
box-shadow: $box-shadow-medium;
|
|
||||||
width: calc(100% - (320px + 270px + 90px));
|
width: calc(100% - (320px + 270px + 90px));
|
||||||
height: calc(100% - (250px));
|
height: calc(100% - (250px));
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -12,8 +10,8 @@
|
||||||
left: calc(270px + 45px);
|
left: calc(270px + 45px);
|
||||||
transform: translate(0, -50%);
|
transform: translate(0, -50%);
|
||||||
border-radius: #{$border-radius-medium};
|
border-radius: #{$border-radius-medium};
|
||||||
transition: all 0.2s;
|
z-index: 2;
|
||||||
z-index: #{$z-index-default};
|
pointer-events: none;
|
||||||
|
|
||||||
.realTime-viz-wrapper {
|
.realTime-viz-wrapper {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -39,10 +37,6 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scene-container {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -74,6 +68,8 @@
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
transform: translate(-50%, -10%);
|
transform: translate(-50%, -10%);
|
||||||
transition: transform 0.5s linear;
|
transition: transform 0.5s linear;
|
||||||
|
pointer-events: all;
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -367,6 +363,7 @@
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
box-shadow: #{$box-shadow-medium};
|
box-shadow: #{$box-shadow-medium};
|
||||||
|
pointer-events: all;
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
stroke: var(--icon-default-color) !important;
|
stroke: var(--icon-default-color) !important;
|
||||||
|
@ -426,10 +423,8 @@
|
||||||
|
|
||||||
path {
|
path {
|
||||||
stroke: #f65648;
|
stroke: #f65648;
|
||||||
stroke-width: 1.3;
|
strokeWidth: 1.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -778,17 +773,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.panel-content {
|
.panel-content {
|
||||||
background: var(--background-color);
|
background: var(--background-color);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* RIGHT */
|
/* RIGHT */
|
||||||
.panel-content.right-opening {
|
.panel-content.right-opening {
|
||||||
animation: rightExpand 0.5s ease-in-out forwards;
|
animation: rightExpand 0.5s ease-in-out forwards;
|
||||||
|
@ -913,9 +901,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Add button
|
// Add button
|
||||||
|
|
||||||
.extra-Bs-addopening {
|
.extra-Bs-addopening {
|
||||||
|
@ -926,7 +911,6 @@
|
||||||
animation: slideUp 0.3s ease forwards;
|
animation: slideUp 0.3s ease forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@keyframes slideDown {
|
@keyframes slideDown {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
Loading…
Reference in New Issue