diff --git a/app/src/components/SimulationDashboard/AnalyzerManager.tsx b/app/src/components/SimulationDashboard/AnalyzerManager.tsx
new file mode 100644
index 0000000..55e8a3b
--- /dev/null
+++ b/app/src/components/SimulationDashboard/AnalyzerManager.tsx
@@ -0,0 +1,170 @@
+import { useEffect } from "react";
+import { useSceneContext } from "../../modules/scene/sceneContext";
+
+const AnalyzerManager: React.FC = () => {
+ const { analysisStore, simulationDashBoardStore } = useSceneContext();
+ const { analysis, getAssetAnalysis, getSystemMetrics } = analysisStore();
+ const { blocks, updateGraphData } = simulationDashBoardStore();
+
+ // Helper to resolve value from path like "efficiency.overallEffectiveness"
+ const resolvePath = (obj: any, path: string | string[]) => {
+ if (!obj || !path) return undefined;
+ const actualPath = Array.isArray(path) ? path[0] : path;
+ if (typeof actualPath !== "string") return undefined;
+ return actualPath.split(".").reduce((prev, curr) => (prev ? prev[curr] : undefined), obj);
+ };
+
+ // Helper to get formatted value
+ const getFormattedValue = (value: any): string => {
+ if (typeof value === "number") {
+ return value.toFixed(2);
+ }
+ return String(value ?? "-");
+ };
+
+ useEffect(() => {
+ if (!analysis) return;
+
+ blocks.forEach((block) => {
+ block.elements.forEach((element) => {
+ // 1. Handle Label-Value (Direct DOM Manipulation)
+ if (element.type === "label-value") {
+ if (!element.dataSource || !element.dataValue) return;
+
+ let value: any = "-";
+ // Ensure dataValue is treated as string if possible, or take first if array
+ const mixedDataValue = element.dataValue;
+ const dataValueStr = Array.isArray(mixedDataValue) ? mixedDataValue[0] : mixedDataValue;
+
+ if (typeof dataValueStr !== "string") return;
+
+ if (element.dataSource === "global") {
+ // Handle global metrics
+ // Expected format: "global.systemPerformance.overallOEE" -> we need last part relative to metrics
+ // But dataValue usually comes as "systemPerformance.overallOEE" if dataSource is global?
+ // Let's check ElementEditor:
+ // It passes "global.systemPerformance.overallOEE" as the ID.
+ // We need to parse this.
+
+ const metrics = getSystemMetrics();
+ if (metrics) {
+ // If the ID starts with global., strip it.
+ const path = dataValueStr.startsWith("global.")
+ ? dataValueStr.replace("global.", "")
+ : dataValueStr;
+
+ value = resolvePath(metrics, path);
+ }
+
+ } else {
+ // Handle Asset Specific
+ const assetAnalysis = getAssetAnalysis(element.dataSource);
+ if (assetAnalysis) {
+ value = resolvePath(assetAnalysis, dataValueStr);
+ }
+ }
+
+ // Update DOM
+ const valueElement = document.querySelector(`[data-element-id="${element.elementUuid}"] .value-text`);
+ if (valueElement) {
+ valueElement.textContent = getFormattedValue(value);
+ }
+ }
+
+ // 2. Handle Graph (Store Update)
+ // We shouldn't update store on every frame if data hasn't changed or simpler approach?
+ // For graphs, we usually push new data points.
+ // Assuming we want to visualize historical data or current state trends.
+ else if (element.type === "graph") {
+
+ if (element.dataType === "single-machine") {
+ if (!element.dataSource || !element.dataValue) return;
+ // Single machine, multiple values potentially?
+ // element.dataValue is string[] for single-machine graph
+
+ const assetId = element.dataSource as string;
+ const dataKeys = element.dataValue as string[]; // e.g. ["efficiency.overallEffectiveness"]
+
+ // For now support getting the FIRST value as the main value to plot?
+ // Or if we track history?
+ // The requirement says: "update the dom ... to show the value".
+ // UseAnalysisStore has 'historicalData'.
+ // But usually graphs update by appending new points.
+ // Here we might just pull the latest historical data or current value.
+
+ const assetAnalysis = getAssetAnalysis(assetId);
+ if (assetAnalysis) {
+ // If it's a historical plot, we might want to read from assetAnalysis.historicalData (if it exists on client)
+ // or just push current value to the graph element's local state.
+ // But here we are asked to manage values using AnalyzerManager.
+
+ // Let's construct a data point.
+ // GraphDataPoint = { name: string, value: number, ... }
+
+ // We use analysis.lastUpdateTime or similar as 'name' (X-axis)
+ const timeLabel = new Date().toLocaleTimeString();
+
+ // We need to construct a new GraphDataPoint
+ const newPoint: any = { name: timeLabel };
+
+ let hasValidData = false;
+ dataKeys.forEach((key, index) => {
+ const val = resolvePath(assetAnalysis, key);
+ if (typeof val === "number") {
+ newPoint["value"] = val; // Primary value
+ // If we have multiple lines, we might need value1, value2 etc, but Recharts usually takes keys.
+ // The ElementContent uses 'value' key hardcoded for single line?
+ // Let's check ElementContent.tsx...
+ // It renders