Merge branch 'v3' into v3-refactor
This commit is contained in:
commit
7cfb53061e
|
@ -2026,7 +2026,7 @@
|
|||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
|
||||
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "0.3.9"
|
||||
},
|
||||
|
@ -2038,7 +2038,7 @@
|
|||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
|
||||
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.0.3",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10"
|
||||
|
@ -4180,25 +4180,6 @@
|
|||
"url": "https://github.com/sponsors/gregberge"
|
||||
}
|
||||
},
|
||||
"node_modules/@testing-library/dom": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
|
||||
"integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@types/aria-query": "^5.0.1",
|
||||
"aria-query": "5.3.0",
|
||||
"chalk": "^4.1.0",
|
||||
"dom-accessibility-api": "^0.5.9",
|
||||
"lz-string": "^1.5.0",
|
||||
"pretty-format": "^27.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@testing-library/jest-dom": {
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz",
|
||||
|
@ -4310,25 +4291,25 @@
|
|||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
|
||||
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
|
||||
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
|
||||
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
|
||||
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@turf/along": {
|
||||
"version": "7.2.0",
|
||||
|
@ -9082,7 +9063,7 @@
|
|||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
|
||||
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cross-env": {
|
||||
"version": "7.0.3",
|
||||
|
@ -9959,7 +9940,7 @@
|
|||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
|
@ -15343,7 +15324,7 @@
|
|||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
|
||||
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/makeerror": {
|
||||
"version": "1.0.12",
|
||||
|
@ -20820,7 +20801,7 @@
|
|||
"version": "10.9.2",
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
|
@ -20863,7 +20844,7 @@
|
|||
"version": "8.3.4",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
|
||||
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.0"
|
||||
},
|
||||
|
@ -20875,7 +20856,7 @@
|
|||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
|
||||
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
"version": "3.15.0",
|
||||
|
@ -21371,7 +21352,7 @@
|
|||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
|
||||
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
|
||||
"devOptional": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/v8-to-istanbul": {
|
||||
"version": "8.1.1",
|
||||
|
@ -22430,7 +22411,7 @@
|
|||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
|
||||
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
|
||||
"devOptional": true,
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
|
@ -183,6 +183,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
|||
className="dashboard-card-container"
|
||||
onClick={navigateToProject}
|
||||
title={projectName}
|
||||
onMouseLeave={() => setIsKebabOpen(false)}
|
||||
>
|
||||
<div className="dashboard-card-wrapper">
|
||||
<div className="preview-container">
|
||||
|
|
|
@ -22,7 +22,6 @@ function ComparisonScene() {
|
|||
const product = products.find((product) => product.productName === option);
|
||||
if (product) {
|
||||
setComparisonProduct(product.productUuid, product.productName);
|
||||
setIsPlaying(true);
|
||||
setIsPaused(true);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -48,12 +48,12 @@ function MainScene() {
|
|||
const { setFloatingWidget } = useFloatingWidget();
|
||||
const { comparisonProduct } = useComparisonProduct();
|
||||
|
||||
const handleSelectLayout = (option: string) => {
|
||||
const product = products.find((product) => product.productName === option);
|
||||
if (product) {
|
||||
setMainProduct(product.productUuid, product.productName);
|
||||
}
|
||||
};
|
||||
const handleSelectLayout = (option: string) => {
|
||||
const product = products.find((product) => product.productName === option);
|
||||
if (product) {
|
||||
setMainProduct(product.productUuid, product.productName);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -108,7 +108,7 @@ function MainScene() {
|
|||
<Scene layout="Main Layout" />
|
||||
</div>
|
||||
|
||||
{selectedProduct && isVersionSaved && !isPlaying && (
|
||||
{selectedProduct && isVersionSaved && !isPlaying && activeModule === "simulation" && (
|
||||
<div className="selectLayout-wrapper">
|
||||
<RegularDropDown
|
||||
header={selectedProduct.productName}
|
||||
|
|
|
@ -10,12 +10,13 @@ const Header: React.FC = () => {
|
|||
const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div className="header-container">
|
||||
<div className="header-content">
|
||||
<div className="logo-container" onClick={() => navigate("/Dashboard")}>
|
||||
<button className="logo-container" onClick={()=>navigate("/Dashboard")}>
|
||||
<LogoIcon />
|
||||
</div>
|
||||
</button>
|
||||
<div className="header-title">
|
||||
<FileMenu />
|
||||
</div>
|
||||
|
|
|
@ -35,9 +35,8 @@ const SideBarLeft: React.FC = () => {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`sidebar-left-wrapper ${
|
||||
toggleUILeft && !isVersionSaved ? "open" : "closed"
|
||||
}`}
|
||||
className={`sidebar-left-wrapper ${toggleUILeft && (!isVersionSaved || activeModule !== "simulation") ? "open" : "closed"
|
||||
}`}
|
||||
>
|
||||
<Header />
|
||||
{toggleUILeft && (
|
||||
|
|
|
@ -66,7 +66,7 @@ const SideBarRight: React.FC = () => {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`sidebar-right-wrapper ${toggleUIRight && !isVersionSaved ? "open" : "closed"
|
||||
className={`sidebar-right-wrapper ${toggleUIRight && (!isVersionSaved || activeModule !== "simulation") ? "open" : "closed"
|
||||
}`}
|
||||
>
|
||||
<Header />
|
||||
|
|
|
@ -19,7 +19,7 @@ const Analysis: React.FC = () => {
|
|||
// { type: "default", inputs: { label: "Machine uptime", activeOption: "%" } },
|
||||
],
|
||||
"Production capacity": [
|
||||
{ type: "default", inputs: { label: "Shift length", activeOption: "hr" } },
|
||||
{ type: "range", inputs: { label: "Shift length", activeOption: "hr" } },
|
||||
{ type: "default", inputs: { label: "Shifts / day", activeOption: "unit" } },
|
||||
{ type: "default", inputs: { label: "Working days / year", activeOption: "days" } },
|
||||
{ type: "default", inputs: { label: "Yield rate", activeOption: "%" } },
|
||||
|
|
|
@ -31,7 +31,7 @@ const RenderAnalysisInputs: React.FC<InputRendererProps> = ({ keyName, presets,i
|
|||
key={index}
|
||||
label={preset.inputs.label}
|
||||
min={0}
|
||||
max={0}
|
||||
max={8}
|
||||
value={5}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -82,7 +82,7 @@ const ZoneProperties: React.FC = () => {
|
|||
const checkZoneNameDuplicate = (name: string) => {
|
||||
return zones.some(
|
||||
(zone: any) =>
|
||||
zone.zoneName.trim().toLowerCase() === name.trim().toLowerCase() &&
|
||||
zone.zoneName?.trim().toLowerCase() === name?.trim().toLowerCase() &&
|
||||
zone.zoneUuid !== selectedZone.zoneUuid
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,12 +4,14 @@ import { useDfxUpload } from "../../store/builder/store";
|
|||
import DxfParser from "dxf-parser";
|
||||
import { getWallPointsFromBlueprint } from "../../modules/builder/dfx/functions/getWallPointsFromBlueprint";
|
||||
import { convertDXFToThree } from "../../modules/builder/dfx/functions/convertDxfToThree";
|
||||
type DXFData = any
|
||||
import { AIIcon } from "../icons/ExportCommonIcons";
|
||||
type DXFData = any;
|
||||
const SelectFloorPlan: React.FC = () => {
|
||||
// Access layout state and state setters
|
||||
const { currentLayout, setLayout } = useLayoutStore();
|
||||
// Access DXF-related states and setters
|
||||
const { setDfxUploaded, setDfxGenerate, setObjValue, objValue } = useDfxUpload();
|
||||
const { setDfxUploaded, setDfxGenerate, setObjValue, objValue } =
|
||||
useDfxUpload();
|
||||
|
||||
// Local state to store the parsed DXF file
|
||||
const [parsedFile, setParsedFile] = useState<DXFData | undefined>(undefined);
|
||||
|
@ -18,7 +20,9 @@ const SelectFloorPlan: React.FC = () => {
|
|||
const [generate, setGenerate] = useState<boolean>(false);
|
||||
|
||||
// Handles file upload and DXF parsing
|
||||
const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const handleFileUpload = async (
|
||||
event: React.ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
setLayout(null); // Reset current layout
|
||||
setParsedFile(undefined); // Clear any previously parsed file
|
||||
const file = event.target.files?.[0];
|
||||
|
@ -52,15 +56,54 @@ const SelectFloorPlan: React.FC = () => {
|
|||
// Trigger wall point generation when `generate` flag changes
|
||||
useEffect(() => {
|
||||
if (parsedFile !== undefined) {
|
||||
getWallPointsFromBlueprint({ parsedData: parsedFile, setDfxGenerate, objValue });
|
||||
getWallPointsFromBlueprint({
|
||||
parsedData: parsedFile,
|
||||
setDfxGenerate,
|
||||
objValue,
|
||||
});
|
||||
}
|
||||
}, [generate]);
|
||||
|
||||
|
||||
return (
|
||||
<div className="select-floorplane-wrapper">
|
||||
Preset Layouts
|
||||
Upload Layouts
|
||||
<div className="presets-container">
|
||||
<input
|
||||
type="file"
|
||||
id="file-upload"
|
||||
accept=".dxf"
|
||||
style={{ display: "none", width: "10px" }}
|
||||
onChange={handleFileUpload}
|
||||
/>
|
||||
|
||||
<label
|
||||
htmlFor="file-upload"
|
||||
className="preset upload-btn"
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
padding: "10px 48px",
|
||||
}}
|
||||
>
|
||||
Upload
|
||||
</label>
|
||||
|
||||
{parsedFile && (
|
||||
<button
|
||||
type="button"
|
||||
id="generate-upload"
|
||||
className="generate-walls-btn"
|
||||
onClick={() => {
|
||||
setDfxUploaded([]);
|
||||
setLayout(null);
|
||||
setGenerate(!generate);
|
||||
}}
|
||||
>
|
||||
<AIIcon />
|
||||
Generate
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
or
|
||||
<div className="presets-container">
|
||||
<button
|
||||
className={`preset ${currentLayout === "layout1" ? "active" : ""}`}
|
||||
|
@ -83,40 +126,9 @@ const SelectFloorPlan: React.FC = () => {
|
|||
>
|
||||
Preset 2
|
||||
</button>
|
||||
|
||||
<input
|
||||
type="file"
|
||||
id="file-upload"
|
||||
accept=".dxf"
|
||||
style={{ display: "none", width: "10px" }}
|
||||
onChange={handleFileUpload}
|
||||
/>
|
||||
|
||||
<label
|
||||
htmlFor="file-upload"
|
||||
className="preset"
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
padding: "10px 48px",
|
||||
}}
|
||||
>
|
||||
Upload
|
||||
</label>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
id="generate-upload"
|
||||
onClick={() => {
|
||||
setDfxUploaded([]);
|
||||
setLayout(null);
|
||||
setGenerate(!generate);
|
||||
}}
|
||||
>
|
||||
Generate
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectFloorPlan;
|
||||
export default SelectFloorPlan;
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
} from "chart.js";
|
||||
import { PowerIcon, ProductionCapacityIcon } from "../../icons/analysis";
|
||||
import SkeletonUI from "../../templates/SkeletonUI";
|
||||
import { useInputValues, useMachineUptime, useProductionCapacityData } from "../../../store/builder/store";
|
||||
import { useInputValues, useMachineUptime, useProductionCapacityData, useThroughPutData } from "../../../store/builder/store";
|
||||
|
||||
ChartJS.register(LineElement, CategoryScale, LinearScale, PointElement);
|
||||
|
||||
|
@ -34,6 +34,7 @@ const ThroughputSummary: React.FC = () => {
|
|||
];
|
||||
|
||||
const { productionCapacityData } = useProductionCapacityData()
|
||||
const { throughputData: data } = useThroughPutData()
|
||||
|
||||
|
||||
const chartOptions = {
|
||||
|
@ -103,6 +104,7 @@ const ThroughputSummary: React.FC = () => {
|
|||
}
|
||||
}, [productionCapacityData]);
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isLoading && <div className="production analysis-card">
|
||||
|
|
|
@ -14,7 +14,6 @@ const ProductionCapacity = ({
|
|||
const { machineActiveTime } = useMachineUptime();
|
||||
const { materialCycleTime } = useMaterialCycle();
|
||||
const { throughputData } = useThroughPutData()
|
||||
const { productionCapacityData } = useProductionCapacityData()
|
||||
|
||||
const progressPercent = machineActiveTime;
|
||||
|
||||
|
|
|
@ -118,7 +118,6 @@ const CompareLayOut = () => {
|
|||
if (product) {
|
||||
setComparisonProduct(product.productUuid, product.productName);
|
||||
setLoadingProgress(1);
|
||||
setIsPlaying(true);
|
||||
setIsPaused(true);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,57 +1,89 @@
|
|||
import React, { useMemo } from "react";
|
||||
import PerformanceResult from "./result-card/PerformanceResult";
|
||||
import EnergyUsage from "./result-card/EnergyUsage";
|
||||
import { Bar } from "react-chartjs-2";
|
||||
import { Bar, Line } from "react-chartjs-2";
|
||||
|
||||
const ComparisonResult = () => {
|
||||
const defaultData = {
|
||||
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Dataset",
|
||||
data: [12, 19, 3, 5, 2, 3],
|
||||
backgroundColor: ["#6f42c1"],
|
||||
borderColor: "#b392f0",
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Memoize Chart Options
|
||||
const options = useMemo(
|
||||
() => ({
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
title: { display: false },
|
||||
legend: { display: false },
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
display: false, // Hide x-axis
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
y: {
|
||||
display: false, // Hide y-axis
|
||||
grid: {
|
||||
display: false,
|
||||
},
|
||||
},
|
||||
x: { display: false, grid: { display: false } },
|
||||
y: { display: false, grid: { display: false } },
|
||||
},
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
// Color palette
|
||||
const purpleDark = "#6a0dad";
|
||||
const purpleLight = "#b19cd9";
|
||||
|
||||
const throughputData = {
|
||||
labels: ["Layout 1", "Layout 2"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Throughput (units/hr)",
|
||||
data: [500, 550],
|
||||
backgroundColor: [purpleDark, purpleLight],
|
||||
borderColor: [purpleDark, purpleLight],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const cycleTimeData = {
|
||||
labels: ["Layout 1", "Layout 2"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Cycle Time (sec)",
|
||||
data: [110, 110],
|
||||
backgroundColor: [purpleLight],
|
||||
borderColor: purpleDark,
|
||||
borderWidth: 2,
|
||||
tension: 0.4,
|
||||
fill: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const downtimeData = {
|
||||
labels: ["Layout 1", "Layout 2"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Downtime (mins)",
|
||||
data: [17, 12],
|
||||
backgroundColor: [purpleDark, purpleLight],
|
||||
borderColor: [purpleDark, purpleLight],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const scrapRateData = {
|
||||
labels: ["Layout 1", "Layout 2"],
|
||||
datasets: [
|
||||
{
|
||||
label: "Scrap Rate (tons)",
|
||||
data: [2.7, 1.9],
|
||||
backgroundColor: [purpleDark, purpleLight],
|
||||
borderColor: [purpleDark, purpleLight],
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="compare-result-container">
|
||||
<div className="header">Performance Comparison</div>
|
||||
<div className="compare-result-wrapper">
|
||||
<EnergyUsage />
|
||||
|
||||
<div className="throughPutCard-container comparisionCard">
|
||||
<h4>Throughput (units/hr)</h4>
|
||||
<div className="layers-wrapper">
|
||||
|
@ -64,8 +96,11 @@ const ComparisonResult = () => {
|
|||
<div className="value">550/ hr</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="chart"></div>
|
||||
<div className="chart">
|
||||
<Bar data={throughputData} options={options} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="cycle-time-container comparisionCard">
|
||||
<div className="cycle-main">
|
||||
<div className="cycle-header">Cycle Time</div>
|
||||
|
@ -81,12 +116,16 @@ const ComparisonResult = () => {
|
|||
<div className="layer-name">Layout 2</div>
|
||||
<div className="layer-time">110 Sec</div>
|
||||
<div className="layer-profit">
|
||||
<span>↑</span>19.6%1.6%
|
||||
<span>↑</span>1.6%
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="chart">
|
||||
<Line data={cycleTimeData} options={options} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="overallDowntime-container comparisionCard">
|
||||
<div className="overallDowntime-header">Overall Downtime</div>
|
||||
<div className="totalDownTime-wrapper">
|
||||
|
@ -101,10 +140,7 @@ const ComparisonResult = () => {
|
|||
</div>
|
||||
</div>
|
||||
<div className="chart">
|
||||
<div className="vertical-chart">
|
||||
<div className="layout1"></div>
|
||||
<div className="layout2"></div>
|
||||
</div>
|
||||
<Bar data={downtimeData} options={options} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -114,16 +150,15 @@ const ComparisonResult = () => {
|
|||
<div className="overallScrapRate-wrapper">
|
||||
<div className="overallScrapRate-value">
|
||||
<div className="overallScrapRate-label">Layout 1</div>
|
||||
<div className="overallScrapRate-key">
|
||||
Total scrap produced by
|
||||
</div>
|
||||
<div className="overallScrapRate-key">Total scrap produced by</div>
|
||||
<div className="overallScrapRateKey-value">2.7 ton</div>
|
||||
</div>
|
||||
<div className="chart">
|
||||
<Bar data={defaultData} options={options} />
|
||||
<Bar data={scrapRateData} options={options} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PerformanceResult />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -18,7 +18,6 @@ import {
|
|||
} from "../../../store/builder/store";
|
||||
import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation";
|
||||
import { setFloorItemApi } from "../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||
import OuterClick from "../../../utils/outerClick";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useAssetsStore } from "../../../store/builder/useAssetStore";
|
||||
|
||||
|
@ -111,7 +110,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
|||
|
||||
const isDuplicate = zones.some(
|
||||
(zone: any) =>
|
||||
zone.zoneName.trim().toLowerCase() === newName.trim().toLowerCase() &&
|
||||
zone.zoneName?.trim().toLowerCase() === newName?.trim().toLowerCase() &&
|
||||
zone.zoneUuid !== selectedZone.zoneUuid
|
||||
);
|
||||
|
||||
|
@ -154,7 +153,7 @@ const List: React.FC<ListProps> = ({ items = [], remove }) => {
|
|||
const checkZoneNameDuplicate = (name: string) => {
|
||||
return zones.some(
|
||||
(zone: any) =>
|
||||
zone.zoneName.trim().toLowerCase() === name.trim().toLowerCase() &&
|
||||
zone.zoneName?.trim().toLowerCase() === name?.trim().toLowerCase() &&
|
||||
zone.zoneUuid !== selectedZone.zoneUuid
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import React, { useState, useRef, useEffect } from "react";
|
||||
import { ExitIcon, PlayStopIcon, ResetIcon } from "../../icons/SimulationIcons";
|
||||
import { useActiveTool, useProcessBar } from "../../../store/builder/store";
|
||||
import {
|
||||
useActiveTool,
|
||||
useProcessBar,
|
||||
useViewSceneStore,
|
||||
} from "../../../store/builder/store";
|
||||
import {
|
||||
useAnimationPlaySpeed,
|
||||
usePauseButtonStore,
|
||||
|
@ -19,12 +23,15 @@ import {
|
|||
StartIcon,
|
||||
} from "../../icons/ExportCommonIcons";
|
||||
import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
|
||||
import { useSubModuleStore } from "../../../store/useModuleStore";
|
||||
import useModuleStore, {
|
||||
useSubModuleStore,
|
||||
} from "../../../store/useModuleStore";
|
||||
import ProductionCapacity from "../analysis/ThroughputSummary";
|
||||
import ThroughputSummary from "../analysis/ProductionCapacity";
|
||||
import ROISummary from "../analysis/ROISummary";
|
||||
import { usePlayerStore } from "../../../store/useUIToggleStore";
|
||||
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
|
||||
import InputToggle from "../inputs/InputToggle";
|
||||
|
||||
const SimulationPlayer: React.FC = () => {
|
||||
const MAX_SPEED = 4; // Maximum speed
|
||||
|
@ -41,7 +48,10 @@ const SimulationPlayer: React.FC = () => {
|
|||
const { isReset, setReset } = useResetButtonStore();
|
||||
const { subModule } = useSubModuleStore();
|
||||
const { clearComparisonProduct } = useComparisonProduct();
|
||||
const { viewSceneLabels, setViewSceneLabels } = useViewSceneStore();
|
||||
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { activeModule } = useModuleStore();
|
||||
useEffect(() => {
|
||||
if (isReset) {
|
||||
setTimeout(() => {
|
||||
|
@ -59,6 +69,9 @@ const SimulationPlayer: React.FC = () => {
|
|||
};
|
||||
const handlePlayStop = () => {
|
||||
setIsPaused(!isPaused);
|
||||
if (isPaused) {
|
||||
setIsPlaying(true);
|
||||
}
|
||||
echo.warn(`Simulation is ${isPaused ? "Resumed" : "Paused"}`);
|
||||
};
|
||||
const handleExit = () => {
|
||||
|
@ -110,11 +123,10 @@ const SimulationPlayer: React.FC = () => {
|
|||
// UI-Part
|
||||
const hourlySimulation = 25;
|
||||
const dailyProduction = 75;
|
||||
const monthlyROI = 50;
|
||||
const monthlyROI = 10;
|
||||
const { processBar } = useProcessBar();
|
||||
|
||||
useEffect(() => {
|
||||
}, [processBar])
|
||||
useEffect(() => { }, [processBar]);
|
||||
|
||||
const intervals = [50, 20, 30, 40, 50, 60]; // in minutes
|
||||
const totalSegments = intervals.length;
|
||||
|
@ -154,6 +166,16 @@ const SimulationPlayer: React.FC = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{isPlaying && activeModule === "simulation" && (
|
||||
<div className="label-toogler">
|
||||
<InputToggle
|
||||
value={viewSceneLabels}
|
||||
inputKey="1"
|
||||
label="Enable View Labels"
|
||||
onClick={() => setViewSceneLabels(!viewSceneLabels)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className={`simulation-player-wrapper${hidePlayer ? " hide" : ""}`}>
|
||||
<div className={`simulation-player-container ${expand ? "open" : ""}`}>
|
||||
<div className="controls-container">
|
||||
|
@ -200,7 +222,7 @@ const SimulationPlayer: React.FC = () => {
|
|||
<div className="progress-wrapper">
|
||||
<div
|
||||
className="progress"
|
||||
style={{ width: monthlyROI }}
|
||||
style={{ width: `${monthlyROI}%` }}
|
||||
></div>
|
||||
</div>{" "}
|
||||
</div>
|
||||
|
@ -209,9 +231,7 @@ const SimulationPlayer: React.FC = () => {
|
|||
{!hidePlayer && subModule !== "analysis" && (
|
||||
<div className="header">
|
||||
<InfoIcon />
|
||||
{isPaused
|
||||
? "Paused - system idle."
|
||||
: "Running simulation..."}
|
||||
{isPaused ? "Paused - system idle." : "Running simulation..."}
|
||||
</div>
|
||||
)}
|
||||
<div className="controls-wrapper">
|
||||
|
|
|
@ -259,10 +259,9 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
|
|||
}
|
||||
});
|
||||
|
||||
//Helper to Visible the Circle and Curve
|
||||
return (
|
||||
<>
|
||||
{customCurvePoints && customCurvePoints?.length >= 2 && currentPath && isPlaying && (
|
||||
{/* {customCurvePoints && customCurvePoints?.length >= 2 && currentPath && isPlaying && (
|
||||
<mesh rotation={armBot.rotation} position={armBot.position} visible={false}>
|
||||
<Line
|
||||
points={customCurvePoints.map((p) => [p.x, p.y, p.z] as [number, number, number])}
|
||||
|
@ -277,19 +276,16 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
|
|||
rotation={[armBot.rotation[0], armBot.rotation[1], armBot.rotation[2]]}
|
||||
visible={false}
|
||||
>
|
||||
{/* Green ring */}
|
||||
<mesh rotation={[-Math.PI / 2, 0, 0]} visible={false}>
|
||||
<ringGeometry args={[CIRCLE_RADIUS, CIRCLE_RADIUS + 0.02, 64]} />
|
||||
<meshBasicMaterial color="green" side={THREE.DoubleSide} />
|
||||
</mesh>
|
||||
|
||||
{/* Markers at 90°, 180°, 270°, 360° */}
|
||||
{[90, 180, 270, 360].map((degree, index) => {
|
||||
const rad = ((degree) * Math.PI) / 180;
|
||||
const x = CIRCLE_RADIUS * Math.cos(rad);
|
||||
const z = CIRCLE_RADIUS * Math.sin(rad);
|
||||
const y = 0; // same plane as the ring (Y axis)
|
||||
|
||||
const y = 0;
|
||||
return (
|
||||
<mesh key={index} position={[x, y, z]}>
|
||||
<sphereGeometry args={[0.05, 16, 16]} />
|
||||
|
@ -302,7 +298,7 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
|
|||
const rad = ((degree) * Math.PI) / 180;
|
||||
const x = CIRCLE_RADIUS * Math.cos(rad);
|
||||
const z = CIRCLE_RADIUS * Math.sin(rad);
|
||||
const y = 0.15; // lift the text slightly above the ring
|
||||
const y = 0.15;
|
||||
|
||||
return (
|
||||
<Text
|
||||
|
@ -317,9 +313,7 @@ function RoboticArmAnimator({ HandleCallback, restPosition, ikSolver, targetBone
|
|||
</Text>
|
||||
);
|
||||
})}
|
||||
|
||||
|
||||
</group>
|
||||
</group> */}
|
||||
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -10,6 +10,7 @@ import { useProductStore } from '../../../../../store/simulation/useProductStore
|
|||
import { useTriggerHandler } from '../../../triggers/triggerHandler/useTriggerHandler';
|
||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||
import { useProductContext } from '../../../products/productContext';
|
||||
import { Preload } from '@react-three/drei';
|
||||
|
||||
function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
||||
|
||||
|
@ -392,7 +393,7 @@ function RoboticArmInstance({ armBot }: { readonly armBot: ArmBotStatus }) {
|
|||
<>
|
||||
{!isReset && isPlaying && (
|
||||
<>
|
||||
<IKInstance modelUrl={armModel} setIkSolver={setIkSolver} ikSolver={ikSolver} armBot={armBot} groupRef={groupRef} />
|
||||
<IKInstance modelUrl={armModel} setIkSolver={setIkSolver} armBot={armBot} groupRef={groupRef} />
|
||||
<RoboticArmAnimator
|
||||
HandleCallback={HandleCallback}
|
||||
restPosition={restPosition}
|
||||
|
|
|
@ -1,21 +1,19 @@
|
|||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useEffect, useMemo } from 'react'
|
||||
import * as THREE from "three";
|
||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||
import { clone } from "three/examples/jsm/utils/SkeletonUtils";
|
||||
import { useLoader, useThree } from "@react-three/fiber";
|
||||
import { CCDIKSolver, CCDIKHelper, } from "three/examples/jsm/animation/CCDIKSolver";
|
||||
import { TransformControls } from '@react-three/drei';
|
||||
import { useLoader } from "@react-three/fiber";
|
||||
import { CCDIKSolver, CCDIKHelper } from "three/examples/jsm/animation/CCDIKSolver";
|
||||
|
||||
type IKInstanceProps = {
|
||||
modelUrl: string;
|
||||
ikSolver: any;
|
||||
setIkSolver: any
|
||||
armBot: ArmBotStatus;
|
||||
groupRef: any;
|
||||
};
|
||||
function IKInstance({ modelUrl, setIkSolver, ikSolver, armBot, groupRef }: IKInstanceProps) {
|
||||
const { scene } = useThree()
|
||||
|
||||
function IKInstance({ modelUrl, setIkSolver, armBot, groupRef }: IKInstanceProps) {
|
||||
const gltf = useLoader(GLTFLoader, modelUrl, (loader) => {
|
||||
const draco = new DRACOLoader();
|
||||
draco.setDecoderPath("https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco/");
|
||||
|
@ -24,7 +22,6 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, armBot, groupRef }: IKIns
|
|||
const cloned = useMemo(() => clone(gltf?.scene), [gltf]);
|
||||
const targetBoneName = "Target";
|
||||
const skinnedMeshName = "link_0";
|
||||
const [selectedArm, setSelectedArm] = useState<THREE.Group>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!gltf) return;
|
||||
|
@ -66,28 +63,21 @@ function IKInstance({ modelUrl, setIkSolver, ikSolver, armBot, groupRef }: IKIns
|
|||
const solver = new CCDIKSolver(OOI.Skinned_Mesh, iks);
|
||||
setIkSolver(solver);
|
||||
|
||||
const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05)
|
||||
|
||||
setSelectedArm(OOI.Target_Bone);
|
||||
// const helper = new CCDIKHelper(OOI.Skinned_Mesh, iks, 0.05)
|
||||
|
||||
// scene.add(helper);
|
||||
|
||||
}, [cloned, gltf, setIkSolver]);
|
||||
}, [cloned, gltf]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<group ref={groupRef} position={armBot.position} rotation={armBot.rotation} onClick={() => {
|
||||
setSelectedArm(groupRef.current?.getObjectByName(targetBoneName))
|
||||
}}>
|
||||
<primitive
|
||||
uuid={`${armBot.modelUuid}_IK`}
|
||||
object={cloned}
|
||||
scale={[1, 1, 1]}
|
||||
name={armBot.modelName}
|
||||
/>
|
||||
</group>
|
||||
{/* {selectedArm && <TransformControls object={selectedArm} />} */}
|
||||
</>
|
||||
<group ref={groupRef} position={armBot.position} rotation={armBot.rotation}>
|
||||
<primitive
|
||||
uuid={`${armBot.modelUuid}_IK`}
|
||||
object={cloned}
|
||||
scale={[1, 1, 1]}
|
||||
name={armBot.modelName}
|
||||
/>
|
||||
</group>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
import { useViewSceneStore } from "../../../../store/builder/store";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import RoboticArmInstance from "./armInstance/roboticArmInstance";
|
||||
// import RoboticArmContentUi from "../../ui3d/RoboticArmContentUi";
|
||||
import RoboticArmContentUi from "../../ui3d/RoboticArmContentUi";
|
||||
import React from "react";
|
||||
|
||||
function RoboticArmInstances() {
|
||||
const {armBotStore} = useSceneContext();
|
||||
const { armBotStore } = useSceneContext();
|
||||
const { armBots } = armBotStore();
|
||||
const { viewSceneLabels } = useViewSceneStore();
|
||||
|
||||
return (
|
||||
<>
|
||||
{armBots?.map((robot: ArmBotStatus) => (
|
||||
<React.Fragment key={robot.modelUuid}>
|
||||
<RoboticArmInstance armBot={robot} />
|
||||
{/* <RoboticArmContentUi roboticArm={robot} /> */}
|
||||
{viewSceneLabels && <RoboticArmContentUi roboticArm={robot} />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</>
|
||||
|
|
|
@ -15,6 +15,7 @@ function Simulator() {
|
|||
|
||||
useEffect(() => {
|
||||
if (!isPlaying || isReset || !selectedProduct.productUuid) return;
|
||||
console.log('selectedProduct: ', selectedProduct);
|
||||
|
||||
const product = getProductById(selectedProduct.productUuid);
|
||||
if (!product) return;
|
||||
|
|
|
@ -8,11 +8,20 @@ import DashboardTrash from "../components/Dashboard/DashboardTrash";
|
|||
import { getUserData } from "../components/Dashboard/functions/getUserData";
|
||||
import SidePannel from "../components/Dashboard/SidePannel";
|
||||
import DashboardTutorial from "../components/Dashboard/DashboardTutorial";
|
||||
import { useProductStore } from "../store/simulation/useProductStore";
|
||||
import { useEventsStore } from "../store/simulation/useEventsStore";
|
||||
|
||||
const Dashboard: React.FC = () => {
|
||||
const [activeTab, setActiveTab] = useState<string>("Home");
|
||||
const { socket } = useSocketStore();
|
||||
const { userId, organization, email, userName } = getUserData();
|
||||
const { clearProducts } = useProductStore();
|
||||
const { clearEvents } = useEventsStore();
|
||||
|
||||
useEffect(() => {
|
||||
clearEvents();
|
||||
clearProducts();
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem("token");
|
||||
|
|
|
@ -7,6 +7,7 @@ type EventsStore = {
|
|||
// Event-level actions
|
||||
addEvent: (event: EventsSchema) => void;
|
||||
removeEvent: (modelUuid: string) => void;
|
||||
clearEvents: () => void;
|
||||
updateEvent: (modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;
|
||||
|
||||
// Point-level actions
|
||||
|
@ -61,6 +62,12 @@ export const useEventsStore = create<EventsStore>()(
|
|||
});
|
||||
},
|
||||
|
||||
clearEvents: () => {
|
||||
set((state) => {
|
||||
state.events = [];
|
||||
});
|
||||
},
|
||||
|
||||
updateEvent: (modelUuid, updates) => {
|
||||
let updatedEvent: EventsSchema | undefined;
|
||||
set((state) => {
|
||||
|
|
|
@ -7,6 +7,7 @@ type ProductsStore = {
|
|||
// Product-level actions
|
||||
addProduct: (productName: string, productUuid: string) => void;
|
||||
setProducts: (products: productsSchema) => void;
|
||||
clearProducts: () => void;
|
||||
removeProduct: (productUuid: string) => void;
|
||||
updateProduct: (productUuid: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;
|
||||
|
||||
|
@ -99,6 +100,12 @@ export const useProductStore = create<ProductsStore>()(
|
|||
});
|
||||
},
|
||||
|
||||
clearProducts: () => {
|
||||
set((state) => {
|
||||
state.products = [];
|
||||
});
|
||||
},
|
||||
|
||||
removeProduct: (productUuid) => {
|
||||
set((state) => {
|
||||
state.products = state.products.filter(p => p.productUuid !== productUuid);
|
||||
|
|
|
@ -373,7 +373,7 @@
|
|||
left: 50%;
|
||||
transform: translate(-50%, 0);
|
||||
color: var(--accent-color);
|
||||
z-index: 100;
|
||||
z-index: 2;
|
||||
isolation: isolate;
|
||||
font-weight: 700;
|
||||
padding: 8px;
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
align-items: center;
|
||||
animation: slideInFromRight 0.4s ease-out forwards;
|
||||
user-select: none;
|
||||
border-left: 2px solid var(--border-color);
|
||||
|
||||
.resizer {
|
||||
width: 32px;
|
||||
|
@ -474,6 +475,7 @@
|
|||
}
|
||||
|
||||
.chart {
|
||||
width: 80%;
|
||||
height: 90%;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
|
||||
.logo-container {
|
||||
@include flex-center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
|
@ -221,7 +222,7 @@
|
|||
padding: 13px 5px;
|
||||
background: var(--background-color-secondary);
|
||||
border-radius: #{$border-radius-medium};
|
||||
box-shadow:var(--box-shadow-light);
|
||||
box-shadow: var(--box-shadow-light);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
|
@ -873,8 +874,6 @@
|
|||
.input-range-container {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
|
||||
.input-container {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1360,9 +1359,11 @@
|
|||
.aisle-properties-container {
|
||||
max-height: 65vh;
|
||||
overflow: auto;
|
||||
|
||||
.aisle-texture-container {
|
||||
max-height: 40vh;
|
||||
overflow: auto;
|
||||
|
||||
.aisle-list {
|
||||
width: calc(100% - 8px);
|
||||
text-align: start;
|
||||
|
@ -1372,6 +1373,7 @@
|
|||
gap: 6px;
|
||||
border-radius: #{$border-radius-large};
|
||||
margin: 2px 6px;
|
||||
|
||||
.texture-display {
|
||||
height: 34px;
|
||||
width: 34px;
|
||||
|
@ -1380,63 +1382,78 @@
|
|||
margin-right: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.aisle-color {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.aisle-brief {
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--input-text-color);
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: var(--background-color-accent);
|
||||
color: var(--text-button-color);
|
||||
|
||||
&:hover {
|
||||
background: var(--background-color-accent);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--background-color-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.value-field-container {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.presets-list-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
padding: 6px;
|
||||
padding-left: 7px;
|
||||
|
||||
.preset-list {
|
||||
background: #444;
|
||||
height: 90px;
|
||||
width: 90px;
|
||||
border-radius: #{$border-radius-large};
|
||||
overflow: hidden;
|
||||
|
||||
.thumbnail {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: #{$border-radius-large};
|
||||
outline-offset: -1px;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
outline: 2px solid var(--border-color-accent);
|
||||
outline-offset: -2px;
|
||||
|
||||
&:hover {
|
||||
outline: 2px solid var(--border-color-accent);
|
||||
|
||||
img {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
outline: 1px solid var(--border-color);
|
||||
|
||||
img {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
@ -1456,6 +1473,7 @@
|
|||
padding: 10px 12px;
|
||||
color: var(--text-color);
|
||||
width: 100%;
|
||||
|
||||
.input-value {
|
||||
color: inherit;
|
||||
}
|
||||
|
@ -1509,7 +1527,6 @@
|
|||
.header {
|
||||
@include flex-space-between;
|
||||
border: none;
|
||||
|
||||
.eyedrop-button {
|
||||
@include flex-center;
|
||||
}
|
||||
|
@ -1517,9 +1534,8 @@
|
|||
|
||||
.inputs-container {
|
||||
@include flex-space-between;
|
||||
|
||||
.input-container {
|
||||
padding: 0 12px;
|
||||
padding: 0 4px;
|
||||
gap: 6px;
|
||||
}
|
||||
}
|
||||
|
@ -1837,11 +1853,9 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: var(--font-size-regular);
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
rgba(37, 24, 51, 0) 0%,
|
||||
rgba(52, 41, 61, 0.5) 100%
|
||||
);
|
||||
background: linear-gradient(0deg,
|
||||
rgba(37, 24, 51, 0) 0%,
|
||||
rgba(52, 41, 61, 0.5) 100%);
|
||||
pointer-events: none;
|
||||
backdrop-filter: blur(8px);
|
||||
opacity: 0;
|
||||
|
@ -2099,4 +2113,4 @@
|
|||
text-transform: capitalize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
// border-right: 1px solid var(--border-color);
|
||||
background: var(--background-color);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 30px;
|
||||
|
@ -33,8 +32,8 @@
|
|||
line-height: 32px;
|
||||
text-align: center;
|
||||
font-weight: var(--font-weight-medium);
|
||||
background: var(--accent-color);
|
||||
color: var(--primary-color);
|
||||
background: var(--background-color-accent);
|
||||
color: var(--text-button-color);
|
||||
border-radius: #{$border-radius-circle};
|
||||
}
|
||||
|
||||
|
@ -85,6 +84,12 @@
|
|||
font-weight: var(--font-weight-medium);
|
||||
background: var(--background-color-button);
|
||||
|
||||
svg {
|
||||
path {
|
||||
stroke: var(--background-color-selected);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--background-color-button);
|
||||
}
|
||||
|
@ -165,10 +170,8 @@
|
|||
position: relative;
|
||||
border: 1px solid var(--border-color);
|
||||
border-radius: #{$border-radius-extra-large};
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
|
||||
.dashboard-card-wrapper {
|
||||
width: 100%;
|
||||
|
@ -199,13 +202,16 @@
|
|||
width: 100%;
|
||||
padding: 13px 16px;
|
||||
background: var(--background-color);
|
||||
// backdrop-filter: blur(18px);
|
||||
|
||||
border-radius: #{$border-radius-xlarge};
|
||||
// transform: translateY(100%);///////hovered
|
||||
transition: transform 0.25s linear;
|
||||
|
||||
.project-details {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
|
||||
.project-name {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
|
@ -226,7 +232,7 @@
|
|||
line-height: 26px;
|
||||
text-align: center;
|
||||
background: var(--accent-color);
|
||||
color: var(--primary-color);
|
||||
color: var(--text-color);
|
||||
border-radius: #{$border-radius-circle};
|
||||
}
|
||||
|
||||
|
@ -247,7 +253,7 @@
|
|||
border-radius: 8px;
|
||||
z-index: 100;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
backdrop-filter: blur(20px);
|
||||
flex-direction: column;
|
||||
transform: translate(100%, 100%);
|
||||
overflow: hidden;
|
||||
|
@ -265,16 +271,18 @@
|
|||
text-transform: capitalize;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--background-color-secondary);
|
||||
background-color: var(--background-color-selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
overflow: visible;
|
||||
|
||||
.kebab-options-wrapper {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.project-details-container {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
.presets-container {
|
||||
@include flex-center;
|
||||
gap: 4px;
|
||||
gap: 6px;
|
||||
|
||||
.preset {
|
||||
background: var(--background-color);
|
||||
|
@ -74,7 +74,17 @@
|
|||
border-radius: #{$border-radius-large};
|
||||
outline: 1px solid var(--border-color);
|
||||
}
|
||||
|
||||
.upload-btn{
|
||||
padding: 4px 16px !important;
|
||||
}
|
||||
.generate-walls-btn{
|
||||
padding: 4px 16px;
|
||||
@include flex-center;
|
||||
gap: 4px;
|
||||
color: var(--text-button-color);
|
||||
background: var(--background-color-button);
|
||||
border-radius: #{$border-radius-extra-large};
|
||||
}
|
||||
.active {
|
||||
background: var(--background-color-accent);
|
||||
color: var(--text-button-color);
|
||||
|
@ -82,17 +92,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.label-toogler {
|
||||
position: fixed;
|
||||
bottom: 4%;
|
||||
right: 1.5%;
|
||||
z-index: 10;
|
||||
|
||||
// background: var(--background-color);
|
||||
// backdrop-filter: blur(10px);
|
||||
// outline: 1px solid var(--border-color);
|
||||
border-radius: 8px;
|
||||
|
||||
.input-toggle-container {
|
||||
|
@ -113,4 +117,4 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ type Preset = {
|
|||
inputs: {
|
||||
label: string;
|
||||
activeOption: string;
|
||||
min?: number;
|
||||
max?: number;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue