Refactor components and improve loading behavior
- Simplified rendering of CompareLayOut and ComparisonScene components. - Enhanced MainScene to log createNewWindow state and conditionally render LoadingPage. - Updated GlobalProperties to improve environment settings handling. - Refactored LoadingPage to support rendering as a portal and added new props for flexibility. - Improved NewWindowScene to include LoadingPage and handle loading progress. - Added console logs for debugging in calculateSimulationData and ComparisonResult components. - Cleaned up unused code and improved readability across various components. - Adjusted styles in loading.scss for better visual consistency and responsiveness.
This commit is contained in:
@@ -220,7 +220,7 @@ function ComparisonScene() {
|
||||
<Button />
|
||||
</div>
|
||||
)}
|
||||
{<CompareLayOut />}
|
||||
<CompareLayOut />
|
||||
{createNewWindow && <NewWindowScene />}
|
||||
{shouldShowComparisonResult && !loadingProgress && <ComparisonResult />}
|
||||
</>
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { useEffect } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useLoadingProgress, useRenameModeStore, useIsComparing, useSelectedComment, useWidgetSubOption, useToggleView } from "../../../store/builder/store";
|
||||
import {
|
||||
useLoadingProgress,
|
||||
useRenameModeStore,
|
||||
useIsComparing,
|
||||
useSelectedComment,
|
||||
useWidgetSubOption,
|
||||
useToggleView,
|
||||
useCreateNewWindow,
|
||||
} from "../../../store/builder/store";
|
||||
import useModuleStore from "../../../store/ui/useModuleStore";
|
||||
import { useSocketStore } from "../../../store/socket/useSocketStore";
|
||||
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
|
||||
@@ -55,7 +63,11 @@ function MainScene() {
|
||||
const { selectedComment, commentPositionState } = useSelectedComment();
|
||||
const { resetStates } = useRestStates();
|
||||
const { organization, userId } = getUserData();
|
||||
const { createNewWindow } = useCreateNewWindow();
|
||||
|
||||
useEffect(() => {
|
||||
console.log("createNewWindow: ", createNewWindow);
|
||||
}, [createNewWindow]);
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
resetStates();
|
||||
@@ -106,9 +118,13 @@ function MainScene() {
|
||||
useEffect(() => {
|
||||
if (versionHistory.length > 0) {
|
||||
recentlyViewedApi().then((projects) => {
|
||||
const recent_opened_verisionID = (Object.values(projects?.RecentlyViewed || {})[0] as any)?.Present_version._id;
|
||||
const recent_opened_verisionID = (
|
||||
Object.values(projects?.RecentlyViewed || {})[0] as any
|
||||
)?.Present_version._id;
|
||||
if (recent_opened_verisionID && projects.RecentlyViewed[0]._id === projectId) {
|
||||
const version = versionHistory.find((ver) => ver.versionId === recent_opened_verisionID);
|
||||
const version = versionHistory.find(
|
||||
(ver) => ver.versionId === recent_opened_verisionID
|
||||
);
|
||||
if (version) {
|
||||
setSelectedVersion(version);
|
||||
}
|
||||
@@ -186,7 +202,9 @@ function MainScene() {
|
||||
{!selectedUser && (
|
||||
<>
|
||||
<KeyPressListener />
|
||||
{loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
|
||||
{!createNewWindow && loadingProgress > 0 && (
|
||||
<LoadingPage progress={loadingProgress} />
|
||||
)}
|
||||
{!isPlaying && (
|
||||
<>
|
||||
{!toggleView && !isComparing && <ModuleToggle />}
|
||||
@@ -197,20 +215,41 @@ function MainScene() {
|
||||
<RealTimeVisulization />
|
||||
{activeModule === "market" && <MarketPlace />}
|
||||
{activeModule !== "market" && !isPlaying && !isComparing && <Tools />}
|
||||
{isPlaying && activeModule === "simulation" && loadingProgress === 0 && <SimulationPlayer />}
|
||||
{isPlaying && activeModule === "simulation" && loadingProgress === 0 && (
|
||||
<SimulationPlayer />
|
||||
)}
|
||||
{isPlaying && activeModule !== "simulation" && <ControlsPlayer />}
|
||||
|
||||
{isRenameMode && selectedAssets.length === 1 && <RenameTooltip name={selectedAssets[0].userData.modelName} onSubmit={handleObjectRename} />}
|
||||
{isRenameMode && selectedAssets.length === 1 && (
|
||||
<RenameTooltip
|
||||
name={selectedAssets[0].userData.modelName}
|
||||
onSubmit={handleObjectRename}
|
||||
/>
|
||||
)}
|
||||
|
||||
{activeModule === "builder" && toggleView && <SelectFloorPlan />}
|
||||
|
||||
{selectedProduct && selectedVersion && isComparing && !isPlaying && activeModule === "simulation" && (
|
||||
<div className="selectLayout-wrapper">
|
||||
<RegularDropDown header={selectedVersion.versionName} options={versionHistory.map((v) => v.versionName)} onSelect={handleSelectVersion} search={false} />
|
||||
<br />
|
||||
<RegularDropDown header={selectedProduct.productName} options={products.map((l) => l.productName)} onSelect={handleSelectProduct} search={false} />
|
||||
</div>
|
||||
)}
|
||||
{selectedProduct &&
|
||||
selectedVersion &&
|
||||
isComparing &&
|
||||
!isPlaying &&
|
||||
activeModule === "simulation" && (
|
||||
<div className="selectLayout-wrapper">
|
||||
<RegularDropDown
|
||||
header={selectedVersion.versionName}
|
||||
options={versionHistory.map((v) => v.versionName)}
|
||||
onSelect={handleSelectVersion}
|
||||
search={false}
|
||||
/>
|
||||
<br />
|
||||
<RegularDropDown
|
||||
header={selectedProduct.productName}
|
||||
options={products.map((l) => l.productName)}
|
||||
onSelect={handleSelectProduct}
|
||||
search={false}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<VersionSaved />
|
||||
</>
|
||||
|
||||
@@ -68,6 +68,7 @@ export const calculateSimulationData = (assets: AssetData[]) => {
|
||||
});
|
||||
|
||||
const machineActiveTime = assets.filter((a) => a.type === "human").reduce((acc, a) => acc + a.activeTime, 0);
|
||||
console.log('assets: ', assets);
|
||||
|
||||
const machineIdleTime = assets.filter((a) => a.type === "machine").reduce((acc, a) => acc + a.idleTime, 0);
|
||||
|
||||
|
||||
@@ -44,7 +44,16 @@ const GlobalProperties: React.FC = () => {
|
||||
|
||||
const optimizeScene = async (value: any) => {
|
||||
if (!projectId) return;
|
||||
setEnvironment(organization, userId, wallVisibility, roofVisibility, shadows, 30, true, projectId);
|
||||
setEnvironment(
|
||||
organization,
|
||||
userId,
|
||||
wallVisibility,
|
||||
roofVisibility,
|
||||
shadows,
|
||||
30,
|
||||
true,
|
||||
projectId
|
||||
);
|
||||
setRenderDistance(30);
|
||||
setLimitDistance(true);
|
||||
};
|
||||
@@ -52,10 +61,28 @@ const GlobalProperties: React.FC = () => {
|
||||
const limitRenderDistance = async () => {
|
||||
if (!projectId) return;
|
||||
if (limitDistance) {
|
||||
setEnvironment(organization, userId, wallVisibility, roofVisibility, shadows, 75, !limitDistance, projectId);
|
||||
setEnvironment(
|
||||
organization,
|
||||
userId,
|
||||
wallVisibility,
|
||||
roofVisibility,
|
||||
shadows,
|
||||
75,
|
||||
!limitDistance,
|
||||
projectId
|
||||
);
|
||||
setRenderDistance(75);
|
||||
} else {
|
||||
setEnvironment(organization, userId, wallVisibility, roofVisibility, shadows, renderDistance, !limitDistance, projectId);
|
||||
setEnvironment(
|
||||
organization,
|
||||
userId,
|
||||
wallVisibility,
|
||||
roofVisibility,
|
||||
shadows,
|
||||
renderDistance,
|
||||
!limitDistance,
|
||||
projectId
|
||||
);
|
||||
}
|
||||
setLimitDistance(!limitDistance);
|
||||
};
|
||||
@@ -84,7 +111,16 @@ const GlobalProperties: React.FC = () => {
|
||||
if (!projectId) return;
|
||||
setRenderDistance(value);
|
||||
// setDistance(value);
|
||||
const data = await setEnvironment(organization, userId, wallVisibility, roofVisibility, shadows, value, limitDistance, projectId);
|
||||
const data = await setEnvironment(
|
||||
organization,
|
||||
userId,
|
||||
wallVisibility,
|
||||
roofVisibility,
|
||||
shadows,
|
||||
value,
|
||||
limitDistance,
|
||||
projectId
|
||||
);
|
||||
};
|
||||
|
||||
// Function to toggle roof visibility
|
||||
@@ -92,7 +128,16 @@ const GlobalProperties: React.FC = () => {
|
||||
if (!projectId) return;
|
||||
|
||||
//using REST
|
||||
const data = await setEnvironment(organization, userId, wallVisibility, !roofVisibility, shadows, renderDistance, limitDistance, projectId);
|
||||
const data = await setEnvironment(
|
||||
organization,
|
||||
userId,
|
||||
wallVisibility,
|
||||
!roofVisibility,
|
||||
shadows,
|
||||
renderDistance,
|
||||
limitDistance,
|
||||
projectId
|
||||
);
|
||||
|
||||
//using Socket
|
||||
// const visData = {
|
||||
@@ -112,7 +157,16 @@ const GlobalProperties: React.FC = () => {
|
||||
if (!projectId) return;
|
||||
|
||||
//using REST
|
||||
const data = await setEnvironment(organization, userId, !wallVisibility, roofVisibility, shadows, renderDistance, limitDistance, projectId);
|
||||
const data = await setEnvironment(
|
||||
organization,
|
||||
userId,
|
||||
!wallVisibility,
|
||||
roofVisibility,
|
||||
shadows,
|
||||
renderDistance,
|
||||
limitDistance,
|
||||
projectId
|
||||
);
|
||||
|
||||
//using Socket
|
||||
// const visData = {
|
||||
@@ -132,7 +186,16 @@ const GlobalProperties: React.FC = () => {
|
||||
if (!projectId) return;
|
||||
|
||||
//using REST
|
||||
const data = await setEnvironment(organization, userId, wallVisibility, roofVisibility, !shadows, renderDistance, limitDistance, projectId);
|
||||
const data = await setEnvironment(
|
||||
organization,
|
||||
userId,
|
||||
wallVisibility,
|
||||
roofVisibility,
|
||||
!shadows,
|
||||
renderDistance,
|
||||
limitDistance,
|
||||
projectId
|
||||
);
|
||||
|
||||
//using Socket
|
||||
// const visData = {
|
||||
@@ -165,14 +228,34 @@ const GlobalProperties: React.FC = () => {
|
||||
|
||||
<div className="split"></div>
|
||||
|
||||
<InputToggle value={roofVisibility} inputKey="1" label="Roof Visibility" onClick={changeRoofVisibility} />
|
||||
<InputToggle value={wallVisibility} inputKey="2" label="Wall Visibility" onClick={changeWallVisibility} />
|
||||
<InputToggle value={shadows} inputKey="3" label="Shadows Visibility" onClick={shadowVisibility} />
|
||||
<InputToggle
|
||||
value={roofVisibility}
|
||||
inputKey="1"
|
||||
label="Roof Visibility"
|
||||
onClick={changeRoofVisibility}
|
||||
/>
|
||||
<InputToggle
|
||||
value={wallVisibility}
|
||||
inputKey="2"
|
||||
label="Wall Visibility"
|
||||
onClick={changeWallVisibility}
|
||||
/>
|
||||
<InputToggle
|
||||
value={shadows}
|
||||
inputKey="3"
|
||||
label="Shadows Visibility"
|
||||
onClick={shadowVisibility}
|
||||
/>
|
||||
<LabeledButton label="Reset Camera" onClick={toggleResetCamera} value="Reset" />
|
||||
|
||||
<div className="split"></div>
|
||||
|
||||
<InputToggle inputKey="4" label="Limit Render Distance" value={limitDistance} onClick={limitRenderDistance} />
|
||||
<InputToggle
|
||||
inputKey="4"
|
||||
label="Limit Render Distance"
|
||||
value={limitDistance}
|
||||
onClick={limitRenderDistance}
|
||||
/>
|
||||
<InputRange
|
||||
label="Distance"
|
||||
disabled={!limitDistance}
|
||||
@@ -186,7 +269,12 @@ const GlobalProperties: React.FC = () => {
|
||||
|
||||
<div className="split"></div>
|
||||
|
||||
<InputToggle inputKey="7" label="Limit Fps" value={limitFps} onClick={limitFpsToggle} />
|
||||
<InputToggle
|
||||
inputKey="7"
|
||||
label="Limit Fps"
|
||||
value={limitFps}
|
||||
onClick={limitFpsToggle}
|
||||
/>
|
||||
<InputRange
|
||||
label="Fps"
|
||||
disabled={!limitFps}
|
||||
|
||||
@@ -24,159 +24,6 @@ type NewWindowProps = {
|
||||
theme?: string | null;
|
||||
};
|
||||
|
||||
// export const RenderInNewWindow: React.FC<NewWindowProps> = ({
|
||||
// children,
|
||||
// title = "New Window",
|
||||
// width = 900,
|
||||
// height = 700,
|
||||
// left,
|
||||
// top,
|
||||
// center = true,
|
||||
// features,
|
||||
// onClose,
|
||||
// copyStyles = true,
|
||||
// noopener = true,
|
||||
// className,
|
||||
// theme = localStorage.getItem("theme") ?? "light",
|
||||
// }) => {
|
||||
// const [mounted, setMounted] = useState(false);
|
||||
// const childWindowRef = useRef<Window | null>(null);
|
||||
// const containerElRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (typeof window === "undefined") return;
|
||||
|
||||
// const screenLeft = window.screenLeft ?? window.screenX ?? 0;
|
||||
// const screenTop = window.screenTop ?? window.screenY ?? 0;
|
||||
// const availWidth = window.outerWidth ?? window.innerWidth;
|
||||
// const availHeight = window.outerHeight ?? window.innerHeight;
|
||||
|
||||
// const finalLeft =
|
||||
// center && availWidth ? Math.max(0, screenLeft + (availWidth - width) / 2) : left ?? 100;
|
||||
|
||||
// const finalTop =
|
||||
// center && availHeight
|
||||
// ? Math.max(0, screenTop + (availHeight - height) / 2)
|
||||
// : top ?? 100;
|
||||
|
||||
// const baseFeatures = [
|
||||
// `width=${Math.floor(width)}`,
|
||||
// `height=${Math.floor(height)}`,
|
||||
// `left=${Math.floor(finalLeft)}`,
|
||||
// `top=${Math.floor(finalTop)}`,
|
||||
// ];
|
||||
|
||||
// const featureFlags = features ?? {
|
||||
// toolbar: false,
|
||||
// menubar: false,
|
||||
// scrollbars: true,
|
||||
// resizable: true,
|
||||
// location: false,
|
||||
// status: false,
|
||||
// };
|
||||
|
||||
// Object.entries(featureFlags).forEach(([k, v]) =>
|
||||
// baseFeatures.push(`${k}=${v ? "yes" : "no"}`)
|
||||
// );
|
||||
|
||||
// const newWin = window.open("", "_blank", baseFeatures.join(","));
|
||||
// if (!newWin) {
|
||||
// console.warn("Popup blocked or failed to open window.");
|
||||
// onClose?.();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (noopener) {
|
||||
// try {
|
||||
// newWin.opener = null;
|
||||
// } catch {}
|
||||
// }
|
||||
|
||||
// newWin.document.open();
|
||||
// newWin.document.write(`<!doctype html>
|
||||
// <html data-theme=${theme}>
|
||||
// <head>
|
||||
// <meta charset="utf-8" />
|
||||
// <title>${title}</title>
|
||||
// <meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
// </head>
|
||||
// <body style="margin:0;"></body>
|
||||
// </html>`);
|
||||
// newWin.document.close();
|
||||
|
||||
// if (copyStyles) {
|
||||
// const head = newWin.document.head;
|
||||
// Array.from(document.styleSheets).forEach((styleSheet) => {
|
||||
// try {
|
||||
// if ((styleSheet as CSSStyleSheet).cssRules) {
|
||||
// const newStyleEl = newWin.document.createElement("style");
|
||||
// const rules = Array.from((styleSheet as CSSStyleSheet).cssRules).map(
|
||||
// (r) => r.cssText
|
||||
// );
|
||||
// newStyleEl.appendChild(newWin.document.createTextNode(rules.join("\n")));
|
||||
// head.appendChild(newStyleEl);
|
||||
// }
|
||||
// } catch {
|
||||
// const ownerNode = styleSheet.ownerNode as HTMLElement | null;
|
||||
// if (ownerNode && ownerNode.tagName === "LINK") {
|
||||
// const link = ownerNode as HTMLLinkElement;
|
||||
// const newLink = newWin.document.createElement("link");
|
||||
// newLink.rel = link.rel;
|
||||
// newLink.href = link.href;
|
||||
// newLink.media = link.media;
|
||||
// head.appendChild(newLink);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// const container = newWin.document.createElement("div");
|
||||
// if (className) container.className = className;
|
||||
// newWin.document.body.appendChild(container);
|
||||
|
||||
// newWin.document.title = title;
|
||||
|
||||
// // Handle child window close
|
||||
// const handleChildUnload = () => {
|
||||
// onClose?.();
|
||||
// };
|
||||
// newWin.addEventListener("beforeunload", handleChildUnload);
|
||||
|
||||
// // 👇 Handle parent refresh/close → auto close child
|
||||
// const handleParentUnload = () => {
|
||||
// try {
|
||||
// newWin.close();
|
||||
// } catch {}
|
||||
// };
|
||||
// window.addEventListener("beforeunload", handleParentUnload);
|
||||
|
||||
// childWindowRef.current = newWin;
|
||||
// containerElRef.current = container;
|
||||
// setMounted(true);
|
||||
|
||||
// return () => {
|
||||
// newWin.removeEventListener("beforeunload", handleChildUnload);
|
||||
// window.removeEventListener("beforeunload", handleParentUnload);
|
||||
// try {
|
||||
// newWin.close();
|
||||
// } catch {}
|
||||
// childWindowRef.current = null;
|
||||
// containerElRef.current = null;
|
||||
// };
|
||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// }, []);
|
||||
|
||||
// useEffect(() => {
|
||||
// const w = childWindowRef.current;
|
||||
// if (w && !w.closed) {
|
||||
// w.document.title = title;
|
||||
// }
|
||||
// }, [title]);
|
||||
|
||||
// if (!mounted || !containerElRef.current) return null;
|
||||
|
||||
// return createPortal(children, containerElRef.current);
|
||||
// };
|
||||
export const RenderInNewWindow: React.FC<NewWindowProps> = ({
|
||||
children,
|
||||
title = "3D Viewer",
|
||||
@@ -207,10 +54,12 @@ export const RenderInNewWindow: React.FC<NewWindowProps> = ({
|
||||
const finalLeft =
|
||||
center && availWidth ? Math.max(0, screenLeft + (availWidth - width) / 2) : left ?? 100;
|
||||
|
||||
console.log("finalLeft: ", finalLeft);
|
||||
const finalTop =
|
||||
center && availHeight
|
||||
? Math.max(0, screenTop + (availHeight - height) / 2)
|
||||
: top ?? 100;
|
||||
console.log("finalTop: ", finalTop);
|
||||
|
||||
const baseFeatures = [
|
||||
`width=${Math.floor(width)}`,
|
||||
@@ -370,6 +219,16 @@ export const RenderInNewWindow: React.FC<NewWindowProps> = ({
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handleResize = () => {
|
||||
childWindowRef.current?.dispatchEvent(new Event("resize"));
|
||||
};
|
||||
childWindowRef.current?.addEventListener("resize", handleResize);
|
||||
return () => {
|
||||
childWindowRef.current?.removeEventListener("resize", handleResize);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const w = childWindowRef.current;
|
||||
if (w && !w.closed) {
|
||||
|
||||
@@ -1,47 +1,65 @@
|
||||
import React from "react";
|
||||
import RenderOverlay from "./Overlay";
|
||||
import ReactDOM from "react-dom";
|
||||
import { LogoIconLarge } from "../icons/Logo";
|
||||
import { useProjectName } from "../../store/builder/store";
|
||||
import { useSimulationState } from "../../store/simulation/useSimulationStore";
|
||||
import RenderOverlay from "./Overlay";
|
||||
|
||||
interface LoadingPageProps {
|
||||
progress: number; // Expect progress as a percentage (0-100)
|
||||
progress: number;
|
||||
renderOver?: boolean;
|
||||
returnDefault?: boolean;
|
||||
}
|
||||
|
||||
const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
|
||||
console.log('progress: ', progress);
|
||||
const LoadingPage: React.FC<LoadingPageProps> = ({
|
||||
progress,
|
||||
renderOver = true,
|
||||
returnDefault = false,
|
||||
}) => {
|
||||
const { projectName } = useProjectName();
|
||||
const { comparisonScene } = useSimulationState();
|
||||
|
||||
const validatedProgress = Math.min(100, Math.max(0, progress));
|
||||
|
||||
console.log("comparisonScene: ", comparisonScene);
|
||||
return (
|
||||
<RenderOverlay>
|
||||
<div
|
||||
className={`loading-wrapper ${comparisonScene != null ? "comparisionLoading" : ""}`}
|
||||
>
|
||||
<div className="loading-container">
|
||||
<div className="project-name">{projectName}</div>
|
||||
<div className="loading-hero-container">
|
||||
<div className="logo">
|
||||
<LogoIconLarge />
|
||||
</div>
|
||||
<div className="content">Entering A New World with your Aalai</div>
|
||||
// Portal target (defaults to body)
|
||||
const portalRoot = document.getElementById("root") || document.body;
|
||||
|
||||
const content = (
|
||||
<div
|
||||
className={`loading-wrapper ${
|
||||
comparisonScene != null && !returnDefault ? "comparisionLoading" : ""
|
||||
}`}
|
||||
>
|
||||
<div className="loading-container">
|
||||
<div className="project-name">{projectName}</div>
|
||||
<div className="loading-hero-container">
|
||||
<div className="logo">
|
||||
<LogoIconLarge />
|
||||
</div>
|
||||
<div className="progress-container">
|
||||
<div className="progress-value">{validatedProgress}%</div>
|
||||
<div className="progress-indicator-container">
|
||||
<div
|
||||
className="progress-bar"
|
||||
style={{ width: `${validatedProgress}%` }} // Dynamic width
|
||||
></div>
|
||||
</div>
|
||||
<div className="content">Entering A New World with your Aalai</div>
|
||||
</div>
|
||||
<div className="progress-container">
|
||||
<div className="progress-value">{validatedProgress}%</div>
|
||||
<div className="progress-indicator-container">
|
||||
<div
|
||||
className="progress-bar"
|
||||
style={{ width: `${validatedProgress}%` }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</RenderOverlay>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (returnDefault) {
|
||||
return content;
|
||||
}
|
||||
|
||||
if (renderOver) {
|
||||
return <RenderOverlay>{content}</RenderOverlay>;
|
||||
}
|
||||
// Render the loading screen as a portal
|
||||
return ReactDOM.createPortal(content, portalRoot);
|
||||
};
|
||||
|
||||
export default LoadingPage;
|
||||
|
||||
@@ -2,26 +2,35 @@ import React from "react";
|
||||
import {
|
||||
useCreateNewWindow,
|
||||
useIsComparing,
|
||||
useLoadingProgress,
|
||||
useLimitDistance,
|
||||
useRenderDistance,
|
||||
} from "../../../store/builder/store";
|
||||
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { findEnvironment } from "../../../services/factoryBuilder/environment/findEnvironment";
|
||||
|
||||
const Button = () => {
|
||||
const { isComparing, setIsComparing } = useIsComparing();
|
||||
const { createNewWindow, setCreateNewWindow } = useCreateNewWindow();
|
||||
const { setLoadingProgress } = useLoadingProgress();
|
||||
const { clearComparisonState } = useSimulationState();
|
||||
const { projectId } = useParams();
|
||||
const { setRenderDistance } = useRenderDistance();
|
||||
const { setLimitDistance } = useLimitDistance();
|
||||
|
||||
const handleExit = () => {
|
||||
setIsComparing(false);
|
||||
setCreateNewWindow(false);
|
||||
setLoadingProgress(0);
|
||||
clearComparisonState();
|
||||
if (!projectId) return;
|
||||
findEnvironment(projectId).then((data) => {
|
||||
if (!data) return;
|
||||
setRenderDistance(data.renderDistance);
|
||||
setLimitDistance(data.limitDistance);
|
||||
});
|
||||
};
|
||||
|
||||
const handleOpenInNewWindow = () => {
|
||||
// 🧹 Immediately reset any loading or scene state
|
||||
setLoadingProgress(0);
|
||||
// setLoadingProgress(0);
|
||||
setCreateNewWindow(true);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
useLoadingProgress,
|
||||
useIsComparing,
|
||||
useCreateNewWindow,
|
||||
useLimitDistance,
|
||||
} from "../../../store/builder/store";
|
||||
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
|
||||
import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
|
||||
@@ -17,7 +18,6 @@ import useRestStates from "../../../hooks/useResetStates";
|
||||
|
||||
import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
|
||||
import { validateSimulationDataApi } from "../../../services/simulation/comparison/validateSimulationDataApi";
|
||||
import Button from "./Button";
|
||||
|
||||
const CompareLayOut = () => {
|
||||
const { clearComparisonState, comparisonScene, setComparisonState } = useSimulationState();
|
||||
@@ -42,6 +42,7 @@ const CompareLayOut = () => {
|
||||
const { projectId } = useParams();
|
||||
const { resetStates } = useRestStates();
|
||||
const { createNewWindow } = useCreateNewWindow();
|
||||
const { limitDistance, setLimitDistance } = useLimitDistance();
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
resetStates();
|
||||
@@ -188,7 +189,10 @@ const CompareLayOut = () => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
console.log("limitDistance: ", limitDistance);
|
||||
useEffect(() => {
|
||||
setLimitDistance(false);
|
||||
}, [limitDistance]);
|
||||
return (
|
||||
<>
|
||||
{!createNewWindow && (
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import PerformanceResult from "./result-card/PerformanceResult";
|
||||
import { Bar, Pie } from "react-chartjs-2";
|
||||
import { useCompareProductDataStore } from "../../../store/builder/store";
|
||||
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
|
||||
import { useSimulationState } from "../../../store/simulation/useSimulationStore";
|
||||
|
||||
export interface CompareProduct {
|
||||
productUuid: string;
|
||||
@@ -24,9 +24,12 @@ export interface CompareProduct {
|
||||
const ComparisonResult = () => {
|
||||
const { compareProductsData } = useCompareProductDataStore();
|
||||
const { comparisonScene, mainScene } = useSimulationState();
|
||||
const [comparedProducts, setComparedProducts] = useState<[CompareProduct, CompareProduct] | []>([]);
|
||||
const [comparedProducts, setComparedProducts] = useState<[CompareProduct, CompareProduct] | []>(
|
||||
[]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("compareProductsData: ", compareProductsData);
|
||||
if (compareProductsData.length > 0 && comparisonScene && mainScene) {
|
||||
setComparedProducts([compareProductsData[0], compareProductsData[1]]);
|
||||
} else {
|
||||
@@ -34,11 +37,6 @@ const ComparisonResult = () => {
|
||||
}
|
||||
}, [compareProductsData, comparisonScene, mainScene]);
|
||||
|
||||
useEffect(() => {
|
||||
if (comparedProducts.length === 2) {
|
||||
}
|
||||
}, [comparedProducts]);
|
||||
|
||||
const options = useMemo(
|
||||
() => ({
|
||||
responsive: true,
|
||||
@@ -64,7 +62,10 @@ const ComparisonResult = () => {
|
||||
datasets: [
|
||||
{
|
||||
label: "Throughput (units/hr)",
|
||||
data: [comparedProducts[0]?.simulationData.throughputData, comparedProducts[1]?.simulationData.throughputData],
|
||||
data: [
|
||||
comparedProducts[0]?.simulationData.throughputData,
|
||||
comparedProducts[1]?.simulationData.throughputData,
|
||||
],
|
||||
backgroundColor: [purpleDark, purpleLight],
|
||||
borderColor: [purpleDark, purpleLight],
|
||||
borderWidth: 1,
|
||||
@@ -79,7 +80,10 @@ const ComparisonResult = () => {
|
||||
datasets: [
|
||||
{
|
||||
label: "Cycle Time (sec)",
|
||||
data: [comparedProducts[0]?.simulationData.machineActiveTime, comparedProducts[1]?.simulationData.machineActiveTime],
|
||||
data: [
|
||||
comparedProducts[0]?.simulationData.machineActiveTime,
|
||||
comparedProducts[1]?.simulationData.machineActiveTime,
|
||||
],
|
||||
backgroundColor: [purpleDark, purpleLight],
|
||||
borderColor: "#fff",
|
||||
borderWidth: 2,
|
||||
@@ -92,7 +96,10 @@ const ComparisonResult = () => {
|
||||
datasets: [
|
||||
{
|
||||
label: "Downtime (mins)",
|
||||
data: [comparedProducts[0]?.simulationData.machineIdleTime, comparedProducts[1]?.simulationData.machineIdleTime],
|
||||
data: [
|
||||
comparedProducts[0]?.simulationData.machineIdleTime,
|
||||
comparedProducts[1]?.simulationData.machineIdleTime,
|
||||
],
|
||||
backgroundColor: [purpleDark, purpleLight],
|
||||
borderColor: "#fff",
|
||||
borderWidth: 2,
|
||||
@@ -105,7 +112,10 @@ const ComparisonResult = () => {
|
||||
datasets: [
|
||||
{
|
||||
label: "Production Capacity (units)",
|
||||
data: [comparedProducts[0]?.simulationData.productionCapacity, comparedProducts[1]?.simulationData.productionCapacity],
|
||||
data: [
|
||||
comparedProducts[0]?.simulationData.productionCapacity,
|
||||
comparedProducts[1]?.simulationData.productionCapacity,
|
||||
],
|
||||
backgroundColor: [purpleDark, purpleLight],
|
||||
borderColor: [purpleDark, purpleLight],
|
||||
borderWidth: 1,
|
||||
@@ -116,25 +126,40 @@ const ComparisonResult = () => {
|
||||
};
|
||||
|
||||
const highestProductivityProduct =
|
||||
(comparedProducts[0]?.simulationData?.productionCapacity ?? 0) > (comparedProducts[1]?.simulationData?.productionCapacity ?? 0) ? comparedProducts[0] : comparedProducts[1];
|
||||
(comparedProducts[0]?.simulationData?.productionCapacity ?? 0) >
|
||||
(comparedProducts[1]?.simulationData?.productionCapacity ?? 0)
|
||||
? comparedProducts[0]
|
||||
: comparedProducts[1];
|
||||
|
||||
const product1CyclePercentage =
|
||||
((comparedProducts[0]?.simulationData?.machineActiveTime ?? 0) /
|
||||
((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) +
|
||||
(compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
100;
|
||||
const product2CyclePercentage =
|
||||
((comparedProducts[1]?.simulationData?.machineActiveTime ?? 0) /
|
||||
((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) +
|
||||
(compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
100;
|
||||
|
||||
const product1IdlePercentage =
|
||||
((comparedProducts[0]?.simulationData?.machineIdleTime ?? 0) /
|
||||
((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
((compareProductsData[0]?.simulationData?.machineActiveTime ?? 0) +
|
||||
(compareProductsData[0]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
100;
|
||||
console.log(
|
||||
"product1IdlePercentage: ",
|
||||
compareProductsData[0]?.simulationData?.machineIdleTime
|
||||
);
|
||||
const product2IdlePercentage =
|
||||
((comparedProducts[1]?.simulationData?.machineIdleTime ?? 0) /
|
||||
((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) + (compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
((compareProductsData[1]?.simulationData?.machineActiveTime ?? 0) +
|
||||
(compareProductsData[1]?.simulationData?.machineIdleTime ?? 0))) *
|
||||
100;
|
||||
console.log(
|
||||
"product2IdlePercentage: ",
|
||||
compareProductsData[1]?.simulationData?.machineIdleTime
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="compare-result-container">
|
||||
@@ -147,16 +172,28 @@ const ComparisonResult = () => {
|
||||
<div className="layers-wrapper">
|
||||
<div className="layers">
|
||||
<div className="layer-name">{comparedProducts[0]?.productName}</div>
|
||||
<div className="layer-time">{compareProductsData[0]?.simulationData.machineActiveTime} Sec</div>
|
||||
<div className={`layer-change ${product1CyclePercentage >= 50 ? "profit" : "loss"}`}>
|
||||
<div className="layer-time">
|
||||
{compareProductsData[0]?.simulationData.machineActiveTime} Sec
|
||||
</div>
|
||||
<div
|
||||
className={`layer-change ${
|
||||
product1CyclePercentage >= 50 ? "profit" : "loss"
|
||||
}`}
|
||||
>
|
||||
<span>{product1CyclePercentage >= 50 ? "↑" : "↓"}</span>
|
||||
{(100 - product1CyclePercentage).toFixed(2)}%
|
||||
</div>
|
||||
</div>
|
||||
<div className="layers">
|
||||
<div className="layer-name">{comparedProducts[1]?.productName}</div>
|
||||
<div className="layer-time">{compareProductsData[1]?.simulationData.machineActiveTime} Sec</div>
|
||||
<div className={`layer-change ${product2CyclePercentage >= 50 ? "profit" : "loss"}`}>
|
||||
<div className="layer-time">
|
||||
{compareProductsData[1]?.simulationData.machineActiveTime} Sec
|
||||
</div>
|
||||
<div
|
||||
className={`layer-change ${
|
||||
product2CyclePercentage >= 50 ? "profit" : "loss"
|
||||
}`}
|
||||
>
|
||||
<span>{product2CyclePercentage >= 50 ? "↑" : "↓"}</span>
|
||||
{(100 - product2CyclePercentage).toFixed(2)}%
|
||||
</div>
|
||||
@@ -171,23 +208,69 @@ const ComparisonResult = () => {
|
||||
{/* <EnergyUsage comparedProducts={comparedProducts} /> */}
|
||||
<div className="cycle-time-container comparisionCard">
|
||||
<div className="cycle-main">
|
||||
<div className="cycle-header">Human Idle Time</div>
|
||||
<div className="cycle-header">Machine Idle Time</div>
|
||||
{/* <div className="cycle-header">Overall Downtime</div> */}
|
||||
<div className="layers-wrapper">
|
||||
<div className="layers">
|
||||
<div className="layer-name">{comparedProducts[0]?.productName}</div>
|
||||
<div className="layer-time">{compareProductsData[0]?.simulationData.machineIdleTime} Sec</div>
|
||||
<div className={`layer-profit ${product1IdlePercentage >= 50 ? "profit" : "loss"}`}>
|
||||
<span>{product1IdlePercentage >= 50 ? "↑" : "↓"}</span>
|
||||
{(100 - product1IdlePercentage).toFixed(2)}%
|
||||
<div className="layer-time">
|
||||
{compareProductsData[0]?.simulationData.machineIdleTime} Sec
|
||||
</div>
|
||||
<div
|
||||
className={`layer-profit ${
|
||||
compareProductsData[0]?.simulationData?.machineIdleTime >
|
||||
compareProductsData[1]?.simulationData?.machineIdleTime
|
||||
? "profit"
|
||||
: "loss"
|
||||
}`}
|
||||
>
|
||||
<span>
|
||||
{compareProductsData[0]?.simulationData?.machineIdleTime >
|
||||
compareProductsData[1]?.simulationData?.machineIdleTime
|
||||
? "↑"
|
||||
: "↓"}
|
||||
</span>
|
||||
{(
|
||||
((compareProductsData[0]?.simulationData?.machineIdleTime ??
|
||||
0) /
|
||||
((compareProductsData[0]?.simulationData
|
||||
?.machineActiveTime ?? 0) +
|
||||
(compareProductsData[1]?.simulationData
|
||||
?.machineIdleTime ?? 0))) *
|
||||
100
|
||||
).toFixed(2)}
|
||||
%
|
||||
</div>
|
||||
</div>
|
||||
<div className="layers">
|
||||
<div className="layer-name">{comparedProducts[1]?.productName}</div>
|
||||
<div className="layer-time">{compareProductsData[1]?.simulationData.machineIdleTime} Sec</div>
|
||||
<div className={`layer-profit ${product2IdlePercentage >= 50 ? "profit" : "loss"}`}>
|
||||
<span>{product2IdlePercentage >= 50 ? "↑" : "↓"}</span>
|
||||
{(100 - product2IdlePercentage).toFixed(2)}%
|
||||
<div className="layer-time">
|
||||
{compareProductsData[1]?.simulationData.machineIdleTime} Sec
|
||||
</div>
|
||||
<div
|
||||
className={`layer-profit ${
|
||||
compareProductsData[1]?.simulationData?.machineIdleTime >
|
||||
compareProductsData[0]?.simulationData?.machineIdleTime
|
||||
? "profit"
|
||||
: "loss"
|
||||
}`}
|
||||
>
|
||||
<span>
|
||||
{compareProductsData[1]?.simulationData?.machineIdleTime >
|
||||
compareProductsData[0]?.simulationData?.machineIdleTime
|
||||
? "↑"
|
||||
: "↓"}
|
||||
</span>
|
||||
{(
|
||||
((compareProductsData[1]?.simulationData?.machineIdleTime ??
|
||||
0) /
|
||||
((compareProductsData[1]?.simulationData
|
||||
?.machineActiveTime ?? 0) +
|
||||
(compareProductsData[0]?.simulationData
|
||||
?.machineIdleTime ?? 0))) *
|
||||
100
|
||||
).toFixed(2)}
|
||||
%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -201,11 +284,15 @@ const ComparisonResult = () => {
|
||||
<div className="layers-wrapper">
|
||||
<div className="layer-wrapper">
|
||||
<div className="key">{comparedProducts[0]?.productName}</div>
|
||||
<div className="value">{comparedProducts[0]?.simulationData.throughputData}/ hr</div>
|
||||
<div className="value">
|
||||
{comparedProducts[0]?.simulationData.throughputData}/ hr
|
||||
</div>
|
||||
</div>
|
||||
<div className="layer-wrapper">
|
||||
<div className="key">{comparedProducts[1]?.productName}</div>
|
||||
<div className="value">{comparedProducts[1]?.simulationData.throughputData}/ hr</div>
|
||||
<div className="value">
|
||||
{comparedProducts[1]?.simulationData.throughputData}/ hr
|
||||
</div>
|
||||
</div>
|
||||
<div className="chart">
|
||||
<Bar data={throughputData} options={options} />
|
||||
@@ -236,9 +323,13 @@ const ComparisonResult = () => {
|
||||
<h4 className="overallScrapRate-header">Production Capacity</h4>
|
||||
<div className="overallScrapRate-wrapper">
|
||||
<div className="overallScrapRate-value">
|
||||
<div className="overallScrapRate-label">{highestProductivityProduct?.productName}</div>
|
||||
<div className="overallScrapRate-label">
|
||||
{highestProductivityProduct?.productName}
|
||||
</div>
|
||||
<div className="overallScrapRate-key">Total product produced</div>
|
||||
<div className="overallScrapRateKey-value">{highestProductivityProduct?.simulationData.productionCapacity}</div>
|
||||
<div className="overallScrapRateKey-value">
|
||||
{highestProductivityProduct?.simulationData.productionCapacity}
|
||||
</div>
|
||||
</div>
|
||||
<div className="chart">
|
||||
<Bar data={productionCapacityData} options={options} />
|
||||
@@ -246,7 +337,9 @@ const ComparisonResult = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{comparedProducts.length === 2 && <PerformanceResult comparedProducts={comparedProducts} />}
|
||||
{comparedProducts.length === 2 && (
|
||||
<PerformanceResult comparedProducts={comparedProducts} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { Suspense, useEffect, useState } from "react";
|
||||
import { Suspense } from "react";
|
||||
import { RenderInNewWindow } from "../../templates/CreateNewWindow";
|
||||
import { useSceneContext } from "../../../modules/scene/sceneContext";
|
||||
import { useCreateNewWindow, useLoadingProgress } from "../../../store/builder/store";
|
||||
import Scene from "../../../modules/scene/scene";
|
||||
import ComparisonResult from "./ComparisonResult";
|
||||
import Button from "./Button";
|
||||
import LoadingPage from "../../templates/LoadingPage";
|
||||
|
||||
const NewWindowScene = () => {
|
||||
const { versionStore } = useSceneContext();
|
||||
@@ -15,12 +16,21 @@ const NewWindowScene = () => {
|
||||
return (
|
||||
<>
|
||||
{selectedVersion?.versionId && (
|
||||
<div style={{ width: "100%", height: "100%" }}>
|
||||
<div>
|
||||
<Suspense fallback={null}>
|
||||
<RenderInNewWindow
|
||||
title="3D Viewer"
|
||||
onClose={() => setCreateNewWindow(false)}
|
||||
>
|
||||
{/* Wait a tick to access child window */}
|
||||
<Scene layout="Comparison Layout" />
|
||||
{
|
||||
<LoadingPage
|
||||
progress={loadingProgress}
|
||||
renderOver={false}
|
||||
returnDefault={true}
|
||||
/>
|
||||
}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
@@ -31,7 +41,6 @@ const NewWindowScene = () => {
|
||||
>
|
||||
<Button />
|
||||
</div>
|
||||
<Scene layout="Comparison Layout" />
|
||||
{!loadingProgress && <ComparisonResult />}
|
||||
</RenderInNewWindow>
|
||||
</Suspense>
|
||||
|
||||
@@ -11,7 +11,15 @@ import { useFrame, useThree } from "@react-three/fiber";
|
||||
|
||||
import { useSceneContext } from "../scene/sceneContext";
|
||||
import { useBuilderStore } from "../../store/builder/useBuilderStore";
|
||||
import { useToggleView, useWallVisibility, useRoofVisibility, useShadows, useToolMode, useRenderDistance, useLimitDistance } from "../../store/builder/store";
|
||||
import {
|
||||
useToggleView,
|
||||
useWallVisibility,
|
||||
useRoofVisibility,
|
||||
useShadows,
|
||||
useToolMode,
|
||||
useRenderDistance,
|
||||
useLimitDistance,
|
||||
} from "../../store/builder/store";
|
||||
|
||||
////////// 3D Function Imports //////////
|
||||
|
||||
@@ -36,12 +44,12 @@ export default function Builder() {
|
||||
const csgRef = useRef<any>(null);
|
||||
|
||||
const { toggleView } = useToggleView();
|
||||
const { setToolMode } = useToolMode();
|
||||
const { toolMode, setToolMode } = useToolMode();
|
||||
const { setRoofVisibility } = useRoofVisibility();
|
||||
const { setWallVisibility } = useWallVisibility();
|
||||
const { setShadows } = useShadows();
|
||||
const { setRenderDistance } = useRenderDistance();
|
||||
const { setLimitDistance } = useLimitDistance();
|
||||
const { limitDistance, setLimitDistance } = useLimitDistance();
|
||||
const { projectId } = useParams();
|
||||
const { scene: storeScene, camera: storeCamera, controls: storeControls } = useSceneContext();
|
||||
const { setHoveredPoint, setHoveredLine } = useBuilderStore();
|
||||
@@ -72,7 +80,7 @@ export default function Builder() {
|
||||
setRenderDistance(data.renderDistance);
|
||||
setLimitDistance(data.limitDistance);
|
||||
});
|
||||
}, [projectId]);
|
||||
}, [projectId, toolMode]);
|
||||
|
||||
useFrame(() => {
|
||||
if (csgRef.current) {
|
||||
|
||||
@@ -2,104 +2,110 @@
|
||||
@use "../abstracts/mixins" as *;
|
||||
|
||||
.loading-wrapper {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
background: var(--background-color-solid);
|
||||
|
||||
&.comparisionLoading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
|
||||
height: 100vh;
|
||||
width: 50vw;
|
||||
}
|
||||
width: 100vw;
|
||||
background: var(--background-color-solid);
|
||||
z-index: 1000;
|
||||
|
||||
.loading-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 28px;
|
||||
z-index: 5;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: var(--faint-gradient-color);
|
||||
height: 50vh;
|
||||
width: 50vw;
|
||||
top: 0;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: #{$border-radius-circle};
|
||||
filter: blur(200px);
|
||||
z-index: -1;
|
||||
&.comparisionLoading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 100vh;
|
||||
width: 50vw;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
font-size: var(--font-size-regular);
|
||||
&.newWindowLoading {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.loading-hero-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.logo {
|
||||
@include flex-center;
|
||||
width: 100%;
|
||||
margin-bottom: 35px;
|
||||
scale: 0.8;
|
||||
circle {
|
||||
fill: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-family: #{$font-josefin-sans};
|
||||
font-size: #{$xxlarge};
|
||||
font-weight: #{$thin-weight};
|
||||
max-width: 250px;
|
||||
text-align: center;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.progress-value {
|
||||
font-family: #{$font-josefin-sans};
|
||||
font-weight: #{$thin-weight};
|
||||
font-size: 96px;
|
||||
margin-bottom: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.progress-indicator-container {
|
||||
height: 6px;
|
||||
width: 60%;
|
||||
background: var(--highlight-accent-color);
|
||||
border-radius: #{$border-radius-small};
|
||||
.loading-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 28px;
|
||||
z-index: 5;
|
||||
|
||||
.progress-bar {
|
||||
height: 6px;
|
||||
background: var(--accent-color);
|
||||
border-radius: #{$border-radius-small};
|
||||
transition: width 0.2 ease;
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
background: var(--faint-gradient-color);
|
||||
height: 50vh;
|
||||
width: 50vw;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
border-radius: #{$border-radius-circle};
|
||||
filter: blur(200px);
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.project-name {
|
||||
font-size: var(--font-size-regular);
|
||||
}
|
||||
|
||||
.loading-hero-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
.logo {
|
||||
@include flex-center;
|
||||
width: 100%;
|
||||
margin-bottom: 35px;
|
||||
scale: 0.8;
|
||||
circle {
|
||||
fill: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
font-family: #{$font-josefin-sans};
|
||||
font-size: #{$xxlarge};
|
||||
font-weight: #{$thin-weight};
|
||||
max-width: 250px;
|
||||
text-align: center;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.progress-value {
|
||||
font-family: #{$font-josefin-sans};
|
||||
font-weight: #{$thin-weight};
|
||||
font-size: 96px;
|
||||
margin-bottom: 22px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.progress-indicator-container {
|
||||
height: 6px;
|
||||
width: 60%;
|
||||
background: var(--highlight-accent-color);
|
||||
border-radius: #{$border-radius-small};
|
||||
position: relative;
|
||||
|
||||
.progress-bar {
|
||||
height: 6px;
|
||||
background: var(--accent-color);
|
||||
border-radius: #{$border-radius-small};
|
||||
transition: width 0.2 ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user