From c187a07b2269f691ce6e0114ec68ea12314f2ea0 Mon Sep 17 00:00:00 2001 From: Nalvazhuthi Date: Sat, 3 May 2025 10:03:39 +0530 Subject: [PATCH 01/14] updating UI --- app/src/components/icons/analysis.tsx | 119 ++++++++++- .../ui/analysis/ProductionCapacity.tsx | 187 +++++++++++++---- app/src/components/ui/analysis/ROISummary.tsx | 19 +- .../ui/analysis/ThroughputSummary.tsx | 188 ++++-------------- app/src/components/ui/log/logger.ts | 71 ------- .../ui/simulation/simulationPlayer.tsx | 4 +- app/src/modules/builder/builder.tsx | 2 +- app/src/pages/Project.tsx | 4 +- .../styles/components/analysis/analysis.scss | 28 ++- app/src/styles/pages/realTimeViz.scss | 6 +- 10 files changed, 346 insertions(+), 282 deletions(-) delete mode 100644 app/src/components/ui/log/logger.ts diff --git a/app/src/components/icons/analysis.tsx b/app/src/components/icons/analysis.tsx index 591df60..30115cc 100644 --- a/app/src/components/icons/analysis.tsx +++ b/app/src/components/icons/analysis.tsx @@ -17,25 +17,39 @@ export function ThroughputSummaryIcon() { ); } + export function ProductionCapacityIcon() { return ( - - + + + + + + + + + ); } + export function ROISummaryIcon() { return ( ); } + export function PowerIcon() { return ( ); } + +export function ROISummaryProductName() { + return ( + + + + + ); +} + +export function SonarCrownIcon() { + return ( + + + + + ); +} + +export function CostBreakDownIcon() { + return ( + + + + ); +} + +export function LightBulpIcon() { + return ( + + + + ); +} diff --git a/app/src/components/ui/analysis/ProductionCapacity.tsx b/app/src/components/ui/analysis/ProductionCapacity.tsx index 31c3a02..08ddb05 100644 --- a/app/src/components/ui/analysis/ProductionCapacity.tsx +++ b/app/src/components/ui/analysis/ProductionCapacity.tsx @@ -1,21 +1,101 @@ -import React, { useState } from "react"; -import { ProductionCapacityIcon } from "../../icons/analysis"; +import React from "react"; +import { Line } from "react-chartjs-2"; +import { + Chart as ChartJS, + LineElement, + CategoryScale, + LinearScale, + PointElement, +} from "chart.js"; +import { PowerIcon, ProductionCapacityIcon } from "../../icons/analysis"; -const ProductionCapacity = ({ - progressPercent = 50, - avgProcessTime = "28.4 Secs/unit", - machineUtilization = "78%", - throughputValue = 128, - timeRange = { startTime: "08:00 AM", endTime: "09:00 AM" }, -}) => { - const totalBars = 6; - const barsToFill = Math.floor((progressPercent / 100) * totalBars); - const partialFillPercent = - ((progressPercent / 100) * totalBars - barsToFill) * 100; +ChartJS.register(LineElement, CategoryScale, LinearScale, PointElement); + +// Helper function to generate random colors +const getRandomColor = () => { + const letters = "0123456789ABCDEF"; + let color = "#"; + for (let i = 0; i < 6; i++) { + color += letters[Math.floor(Math.random() * 16)]; + } + return color; +}; + +const ThroughputSummary = () => { + // Define all data internally within the component + const timeRange = { + startTime: "08:00 AM", + endTime: "09:00 AM", + }; + + const throughputData = { + labels: ["08:00", "08:10", "08:20", "08:30", "08:40", "08:50", "09:00"], + data: [100, 120, 110, 130, 125, 128, 132], + totalThroughput: 1240, + assetUsage: 85, + }; + + const energyConsumption = { + energyConsumed: 456, + unit: "KWH", + }; + + // Dynamic shift data + const shiftUtilization = [ + { shift: 1, percentage: 30, color: "#F3C64D" }, + { shift: 2, percentage: 40, color: "#67B3F4" }, + { shift: 3, percentage: 30, color: "#7981F5" }, + ]; + + // Chart data configuration + const chartData = { + labels: throughputData.labels, + datasets: [ + { + label: "Units/hour", + data: throughputData.data, + borderColor: "#B392F0", + tension: 0.4, + pointRadius: 0, // Hide points + }, + ], + }; + + const chartOptions = { + responsive: true, + scales: { + x: { + grid: { + display: false, + }, + ticks: { + display: false, + color: "#fff", + }, + }, + y: { + grid: { + display: false, + }, + ticks: { + display: false, + color: "#fff", + }, + }, + }, + plugins: { + legend: { + display: false, + }, + tooltip: { + enabled: true, + }, + }, + }; return ( -
-
+
+
Production Capacity
@@ -30,34 +110,63 @@ const ProductionCapacity = ({
- {throughputValue} Units/hour + {throughputData.totalThroughput}{" "} + Units/hour
- - {/* Dynamic Progress Bar */} -
- {[...Array(totalBars)].map((_, i) => ( -
- {i < barsToFill ? ( -
- ) : i === barsToFill ? ( -
- ) : null} -
- ))} +
+
+
Asset usage
+
{throughputData.assetUsage}%
+
+
-
-
- Avg. Process Time - {avgProcessTime} +
+
+
Energy Consumption
+
+
+ +
+
+
{energyConsumption.energyConsumed}
+
{energyConsumption.unit}
+
+
-
- Machine Utilization - {machineUtilization} +
+
Shift Utilization
+
+
{throughputData.assetUsage}%
+ +
+ {/* Dynamically create progress bars based on shiftUtilization array */} + {shiftUtilization.map((shift, index) => ( +
+ ))} +
+ +
+ {/* Dynamically create shift indicators with random colors */} + {shiftUtilization.map((shift, index) => ( +
+ + +
+ ))} +
+
@@ -65,4 +174,4 @@ const ProductionCapacity = ({ ); }; -export default ProductionCapacity; +export default ThroughputSummary; diff --git a/app/src/components/ui/analysis/ROISummary.tsx b/app/src/components/ui/analysis/ROISummary.tsx index 11101fd..92628af 100644 --- a/app/src/components/ui/analysis/ROISummary.tsx +++ b/app/src/components/ui/analysis/ROISummary.tsx @@ -1,5 +1,11 @@ import React, { useState } from "react"; -import { ROISummaryIcon } from "../../icons/analysis"; +import { + CostBreakDownIcon, + LightBulpIcon, + ROISummaryIcon, + ROISummaryProductName, + SonarCrownIcon, +} from "../../icons/analysis"; import SemiCircleProgress from "./SemiCircleProgress"; const ROISummary = ({ @@ -76,10 +82,12 @@ const ROISummary = ({
+
Product :
{roiSummaryData.productName}
+
+{roiSummaryData.roiPercentage}% ROI with payback in @@ -116,7 +124,7 @@ const ROISummary = ({
- + Cost Breakdown
@@ -168,13 +176,18 @@ const ROISummary = ({
- 💡 + + + How to improve ROI?
Increase CNC utilization by 10%{" "} to shave 0.5 months of payback period +
+
+
- {openObjects && - events.map((event, index) => )} -
- -
-
- Need to Compare Layout? -
-
- Click 'Compare' to review and analyze the layout - differences between them. -
-
- -
-
-
- - {selectedAsset && ( - - { - if (option === "Add to Product") { - handleAddEventToProduct({ - event: getEventByModelUuid(selectedAsset.modelUuid), - addEvent, - selectedProduct, - clearSelectedAsset - }); - } else { - handleRemoveEventFromProduct(); - } - }} + return ( +
+
Simulations
+
+
+
+
Products
+ +
+
+
+ {products.map((product, index) => ( +
+ {/* eslint-disable-next-line */} +
+ setSelectedProduct(product.productId, product.productName) + } + > + - - )} + + handleRenameProduct(product.productId, newName) + } + /> +
+ {products.length > 1 && ( + + )} +
+ ))} +
+ +
- ) + +
+ + {openObjects && + events.map((event, index) => ( + + ))} +
+ +
+
+ Need to Compare Layout? +
+
+ Click 'Compare' to review and analyze the layout + differences between them. +
+
+ +
+
+
+ + {selectedAsset && ( + + { + if (option === "Add to Product") { + handleAddEventToProduct({ + event: getEventByModelUuid(selectedAsset.modelUuid), + addEvent, + selectedProduct, + clearSelectedAsset, + }); + } else { + handleRemoveEventFromProduct(); + } + }} + /> + + )} +
+ ); }; export default Simulations; diff --git a/app/src/components/ui/features/RenameTooltip.tsx b/app/src/components/ui/features/RenameTooltip.tsx index ae64bf0..180ba85 100644 --- a/app/src/components/ui/features/RenameTooltip.tsx +++ b/app/src/components/ui/features/RenameTooltip.tsx @@ -25,10 +25,8 @@ const RenameTooltip: React.FC = ({ name, onSubmit }) => {
diff --git a/app/src/components/ui/menu/EditWidgetOption.tsx b/app/src/components/ui/menu/EditWidgetOption.tsx index 035b26b..558957b 100644 --- a/app/src/components/ui/menu/EditWidgetOption.tsx +++ b/app/src/components/ui/menu/EditWidgetOption.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React from "react"; import { useLeftData, useTopData, @@ -28,13 +28,13 @@ const EditWidgetOption: React.FC = ({ >
{options.map((option, index) => ( -
onClick(option)} > {option} -
+ ))}
diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx index e569250..2b8dcff 100644 --- a/app/src/components/ui/simulation/simulationPlayer.tsx +++ b/app/src/components/ui/simulation/simulationPlayer.tsx @@ -64,8 +64,6 @@ const SimulationPlayer: React.FC = () => { const handleMouseDown = () => { isDragging.current = true; - document.addEventListener("mousemove", handleMouseMove); - document.addEventListener("mouseup", handleMouseUp); }; const handleMouseMove = (e: MouseEvent) => { @@ -80,11 +78,11 @@ const SimulationPlayer: React.FC = () => { const handleMouseUp = () => { isDragging.current = false; - document.removeEventListener("mousemove", handleMouseMove); - document.removeEventListener("mouseup", handleMouseUp); }; useEffect(() => { + document.addEventListener("mousemove", handleMouseMove); + document.addEventListener("mouseup", handleMouseUp); return () => { document.removeEventListener("mousemove", handleMouseMove); document.removeEventListener("mouseup", handleMouseUp); @@ -109,24 +107,6 @@ const SimulationPlayer: React.FC = () => { { name: "process 9", completed: 90 }, // 90% completed { name: "process 10", completed: 30 }, // 30% completed ]; - // Move getRandomColor out of render - const getRandomColor = () => { - const letters = "0123456789ABCDEF"; - let color = "#"; - for (let i = 0; i < 6; i++) { - color += letters[Math.floor(Math.random() * 16)]; - } - return color; - }; - - // Store colors for each process item - const [_, setProcessColors] = useState([]); - - // Generate colors on mount or when process changes - useEffect(() => { - const generatedColors = process.map(() => getRandomColor()); - setProcessColors(generatedColors); - }, []); const intervals = [10, 20, 30, 40, 50, 60]; // in minutes const totalSegments = intervals.length; @@ -218,7 +198,7 @@ const SimulationPlayer: React.FC = () => {
)} - {subModule === "simulations" && ( + {subModule !== "analysis" && (
{playSimulation @@ -281,7 +261,7 @@ const SimulationPlayer: React.FC = () => { const segmentProgress = (index / totalSegments) * 100; const isFilled = progress >= segmentProgress; return ( - +
{label} mins
{ className="process-wrapper" style={{ padding: expand ? "0px" : "5px 35px" }} > + {/* eslint-disable-next-line */}
{ > {process.map((item, index) => (
(null); - const [currentPath, setCurrentPath] = useState<[number, number, number][]>([]); - const [circlePoints, setCirclePoints] = useState<[number, number, number][]>([]); - const [customCurvePoints, setCustomCurvePoints] = useState(null); + const progressRef = useRef(0); + const curveRef = useRef(null); + const [currentPath, setCurrentPath] = useState<[number, number, number][]>( + [] + ); + const [circlePoints, setCirclePoints] = useState<[number, number, number][]>( + [] + ); + const [customCurvePoints, setCustomCurvePoints] = useState< + THREE.Vector3[] | null + >(null); - // Zustand stores - const { isPlaying } = usePlayButtonStore(); - const { isPaused } = usePauseButtonStore(); - const { isReset } = useResetButtonStore(); - const { speed } = useAnimationPlaySpeed(); + // Zustand stores + const { isPlaying } = usePlayButtonStore(); + const { isPaused } = usePauseButtonStore(); + const { isReset } = useResetButtonStore(); + const { speed } = useAnimationPlaySpeed(); - // Update path state whenever `path` prop changes - useEffect(() => { - setCurrentPath(path); - }, [path]); + // Update path state whenever `path` prop changes + useEffect(() => { + setCurrentPath(path); + }, [path]); - // Reset logic when `isPlaying` changes - useEffect(() => { - if (!isPlaying) { - setCurrentPath([]); - curveRef.current = null; - } - }, [isPlaying]); - - // Handle circle points based on armBot position - useEffect(() => { - const points = generateRingPoints(1.6, 64) - setCirclePoints(points); - }, [armBot.position]); - - - function generateRingPoints(radius: any, segments: any) { - const points: [number, number, number][] = []; - for (let i = 0; i < segments; i++) { - // Calculate angle for current segment - const angle = (i / segments) * Math.PI * 2; - // Calculate x and z coordinates (y remains the same for a flat ring) - const x = Math.cos(angle) * radius; - const z = Math.sin(angle) * radius; - points.push([x, 1.5, z]); - } - return points; + // Reset logic when `isPlaying` changes + useEffect(() => { + if (!isPlaying) { + setCurrentPath([]); + curveRef.current = null; } + }, [isPlaying]); - const findNearestIndex = (nearestPoint: [number, number, number], points: [number, number, number][], epsilon = 1e-6) => { - for (let i = 0; i < points.length; i++) { - const [x, y, z] = points[i]; - if ( - Math.abs(x - nearestPoint[0]) < epsilon && - Math.abs(y - nearestPoint[1]) < epsilon && - Math.abs(z - nearestPoint[2]) < epsilon - ) { - return i; // Found the matching index - } + // Handle circle points based on armBot position + useEffect(() => { + const points = generateRingPoints(1.6, 64); + setCirclePoints(points); + }, [armBot.position]); + + function generateRingPoints(radius: any, segments: any) { + const points: [number, number, number][] = []; + for (let i = 0; i < segments; i++) { + // Calculate angle for current segment + const angle = (i / segments) * Math.PI * 2; + // Calculate x and z coordinates (y remains the same for a flat ring) + const x = Math.cos(angle) * radius; + const z = Math.sin(angle) * radius; + points.push([x, 1.5, z]); + } + return points; + } + + const findNearestIndex = ( + nearestPoint: [number, number, number], + points: [number, number, number][], + epsilon = 1e-6 + ) => { + for (let i = 0; i < points.length; i++) { + const [x, y, z] = points[i]; + if ( + Math.abs(x - nearestPoint[0]) < epsilon && + Math.abs(y - nearestPoint[1]) < epsilon && + Math.abs(z - nearestPoint[2]) < epsilon + ) { + return i; // Found the matching index + } + } + return -1; // Not found + }; + + // Handle nearest points and final path (including arc points) + useEffect(() => { + if (circlePoints.length > 0 && currentPath.length > 0) { + const start = currentPath[0]; + const end = currentPath[currentPath.length - 1]; + + const raisedStart = [start[0], start[1] + 0.5, start[2]] as [ + number, + number, + number + ]; + const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [ + number, + number, + number + ]; + + const findNearest = (target: [number, number, number]) => { + return circlePoints.reduce((nearest, point) => { + const distance = Math.hypot( + target[0] - point[0], + target[1] - point[1], + target[2] - point[2] + ); + const nearestDistance = Math.hypot( + target[0] - nearest[0], + target[1] - nearest[1], + target[2] - nearest[2] + ); + return distance < nearestDistance ? point : nearest; + }, circlePoints[0]); + }; + + const nearestToStart = findNearest(raisedStart); + + const nearestToEnd = findNearest(raisedEnd); + + const indexOfNearestStart = findNearestIndex( + nearestToStart, + circlePoints + ); + + const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints); + + // Find clockwise and counter-clockwise distances + const clockwiseDistance = + (indexOfNearestEnd - indexOfNearestStart + 64) % 64; + + const counterClockwiseDistance = + (indexOfNearestStart - indexOfNearestEnd + 64) % 64; + + const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance; + + // Collect arc points between start and end + let arcPoints: [number, number, number][] = []; + + if (clockwiseIsShorter) { + if (indexOfNearestStart <= indexOfNearestEnd) { + arcPoints = circlePoints.slice( + indexOfNearestStart, + indexOfNearestEnd + 1 + ); + } else { + // Wrap around + arcPoints = [ + ...circlePoints.slice(indexOfNearestStart, 64), + ...circlePoints.slice(0, indexOfNearestEnd + 1), + ]; } - return -1; // Not found - }; - - - // Handle nearest points and final path (including arc points) - useEffect(() => { - if (circlePoints.length > 0 && currentPath.length > 0) { - const start = currentPath[0]; - const end = currentPath[currentPath.length - 1]; - - const raisedStart = [start[0], start[1] + 0.5, start[2]] as [number, number, number]; - const raisedEnd = [end[0], end[1] + 0.5, end[2]] as [number, number, number]; - - const findNearest = (target: [number, number, number]) => { - return circlePoints.reduce((nearest, point) => { - const distance = Math.hypot( - target[0] - point[0], - target[1] - point[1], - target[2] - point[2] - ); - const nearestDistance = Math.hypot( - target[0] - nearest[0], - target[1] - nearest[1], - target[2] - nearest[2] - ); - return distance < nearestDistance ? point : nearest; - }, circlePoints[0]); - }; - - const nearestToStart = findNearest(raisedStart); - - const nearestToEnd = findNearest(raisedEnd); - - const indexOfNearestStart = findNearestIndex(nearestToStart, circlePoints); - - const indexOfNearestEnd = findNearestIndex(nearestToEnd, circlePoints); - - // Find clockwise and counter-clockwise distances - const clockwiseDistance = (indexOfNearestEnd - indexOfNearestStart + 64) % 64; - - const counterClockwiseDistance = (indexOfNearestStart - indexOfNearestEnd + 64) % 64; - - const clockwiseIsShorter = clockwiseDistance <= counterClockwiseDistance; - - // Collect arc points between start and end - let arcPoints: [number, number, number][] = []; - - if (clockwiseIsShorter) { - if (indexOfNearestStart <= indexOfNearestEnd) { - arcPoints = circlePoints.slice(indexOfNearestStart, indexOfNearestEnd + 1); - } else { - // Wrap around - arcPoints = [ - ...circlePoints.slice(indexOfNearestStart, 64), - ...circlePoints.slice(0, indexOfNearestEnd + 1) - ]; - } - } else { - if (indexOfNearestStart >= indexOfNearestEnd) { - for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) { - arcPoints.push(circlePoints[i]); - } - } else { - for (let i = indexOfNearestStart; i !== (indexOfNearestEnd - 1 + 64) % 64; i = (i - 1 + 64) % 64) { - arcPoints.push(circlePoints[i]); - } - } - } - - // Continue your custom path logic - const pathVectors = [ - new THREE.Vector3(start[0], start[1], start[2]), // start - new THREE.Vector3(raisedStart[0], raisedStart[1], raisedStart[2]), // lift up - new THREE.Vector3(nearestToStart[0], raisedStart[1], nearestToStart[2]), // move to arc start - ...arcPoints.map(point => new THREE.Vector3(point[0], raisedStart[1], point[2])), - new THREE.Vector3(nearestToEnd[0], raisedEnd[1], nearestToEnd[2]), // move from arc end - new THREE.Vector3(raisedEnd[0], raisedEnd[1], raisedEnd[2]), // lowered end - new THREE.Vector3(end[0], end[1], end[2]) // end - ]; - - const customCurve = new THREE.CatmullRomCurve3(pathVectors, false, 'centripetal', 1); - const generatedPoints = customCurve.getPoints(100); - setCustomCurvePoints(generatedPoints); + } else if (indexOfNearestStart >= indexOfNearestEnd) { + for ( + let i = indexOfNearestStart; + i !== (indexOfNearestEnd - 1 + 64) % 64; + i = (i - 1 + 64) % 64 + ) { + arcPoints.push(circlePoints[i]); } - }, [circlePoints, currentPath]); + } - // Frame update for animation - useFrame((_, delta) => { - if (!ikSolver) return; + // Continue your custom path logic + const pathVectors = [ + new THREE.Vector3(start[0], start[1], start[2]), // start + new THREE.Vector3(raisedStart[0], raisedStart[1], raisedStart[2]), // lift up + new THREE.Vector3(nearestToStart[0], raisedStart[1], nearestToStart[2]), // move to arc start + ...arcPoints.map( + (point) => new THREE.Vector3(point[0], raisedStart[1], point[2]) + ), + new THREE.Vector3(nearestToEnd[0], raisedEnd[1], nearestToEnd[2]), // move from arc end + new THREE.Vector3(raisedEnd[0], raisedEnd[1], raisedEnd[2]), // lowered end + new THREE.Vector3(end[0], end[1], end[2]), // end + ]; - const bone = ikSolver.mesh.skeleton.bones.find((b: any) => b.name === targetBone); - if (!bone) return; + const customCurve = new THREE.CatmullRomCurve3( + pathVectors, + false, + "centripetal", + 1 + ); + const generatedPoints = customCurve.getPoints(100); + setCustomCurvePoints(generatedPoints); + } + }, [circlePoints, currentPath]); - if (isPlaying) { - if (!isPaused && customCurvePoints && currentPath.length > 0) { - const curvePoints = customCurvePoints; - const speedAdjustedProgress = progressRef.current + (speed * armBot.speed); - const index = Math.floor(speedAdjustedProgress); + // Frame update for animation + useFrame((_, delta) => { + if (!ikSolver) return; - if (index >= curvePoints.length) { - // Reached the end of the curve - HandleCallback(); - setCurrentPath([]); - curveRef.current = null; - progressRef.current = 0; - } else { - const point = curvePoints[index]; - bone.position.copy(point); - progressRef.current = speedAdjustedProgress; - } - } else if (isPaused) { - logStatus(armBot.modelUuid, 'Simulation Paused'); - } - - ikSolver.update(); - } else if (!isPlaying && currentPath.length === 0) { - // Not playing anymore, reset to rest - bone.position.copy(restPosition); - ikSolver.update(); - } - }); - - - return ( - <> - {customCurvePoints && currentPath && isPlaying && ( - - [p.x, p.y, p.z] as [number, number, number])} - color="green" - lineWidth={5} - dashed={false} - /> - - )} - - - - - + const bone = ikSolver.mesh.skeleton.bones.find( + (b: any) => b.name === targetBone ); + if (!bone) return; + + if (isPlaying) { + if (!isPaused && customCurvePoints && currentPath.length > 0) { + const curvePoints = customCurvePoints; + const speedAdjustedProgress = + progressRef.current + speed * armBot.speed; + const index = Math.floor(speedAdjustedProgress); + + if (index >= curvePoints.length) { + // Reached the end of the curve + HandleCallback(); + setCurrentPath([]); + curveRef.current = null; + progressRef.current = 0; + } else { + const point = curvePoints[index]; + bone.position.copy(point); + progressRef.current = speedAdjustedProgress; + } + } else if (isPaused) { + logStatus(armBot.modelUuid, "Simulation Paused"); + } + + ikSolver.update(); + } else if (!isPlaying && currentPath.length === 0) { + // Not playing anymore, reset to rest + bone.position.copy(restPosition); + ikSolver.update(); + } + }); + + return ( + <> + {customCurvePoints && currentPath && isPlaying && ( + + [p.x, p.y, p.z] as [number, number, number] + )} + color="green" + lineWidth={5} + dashed={false} + /> + + )} + + + + + + ); } export default RoboticArmAnimator; From b4e3d3ef7361981b503726f793cb5a09a17bee7b Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 3 May 2025 11:17:20 +0530 Subject: [PATCH 04/14] Refactor styles: update backdrop-filter values for improved UI consistency; clean up code formatting in various components. --- app/src/styles/components/form.scss | 26 ++++++ .../components/simulation/simulation.scss | 89 ++++++++----------- app/src/styles/components/tools.scss | 33 ++++--- app/src/styles/layout/sidebar.scss | 10 +-- 4 files changed, 86 insertions(+), 72 deletions(-) diff --git a/app/src/styles/components/form.scss b/app/src/styles/components/form.scss index e69de29..67accd2 100644 --- a/app/src/styles/components/form.scss +++ b/app/src/styles/components/form.scss @@ -0,0 +1,26 @@ +@use "../abstracts/variables" as *; +@use "../abstracts/mixins" as *; + +.rename-tool-tip { + position: absolute; + background: var(--background-color); + padding: 10px 16px; + width: 260px; + border-radius: #{$border-radius-large}; + outline: 1px solid var(--border-color); + z-index: 100; + .header { + @include flex-center; + gap: 8px; + .icon { + @include flex-center; + } + .name { + color: var(--text-color); + } + input { + width: 100%; + margin-top: 6px; + } + } +} diff --git a/app/src/styles/components/simulation/simulation.scss b/app/src/styles/components/simulation/simulation.scss index 88f85dc..9b6c93d 100644 --- a/app/src/styles/components/simulation/simulation.scss +++ b/app/src/styles/components/simulation/simulation.scss @@ -3,7 +3,7 @@ .simulation-player-wrapper { position: fixed; - bottom: 12px; + bottom: 32px; left: 50%; z-index: 2; transform: translate(-50%, 0); @@ -35,11 +35,11 @@ @include flex-space-between; gap: 12px; justify-content: space-between; - .header{ + .header { @include flex-center; gap: 6px; padding: 0 8px; - svg{ + svg { scale: 1.3; } } @@ -299,6 +299,37 @@ } } } + + .open { + .start-displayer, + .end-displayer { + display: none; + } + + .timmer { + display: none; + } + .progresser-wrapper { + padding-top: 4px; + } + + .time-displayer { + height: 0; + opacity: 0; + pointer-events: none; + display: none; + } + + .processDisplayer { + padding: 0 8px; + background: transparent; + + .process-player { + width: 0; + display: none !important; + } + } + } } .processDisplayer { @@ -314,22 +345,6 @@ font-size: var(--font-size-tiny); } - .timmer { - width: auto; - position: absolute; - bottom: 0; - font-size: var(--font-size-tiny); - } - - .start-displayer { - left: 8px; - } - - .end-displayer { - width: auto; - right: 8px; - } - .start-displayer { bottom: 4px; left: 16px; @@ -351,12 +366,12 @@ border-width: 1px; background: var(--background-color-accent, #6f42c1); } - .process-wrapper{ + .process-wrapper { .process-container { position: relative; display: flex; width: 100%; - + .process { height: 5px; border-radius: 4px; @@ -368,35 +383,3 @@ } } } - -.simulation-player-container.open { - - .start-displayer, - .end-displayer { - display: none; - } - - .timmer { - display: none; - } - .progresser-wrapper { - padding-top: 4px; - } - - .time-displayer { - height: 0; - opacity: 0; - pointer-events: none; - display: none; - } - - .processDisplayer { - padding: 0 8px; - background: transparent; - - .process-player { - width: 0; - display: none !important; - } - } -} diff --git a/app/src/styles/components/tools.scss b/app/src/styles/components/tools.scss index 29d37b4..902e0fb 100644 --- a/app/src/styles/components/tools.scss +++ b/app/src/styles/components/tools.scss @@ -14,7 +14,7 @@ width: fit-content; transition: width 0.2s; background: var(--background-color); - backdrop-filter: blur(8px); + backdrop-filter: blur(20px); z-index: 2; outline: 1px solid var(--border-color); outline-offset: -1px; @@ -31,6 +31,7 @@ .activeDropicon { @include flex-center; gap: 2px; + // stylelint-disable-next-line interpolate-size: allow-keywords; width: 0; opacity: 0; @@ -44,9 +45,11 @@ border-radius: #{$border-radius-medium}; &:hover { - background: color-mix(in srgb, - var(--highlight-accent-color) 60%, - transparent); + background: color-mix( + in srgb, + var(--highlight-accent-color) 60%, + transparent + ); } } @@ -70,9 +73,11 @@ position: relative; &:hover { - background: color-mix(in srgb, - var(--highlight-accent-color) 60%, - transparent); + background: color-mix( + in srgb, + var(--highlight-accent-color) 60%, + transparent + ); } .drop-down-container { @@ -179,11 +184,11 @@ font-weight: 500; background: var(--accent-color); color: var(--highlight-accent-color); - &::after{ + &::after { animation: pulse 1s ease-out infinite; } } - &::after{ + &::after { content: ""; position: absolute; height: 100%; @@ -195,14 +200,14 @@ } @keyframes pulse { - 0%{ + 0% { opacity: 0; - scale: .5; + scale: 0.5; } - 50%{ + 50% { opacity: 1; } - 100%{ + 100% { opacity: 0; scale: 2; } @@ -218,4 +223,4 @@ width: fit-content; opacity: 1; } -} \ No newline at end of file +} diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index f8c022f..01256a4 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -7,7 +7,7 @@ top: 32px; left: 8px; background: var(--background-color); - backdrop-filter: blur(15px); + backdrop-filter: blur(20px); border-radius: #{$border-radius-extra-large}; outline: 1px solid var(--border-color); box-shadow: #{$box-shadow-medium}; @@ -250,7 +250,7 @@ top: 32px; right: 8px; background: var(--background-color); - backdrop-filter: blur(15px); + backdrop-filter: blur(20px); border-radius: #{$border-radius-extra-large}; outline: 1px solid var(--border-color); box-shadow: #{$box-shadow-medium}; @@ -363,7 +363,7 @@ height: 34px; width: 34px; border-radius: #{$border-radius-circle}; - background: var(--background-color-secondary); + background: var(--background-color-solid-gradient); backdrop-filter: blur(12px); outline: 1px solid var(--border-color); outline-offset: -1px; @@ -416,7 +416,7 @@ outline: none; path { stroke: var(--text-button-color); - strokeWidth: 1.3; + stroke-width: 1.3; } } } @@ -682,7 +682,7 @@ path { stroke: var(--accent-color); - strokeWidth: 1.5px; + stroke-width: 1.5px; } &:hover { From 135633ef7a92bc6ddc5002adbd431ed2cb5f0068 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 3 May 2025 15:20:52 +0530 Subject: [PATCH 05/14] Refactor logging components and styles; remove unused CSS; enhance log icon functionality - Removed the random color generation function from ProductionCapacity component. - Updated ThroughputSummary component to remove unused imports. - Simplified LogList component by removing unnecessary icons and integrating GetLogIcon for log types. - Enhanced LoggerContext to support a new "success" log type and optimized logger methods with useMemo. - Adjusted SimulationPlayer to conditionally render analysis components. - Deleted index.css and removed its import from index.tsx. - Cleaned up builder module by removing unused imports and optimizing state management. - Removed savedTheme from Ground component. - Changed log message from info to warning in Project component. - Updated log color variables in SCSS files for better visibility and consistency. - Added new log icons for success, error, info, and warning in LogIcons component. - Created GetLogIcon utility to streamline log icon rendering based on log type. --- app/src/components/footer/Footer.tsx | 48 +++---- app/src/components/footer/getLogIcons.tsx | 19 +++ .../components/icons/ExportCommonIcons.tsx | 91 +----------- app/src/components/icons/LogIcons.tsx | 98 +++++++++++++ .../ui/analysis/ProductionCapacity.tsx | 10 -- .../ui/analysis/ThroughputSummary.tsx | 1 - app/src/components/ui/log/LogList.tsx | 38 ++--- app/src/components/ui/log/LoggerContext.tsx | 14 +- .../ui/simulation/simulationPlayer.tsx | 14 +- app/src/index.css | 13 -- app/src/index.tsx | 1 - app/src/modules/builder/builder.tsx | 29 ++-- app/src/modules/scene/environment/ground.tsx | 1 - app/src/pages/Project.tsx | 2 +- app/src/styles/abstracts/variables.scss | 18 ++- app/src/styles/base/base.scss | 44 +++--- app/src/styles/components/footer/footer.scss | 130 ++++++++++-------- app/src/styles/components/logs/logs.scss | 27 ++-- app/src/styles/components/tools.scss | 1 + app/src/styles/pages/userAuth.scss | 4 +- 20 files changed, 306 insertions(+), 297 deletions(-) create mode 100644 app/src/components/footer/getLogIcons.tsx create mode 100644 app/src/components/icons/LogIcons.tsx delete mode 100644 app/src/index.css diff --git a/app/src/components/footer/Footer.tsx b/app/src/components/footer/Footer.tsx index 1e22ccd..8da3ba8 100644 --- a/app/src/components/footer/Footer.tsx +++ b/app/src/components/footer/Footer.tsx @@ -1,25 +1,7 @@ import React from "react"; import { HelpIcon } from "../icons/DashboardIcon"; -import { - LogInfoIcon, - ErrorIcon, - WarningIcon, -} from "../icons/ExportCommonIcons"; // Adjust path as needed import { useLogger } from "../ui/log/LoggerContext"; - -const getLogIcon = (type: string) => { - switch (type) { - case "info": - return ; - case "error": - return ; - case "warning": - return ; - case "log": - default: - return ; - } -}; +import { GetLogIcon } from "./getLogIcons"; const Footer: React.FC = () => { const { logs, setIsLogListVisible } = useLogger(); @@ -43,18 +25,22 @@ const Footer: React.FC = () => {
-
setIsLogListVisible(true)} - > - {lastLog ? ( - <> - {getLogIcon(lastLog.type)} - {lastLog.message} - - ) : ( - "No logs yet." - )} +
+
+
+
V 0.01 diff --git a/app/src/components/footer/getLogIcons.tsx b/app/src/components/footer/getLogIcons.tsx new file mode 100644 index 0000000..7a26496 --- /dev/null +++ b/app/src/components/footer/getLogIcons.tsx @@ -0,0 +1,19 @@ +import { ErrorIcon, LogIcon, LogInfoIcon, SucessIcon, WarningIcon } from "../icons/LogIcons"; +import { LogType } from "../ui/log/LoggerContext"; + +export const GetLogIcon = (type: LogType): JSX.Element => { + switch (type) { + case "info": + return ; + case "log": + return ; + case "error": + return ; + case "warning": + return ; + case "success": + return ; + default: + return ; + } +}; diff --git a/app/src/components/icons/ExportCommonIcons.tsx b/app/src/components/icons/ExportCommonIcons.tsx index 4137498..0684a77 100644 --- a/app/src/components/icons/ExportCommonIcons.tsx +++ b/app/src/components/icons/ExportCommonIcons.tsx @@ -826,7 +826,7 @@ export const LogListIcon = () => { > { ); }; - -export const LogInfoIcon = () => { - return ( - - - - - - - ); -}; - -export const WarningIcon = () => { - return ( - - - - - - - ); -}; - -export const ErrorIcon = () => { - return ( - - - - ); -}; diff --git a/app/src/components/icons/LogIcons.tsx b/app/src/components/icons/LogIcons.tsx new file mode 100644 index 0000000..abee971 --- /dev/null +++ b/app/src/components/icons/LogIcons.tsx @@ -0,0 +1,98 @@ +export const LogInfoIcon = () => { + return ( + + + + + ); +}; + +export const WarningIcon = () => { + return ( + + + + + ); +}; + +export const ErrorIcon = () => { + return ( + + + + + ); +}; + +export const SucessIcon = () => { + return ( + + + + + ); +}; + +export const LogIcon = () => { + return ( + + + + + ); +}; diff --git a/app/src/components/ui/analysis/ProductionCapacity.tsx b/app/src/components/ui/analysis/ProductionCapacity.tsx index 08ddb05..803ec47 100644 --- a/app/src/components/ui/analysis/ProductionCapacity.tsx +++ b/app/src/components/ui/analysis/ProductionCapacity.tsx @@ -11,16 +11,6 @@ import { PowerIcon, ProductionCapacityIcon } from "../../icons/analysis"; ChartJS.register(LineElement, CategoryScale, LinearScale, PointElement); -// Helper function to generate random colors -const getRandomColor = () => { - const letters = "0123456789ABCDEF"; - let color = "#"; - for (let i = 0; i < 6; i++) { - color += letters[Math.floor(Math.random() * 16)]; - } - return color; -}; - const ThroughputSummary = () => { // Define all data internally within the component const timeRange = { diff --git a/app/src/components/ui/analysis/ThroughputSummary.tsx b/app/src/components/ui/analysis/ThroughputSummary.tsx index ed80fe5..3462aee 100644 --- a/app/src/components/ui/analysis/ThroughputSummary.tsx +++ b/app/src/components/ui/analysis/ThroughputSummary.tsx @@ -1,4 +1,3 @@ -import React, { useState } from "react"; import { ThroughputSummaryIcon } from "../../icons/analysis"; const ProductionCapacity = ({ diff --git a/app/src/components/ui/log/LogList.tsx b/app/src/components/ui/log/LogList.tsx index fad277c..ed86ba5 100644 --- a/app/src/components/ui/log/LogList.tsx +++ b/app/src/components/ui/log/LogList.tsx @@ -1,34 +1,15 @@ // LogList.tsx import React, { useState } from "react"; -import { - LogListIcon, - LogInfoIcon, - WarningIcon, - ErrorIcon, - CloseIcon, -} from "../../icons/ExportCommonIcons"; // Adjust path as needed +import { LogListIcon, CloseIcon } from "../../icons/ExportCommonIcons"; // Adjust path as needed import { useLogger } from "./LoggerContext"; +import { GetLogIcon } from "../../footer/getLogIcons"; const LogList: React.FC = () => { const { logs, clear, setIsLogListVisible } = useLogger(); const [selectedTab, setSelectedTab] = useState< - "all" | "info" | "warning" | "error" | "log" + "all" | "info" | "warning" | "error" | "log" | "success" >("all"); - const getLogIcon = (type: string) => { - switch (type) { - case "info": - return ; - case "error": - return ; - case "warning": - return ; - case "log": - default: - return ; - } - }; - const formatTimestamp = (date: Date) => new Date(date).toLocaleTimeString(); const filteredLogs = @@ -55,7 +36,11 @@ const LogList: React.FC = () => {
Log List
-
@@ -63,13 +48,14 @@ const LogList: React.FC = () => { {/* Tabs */}
{["all", "info", "warning", "error"].map((type) => ( -
setSelectedTab(type as any)} > {`${type.charAt(0).toUpperCase() + type.slice(1)} Logs`} -
+ ))}
@@ -77,7 +63,7 @@ const LogList: React.FC = () => {
{filteredLogs.map((log) => (
-
{getLogIcon(log.type)}
+
{GetLogIcon(log.type)}
{log.message}
diff --git a/app/src/components/ui/log/LoggerContext.tsx b/app/src/components/ui/log/LoggerContext.tsx index f323b93..71bd467 100644 --- a/app/src/components/ui/log/LoggerContext.tsx +++ b/app/src/components/ui/log/LoggerContext.tsx @@ -1,6 +1,6 @@ -import React, { createContext, useContext, useState, useCallback } from "react"; +import React, { createContext, useContext, useState, useCallback, useMemo } from "react"; -export type LogType = "log" | "info" | "warning" | "error"; +export type LogType = "log" | "info" | "warning" | "error" | "success"; export interface LogEntry { id: string; @@ -18,6 +18,7 @@ interface LoggerContextValue { info: (message: string) => void; warn: (message: string) => void; error: (message: string) => void; + success: (message: string) => void; clear: () => void; } @@ -47,7 +48,7 @@ export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({ [generateId] ); - const loggerMethods: LoggerContextValue = { + const loggerMethods: LoggerContextValue = useMemo(() => ({ logs, setLogs, isLogListVisible, @@ -56,10 +57,9 @@ export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({ info: (message: string) => addLog("info", message), warn: (message: string) => addLog("warning", message), error: (message: string) => addLog("error", message), - clear: () => { - setLogs([]); - }, - }; + success: (message: string) => addLog("success", message), + clear: () => setLogs([]), + }), [logs, setLogs, isLogListVisible, setIsLogListVisible, addLog]); return ( diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx index 9edb0c9..525dc0f 100644 --- a/app/src/components/ui/simulation/simulationPlayer.tsx +++ b/app/src/components/ui/simulation/simulationPlayer.tsx @@ -368,13 +368,15 @@ const SimulationPlayer: React.FC = () => { )}
-
-
- - + {subModule === "analysis" && ( +
+
+ + +
+
- -
+ )} ); }; diff --git a/app/src/index.css b/app/src/index.css deleted file mode 100644 index bd5bd6d..0000000 --- a/app/src/index.css +++ /dev/null @@ -1,13 +0,0 @@ -body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', - sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', - monospace; -} diff --git a/app/src/index.tsx b/app/src/index.tsx index f241ca6..ba329e8 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -1,6 +1,5 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import './index.css'; import App from './app'; import reportWebVitals from './reportWebVitals'; diff --git a/app/src/modules/builder/builder.tsx b/app/src/modules/builder/builder.tsx index eb0d341..c0a3267 100644 --- a/app/src/modules/builder/builder.tsx +++ b/app/src/modules/builder/builder.tsx @@ -22,7 +22,6 @@ import { useDeletePointOrLine, useMovePoint, useActiveLayer, - useSocketStore, useWallVisibility, useRoofVisibility, useShadows, @@ -48,15 +47,11 @@ import FloorGroupAilse from "./groups/floorGroupAisle"; import Draw from "./functions/draw"; import WallsAndWallItems from "./groups/wallsAndWallItems"; import Ground from "../scene/environment/ground"; -// import ZoneGroup from "../groups/zoneGroup1"; import { findEnvironment } from "../../services/factoryBuilder/environment/findEnvironment"; import Layer2DVisibility from "./geomentries/layers/layer2DVisibility"; -import DrieHtmlTemp from "../visualization/mqttTemp/drieHtmlTemp"; import ZoneGroup from "./groups/zoneGroup"; -import useModuleStore from "../../store/useModuleStore"; import MeasurementTool from "../scene/tools/measurementTool"; import NavMesh from "../simulation/vehicle/navMesh/navMesh"; -import ProductionCapacity from "../../components/ui/analysis/ThroughputSummary"; export default function Builder() { const state = useThree(); // Importing the state from the useThree hook, which contains the scene, camera, and other Three.js elements. @@ -113,21 +108,19 @@ export default function Builder() { const [selectedItemsIndex, setSelectedItemsIndex] = useState(null); // State for tracking the index of the selected item. - const { activeLayer, setActiveLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx. - const { toggleView, setToggleView } = useToggleView(); // State for toggling between 2D and 3D. + const { activeLayer } = useActiveLayer(); // State that changes based on which layer the user chooses in Layers.jsx. + const { toggleView } = useToggleView(); // State for toggling between 2D and 3D. const { toolMode, setToolMode } = useToolMode(); - const { movePoint, setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not. - const { deletePointOrLine, setDeletePointOrLine } = useDeletePointOrLine(); - const { socket } = useSocketStore(); - const { roofVisibility, setRoofVisibility } = useRoofVisibility(); - const { wallVisibility, setWallVisibility } = useWallVisibility(); - const { shadows, setShadows } = useShadows(); - const { renderDistance, setRenderDistance } = useRenderDistance(); - const { limitDistance, setLimitDistance } = useLimitDistance(); - const { updateScene, setUpdateScene } = useUpdateScene(); - const { walls, setWalls } = useWalls(); + const { setMovePoint } = useMovePoint(); // State that stores a boolean which represents whether the move mode is active or not. + const { setDeletePointOrLine } = useDeletePointOrLine(); + const { setRoofVisibility } = useRoofVisibility(); + const { setWallVisibility } = useWallVisibility(); + const { setShadows } = useShadows(); + const { setRenderDistance } = useRenderDistance(); + const { setLimitDistance } = useLimitDistance(); + const { setUpdateScene } = useUpdateScene(); + const { setWalls } = useWalls(); const { refTextupdate, setRefTextUpdate } = useRefTextUpdate(); - const { activeModule } = useModuleStore(); // const loader = new GLTFLoader(); // const dracoLoader = new DRACOLoader(); diff --git a/app/src/modules/scene/environment/ground.tsx b/app/src/modules/scene/environment/ground.tsx index 8d2fa22..ef3e690 100644 --- a/app/src/modules/scene/environment/ground.tsx +++ b/app/src/modules/scene/environment/ground.tsx @@ -3,7 +3,6 @@ import * as CONSTANTS from "../../../types/world/worldConstants"; const Ground = ({ grid, plane }: any) => { const { toggleView } = useToggleView(); - const savedTheme: string | null = localStorage.getItem("theme"); const { planeValue, gridValue } = useTileDistance(); return ( diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 17a6315..4fe26b3 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -58,7 +58,7 @@ const Project: React.FC = () => { setOrganization(Organization); setUserName(name); } - echo.info("Log in success full"); + echo.warn("Log in success full"); } else { navigate("/"); } diff --git a/app/src/styles/abstracts/variables.scss b/app/src/styles/abstracts/variables.scss index 29976dc..3545151 100644 --- a/app/src/styles/abstracts/variables.scss +++ b/app/src/styles/abstracts/variables.scss @@ -115,17 +115,23 @@ $color5: #c7a8ff; // log indication colors // ------------ text ------------- $log-default-text-color: #6f42c1; -$log-info-text-color: #488ef6; +$log-info-text-color: #1773fd; $log-warn-text-color: #f3a50c; -$log-error-text-color: #f65648; -$log-success-text-color: #43c06d; +$log-error-text-color: #fc230f; +$log-success-text-color: #23a84f; +// ----------- dark --------------- +$log-default-text-color-dark: #b18ef1; +$log-info-text-color-dark: #7eb0fa; +$log-warn-text-color-dark: #ffaa00; +$log-error-text-color-dark: #ff887d; +$log-success-text-color-dark: #43ff81; // ------------ background ------------- $log-default-backgroung-color: #6e42c133; -$log-info-background-color: #488ef633; +$log-info-background-color: #1773fd5d; $log-warn-background-color: #f3a50c33; -$log-error-background-color: #f6564833; -$log-success-background-color: #43c06d33; +$log-error-background-color: #fc230f33; +$log-success-background-color: #0ef75b33; // old variables $accent-color: #6f42c1; diff --git a/app/src/styles/base/base.scss b/app/src/styles/base/base.scss index f4a260f..8843bfe 100644 --- a/app/src/styles/base/base.scss +++ b/app/src/styles/base/base.scss @@ -35,6 +35,18 @@ --icon-default-color: #{$icon-default-color}; --icon-default-color-active: #{$icon-default-color-active}; + // log colors + --default-text-color: #{$log-default-text-color}; + --log-info-text-color: #{$log-info-text-color}; + --log-warn-text-color: #{$log-warn-text-color}; + --log-error-text-color: #{$log-error-text-color}; + --log-success-text-color: #{$log-success-text-color}; + --log-default-background-color: #{$log-default-backgroung-color}; + --log-info-background-color: #{$log-info-background-color}; + --log-warn-background-color: #{$log-warn-background-color}; + --log-error-background-color: #{$log-error-background-color}; + --log-success-background-color: #{$log-success-background-color}; + // old colors --accent-color: #{$accent-color}; --accent-gradient-color: #{$acent-gradient}; @@ -85,6 +97,18 @@ --icon-default-color: #{$icon-default-color-dark}; --icon-default-color-active: #{$icon-default-color-active-dark}; + // log colors + --default-text-color: #{$log-default-text-color-dark}; + --log-info-text-color: #{$log-info-text-color-dark}; + --log-warn-text-color: #{$log-warn-text-color-dark}; + --log-error-text-color: #{$log-error-text-color-dark}; + --log-success-text-color: #{$log-success-text-color-dark}; + --log-default-background-color: #{$log-default-backgroung-color}; + --log-info-background-color: #{$log-info-background-color}; + --log-warn-background-color: #{$log-warn-background-color}; + --log-error-background-color: #{$log-error-background-color}; + --log-success-background-color: #{$log-success-background-color}; + // old colors --accent-color: #{$accent-color-dark}; --accent-gradient-color: #{$acent-gradient-dark}; @@ -115,7 +139,6 @@ } body { - background: var(--background-color); --font-size-tiny: #{$tiny}; --font-size-small: #{$small}; --font-size-regular: #{$regular}; @@ -133,23 +156,6 @@ body { --color3: #{$color3}; --color4: #{$color4}; --color5: #{$color5}; - - - - - --default-text-color: #{$log-default-text-color}; - --log-info-text-color: #{$log-info-text-color}; - --log-warn-text-color: #{$log-warn-text-color}; - --log-error-text-color: #{$log-error-text-color}; - --log-success-text-color: #{$log-success-text-color}; - - // ------------ background ------------- - --log-default-background-color: #{$log-default-backgroung-color}; - --log-info-background-color: #{$log-info-background-color}; - --log-warn-background-color: #{$log-warn-background-color}; - --log-error-background-color: #{$log-error-background-color}; - --log-success-background-color: #{$log-success-background-color}; - } ::-webkit-scrollbar { @@ -173,4 +179,4 @@ body { ::-webkit-scrollbar-corner { background: transparent; -} \ No newline at end of file +} diff --git a/app/src/styles/components/footer/footer.scss b/app/src/styles/components/footer/footer.scss index ba869a4..a457557 100644 --- a/app/src/styles/components/footer/footer.scss +++ b/app/src/styles/components/footer/footer.scss @@ -23,6 +23,7 @@ padding: 3px 6px; border-radius: 12px; color: var(--text-color); + backdrop-filter: blur(14px); .selector { color: var(--text-color); @@ -33,70 +34,51 @@ .logs-wrapper { display: flex; gap: 6px; + position: relative; + // dummy + .bg-dummy{ + background: var(--background-color-solid); + position: absolute; + z-index: -1; + } + .bg-dummy.left-top{ + top: 1px; + left: 4px; + width: 60%; + height: 16px; + border-radius: 20px; + } + .bg-dummy.right-bottom{ + right: 68px; + bottom: 0; + width: 20%; + height: 100%; + border-radius: 50%; + } + + .log-container { + background: var(--background-color); + backdrop-filter: blur(20px); + border-radius: 12px; + @include flex-center; + overflow: hidden; + } .logs-detail, .version { + @include flex-center; border-radius: 12px; - background: var(--background-color); padding: 3px 6px; + height: 100%; color: var(--text-color); - display: flex; - align-items: center; gap: 6px; } - .log { - background-color: var(--log-default-background-color); - - .log-message { - color: var(--default-text-color); - - } - } - - .info { - background-color: var(--log-info-background-color); - - .log-message { - color: var(--log-info-text-color); - - } - } - - .error { - background-color: var(--log-error-background-color); - - .log-message { - color: var(--log-error-text-color); - - } - } - - .warning { - background-color: var(--log-warn-background-color); - - .log-message { - color: var(--log-warn-text-color); - - } - } - - .success { - background-color: var(--log-success-background-color); - - .log-message { - color: var(--log-success-text-color); - - } - } - - - - .logs-detail { padding: 2px 12px; cursor: pointer; - + outline: 0 solid var(--border-color); + outline-offset: -1px; .log-icon { @include flex-center; } @@ -110,13 +92,51 @@ } .version { + background: var(--background-color); font-size: var(--font-size-tiny); - display: flex; - gap: 6px; .icon { @include flex-center; } } + + .log { + background: var(--log-default-background-color); + outline-color: var(--default-text-color); + .log-message { + color: var(--default-text-color); + } + } + + .info { + background: var(--log-info-background-color); + outline-color: var(--log-info-text-color); + .log-message { + color: var(--log-info-text-color); + } + } + + .error { + background: var(--log-error-background-color); + outline-color: var(--log-error-text-color); + .log-message { + color: var(--log-error-text-color); + } + } + + .warning { + background: var(--log-warn-background-color); + outline-color: var(--log-warn-text-color); + .log-message { + color: var(--log-warn-text-color); + } + } + + .success { + background: var(--log-success-background-color); + .log-message { + color: var(--log-success-text-color); + } + } } -} \ No newline at end of file +} diff --git a/app/src/styles/components/logs/logs.scss b/app/src/styles/components/logs/logs.scss index f07708b..9f85dd0 100644 --- a/app/src/styles/components/logs/logs.scss +++ b/app/src/styles/components/logs/logs.scss @@ -5,14 +5,11 @@ width: 100vw; height: 100vh; background: var(--background-color-secondary); + @include flex-center; .log-list-wrapper { - height: 50%; - min-width: 50%; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); + height: 60%; + min-width: 55%; z-index: 5; background: var(--background-color); padding: 14px 12px; @@ -31,6 +28,10 @@ display: flex; align-items: center; gap: 6px; + .icon{ + @include flex-center; + scale: .8; + } } .close { @@ -38,9 +39,13 @@ height: 28px; width: 28px; cursor: pointer; + border-radius: #{$border-radius-medium}; svg { scale: 1.6; } + &:hover{ + background: var(--background-color); + } } } @@ -60,25 +65,26 @@ } .log-entry-wrapper { - height: 100%; + height: calc(100% - 80px); display: flex; flex-direction: column; gap: 4px; background: var(--background-color); - padding: 18px 10px; + padding: 10px; border-radius: 16px; outline: 1px solid var(--border-color); outline-offset: -1px; + overflow: auto; .log-entry { padding: 4px; border-radius: 4px; font-size: var(--font-size-small); display: flex; - align-items: center; - gap: 6px; .log-icon { + height: 24px; + width: 24px; @include flex-center; } .log-entry-message-container { @@ -90,6 +96,7 @@ font-weight: 300; opacity: 0.8; text-wrap: nowrap; + height: 100%; } .log-entry-message{ width: 100%; diff --git a/app/src/styles/components/tools.scss b/app/src/styles/components/tools.scss index 902e0fb..03813a4 100644 --- a/app/src/styles/components/tools.scss +++ b/app/src/styles/components/tools.scss @@ -36,6 +36,7 @@ width: 0; opacity: 0; animation: expandWidth 0.2s ease-in-out forwards; + will-change: width; .tool-button { @include flex-center; diff --git a/app/src/styles/pages/userAuth.scss b/app/src/styles/pages/userAuth.scss index c27b66f..cb45c13 100644 --- a/app/src/styles/pages/userAuth.scss +++ b/app/src/styles/pages/userAuth.scss @@ -89,7 +89,7 @@ border-radius: #{$border-radius-extra-large}; background: var(--background-color); font-size: 14px; - color: var(--input-text-color); + color: var(--text-button-color); &:focus { border-color: var(--accent-color); @@ -121,7 +121,7 @@ width: 100%; padding: 10px; background: var(--background-color-button); - color: var(--background-color); + color: var(--text-button-color); font-size: 14px; border: none; outline: none; From d5a5b0849c8e223755ea41ff1f3558fb4565b0b1 Mon Sep 17 00:00:00 2001 From: Nalvazhuthi Date: Sat, 3 May 2025 15:21:03 +0530 Subject: [PATCH 06/14] Refactor robotic arm simulation components - Updated MachineInstances to utilize the machine store for rendering multiple MachineInstance components. - Enhanced Machine component to include machine state management and logging. - Refactored RoboticArmAnimator for improved path handling and animation logic. - Modified RoboticArmInstance to streamline state management and integrate with the updated animator. - Improved IKInstance to support armBot state and interaction. - Adjusted RoboticArm to dynamically load armBots based on selected products and events. - Cleaned up unused code and improved overall readability and maintainability. --- .../components/icons/ExportCommonIcons.tsx | 6 ++-- app/src/components/icons/analysis.tsx | 32 +++++++++---------- .../visualization/RealTimeVisulization.tsx | 2 +- .../components/simulation/analysis.scss | 15 ++++++--- app/src/styles/layout/sidebar.scss | 4 +-- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/app/src/components/icons/ExportCommonIcons.tsx b/app/src/components/icons/ExportCommonIcons.tsx index 4137498..5e06fed 100644 --- a/app/src/components/icons/ExportCommonIcons.tsx +++ b/app/src/components/icons/ExportCommonIcons.tsx @@ -844,7 +844,7 @@ export const LogTickIcon = () => { fill="none" xmlns="http://www.w3.org/2000/svg" > - + { xmlns="http://www.w3.org/2000/svg" > diff --git a/app/src/components/icons/analysis.tsx b/app/src/components/icons/analysis.tsx index c387003..76c7f42 100644 --- a/app/src/components/icons/analysis.tsx +++ b/app/src/components/icons/analysis.tsx @@ -12,7 +12,7 @@ export function ThroughputSummaryIcon() { fillRule="evenodd" clipRule="evenodd" d="M13.9063 12.9046L14.2265 13.86L14.4378 14.5073C14.9906 16.2239 15.2594 17.2662 15.2594 17.7299C15.2594 18.8219 14.3742 19.7072 13.2822 19.7072C12.1902 19.7072 11.305 18.8219 11.305 17.7299C11.305 17.2106 11.6422 15.9654 12.3379 13.86L12.658 12.9046C12.8604 12.3082 13.704 12.3082 13.9063 12.9046ZM13.2822 7.84375C16.9222 7.84375 19.873 10.7945 19.873 14.4345C19.873 15.7565 19.4823 17.0219 18.7621 18.0974C18.5596 18.3999 18.1502 18.4809 17.8478 18.2784C17.5453 18.0758 17.4643 17.6665 17.6668 17.364C18.2428 16.5038 18.5548 15.4933 18.5548 14.4345C18.5548 11.5225 16.1942 9.16191 13.2822 9.16191C10.3702 9.16191 8.00956 11.5225 8.00956 14.4345C8.00956 15.4933 8.32153 16.5038 8.89752 17.364C9.10005 17.6665 9.01904 18.0758 8.71659 18.2784C8.41414 18.4809 8.00477 18.3999 7.80224 18.0974C7.08206 17.0219 6.69141 15.7565 6.69141 14.4345C6.69141 10.7945 9.6422 7.84375 13.2822 7.84375ZM13.2822 15.2247L13.0657 15.9238L12.9161 16.4319C12.7219 17.111 12.6231 17.5509 12.6231 17.7299C12.6231 18.0939 12.9182 18.389 13.2822 18.389C13.6462 18.389 13.9413 18.0939 13.9413 17.7299C13.9413 17.511 13.7936 16.9022 13.5044 15.9428L13.2822 15.2247Z" - fill="var(--text-color)" + fill="white" /> ); @@ -28,12 +28,12 @@ export function ProductionCapacityIcon() { xmlns="http://www.w3.org/2000/svg" > - + @@ -62,12 +62,12 @@ export function ROISummaryIcon() { @@ -83,7 +83,7 @@ export function PowerIcon() { fill="none" xmlns="http://www.w3.org/2000/svg" > - + ); @@ -147,8 +147,8 @@ export function SonarCrownIcon() { ); @@ -166,9 +166,9 @@ export function CostBreakDownIcon() { ); diff --git a/app/src/modules/visualization/RealTimeVisulization.tsx b/app/src/modules/visualization/RealTimeVisulization.tsx index 2e1e536..a8f44b4 100644 --- a/app/src/modules/visualization/RealTimeVisulization.tsx +++ b/app/src/modules/visualization/RealTimeVisulization.tsx @@ -249,7 +249,7 @@ const RealTimeVisulization: React.FC = () => { useEffect(() => { const handleClickOutside = (event: MouseEvent) => { const editWidgetOptions = document.querySelector( - ".context-menu-options-wrapper" + ".editWidgetOptions-wrapper" ); if ( editWidgetOptions && diff --git a/app/src/styles/components/simulation/analysis.scss b/app/src/styles/components/simulation/analysis.scss index f33fb46..44d4ba0 100644 --- a/app/src/styles/components/simulation/analysis.scss +++ b/app/src/styles/components/simulation/analysis.scss @@ -51,7 +51,8 @@ .sub-header { font-size: var(--font-size-tiny); - color: var(--text-button-color); + color: var(--text-color); + opacity: 0.8; } } @@ -233,6 +234,7 @@ width: 100%; gap: 6px; padding-top: 3px; + .shift-wrapper { display: flex; align-items: center; @@ -276,6 +278,11 @@ } } + .roiSummary-container { + max-height: 60vh; + overflow-y: auto; + } + .roiSummary-wrapper { max-width: 470px; background-color: var(--background-color); @@ -376,8 +383,8 @@ gap: 6px; .metric-item { - border-radius: #{$border-radius-large}; - background-color: var(--background-color); + border-radius: #{$border-radius-small}; + background: var(--background-color); border: 1px solid var(--border-color); } } @@ -385,7 +392,7 @@ } .cost-breakdown { - background-color: var(--background-color); + background: var(--background-color); border: 1px solid var(--border-color); border-radius: #{$border-radius-extra-large}; padding: 16px; diff --git a/app/src/styles/layout/sidebar.scss b/app/src/styles/layout/sidebar.scss index 01256a4..cffee1e 100644 --- a/app/src/styles/layout/sidebar.scss +++ b/app/src/styles/layout/sidebar.scss @@ -416,7 +416,7 @@ outline: none; path { stroke: var(--text-button-color); - stroke-width: 1.3; + strokeWidth: 1.3; } } } @@ -682,7 +682,7 @@ path { stroke: var(--accent-color); - stroke-width: 1.5px; + strokeWidth: 1.5px; } &:hover { From 06fa09bb4288cedb4c2714f403940ca85461e07f Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 3 May 2025 15:47:38 +0530 Subject: [PATCH 07/14] feat: Update log display messages for clarity; enhance log navigation styles and layout --- app/src/components/footer/Footer.tsx | 2 +- app/src/components/ui/log/LogList.tsx | 50 ++++++++++++++---------- app/src/styles/components/logs/logs.scss | 47 +++++++++++++++------- 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/app/src/components/footer/Footer.tsx b/app/src/components/footer/Footer.tsx index 8da3ba8..697c182 100644 --- a/app/src/components/footer/Footer.tsx +++ b/app/src/components/footer/Footer.tsx @@ -38,7 +38,7 @@ const Footer: React.FC = () => { {lastLog.message} ) : ( - "No logs yet." + "There are no logs to display at the moment." )}
diff --git a/app/src/components/ui/log/LogList.tsx b/app/src/components/ui/log/LogList.tsx index ed86ba5..2ec50f8 100644 --- a/app/src/components/ui/log/LogList.tsx +++ b/app/src/components/ui/log/LogList.tsx @@ -23,6 +23,7 @@ const LogList: React.FC = () => { className="log-list-container" onClick={() => setIsLogListVisible(false)} > + {/* eslint-disable-next-line */}
{ @@ -46,32 +47,41 @@ const LogList: React.FC = () => {
{/* Tabs */} -
- {["all", "info", "warning", "error"].map((type) => ( - - ))} +
+
+ {["all", "info", "warning", "error"].map((type) => ( + + ))} +
+
{/* Log Entries */}
- {filteredLogs.map((log) => ( -
-
{GetLogIcon(log.type)}
-
-
{log.message}
-
- {formatTimestamp(log.timestamp)} + {filteredLogs.length > 0 ? ( + filteredLogs.map((log) => ( +
+
{GetLogIcon(log.type)}
+
+
{log.message}
+
+ {formatTimestamp(log.timestamp)} +
-
- ))} + )) + ) : ( +
There are no logs to display at the moment.
+ )}
diff --git a/app/src/styles/components/logs/logs.scss b/app/src/styles/components/logs/logs.scss index 9f85dd0..b7c1363 100644 --- a/app/src/styles/components/logs/logs.scss +++ b/app/src/styles/components/logs/logs.scss @@ -28,9 +28,9 @@ display: flex; align-items: center; gap: 6px; - .icon{ + .icon { @include flex-center; - scale: .8; + scale: 0.8; } } @@ -43,24 +43,38 @@ svg { scale: 1.6; } - &:hover{ + &:hover { background: var(--background-color); } } } + .log-nav-container { + @include flex-space-between; + align-items: flex-end; + .log-nav-wrapper { + display: flex; + gap: 6px; - .log-nav-wrapper { - display: flex; - gap: 6px; + .log-nav { + padding: 8px 16px; + border-radius: 19px; + } - .log-nav { - padding: 8px 16px; - border-radius: 19px; + .log-nav.active { + background-color: var(--background-color-accent); + color: var(--text-button-color); + } } - - .log-nav.active { - background-color: var(--background-color-accent); - color: var(--text-button-color); + .clear-button{ + margin: 0 6px; + padding: 4px 12px; + color: var(--text-disabled); + border-radius: #{$border-radius-large}; + &:hover{ + font-weight: 300; + color: var(--text-color); + background: var(--background-color-solid-gradient); + } } } @@ -98,7 +112,7 @@ text-wrap: nowrap; height: 100%; } - .log-entry-message{ + .log-entry-message { width: 100%; } } @@ -108,5 +122,10 @@ } } } + .no-log{ + padding: 20px; + text-align: center; + color: var(--text-color); + } } } From f8abd711160700885845a6b6aea040769134d4fd Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 3 May 2025 16:52:48 +0530 Subject: [PATCH 08/14] feat: Replace random ID generation with UUID for log entries; improve log entry consistency --- app/src/components/ui/log/LoggerContext.tsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/src/components/ui/log/LoggerContext.tsx b/app/src/components/ui/log/LoggerContext.tsx index 71bd467..f011609 100644 --- a/app/src/components/ui/log/LoggerContext.tsx +++ b/app/src/components/ui/log/LoggerContext.tsx @@ -1,4 +1,5 @@ import React, { createContext, useContext, useState, useCallback, useMemo } from "react"; +import { MathUtils } from "three"; export type LogType = "log" | "info" | "warning" | "error" | "success"; @@ -30,22 +31,17 @@ export const LoggerProvider: React.FC<{ children: React.ReactNode }> = ({ const [logs, setLogs] = useState([]); const [isLogListVisible, setIsLogListVisible] = useState(false); - const generateId = useCallback( - () => Math.random().toString(36).substring(2, 9), - [] - ); - const addLog = useCallback( (type: LogType, message: string) => { const newLog: LogEntry = { - id: generateId(), + id: MathUtils.generateUUID(), type, message, timestamp: new Date(), }; setLogs((prevLogs) => [...prevLogs, newLog]); }, - [generateId] + [] ); const loggerMethods: LoggerContextValue = useMemo(() => ({ From 2711702efae888419b944287e6141990fdc69ee2 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 3 May 2025 17:21:37 +0530 Subject: [PATCH 09/14] feat: Update icon components for consistency; refactor SVG attributes and styles --- app/src/components/icons/analysis.tsx | 36 +- .../ui/analysis/SemiCircleProgress.tsx | 26 +- .../events/points/creator/pointsCreator.tsx | 484 +++++++++--------- .../components/simulation/analysis.scss | 38 +- 4 files changed, 306 insertions(+), 278 deletions(-) diff --git a/app/src/components/icons/analysis.tsx b/app/src/components/icons/analysis.tsx index c387003..7c36f20 100644 --- a/app/src/components/icons/analysis.tsx +++ b/app/src/components/icons/analysis.tsx @@ -28,10 +28,10 @@ export function ProductionCapacityIcon() { xmlns="http://www.w3.org/2000/svg" > - + @@ -59,15 +59,11 @@ export function ROISummaryIcon() { fill="none" xmlns="http://www.w3.org/2000/svg" > - + + - @@ -83,7 +79,7 @@ export function PowerIcon() { fill="none" xmlns="http://www.w3.org/2000/svg" > - + ); @@ -147,8 +143,8 @@ export function SonarCrownIcon() { ); @@ -166,9 +162,9 @@ export function CostBreakDownIcon() { ); diff --git a/app/src/components/ui/analysis/SemiCircleProgress.tsx b/app/src/components/ui/analysis/SemiCircleProgress.tsx index b2a3622..78422d3 100644 --- a/app/src/components/ui/analysis/SemiCircleProgress.tsx +++ b/app/src/components/ui/analysis/SemiCircleProgress.tsx @@ -1,9 +1,7 @@ -import React from "react"; - -const SemiCircleProgress = ({ progress = 10 }) => { +const SemiCircleProgress = ({ progress = 60, years = 4.02 }) => { const clampedProgress = Math.min(Math.max(progress, 0), 100); const radius = 80; - const strokeWidth = 20; + const strokeWidth = 26; const circumference = Math.PI * radius; const strokeDashoffset = circumference - (clampedProgress / 100) * circumference; @@ -15,22 +13,36 @@ const SemiCircleProgress = ({ progress = 10 }) => { {/* Progress track */} + + + + + + +
-
{clampedProgress}%
+
{years}
Years
diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx index 94128ce..1252446 100644 --- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx +++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx @@ -1,250 +1,272 @@ import React, { useEffect, useRef, useState } from "react"; import * as THREE from "three"; import { useEventsStore } from "../../../../../store/simulation/useEventsStore"; -import useModuleStore, { useSubModuleStore } from "../../../../../store/useModuleStore"; +import useModuleStore, { + useSubModuleStore, +} from "../../../../../store/useModuleStore"; import { TransformControls } from "@react-three/drei"; import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys"; import { - useSelectedEventSphere, - useSelectedEventData, + useSelectedEventSphere, + useSelectedEventData, } from "../../../../../store/simulation/useSimulationStore"; import { useThree } from "@react-three/fiber"; function PointsCreator() { - const { gl, raycaster, scene, pointer, camera } = useThree(); - const { subModule } = useSubModuleStore(); - const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore(); - const { activeModule } = useModuleStore(); - const transformRef = useRef(null); - const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null); - const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); - const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere(); - const { selectedEventData, setSelectedEventData, clearSelectedEventData } = useSelectedEventData(); + const { gl, raycaster, scene, pointer, camera } = useThree(); + const { subModule } = useSubModuleStore(); + const { events, updatePoint, getPointByUuid, getEventByModelUuid } = + useEventsStore(); + const { activeModule } = useModuleStore(); + const transformRef = useRef(null); + const [transformMode, setTransformMode] = useState< + "translate" | "rotate" | null + >(null); + const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); + const { + selectedEventSphere, + setSelectedEventSphere, + clearSelectedEventSphere, + } = useSelectedEventSphere(); + const { setSelectedEventData, clearSelectedEventData } = + useSelectedEventData(); - useEffect(() => { - if (selectedEventSphere) { - const eventData = getEventByModelUuid( - selectedEventSphere.userData.modelUuid - ); + useEffect(() => { + if (selectedEventSphere) { + const eventData = getEventByModelUuid( + selectedEventSphere.userData.modelUuid + ); - if (eventData) { - setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid); - } else { - clearSelectedEventData(); - } - } else { - clearSelectedEventData(); - } - }, [selectedEventSphere]); + if (eventData) { + setSelectedEventData(eventData, selectedEventSphere.userData.pointUuid); + } else { + clearSelectedEventData(); + } + } else { + clearSelectedEventData(); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedEventSphere]); - useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { - const keyCombination = detectModifierKeys(e); - if (!selectedEventSphere) return; - if (keyCombination === "G") { - setTransformMode((prev) => (prev === "translate" ? null : "translate")); - } - if (keyCombination === "R") { - setTransformMode((prev) => (prev === "rotate" ? null : "rotate")); - } - }; - - window.addEventListener("keydown", handleKeyDown); - return () => window.removeEventListener("keydown", handleKeyDown); - }, [selectedEventSphere]); - - const updatePointToState = (selectedEventSphere: THREE.Mesh) => { - let point = JSON.parse( - JSON.stringify(getPointByUuid(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid)) - ); - if (point) { - point.position = [selectedEventSphere.position.x, selectedEventSphere.position.y, selectedEventSphere.position.z,]; - updatePoint(selectedEventSphere.userData.modelUuid, selectedEventSphere.userData.pointUuid, point); - } + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + const keyCombination = detectModifierKeys(e); + if (!selectedEventSphere) return; + if (keyCombination === "G") { + setTransformMode((prev) => (prev === "translate" ? null : "translate")); + } + if (keyCombination === "R") { + setTransformMode((prev) => (prev === "rotate" ? null : "rotate")); + } }; - useEffect(() => { - const canvasElement = gl.domElement; + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [selectedEventSphere]); - let drag = false; - let isMouseDown = false; - - const onMouseDown = () => { - isMouseDown = true; - drag = false; - }; - - const onMouseUp = () => { - if (selectedEventSphere && !drag) { - raycaster.setFromCamera(pointer, camera); - const intersects = raycaster - .intersectObjects(scene.children, true) - .filter( - (intersect) => - intersect.object.name === ('Event-Sphere') - ); - if (intersects.length === 0) { - clearSelectedEventSphere(); - setTransformMode(null); - } - } - } - - const onMouseMove = () => { - if (isMouseDown) { - drag = true; - } - }; - - if (subModule === 'mechanics') { - canvasElement.addEventListener("mousedown", onMouseDown); - canvasElement.addEventListener("mouseup", onMouseUp); - canvasElement.addEventListener("mousemove", onMouseMove); - } - - return () => { - canvasElement.removeEventListener("mousedown", onMouseDown); - canvasElement.removeEventListener("mouseup", onMouseUp); - canvasElement.removeEventListener("mousemove", onMouseMove); - }; - - }, [gl, subModule, selectedEventSphere]); - - return ( - <> - {activeModule === "simulation" && ( - <> - - {events.map((event, i) => { - if (event.type === "transfer") { - return ( - - {event.points.map((point) => ( - (sphereRefs.current[point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[point.uuid] - ); - }} - position={new THREE.Vector3(...point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: point.uuid, - }} - > - - - - ))} - - ); - } else if (event.type === "vehicle") { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[event.point.uuid] - ); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: event.point.uuid, - }} - > - - - - - ); - } else if (event.type === "roboticArm") { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[event.point.uuid] - ); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: event.point.uuid, - }} - > - - - - - ); - } else if (event.type === "machine") { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[event.point.uuid] - ); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: event.point.uuid, - }} - > - - - - - ); - } else { - return null; - } - })} - - {selectedEventSphere && transformMode && ( - { - updatePointToState(selectedEventSphere); - }} - /> - )} - - )} - + const updatePointToState = (selectedEventSphere: THREE.Mesh) => { + let point = JSON.parse( + JSON.stringify( + getPointByUuid( + selectedEventSphere.userData.modelUuid, + selectedEventSphere.userData.pointUuid + ) + ) ); + if (point) { + point.position = [ + selectedEventSphere.position.x, + selectedEventSphere.position.y, + selectedEventSphere.position.z, + ]; + updatePoint( + selectedEventSphere.userData.modelUuid, + selectedEventSphere.userData.pointUuid, + point + ); + } + }; + + useEffect(() => { + const canvasElement = gl.domElement; + + let drag = false; + let isMouseDown = false; + + const onMouseDown = () => { + isMouseDown = true; + drag = false; + }; + + const onMouseUp = () => { + if (selectedEventSphere && !drag) { + raycaster.setFromCamera(pointer, camera); + const intersects = raycaster + .intersectObjects(scene.children, true) + .filter((intersect) => intersect.object.name === "Event-Sphere"); + if (intersects.length === 0) { + clearSelectedEventSphere(); + setTransformMode(null); + } + } + }; + + const onMouseMove = () => { + if (isMouseDown) { + drag = true; + } + }; + + if (subModule === "mechanics") { + canvasElement.addEventListener("mousedown", onMouseDown); + canvasElement.addEventListener("mouseup", onMouseUp); + canvasElement.addEventListener("mousemove", onMouseMove); + } + + return () => { + canvasElement.removeEventListener("mousedown", onMouseDown); + canvasElement.removeEventListener("mouseup", onMouseUp); + canvasElement.removeEventListener("mousemove", onMouseMove); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [gl, subModule, selectedEventSphere]); + + return ( + <> + {activeModule === "simulation" && ( + <> + + {events.map((event, index) => { + if (event.type === "transfer") { + return ( + + {event.points.map((point, i) => ( + (sphereRefs.current[point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[point.uuid] + ); + }} + position={new THREE.Vector3(...point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: point.uuid, + }} + > + + + + ))} + + ); + } else if (event.type === "vehicle") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else if (event.type === "roboticArm") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else if (event.type === "machine") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else { + return null; + } + })} + + {selectedEventSphere && transformMode && ( + { + updatePointToState(selectedEventSphere); + }} + /> + )} + + )} + + ); } -export default PointsCreator; \ No newline at end of file +export default PointsCreator; diff --git a/app/src/styles/components/simulation/analysis.scss b/app/src/styles/components/simulation/analysis.scss index f33fb46..7cf906e 100644 --- a/app/src/styles/components/simulation/analysis.scss +++ b/app/src/styles/components/simulation/analysis.scss @@ -11,19 +11,12 @@ width: 100%; height: 100vh; pointer-events: none; - padding: 10px; z-index: 2; - .analysis-wrapper { - display: flex; - flex-direction: column; - gap: 12px; - } - .analysis-card { min-width: 333px; border-radius: 20px; - padding: 8px; + margin: 8px; pointer-events: all; .analysis-card-wrapper { @@ -50,6 +43,7 @@ } .sub-header { + font-weight: 300; font-size: var(--font-size-tiny); color: var(--text-button-color); } @@ -170,12 +164,13 @@ .footer-card { width: 100%; - background: var(--background-color-gray); + background: var(--background-color); border-radius: 6px; padding: 8px; display: flex; flex-direction: column; gap: 12px; + outline: 1px solid var(--border-color); &:first-child { width: 85%; @@ -326,10 +321,11 @@ flex-direction: column; gap: 3px; align-items: center; - + font-weight: 300; .key { - font-size: var(--font-size-xlarge); - color: #28B9F3; + font-weight: 500; + font-size: var(--font-size-large); + color: #28b9f3; } } } @@ -376,8 +372,9 @@ gap: 6px; .metric-item { + padding: 8px; border-radius: #{$border-radius-large}; - background-color: var(--background-color); + background: var(--background-color); border: 1px solid var(--border-color); } } @@ -385,10 +382,12 @@ } .cost-breakdown { - background-color: var(--background-color); + background: var(--background-color); border: 1px solid var(--border-color); - border-radius: #{$border-radius-extra-large}; + border-radius: #{$border-radius-large}; + max-height: 20vh; padding: 16px; + overflow: auto; .breakdown-header { display: flex; @@ -448,7 +447,7 @@ } .tips-section { - background-color: var(--background-color); + background: var(--background-color); border-radius: #{$border-radius-large}; outline: 1px solid var(--border-color); display: flex; @@ -510,18 +509,17 @@ .label-wrapper { width: 100%; position: absolute; - bottom: 0px; + bottom: 2px; display: flex; flex-direction: column; justify-content: center; align-items: center; .label { - font-size: var(--font-size-xlarge); + font-size: var(--font-size-xxlarge); } } } - } .breakdown-table-wrapper { @@ -547,4 +545,4 @@ } } -// Breakdown Table Open/Close Logic \ No newline at end of file +// Breakdown Table Open/Close Logic From 2ad1006de4c782bb93618ccdbbf3930938a6e95c Mon Sep 17 00:00:00 2001 From: Nalvazhuthi Date: Sat, 3 May 2025 17:28:46 +0530 Subject: [PATCH 10/14] updating UI --- app/src/components/icons/analysis.tsx | 123 +++- .../ui/analysis/ProductionCapacity.tsx | 5 +- app/src/components/ui/analysis/ROISummary.tsx | 11 +- .../ui/analysis/ThroughputSummary.tsx | 9 +- app/src/components/ui/log/LoggerContext.tsx | 35 +- .../ui/simulation/simulationPlayer.tsx | 4 +- .../builder/groups/floorItemsGroup.tsx | 691 +++++++++++------- .../components/simulation/analysis.scss | 39 +- 8 files changed, 587 insertions(+), 330 deletions(-) diff --git a/app/src/components/icons/analysis.tsx b/app/src/components/icons/analysis.tsx index 76c7f42..444895d 100644 --- a/app/src/components/icons/analysis.tsx +++ b/app/src/components/icons/analysis.tsx @@ -1,19 +1,58 @@ export function ThroughputSummaryIcon() { return ( - + + + + + + + + + + + + + + + ); } @@ -21,28 +60,72 @@ export function ThroughputSummaryIcon() { export function ProductionCapacityIcon() { return ( - - - + + + + - + + + + + + + + + + + diff --git a/app/src/components/ui/analysis/ProductionCapacity.tsx b/app/src/components/ui/analysis/ProductionCapacity.tsx index 803ec47..ad69a43 100644 --- a/app/src/components/ui/analysis/ProductionCapacity.tsx +++ b/app/src/components/ui/analysis/ProductionCapacity.tsx @@ -8,6 +8,7 @@ import { PointElement, } from "chart.js"; import { PowerIcon, ProductionCapacityIcon } from "../../icons/analysis"; +import { ThroughputIcon } from "../../icons/3dChartIcons"; ChartJS.register(LineElement, CategoryScale, LinearScale, PointElement); @@ -84,8 +85,8 @@ const ThroughputSummary = () => { }; return ( -
-
+
+
Production Capacity
diff --git a/app/src/components/ui/analysis/ROISummary.tsx b/app/src/components/ui/analysis/ROISummary.tsx index 8be74e8..81441a2 100644 --- a/app/src/components/ui/analysis/ROISummary.tsx +++ b/app/src/components/ui/analysis/ROISummary.tsx @@ -117,7 +117,9 @@ const ROISummary = ({
- Net Profit + + Net Profit + {roiSummaryData.netProfit}
@@ -186,9 +188,10 @@ const ROISummary = ({ Increase CNC utilization by 10%{" "} to shave 0.5 months of payback period -
-
-
+
+
+
+
- +
+
+ + +
+
4x
-
4x
@@ -369,6 +374,7 @@ const SimulationPlayer: React.FC = () => {
{/* {subModule === "analysis" && ( */} + {subModule === "analysis" && (
@@ -376,6 +382,7 @@ const SimulationPlayer: React.FC = () => {
+ )} {/* )} */} ); diff --git a/app/src/styles/components/simulation/analysis.scss b/app/src/styles/components/simulation/analysis.scss index 4e10bf4..70defeb 100644 --- a/app/src/styles/components/simulation/analysis.scss +++ b/app/src/styles/components/simulation/analysis.scss @@ -45,8 +45,7 @@ .sub-header { font-weight: 300; font-size: var(--font-size-tiny); - color: var(--text-color); - opacity: 0.8; + color: var(--text-button-color); } } @@ -98,6 +97,7 @@ .metrics-section { padding-top: 16px; + border-top: 1px solid var(--background-color-gray); .metric { display: flex; @@ -164,9 +164,6 @@ .footer-card { width: 100%; - background: var(--background-color-gray); - - border: 1px solid var(--border-color); background: var(--background-color); border-radius: 6px; padding: 8px; @@ -231,7 +228,6 @@ width: 100%; gap: 6px; padding-top: 3px; - .shift-wrapper { display: flex; align-items: center; @@ -275,11 +271,6 @@ } } - .roiSummary-container { - max-height: 60vh; - overflow-y: auto; - } - .roiSummary-wrapper { max-width: 470px; background-color: var(--background-color); @@ -300,19 +291,15 @@ border: 1px solid var(--border-color); .info { - opacity: 0.8; - span { font-size: var(--font-size-xlarge); &:first-child { color: #31c756; - opacity: 1; } &:last-child { color: var(--text-color); - opacity: 1; } } } @@ -363,8 +350,6 @@ &:last-child { align-items: center; - - } .metric-label { @@ -382,21 +367,13 @@ } } - .metric-item.net-profit { - .metric-label { - - span { - color: #21ad50; - } - } - } - .metric-wrapper { display: flex; gap: 6px; .metric-item { - border-radius: #{$border-radius-small}; + padding: 8px; + border-radius: #{$border-radius-large}; background: var(--background-color); border: 1px solid var(--border-color); } @@ -461,7 +438,6 @@ padding: 8px; text-align: left; border: 1px solid var(--border-color); - font-size: var(--font-size-small); } th { @@ -502,24 +478,6 @@ color: #488ef6; } } - - .placeHolder-wrapper { - display: flex; - flex-direction: column; - gap: 6px; - padding-top: 6px; - - .placeHolder { - height: 11px; - width: 100%; - background: #EAEAEA; - border-radius: 4px; - - &:nth-child(2) { - width: 50%; - } - } - } } } diff --git a/app/src/styles/components/simulation/simulation.scss b/app/src/styles/components/simulation/simulation.scss index 9b6c93d..37a87a8 100644 --- a/app/src/styles/components/simulation/simulation.scss +++ b/app/src/styles/components/simulation/simulation.scss @@ -144,14 +144,21 @@ &::after { content: ""; - background-color: #e5e5ea; + background: var(--background-color-solid); + opacity: 0.4; position: absolute; top: 50%; transform: translate(0, -50%); width: 100%; height: 3px; } - + .custom-slider-wrapper { + height: 100%; + width: 100%; + padding: 0 26px; + background: transparent; + border-radius: #{$border-radius-large}; + } .custom-slider { height: 100%; width: 100%; @@ -185,11 +192,13 @@ .marker { position: absolute; - background-color: var(--text-disabled); + background: var(--background-color-solid); + opacity: 0.6; width: 2px; height: 12px; border-radius: 1px; top: 8px; + z-index: 1; } .marker.marker-10 { From d551241ff02fbcca48d4e5a402a8d0966c76e5f4 Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 3 May 2025 18:12:13 +0530 Subject: [PATCH 13/14] style: Update styles in analysis component for improved consistency and appearance; adjust colors, padding, and border-radius --- .../components/simulation/analysis.scss | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/app/src/styles/components/simulation/analysis.scss b/app/src/styles/components/simulation/analysis.scss index 91bc66a..b838b0b 100644 --- a/app/src/styles/components/simulation/analysis.scss +++ b/app/src/styles/components/simulation/analysis.scss @@ -45,7 +45,8 @@ .sub-header { font-weight: 300; font-size: var(--font-size-tiny); - color: var(--text-button-color); + color: var(--text-color); + opacity: 0.8; } } @@ -97,7 +98,7 @@ .metrics-section { padding-top: 16px; - border-top: 1px solid var(--background-color-gray); + border-top: 1px solid var(--border-color); .metric { display: flex; @@ -144,7 +145,7 @@ max-width: 200px; height: 100px; position: relative; - background-image: radial-gradient(#d3d3d3 1px, transparent 1px); + background-image: radial-gradient(#8d8d8da4 1px, transparent 1px); background-size: 10px 10px; border-radius: 8px; @@ -174,8 +175,8 @@ .footer-card { width: 100%; background: var(--background-color); - border-radius: 6px; - padding: 8px; + border-radius: #{$border-radius-large}; + padding: 12px; display: flex; flex-direction: column; gap: 12px; @@ -262,7 +263,8 @@ } label { - font-size: var(--font-size-small); + font-weight: 200; + font-size: var(--font-size-tiny); position: relative; } @@ -299,6 +301,10 @@ padding: 6px 12px; border: 1px solid var(--border-color); + svg { + scale: 0.8; + } + .info { span { font-size: var(--font-size-xlarge); @@ -394,7 +400,7 @@ .cost-breakdown { background: var(--background-color); border: 1px solid var(--border-color); - border-radius: #{$border-radius-large}; + border-radius: #{$border-radius-extra-large}; max-height: 20vh; padding: 16px; overflow: auto; @@ -407,7 +413,7 @@ .section-wrapper { display: flex; - gap: 4px; + gap: 6px; align-items: center; } @@ -458,7 +464,7 @@ .tips-section { background: var(--background-color); - border-radius: #{$border-radius-large}; + border-radius: #{$border-radius-extra-large}; outline: 1px solid var(--border-color); display: flex; flex-direction: column; @@ -468,7 +474,10 @@ .tip-header { display: flex; align-items: center; - + gap: 4px; + .lightbulb-icon{ + @include flex-center; + } .tip-title { color: var(--text-color); font-weight: 600; @@ -555,4 +564,4 @@ } } -// Breakdown Table Open/Close Logic \ No newline at end of file +// Breakdown Table Open/Close Logic From ae9c2fda6691d65effe645e9a809ba61335b7e1d Mon Sep 17 00:00:00 2001 From: Vishnu Date: Sat, 3 May 2025 18:16:31 +0530 Subject: [PATCH 14/14] refactor: Improve code readability and consistency in PointsCreator component; streamline JSX structure and enhance key usage in event mapping --- .../events/points/creator/pointsCreator.tsx | 302 +++++++++--------- 1 file changed, 155 insertions(+), 147 deletions(-) diff --git a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx index 8c6f852..29a6db7 100644 --- a/app/src/modules/simulation/events/points/creator/pointsCreator.tsx +++ b/app/src/modules/simulation/events/points/creator/pointsCreator.tsx @@ -13,15 +13,23 @@ import { import { useThree } from "@react-three/fiber"; function PointsCreator() { - const { gl, raycaster, scene, pointer, camera } = useThree(); - const { subModule } = useSubModuleStore(); - const { events, updatePoint, getPointByUuid, getEventByModelUuid } = useEventsStore(); - const { activeModule } = useModuleStore(); - const transformRef = useRef(null); - const [transformMode, setTransformMode] = useState<"translate" | "rotate" | null>(null); - const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); - const { selectedEventSphere, setSelectedEventSphere, clearSelectedEventSphere, } = useSelectedEventSphere(); - const { selectedEventData, setSelectedEventData, clearSelectedEventData } = useSelectedEventData(); + const { gl, raycaster, scene, pointer, camera } = useThree(); + const { subModule } = useSubModuleStore(); + const { events, updatePoint, getPointByUuid, getEventByModelUuid } = + useEventsStore(); + const { activeModule } = useModuleStore(); + const transformRef = useRef(null); + const [transformMode, setTransformMode] = useState< + "translate" | "rotate" | null + >(null); + const sphereRefs = useRef<{ [key: string]: THREE.Mesh }>({}); + const { + selectedEventSphere, + setSelectedEventSphere, + clearSelectedEventSphere, + } = useSelectedEventSphere(); + const { setSelectedEventData, clearSelectedEventData } = + useSelectedEventData(); useEffect(() => { if (selectedEventSphere) { @@ -123,146 +131,146 @@ function PointsCreator() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [gl, subModule, selectedEventSphere]); - return ( + return ( + <> + {activeModule === "simulation" && ( <> - {activeModule === "simulation" && ( - <> - - {events.map((event, i) => { - if (event.type === "transfer") { - return ( - - {event.points.map((point, j) => ( - (sphereRefs.current[point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[point.uuid] - ); - }} - key={`${i}-${j}`} - position={new THREE.Vector3(...point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: point.uuid, - }} - > - - - - ))} - - ); - } else if (event.type === "vehicle") { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[event.point.uuid] - ); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: event.point.uuid, - }} - > - - - - - ); - } else if (event.type === "roboticArm") { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[event.point.uuid] - ); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: event.point.uuid, - }} - > - - - - - ); - } else if (event.type === "machine") { - return ( - - (sphereRefs.current[event.point.uuid] = el!)} - onClick={(e) => { - e.stopPropagation(); - setSelectedEventSphere( - sphereRefs.current[event.point.uuid] - ); - }} - position={new THREE.Vector3(...event.point.position)} - userData={{ - modelUuid: event.modelUuid, - pointUuid: event.point.uuid, - }} - > - - - - - ); - } else { - return null; - } - })} - - {selectedEventSphere && transformMode && ( - { - updatePointToState(selectedEventSphere); - }} - /> - )} - - )} + + {events.map((event, index) => { + if (event.type === "transfer") { + return ( + + {event.points.map((point, j) => ( + (sphereRefs.current[point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[point.uuid] + ); + }} + key={`${index}-${point.uuid}`} + position={new THREE.Vector3(...point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: point.uuid, + }} + > + + + + ))} + + ); + } else if (event.type === "vehicle") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else if (event.type === "roboticArm") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else if (event.type === "machine") { + return ( + + (sphereRefs.current[event.point.uuid] = el!)} + onClick={(e) => { + e.stopPropagation(); + setSelectedEventSphere( + sphereRefs.current[event.point.uuid] + ); + }} + position={new THREE.Vector3(...event.point.position)} + userData={{ + modelUuid: event.modelUuid, + pointUuid: event.point.uuid, + }} + > + + + + + ); + } else { + return null; + } + })} + + {selectedEventSphere && transformMode && ( + { + updatePointToState(selectedEventSphere); + }} + /> + )} - ); + )} + + ); } export default PointsCreator;