diff --git a/app/package-lock.json b/app/package-lock.json index ed85f25..d63595f 100644 --- a/app/package-lock.json +++ b/app/package-lock.json @@ -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" } diff --git a/app/src/components/Dashboard/DashboardCard.tsx b/app/src/components/Dashboard/DashboardCard.tsx index a653110..1a532b9 100644 --- a/app/src/components/Dashboard/DashboardCard.tsx +++ b/app/src/components/Dashboard/DashboardCard.tsx @@ -183,6 +183,7 @@ const DashboardCard: React.FC = ({ className="dashboard-card-container" onClick={navigateToProject} title={projectName} + onMouseLeave={() => setIsKebabOpen(false)} >
diff --git a/app/src/components/layout/scenes/ComparisonScene.tsx b/app/src/components/layout/scenes/ComparisonScene.tsx index 635ebec..311f4a3 100644 --- a/app/src/components/layout/scenes/ComparisonScene.tsx +++ b/app/src/components/layout/scenes/ComparisonScene.tsx @@ -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); } }; diff --git a/app/src/components/layout/scenes/MainScene.tsx b/app/src/components/layout/scenes/MainScene.tsx index 10894eb..d299dc9 100644 --- a/app/src/components/layout/scenes/MainScene.tsx +++ b/app/src/components/layout/scenes/MainScene.tsx @@ -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() {
- {selectedProduct && isVersionSaved && !isPlaying && ( + {selectedProduct && isVersionSaved && !isPlaying && activeModule === "simulation" && (
{ const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore(); const { activeModule } = useModuleStore(); const navigate = useNavigate(); + return (
-
navigate("/Dashboard")}> +
+
diff --git a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx index e983f9a..8fd5bea 100644 --- a/app/src/components/layout/sidebarLeft/SideBarLeft.tsx +++ b/app/src/components/layout/sidebarLeft/SideBarLeft.tsx @@ -35,9 +35,8 @@ const SideBarLeft: React.FC = () => { return (
{toggleUILeft && ( diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index ddb27a0..86c98cb 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -66,7 +66,7 @@ const SideBarRight: React.FC = () => { return (
diff --git a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx index 1ad18a0..b314f19 100644 --- a/app/src/components/layout/sidebarRight/analysis/Analysis.tsx +++ b/app/src/components/layout/sidebarRight/analysis/Analysis.tsx @@ -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: "%" } }, diff --git a/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx b/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx index 0204582..6f52438 100644 --- a/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx +++ b/app/src/components/layout/sidebarRight/analysis/RenderAnalysisInputs.tsx @@ -31,7 +31,7 @@ const RenderAnalysisInputs: React.FC = ({ keyName, presets,i key={index} label={preset.inputs.label} min={0} - max={0} + max={8} value={5} /> ); diff --git a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx index 2cad712..fa244fd 100644 --- a/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx +++ b/app/src/components/layout/sidebarRight/properties/ZoneProperties.tsx @@ -35,9 +35,9 @@ const ZoneProperties: React.FC = () => { viewPortCenter: zoneTarget, }; - let response = await zoneCameraUpdate(zonesdata, organization,projectId); + let response = await zoneCameraUpdate(zonesdata, organization, projectId); console.log('response: ', response); - if (response.message === "updated successfully") { + if (response.message === "zone updated") { setEdit(false); } else { // console.log(response); @@ -59,10 +59,9 @@ const ZoneProperties: React.FC = () => { zoneName: newName, }; // Call your API to update the zone - let response = await zoneCameraUpdate(zonesdata, organization,projectId); - console.log('response: ', response); - // console.log("response: ", response); - if (response.message === "updated successfully") { + let response = await zoneCameraUpdate(zonesdata, organization, projectId); + if (response.message === "zone updated") { + setSelectedZone((prev) => ({ ...prev, zoneName: newName })); setZones((prevZones: any[]) => prevZones.map((zone) => zone.zoneUuid === selectedZone.zoneUuid @@ -83,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 ); }; diff --git a/app/src/components/temporary/SelectFloorPlan.tsx b/app/src/components/temporary/SelectFloorPlan.tsx index 6c45f08..310b2b0 100644 --- a/app/src/components/temporary/SelectFloorPlan.tsx +++ b/app/src/components/temporary/SelectFloorPlan.tsx @@ -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(undefined); @@ -18,7 +20,9 @@ const SelectFloorPlan: React.FC = () => { const [generate, setGenerate] = useState(false); // Handles file upload and DXF parsing - const handleFileUpload = async (event: React.ChangeEvent) => { + const handleFileUpload = async ( + event: React.ChangeEvent + ) => { 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 (
- Preset Layouts + Upload Layouts +
+ + + + {parsedFile && ( + + )} +
+ or
- - - - - -
); }; -export default SelectFloorPlan; \ No newline at end of file +export default SelectFloorPlan; diff --git a/app/src/components/ui/analysis/ProductionCapacity.tsx b/app/src/components/ui/analysis/ProductionCapacity.tsx index 7c2e883..84d293d 100644 --- a/app/src/components/ui/analysis/ProductionCapacity.tsx +++ b/app/src/components/ui/analysis/ProductionCapacity.tsx @@ -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 = { @@ -91,15 +92,19 @@ const ThroughputSummary: React.FC = () => { const [isLoading, setIsLoading] = useState(true); useEffect(() => { - // console.log('productionCapacityData > 0: ', productionCapacityData > 0); + // if (productionCapacityData > 0) { - setIsLoading(false); - console.log("productionCapacityData: ", productionCapacityData); + setTimeout(() => { + + setIsLoading(false); + }, 3000) + } else { setIsLoading(true); } }, [productionCapacityData]); + return ( <> {!isLoading &&
diff --git a/app/src/components/ui/analysis/ROISummary.tsx b/app/src/components/ui/analysis/ROISummary.tsx index a03b15c..56ac5dd 100644 --- a/app/src/components/ui/analysis/ROISummary.tsx +++ b/app/src/components/ui/analysis/ROISummary.tsx @@ -80,14 +80,15 @@ const ROISummary = ({ const year = now.getFullYear(); return `${day} ${month}, ${year}`; } - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const { roiSummary } = useROISummaryData(); useEffect(() => { if (roiSummary.productName) { - // If productName is set, assume data is loaded - setIsLoading(false); + setTimeout(() => { + setIsLoading(false); + }, 4500) } else { // If productName is empty, assume still loading setIsLoading(true); diff --git a/app/src/components/ui/analysis/ThroughputSummary.tsx b/app/src/components/ui/analysis/ThroughputSummary.tsx index a01ac61..0568b5d 100644 --- a/app/src/components/ui/analysis/ThroughputSummary.tsx +++ b/app/src/components/ui/analysis/ThroughputSummary.tsx @@ -11,13 +11,9 @@ const ProductionCapacity = ({ throughputValue = 128, timeRange = { startTime: "08:00 AM", endTime: "09:00 AM" }, }) => { - - - const { machineActiveTime } = useMachineUptime(); const { materialCycleTime } = useMaterialCycle(); const { throughputData } = useThroughPutData() - const { productionCapacityData } = useProductionCapacityData() const progressPercent = machineActiveTime; @@ -27,21 +23,14 @@ const ProductionCapacity = ({ const partialFillPercent = ((progressPercent / 100) * totalBars - barsToFill) * 100; - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); useEffect(() => { - console.log('typeof throughputData:', typeof throughputData); - console.log('throughputData > 0: ', throughputData > 0); if (throughputData > 0) { - // console.log('machineActiveTime: ', machineActiveTime); - // console.log('materialCycleTime: ', materialCycleTime); - // console.log('throughputData: ', throughputData); - // console.log('productionCapacityData: ', productionCapacityData); setIsLoading(false); } else { setIsLoading(true); } - }, [throughputData]) return ( @@ -60,7 +49,7 @@ const ProductionCapacity = ({
- {isLoading ? ( + {!isLoading ? ( <>
diff --git a/app/src/components/ui/compareVersion/CompareLayOut.tsx b/app/src/components/ui/compareVersion/CompareLayOut.tsx index 6cce453..48bb686 100644 --- a/app/src/components/ui/compareVersion/CompareLayOut.tsx +++ b/app/src/components/ui/compareVersion/CompareLayOut.tsx @@ -118,7 +118,6 @@ const CompareLayOut = () => { if (product) { setComparisonProduct(product.productUuid, product.productName); setLoadingProgress(1); - setIsPlaying(true); setIsPaused(true); } }; diff --git a/app/src/components/ui/compareVersion/ComparisonResult.tsx b/app/src/components/ui/compareVersion/ComparisonResult.tsx index 85d1c6c..0f91a36 100644 --- a/app/src/components/ui/compareVersion/ComparisonResult.tsx +++ b/app/src/components/ui/compareVersion/ComparisonResult.tsx @@ -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 (
Performance Comparison
+

Throughput (units/hr)

@@ -64,8 +96,11 @@ const ComparisonResult = () => {
550/ hr
-
+
+ +
+
Cycle Time
@@ -81,12 +116,16 @@ const ComparisonResult = () => {
Layout 2
110 Sec
- 19.6%1.6% + 1.6%
+
+ +
+
Overall Downtime
@@ -101,10 +140,7 @@ const ComparisonResult = () => {
-
-
-
-
+
@@ -114,16 +150,15 @@ const ComparisonResult = () => {
Layout 1
-
- Total scrap produced by -
+
Total scrap produced by
2.7 ton
- +
+
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx index 8136a18..22653ff 100644 --- a/app/src/components/ui/list/List.tsx +++ b/app/src/components/ui/list/List.tsx @@ -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 = ({ 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 ); @@ -119,17 +118,13 @@ const List: React.FC = ({ items = [], remove }) => { alert("Zone name already exists. Please choose a different name."); return; // DO NOT update state } - const zonesdata = { zoneUuid: selectedZone.zoneUuid, zoneName: newName, }; - const response = await zoneCameraUpdate(zonesdata, organization,projectId); - console.log('response: ', response); - if (response.message === "updated successfully") { + if (response.message === "zone updated") { setSelectedZone((prev) => ({ ...prev, zoneName: newName })); - setZones((prevZones: any[]) => prevZones.map((zone) => zone.zoneUuid === selectedZone.zoneUuid @@ -158,7 +153,7 @@ const List: React.FC = ({ 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 ); }; diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx index 1002a9b..ab0631a 100644 --- a/app/src/components/ui/simulation/simulationPlayer.tsx +++ b/app/src/components/ui/simulation/simulationPlayer.tsx @@ -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" && ( +
+ setViewSceneLabels(!viewSceneLabels)} + /> +
+ )}
@@ -200,7 +222,7 @@ const SimulationPlayer: React.FC = () => {
{" "}
@@ -209,9 +231,7 @@ const SimulationPlayer: React.FC = () => { {!hidePlayer && subModule !== "analysis" && (
- {isPaused - ? "Paused - system idle." - : "Running simulation..."} + {isPaused ? "Paused - system idle." : "Running simulation..."}
)}
diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx index 4ca6c45..c83eb64 100644 --- a/app/src/modules/builder/asset/assetsGroup.tsx +++ b/app/src/modules/builder/asset/assetsGroup.tsx @@ -176,7 +176,7 @@ function AssetsGroup({ floorGroup, plane }: { readonly floorGroup: RefGroup, rea actionName: "Action 1", actionType: "process", processTime: 10, - swapMaterial: "material-id", + swapMaterial: "Default Material", triggers: [] } } diff --git a/app/src/modules/builder/asset/models/model/model.tsx b/app/src/modules/builder/asset/models/model/model.tsx index f70176b..f28c16a 100644 --- a/app/src/modules/builder/asset/models/model/model.tsx +++ b/app/src/modules/builder/asset/models/model/model.tsx @@ -36,7 +36,7 @@ function Model({ asset }: { readonly asset: Asset }) { const { renderDistance } = useRenderDistance(); const [isRendered, setIsRendered] = useState(false); const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`; - const [gltfScene, setGltfScene] = useState(null); + const [gltfScene, setGltfScene] = useState(null); const [boundingBox, setBoundingBox] = useState(null); const groupRef = useRef(null); const { projectId } = useParams(); @@ -53,7 +53,7 @@ function Model({ asset }: { readonly asset: Asset }) { const assetId = asset.assetId; const cachedModel = THREE.Cache.get(assetId); if (cachedModel) { - setGltfScene(cachedModel); + setGltfScene(cachedModel.scene.clone()); calculateBoundingBox(cachedModel.scene); return; } @@ -66,7 +66,7 @@ function Model({ asset }: { readonly asset: Asset }) { URL.revokeObjectURL(blobUrl); THREE.Cache.remove(blobUrl); THREE.Cache.add(assetId, gltf); - setGltfScene(gltf); + setGltfScene(gltf.scene.clone()); calculateBoundingBox(gltf.scene); }, undefined, @@ -86,7 +86,7 @@ function Model({ asset }: { readonly asset: Asset }) { const modelBlob = await response.blob(); await storeGLTF(assetId, modelBlob); THREE.Cache.add(assetId, gltf); - setGltfScene(gltf); + setGltfScene(gltf.scene.clone()); calculateBoundingBox(gltf.scene); } catch (error) { console.error(`[Backend] Error storing/loading ${asset.modelName}:`, error); @@ -285,7 +285,7 @@ function Model({ asset }: { readonly asset: Asset }) { > {gltfScene && ( isRendered ? ( - + ) : ( ) diff --git a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx index aa7fc19..bb548ba 100644 --- a/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx +++ b/app/src/modules/simulation/analysis/throughPut/throughPutData.tsx @@ -16,7 +16,7 @@ export default function ThroughPutData() { const { machines } = machineStore(); const { conveyors } = conveyorStore(); const { storageUnits } = storageUnitStore(); - const { materialHistory } = materialStore(); + const { materialHistory, materials } = materialStore(); const { machineCount, setMachineCount } = useMachineCount(); const { machineActiveTime, setMachineActiveTime } = useMachineUptime(); const { materialCycleTime, setMaterialCycleTime } = useMaterialCycle(); @@ -49,16 +49,15 @@ export default function ThroughPutData() { if (item.type === "roboticArm") { armBots.filter(arm => arm.modelUuid === item.modelUuid) .forEach(arm => { - if (arm.activeTime >= 0) { + if (arm.activeTime > 0) { process.push({ modelid: arm.modelUuid, modelName: arm.modelName, activeTime: arm?.activeTime }) totalActiveTime += arm.activeTime; - } }); } else if (item.type === "vehicle") { vehicles.filter(vehicle => vehicle.modelUuid === item.modelUuid) .forEach(vehicle => { - if (vehicle.activeTime >= 0) { + if (vehicle.activeTime > 0) { process.push({ modelid: vehicle.modelUuid, modelName: vehicle.modelName, activeTime: vehicle?.activeTime }) totalActiveTime += vehicle.activeTime; @@ -67,7 +66,7 @@ export default function ThroughPutData() { } else if (item.type === "machine") { machines.filter(machine => machine.modelUuid === item.modelUuid) .forEach(machine => { - if (machine.activeTime >= 0) { + if (machine.activeTime > 0) { process.push({ modelid: machine.modelUuid, modelName: machine.modelName, activeTime: machine?.activeTime }) totalActiveTime += machine.activeTime; } @@ -75,16 +74,16 @@ export default function ThroughPutData() { } else if (item.type === "transfer") { conveyors.filter(conveyor => conveyor.modelUuid === item.modelUuid) .forEach(conveyor => { - if (conveyor.activeTime >= 0) { - totalActiveTime += conveyor.activeTime; + if (conveyor.activeTime > 0) { + // totalActiveTime += conveyor.activeTime; } }); } else if (item.type === "storageUnit") { storageUnits.filter(storage => storage.modelUuid === item.modelUuid) .forEach(storage => { - if (storage.activeTime >= 0) { - totalActiveTime += storage.activeTime; - + if (storage.activeTime > 0) { + // totalActiveTime += storage.activeTime; +// } }); } @@ -93,6 +92,7 @@ export default function ThroughPutData() { totalItems += sequence.length; }); + setMachineCount(totalItems); setMachineActiveTime(totalActiveTime); let arr = process.map((item: any) => ({ @@ -109,39 +109,98 @@ export default function ThroughPutData() { // if (materialCycleTime <= 0) return }, [products, selectedProduct, getProductById, setMachineCount, materialCycleTime, armBots, vehicles, machines]); - // Setting material cycle time useEffect(() => { - materialHistory.forEach((material) => { - const start = material.material.startTime ?? 0; - const end = material.material.endTime ?? 0; - if (start === 0 || end === 0) return; - const totalCycleTime = (end - start) / 1000; // Convert milliseconds to seconds - setMaterialCycleTime(Number(totalCycleTime.toFixed(2))); // Set the material cycle time in the store - }); - }, [materialHistory]); + async function getMachineActive() { + const productData = getProductById(selectedProduct.productUuid); + let anyArmActive; + let anyVehicleActive; + let anyMachineActive; + if (productData) { + const productSequenceData = await determineExecutionMachineSequences([productData]); + if (productSequenceData?.length > 0) { + productSequenceData.forEach(sequence => { + sequence.forEach(item => { + if (item.type === "roboticArm") { + armBots + .filter(arm => arm.modelUuid === item.modelUuid) + .forEach(arm => { + if (arm.isActive) { + anyArmActive = true; + } else { + anyArmActive = false; + } + }); + } + if (item.type === "vehicle") { + vehicles + .filter(vehicle => vehicle.modelUuid === item.modelUuid) + .forEach(vehicle => { + if (vehicle.isActive) { + anyVehicleActive = true; + } else { + anyVehicleActive = false; + } + }); + } + if (item.type === "machine") { + machines + .filter(machine => machine.modelUuid === item.modelUuid) + .forEach(machine => { + if (machine.isActive) { + anyMachineActive = true; + } else { + anyMachineActive = false; + } + }); + } + }); + }); + } + } + const allInactive = !anyArmActive && !anyVehicleActive && !anyMachineActive; + if (allInactive && materials.length === 0 && materialHistory.length > 0) { + + let totalCycleTimeSum = 0; + let cycleCount = 0; + + materialHistory.forEach((material) => { + const start = material.material.startTime ?? 0; + const end = material.material.endTime ?? 0; + if (start === 0 || end === 0) return; + + const totalCycleTime = (end - start) / 1000; // Convert milliseconds to seconds + totalCycleTimeSum += totalCycleTime; + cycleCount++; + }); + + if (cycleCount > 0) { + const averageCycleTime = totalCycleTimeSum / cycleCount; + setMaterialCycleTime(Number(averageCycleTime.toFixed(2))); + } + } + } + if (isPlaying) { + setTimeout(() => { + getMachineActive(); + }, 500) + } + }, [armBots, materials, materialHistory, machines, vehicles, selectedProduct]) useEffect(() => { if (machineActiveTime > 0 && materialCycleTime > 0 && machineCount > 0) { + + + const utilization = machineActiveTime / 3600; // Active time per hour const unitsPerMachinePerHour = 3600 / materialCycleTime; const throughput = unitsPerMachinePerHour * machineCount * utilization; - - setThroughputData(throughput.toFixed(2)); // Set throughput to state/store - - // console.log('---Throughput Results---'); - // console.log('Machine Active Time (s):', machineActiveTime); - // console.log('Material Cycle Time (s):', materialCycleTime); - // console.log('Machine Count:', machineCount); - // console.log('Utilization:', utilization); - // console.log('Throughput (units/hr):', throughput); + setThroughputData(Number(throughput.toFixed(2))); // Keep as number + // } }, [machineActiveTime, materialCycleTime, machineCount]); - - - return ( <> diff --git a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx index 1ad53de..a9681d6 100644 --- a/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx +++ b/app/src/modules/simulation/roboticArm/instances/animator/roboticArmAnimator.tsx @@ -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 && ( [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 */} - {/* 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 ( @@ -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 ( ); })} - - - + */} ); diff --git a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx index f773b7c..51f044d 100644 --- a/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx +++ b/app/src/modules/simulation/roboticArm/instances/armInstance/roboticArmInstance.tsx @@ -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 && ( <> - + { 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(); 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 ( - <> - { - setSelectedArm(groupRef.current?.getObjectByName(targetBoneName)) - }}> - - - {/* {selectedArm && } */} - + + + ) } diff --git a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx index b1295a3..f0958b3 100644 --- a/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx +++ b/app/src/modules/simulation/roboticArm/instances/roboticArmInstances.tsx @@ -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) => ( - {/* */} + {viewSceneLabels && } ))} diff --git a/app/src/modules/simulation/simulator/simulator.tsx b/app/src/modules/simulation/simulator/simulator.tsx index 5b2f8a8..f9e4714 100644 --- a/app/src/modules/simulation/simulator/simulator.tsx +++ b/app/src/modules/simulation/simulator/simulator.tsx @@ -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; diff --git a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx index 4c76e71..9d45fd8 100644 --- a/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx +++ b/app/src/modules/simulation/vehicle/instances/animator/vehicleAnimator.tsx @@ -32,7 +32,7 @@ function VehicleAnimator({ path, handleCallBack, currentPhase, agvUuid, agvDetai useEffect(() => { if (currentPhase === 'stationed-pickup' && path.length > 0) { - console.log('path: ', path); + // console.log('path: ', path); setCurrentPath(path); setObjectRotation(agvDetail.point.action?.pickUpPoint?.rotation) } else if (currentPhase === 'pickup-drop' && path.length > 0) { diff --git a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx index d81a91c..989242b 100644 --- a/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx +++ b/app/src/modules/simulation/vehicle/instances/vehicleInstances.tsx @@ -5,8 +5,8 @@ import { useSceneContext } from "../../../scene/sceneContext"; import { useViewSceneStore } from "../../../../store/builder/store"; function VehicleInstances() { - const { vehicleStore } = useSceneContext(); - const { vehicles } = vehicleStore(); + const { vehicleStore } = useSceneContext(); + const { vehicles } = vehicleStore(); const { viewSceneLabels } = useViewSceneStore(); return ( diff --git a/app/src/pages/Dashboard.tsx b/app/src/pages/Dashboard.tsx index 7065e20..e8de9c3 100644 --- a/app/src/pages/Dashboard.tsx +++ b/app/src/pages/Dashboard.tsx @@ -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("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"); diff --git a/app/src/pages/UserAuth.tsx b/app/src/pages/UserAuth.tsx index 700265a..6ec0036 100644 --- a/app/src/pages/UserAuth.tsx +++ b/app/src/pages/UserAuth.tsx @@ -38,8 +38,6 @@ const UserAuth: React.FC = () => { const { userId, organization } = getUserData(); - - const handleLogin = async (e: FormEvent) => { e.preventDefault(); const organization = email.split("@")[1].split(".")[0]; @@ -58,7 +56,10 @@ const UserAuth: React.FC = () => { localStorage.setItem("refreshToken", res.message.refreshToken); try { + console.log('res.message.userId: ', res.message.userId); + console.log('organization: ', organization); const projects = await recentlyViewed(organization, res.message.userId); + console.log('projects: ', projects); if (res.message.isShare) { if (Object.values(projects.RecentlyViewed).length > 0) { diff --git a/app/src/services/visulization/zone/zoneCameraUpdation.ts b/app/src/services/visulization/zone/zoneCameraUpdation.ts index e7dbdde..57bd153 100644 --- a/app/src/services/visulization/zone/zoneCameraUpdation.ts +++ b/app/src/services/visulization/zone/zoneCameraUpdation.ts @@ -11,7 +11,7 @@ export const zoneCameraUpdate = async (zoneData: {}, organization: string, proje token: localStorage.getItem("token") || "", refresh_token: localStorage.getItem("refreshToken") || "", }, - body: JSON.stringify({ zoneData,projectId }), + body: JSON.stringify({ zoneData, projectId }), }); if (!response.ok) { diff --git a/app/src/store/simulation/useEventsStore.ts b/app/src/store/simulation/useEventsStore.ts index dbba722..105b0b5 100644 --- a/app/src/store/simulation/useEventsStore.ts +++ b/app/src/store/simulation/useEventsStore.ts @@ -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 | undefined; // Point-level actions @@ -61,6 +62,12 @@ export const useEventsStore = create()( }); }, + clearEvents: () => { + set((state) => { + state.events = []; + }); + }, + updateEvent: (modelUuid, updates) => { let updatedEvent: EventsSchema | undefined; set((state) => { diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index ec80d50..7270233 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -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()( }); }, + clearProducts: () => { + set((state) => { + state.products = []; + }); + }, + removeProduct: (productUuid) => { set((state) => { state.products = state.products.filter(p => p.productUuid !== productUuid); diff --git a/app/src/styles/components/simulation/simulation.scss b/app/src/styles/components/simulation/simulation.scss index db7b580..403d7ee 100644 --- a/app/src/styles/components/simulation/simulation.scss +++ b/app/src/styles/components/simulation/simulation.scss @@ -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; diff --git a/app/src/styles/layout/compareLayout.scss b/app/src/styles/layout/compareLayout.scss index c338f7c..07b5ad2 100644 --- a/app/src/styles/layout/compareLayout.scss +++ b/app/src/styles/layout/compareLayout.scss @@ -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; diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 80125e3..b043e29 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -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; } } -} +} \ No newline at end of file diff --git a/app/src/styles/pages/dashboard.scss b/app/src/styles/pages/dashboard.scss index b0e3eea..a136974 100644 --- a/app/src/styles/pages/dashboard.scss +++ b/app/src/styles/pages/dashboard.scss @@ -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); } diff --git a/app/src/styles/scene/scene.scss b/app/src/styles/scene/scene.scss index 2ac8f98..3823ac4 100644 --- a/app/src/styles/scene/scene.scss +++ b/app/src/styles/scene/scene.scss @@ -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 @@ } } } -} \ No newline at end of file +} diff --git a/app/src/types/analysis.d.ts b/app/src/types/analysis.d.ts index 02ce1c1..151afb4 100644 --- a/app/src/types/analysis.d.ts +++ b/app/src/types/analysis.d.ts @@ -3,6 +3,8 @@ type Preset = { inputs: { label: string; activeOption: string; + min?: number; + max?: number; }; };