diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html
index 36093e1..e45b994 100644
--- a/ui/src/app/app.component.html
+++ b/ui/src/app/app.component.html
@@ -1,336 +1,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Hello, {{ title }}
-
Congratulations! Your app is running. 🎉
-
-
-
-
- @for (item of [
- { title: 'Explore the Docs', link: 'https://angular.dev' },
- { title: 'Learn with Tutorials', link: 'https://angular.dev/tutorials' },
- { title: 'CLI Docs', link: 'https://angular.dev/tools/cli' },
- { title: 'Angular Language Service', link: 'https://angular.dev/tools/language-service' },
- { title: 'Angular DevTools', link: 'https://angular.dev/tools/devtools' },
- ]; track item.title) {
-
- {{ item.title }}
-
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/ui/src/app/app.component.scss b/ui/src/app/app.component.scss
index e69de29..b5736d3 100644
--- a/ui/src/app/app.component.scss
+++ b/ui/src/app/app.component.scss
@@ -0,0 +1,4 @@
+ main {
+ min-height: calc(100vh - 64px);
+ background: #fafafa;
+ }
\ No newline at end of file
diff --git a/ui/src/app/app.component.ts b/ui/src/app/app.component.ts
index 3a1913a..92337e0 100644
--- a/ui/src/app/app.component.ts
+++ b/ui/src/app/app.component.ts
@@ -1,13 +1,15 @@
import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
+import { HeaderComponent } from './components/header/header.component';
@Component({
selector: 'app-root',
standalone: true,
- imports: [RouterOutlet],
+ imports: [RouterOutlet, HeaderComponent],
templateUrl: './app.component.html',
styleUrl: './app.component.scss'
})
export class AppComponent {
- title = 'dashboard';
+ title = 'PI_E2EEDA Dashboard';
+
}
diff --git a/ui/src/app/app.routes.ts b/ui/src/app/app.routes.ts
index dc39edb..150891b 100644
--- a/ui/src/app/app.routes.ts
+++ b/ui/src/app/app.routes.ts
@@ -1,3 +1,25 @@
import { Routes } from '@angular/router';
-export const routes: Routes = [];
+export const routes: Routes = [
+ {
+ path: '',
+ redirectTo: '/dashboard',
+ pathMatch: 'full'
+ },
+ {
+ path: 'dashboard',
+ loadComponent: () =>
+ import('./components/room-map/room-map.component').then(m => m.RoomMapComponent),
+ title: 'Dashboard - PI_E2EEDA'
+ },
+ {
+ path: 'room/:id',
+ loadComponent: () =>
+ import('./components/room-details-panel/room-details-panel.component').then(m => m.RoomDetailsPanelComponent),
+ title: 'Room Details - PI_E2EEDA'
+ },
+ {
+ path: '**',
+ redirectTo: '/dashboard'
+ }
+];
diff --git a/ui/src/app/components/header/header.component.html b/ui/src/app/components/header/header.component.html
new file mode 100644
index 0000000..9323fb5
--- /dev/null
+++ b/ui/src/app/components/header/header.component.html
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/ui/src/app/components/header/header.component.scss b/ui/src/app/components/header/header.component.scss
new file mode 100644
index 0000000..a32322c
--- /dev/null
+++ b/ui/src/app/components/header/header.component.scss
@@ -0,0 +1,41 @@
+ header {
+ background: #00bcd4;
+ color: white;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ }
+
+ .header-content {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 16px 24px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ h1 {
+ margin: 0;
+ font-size: 24px;
+ cursor: pointer;
+
+ &:hover {
+ opacity: 0.9;
+ }
+ }
+
+ nav a {
+ color: white;
+ text-decoration: none;
+ margin-left: 24px;
+ padding: 8px 16px;
+ border-radius: 4px;
+ transition: background 0.3s;
+
+ &:hover {
+ background: rgba(255,255,255,0.1);
+ }
+
+ &.active {
+ background: rgba(255,255,255,0.2);
+ }
+ }
\ No newline at end of file
diff --git a/ui/src/app/components/header/header.component.ts b/ui/src/app/components/header/header.component.ts
new file mode 100644
index 0000000..d4be90e
--- /dev/null
+++ b/ui/src/app/components/header/header.component.ts
@@ -0,0 +1,15 @@
+import { CommonModule } from '@angular/common';
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { RouterModule } from '@angular/router';
+
+@Component({
+ selector: 'app-header',
+ standalone: true,
+ imports: [CommonModule, RouterModule],
+ templateUrl: './header.component.html',
+ styleUrl: './header.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class HeaderComponent {
+
+}
diff --git a/ui/src/app/components/legend/legend.component.html b/ui/src/app/components/legend/legend.component.html
new file mode 100644
index 0000000..0281e56
--- /dev/null
+++ b/ui/src/app/components/legend/legend.component.html
@@ -0,0 +1,10 @@
+
+
Air Quality (CO2)
+
+
+
+
{{ level.label }}
+
{{ level.range }}
+
+
+
>
diff --git a/ui/src/app/components/legend/legend.component.scss b/ui/src/app/components/legend/legend.component.scss
new file mode 100644
index 0000000..5efa204
--- /dev/null
+++ b/ui/src/app/components/legend/legend.component.scss
@@ -0,0 +1,42 @@
+ .legend {
+ background: white;
+ border-radius: 8px;
+ padding: 16px;
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+ }
+
+ h3 {
+ margin: 0 0 12px 0;
+ font-size: 14px;
+ font-weight: 600;
+ color: rgba(0,0,0,0.87);
+ }
+
+ .legend-items {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+
+ .legend-item {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ font-size: 13px;
+ }
+
+ .color-box {
+ width: 24px;
+ height: 24px;
+ border-radius: 4px;
+ flex-shrink: 0;
+ }
+
+ .label {
+ font-weight: 500;
+ min-width: 100px;
+ }
+
+ .range {
+ color: rgba(0,0,0,0.6);
+ }
\ No newline at end of file
diff --git a/ui/src/app/components/legend/legend.component.ts b/ui/src/app/components/legend/legend.component.ts
new file mode 100644
index 0000000..5d26739
--- /dev/null
+++ b/ui/src/app/components/legend/legend.component.ts
@@ -0,0 +1,28 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+interface CO2Level {
+ label: string;
+ range: string;
+ color: string;
+}
+
+@Component({
+ selector: 'app-legend',
+ standalone: true,
+ imports: [],
+ templateUrl: './legend.component.html',
+ styleUrl: './legend.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class LegendComponent {
+ levels: CO2Level[] = [
+ { label: 'Excellent', range: '< 800 ppm', color: '#4caf50' },
+ { label: 'Good', range: '800-1000 ppm', color: '#8bc34a' },
+ { label: 'Moderate', range: '1000-1200 ppm', color: '#ffc107' },
+ { label: 'Poor', range: '1200-1500 ppm', color: '#ff9800' },
+ { label: 'Very Poor', range: '1500-2000 ppm', color: '#ff5722' },
+ { label: 'Critical', range: '> 2000 ppm', color: '#f44336' }
+ ];
+
+}
diff --git a/ui/src/app/components/room-details-panel/room-details-panel.component.html b/ui/src/app/components/room-details-panel/room-details-panel.component.html
new file mode 100644
index 0000000..f9f7485
--- /dev/null
+++ b/ui/src/app/components/room-details-panel/room-details-panel.component.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/ui/src/app/components/room-details-panel/room-details-panel.component.scss b/ui/src/app/components/room-details-panel/room-details-panel.component.scss
new file mode 100644
index 0000000..85b77cf
--- /dev/null
+++ b/ui/src/app/components/room-details-panel/room-details-panel.component.scss
@@ -0,0 +1,16 @@
+ .room-details-container {
+ padding: 24px;
+ }
+
+ h1 {
+ margin-bottom: 16px;
+ }
+
+ a {
+ color: #00bcd4;
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
\ No newline at end of file
diff --git a/ui/src/app/components/room-details-panel/room-details-panel.component.ts b/ui/src/app/components/room-details-panel/room-details-panel.component.ts
new file mode 100644
index 0000000..a0e4792
--- /dev/null
+++ b/ui/src/app/components/room-details-panel/room-details-panel.component.ts
@@ -0,0 +1,19 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { CommonModule } from '@angular/common';
+import { ActivatedRoute, RouterModule } from '@angular/router';
+@Component({
+ selector: 'app-room-details-panel',
+ standalone: true,
+ imports: [CommonModule, RouterModule],
+ templateUrl: './room-details-panel.component.html',
+ styleUrl: './room-details-panel.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class RoomDetailsPanelComponent {
+ roomId: string | null = null;
+
+ constructor(private route: ActivatedRoute) {
+ this.roomId = this.route.snapshot.paramMap.get('id');
+ }
+
+}
diff --git a/ui/src/app/components/room-map/room-map.component.html b/ui/src/app/components/room-map/room-map.component.html
new file mode 100644
index 0000000..9ead5cc
--- /dev/null
+++ b/ui/src/app/components/room-map/room-map.component.html
@@ -0,0 +1,4 @@
+
+
Room Map
+
Interactive 2D SVG map will be displayed here.
+
diff --git a/ui/src/app/components/room-map/room-map.component.scss b/ui/src/app/components/room-map/room-map.component.scss
new file mode 100644
index 0000000..44af470
--- /dev/null
+++ b/ui/src/app/components/room-map/room-map.component.scss
@@ -0,0 +1,9 @@
+.room-map-container {
+ padding: 24px;
+ text-align: center;
+ }
+
+ h1 {
+ color: #00bcd4;
+ margin-bottom: 16px;
+ }
\ No newline at end of file
diff --git a/ui/src/app/components/room-map/room-map.component.ts b/ui/src/app/components/room-map/room-map.component.ts
new file mode 100644
index 0000000..36b89f7
--- /dev/null
+++ b/ui/src/app/components/room-map/room-map.component.ts
@@ -0,0 +1,14 @@
+import { CommonModule } from '@angular/common';
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+
+@Component({
+ selector: 'app-room-map',
+ standalone: true,
+ imports: [CommonModule],
+ templateUrl: './room-map.component.html',
+ styleUrl: './room-map.component.scss',
+ changeDetection: ChangeDetectionStrategy.OnPush
+})
+export class RoomMapComponent {
+
+}