Ming Wang commited on
Commit
602851d
·
1 Parent(s): 3a888be

Phase 1: frontend UI skeleton

Browse files
Files changed (44) hide show
  1. frontend/.claude/CLAUDE.md +55 -0
  2. frontend/.cursor/rules/cursor.mdc +60 -0
  3. frontend/.editorconfig +17 -0
  4. frontend/.gemini/GEMINI.md +55 -0
  5. frontend/.github/copilot-instructions.md +55 -0
  6. frontend/.gitignore +44 -0
  7. frontend/.junie/guidelines.md +55 -0
  8. frontend/.prettierrc +12 -0
  9. frontend/.vscode/extensions.json +4 -0
  10. frontend/.vscode/launch.json +20 -0
  11. frontend/.vscode/mcp.json +9 -0
  12. frontend/.vscode/tasks.json +42 -0
  13. frontend/.windsurf/rules/guidelines.md +55 -0
  14. frontend/AGENTS.md +55 -0
  15. frontend/README.md +59 -0
  16. frontend/angular.json +97 -0
  17. frontend/package-lock.json +0 -0
  18. frontend/package.json +32 -0
  19. frontend/public/favicon.ico +0 -0
  20. frontend/src/app/app.config.ts +8 -0
  21. frontend/src/app/app.html +1 -0
  22. frontend/src/app/app.scss +0 -0
  23. frontend/src/app/app.ts +10 -0
  24. frontend/src/app/core/mocks/alerts.mock.ts +45 -0
  25. frontend/src/app/core/mocks/kpi.mock.ts +41 -0
  26. frontend/src/app/dashboard/alert-list/alert-list.html +23 -0
  27. frontend/src/app/dashboard/alert-list/alert-list.scss +92 -0
  28. frontend/src/app/dashboard/alert-list/alert-list.ts +24 -0
  29. frontend/src/app/dashboard/chart-placeholder/chart-placeholder.html +9 -0
  30. frontend/src/app/dashboard/chart-placeholder/chart-placeholder.scss +37 -0
  31. frontend/src/app/dashboard/chart-placeholder/chart-placeholder.ts +13 -0
  32. frontend/src/app/dashboard/dashboard.html +30 -0
  33. frontend/src/app/dashboard/dashboard.scss +71 -0
  34. frontend/src/app/dashboard/dashboard.ts +17 -0
  35. frontend/src/app/dashboard/kpi-card/kpi-card.html +18 -0
  36. frontend/src/app/dashboard/kpi-card/kpi-card.scss +63 -0
  37. frontend/src/app/dashboard/kpi-card/kpi-card.ts +27 -0
  38. frontend/src/app/shared/styles/_tokens.scss +27 -0
  39. frontend/src/index.html +20 -0
  40. frontend/src/main.ts +6 -0
  41. frontend/src/styles.scss +40 -0
  42. frontend/tsconfig.app.json +15 -0
  43. frontend/tsconfig.json +30 -0
  44. frontend/tsconfig.spec.json +15 -0
frontend/.claude/CLAUDE.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
3
+
4
+ ## TypeScript Best Practices
5
+
6
+ - Use strict type checking
7
+ - Prefer type inference when the type is obvious
8
+ - Avoid the `any` type; use `unknown` when type is uncertain
9
+
10
+ ## Angular Best Practices
11
+
12
+ - Always use standalone components over NgModules
13
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
14
+ - Use signals for state management
15
+ - Implement lazy loading for feature routes
16
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
17
+ - Use `NgOptimizedImage` for all static images.
18
+ - `NgOptimizedImage` does not work for inline base64 images.
19
+
20
+ ## Accessibility Requirements
21
+
22
+ - It MUST pass all AXE checks.
23
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
24
+
25
+ ### Components
26
+
27
+ - Keep components small and focused on a single responsibility
28
+ - Use `input()` and `output()` functions instead of decorators
29
+ - Use `computed()` for derived state
30
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
31
+ - Prefer inline templates for small components
32
+ - Prefer Reactive forms instead of Template-driven ones
33
+ - Do NOT use `ngClass`, use `class` bindings instead
34
+ - Do NOT use `ngStyle`, use `style` bindings instead
35
+ - When using external templates/styles, use paths relative to the component TS file.
36
+
37
+ ## State Management
38
+
39
+ - Use signals for local component state
40
+ - Use `computed()` for derived state
41
+ - Keep state transformations pure and predictable
42
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
43
+
44
+ ## Templates
45
+
46
+ - Keep templates simple and avoid complex logic
47
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
48
+ - Use the async pipe to handle observables
49
+ - Do not assume globals like (`new Date()`) are available.
50
+
51
+ ## Services
52
+
53
+ - Design services around a single responsibility
54
+ - Use the `providedIn: 'root'` option for singleton services
55
+ - Use the `inject()` function instead of constructor injection
frontend/.cursor/rules/cursor.mdc ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ context: true
3
+ priority: high
4
+ scope: project
5
+ ---
6
+
7
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
8
+
9
+ ## TypeScript Best Practices
10
+
11
+ - Use strict type checking
12
+ - Prefer type inference when the type is obvious
13
+ - Avoid the `any` type; use `unknown` when type is uncertain
14
+
15
+ ## Angular Best Practices
16
+
17
+ - Always use standalone components over NgModules
18
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
19
+ - Use signals for state management
20
+ - Implement lazy loading for feature routes
21
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
22
+ - Use `NgOptimizedImage` for all static images.
23
+ - `NgOptimizedImage` does not work for inline base64 images.
24
+
25
+ ## Accessibility Requirements
26
+
27
+ - It MUST pass all AXE checks.
28
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
29
+
30
+ ### Components
31
+
32
+ - Keep components small and focused on a single responsibility
33
+ - Use `input()` and `output()` functions instead of decorators
34
+ - Use `computed()` for derived state
35
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
36
+ - Prefer inline templates for small components
37
+ - Prefer Reactive forms instead of Template-driven ones
38
+ - Do NOT use `ngClass`, use `class` bindings instead
39
+ - Do NOT use `ngStyle`, use `style` bindings instead
40
+ - When using external templates/styles, use paths relative to the component TS file.
41
+
42
+ ## State Management
43
+
44
+ - Use signals for local component state
45
+ - Use `computed()` for derived state
46
+ - Keep state transformations pure and predictable
47
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
48
+
49
+ ## Templates
50
+
51
+ - Keep templates simple and avoid complex logic
52
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
53
+ - Use the async pipe to handle observables
54
+ - Do not assume globals like (`new Date()`) are available.
55
+
56
+ ## Services
57
+
58
+ - Design services around a single responsibility
59
+ - Use the `providedIn: 'root'` option for singleton services
60
+ - Use the `inject()` function instead of constructor injection
frontend/.editorconfig ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Editor configuration, see https://editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ charset = utf-8
6
+ indent_style = space
7
+ indent_size = 2
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.ts]
12
+ quote_type = single
13
+ ij_typescript_use_double_quotes = false
14
+
15
+ [*.md]
16
+ max_line_length = off
17
+ trim_trailing_whitespace = false
frontend/.gemini/GEMINI.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
3
+
4
+ ## TypeScript Best Practices
5
+
6
+ - Use strict type checking
7
+ - Prefer type inference when the type is obvious
8
+ - Avoid the `any` type; use `unknown` when type is uncertain
9
+
10
+ ## Angular Best Practices
11
+
12
+ - Always use standalone components over NgModules
13
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
14
+ - Use signals for state management
15
+ - Implement lazy loading for feature routes
16
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
17
+ - Use `NgOptimizedImage` for all static images.
18
+ - `NgOptimizedImage` does not work for inline base64 images.
19
+
20
+ ## Accessibility Requirements
21
+
22
+ - It MUST pass all AXE checks.
23
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
24
+
25
+ ### Components
26
+
27
+ - Keep components small and focused on a single responsibility
28
+ - Use `input()` and `output()` functions instead of decorators
29
+ - Use `computed()` for derived state
30
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
31
+ - Prefer inline templates for small components
32
+ - Prefer Reactive forms instead of Template-driven ones
33
+ - Do NOT use `ngClass`, use `class` bindings instead
34
+ - Do NOT use `ngStyle`, use `style` bindings instead
35
+ - When using external templates/styles, use paths relative to the component TS file.
36
+
37
+ ## State Management
38
+
39
+ - Use signals for local component state
40
+ - Use `computed()` for derived state
41
+ - Keep state transformations pure and predictable
42
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
43
+
44
+ ## Templates
45
+
46
+ - Keep templates simple and avoid complex logic
47
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
48
+ - Use the async pipe to handle observables
49
+ - Do not assume globals like (`new Date()`) are available.
50
+
51
+ ## Services
52
+
53
+ - Design services around a single responsibility
54
+ - Use the `providedIn: 'root'` option for singleton services
55
+ - Use the `inject()` function instead of constructor injection
frontend/.github/copilot-instructions.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
3
+
4
+ ## TypeScript Best Practices
5
+
6
+ - Use strict type checking
7
+ - Prefer type inference when the type is obvious
8
+ - Avoid the `any` type; use `unknown` when type is uncertain
9
+
10
+ ## Angular Best Practices
11
+
12
+ - Always use standalone components over NgModules
13
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
14
+ - Use signals for state management
15
+ - Implement lazy loading for feature routes
16
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
17
+ - Use `NgOptimizedImage` for all static images.
18
+ - `NgOptimizedImage` does not work for inline base64 images.
19
+
20
+ ## Accessibility Requirements
21
+
22
+ - It MUST pass all AXE checks.
23
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
24
+
25
+ ### Components
26
+
27
+ - Keep components small and focused on a single responsibility
28
+ - Use `input()` and `output()` functions instead of decorators
29
+ - Use `computed()` for derived state
30
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
31
+ - Prefer inline templates for small components
32
+ - Prefer Reactive forms instead of Template-driven ones
33
+ - Do NOT use `ngClass`, use `class` bindings instead
34
+ - Do NOT use `ngStyle`, use `style` bindings instead
35
+ - When using external templates/styles, use paths relative to the component TS file.
36
+
37
+ ## State Management
38
+
39
+ - Use signals for local component state
40
+ - Use `computed()` for derived state
41
+ - Keep state transformations pure and predictable
42
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
43
+
44
+ ## Templates
45
+
46
+ - Keep templates simple and avoid complex logic
47
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
48
+ - Use the async pipe to handle observables
49
+ - Do not assume globals like (`new Date()`) are available.
50
+
51
+ ## Services
52
+
53
+ - Design services around a single responsibility
54
+ - Use the `providedIn: 'root'` option for singleton services
55
+ - Use the `inject()` function instead of constructor injection
frontend/.gitignore ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files.
2
+
3
+ # Compiled output
4
+ /dist
5
+ /tmp
6
+ /out-tsc
7
+ /bazel-out
8
+
9
+ # Node
10
+ /node_modules
11
+ npm-debug.log
12
+ yarn-error.log
13
+
14
+ # IDEs and editors
15
+ .idea/
16
+ .project
17
+ .classpath
18
+ .c9/
19
+ *.launch
20
+ .settings/
21
+ *.sublime-workspace
22
+
23
+ # Visual Studio Code
24
+ .vscode/*
25
+ !.vscode/settings.json
26
+ !.vscode/tasks.json
27
+ !.vscode/launch.json
28
+ !.vscode/extensions.json
29
+ !.vscode/mcp.json
30
+ .history/*
31
+
32
+ # Miscellaneous
33
+ /.angular/cache
34
+ .sass-cache/
35
+ /connect.lock
36
+ /coverage
37
+ /libpeerconnection.log
38
+ testem.log
39
+ /typings
40
+ __screenshots__/
41
+
42
+ # System files
43
+ .DS_Store
44
+ Thumbs.db
frontend/.junie/guidelines.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
3
+
4
+ ## TypeScript Best Practices
5
+
6
+ - Use strict type checking
7
+ - Prefer type inference when the type is obvious
8
+ - Avoid the `any` type; use `unknown` when type is uncertain
9
+
10
+ ## Angular Best Practices
11
+
12
+ - Always use standalone components over NgModules
13
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
14
+ - Use signals for state management
15
+ - Implement lazy loading for feature routes
16
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
17
+ - Use `NgOptimizedImage` for all static images.
18
+ - `NgOptimizedImage` does not work for inline base64 images.
19
+
20
+ ## Accessibility Requirements
21
+
22
+ - It MUST pass all AXE checks.
23
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
24
+
25
+ ### Components
26
+
27
+ - Keep components small and focused on a single responsibility
28
+ - Use `input()` and `output()` functions instead of decorators
29
+ - Use `computed()` for derived state
30
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
31
+ - Prefer inline templates for small components
32
+ - Prefer Reactive forms instead of Template-driven ones
33
+ - Do NOT use `ngClass`, use `class` bindings instead
34
+ - Do NOT use `ngStyle`, use `style` bindings instead
35
+ - When using external templates/styles, use paths relative to the component TS file.
36
+
37
+ ## State Management
38
+
39
+ - Use signals for local component state
40
+ - Use `computed()` for derived state
41
+ - Keep state transformations pure and predictable
42
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
43
+
44
+ ## Templates
45
+
46
+ - Keep templates simple and avoid complex logic
47
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
48
+ - Use the async pipe to handle observables
49
+ - Do not assume globals like (`new Date()`) are available.
50
+
51
+ ## Services
52
+
53
+ - Design services around a single responsibility
54
+ - Use the `providedIn: 'root'` option for singleton services
55
+ - Use the `inject()` function instead of constructor injection
frontend/.prettierrc ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "printWidth": 100,
3
+ "singleQuote": true,
4
+ "overrides": [
5
+ {
6
+ "files": "*.html",
7
+ "options": {
8
+ "parser": "angular"
9
+ }
10
+ }
11
+ ]
12
+ }
frontend/.vscode/extensions.json ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ {
2
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
3
+ "recommendations": ["angular.ng-template"]
4
+ }
frontend/.vscode/launch.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
3
+ "version": "0.2.0",
4
+ "configurations": [
5
+ {
6
+ "name": "ng serve",
7
+ "type": "chrome",
8
+ "request": "launch",
9
+ "preLaunchTask": "npm: start",
10
+ "url": "http://localhost:4200/"
11
+ },
12
+ {
13
+ "name": "ng test",
14
+ "type": "chrome",
15
+ "request": "launch",
16
+ "preLaunchTask": "npm: test",
17
+ "url": "http://localhost:9876/debug.html"
18
+ }
19
+ ]
20
+ }
frontend/.vscode/mcp.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ // For more information, visit: https://angular.dev/ai/mcp
3
+ "servers": {
4
+ "angular-cli": {
5
+ "command": "npx",
6
+ "args": ["-y", "@angular/cli", "mcp"]
7
+ }
8
+ }
9
+ }
frontend/.vscode/tasks.json ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
3
+ "version": "2.0.0",
4
+ "tasks": [
5
+ {
6
+ "type": "npm",
7
+ "script": "start",
8
+ "isBackground": true,
9
+ "problemMatcher": {
10
+ "owner": "typescript",
11
+ "pattern": "$tsc",
12
+ "background": {
13
+ "activeOnStart": true,
14
+ "beginsPattern": {
15
+ "regexp": "Changes detected"
16
+ },
17
+ "endsPattern": {
18
+ "regexp": "bundle generation (complete|failed)"
19
+ }
20
+ }
21
+ }
22
+ },
23
+ {
24
+ "type": "npm",
25
+ "script": "test",
26
+ "isBackground": true,
27
+ "problemMatcher": {
28
+ "owner": "typescript",
29
+ "pattern": "$tsc",
30
+ "background": {
31
+ "activeOnStart": true,
32
+ "beginsPattern": {
33
+ "regexp": "Changes detected"
34
+ },
35
+ "endsPattern": {
36
+ "regexp": "bundle generation (complete|failed)"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ ]
42
+ }
frontend/.windsurf/rules/guidelines.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
3
+
4
+ ## TypeScript Best Practices
5
+
6
+ - Use strict type checking
7
+ - Prefer type inference when the type is obvious
8
+ - Avoid the `any` type; use `unknown` when type is uncertain
9
+
10
+ ## Angular Best Practices
11
+
12
+ - Always use standalone components over NgModules
13
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
14
+ - Use signals for state management
15
+ - Implement lazy loading for feature routes
16
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
17
+ - Use `NgOptimizedImage` for all static images.
18
+ - `NgOptimizedImage` does not work for inline base64 images.
19
+
20
+ ## Accessibility Requirements
21
+
22
+ - It MUST pass all AXE checks.
23
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
24
+
25
+ ### Components
26
+
27
+ - Keep components small and focused on a single responsibility
28
+ - Use `input()` and `output()` functions instead of decorators
29
+ - Use `computed()` for derived state
30
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
31
+ - Prefer inline templates for small components
32
+ - Prefer Reactive forms instead of Template-driven ones
33
+ - Do NOT use `ngClass`, use `class` bindings instead
34
+ - Do NOT use `ngStyle`, use `style` bindings instead
35
+ - When using external templates/styles, use paths relative to the component TS file.
36
+
37
+ ## State Management
38
+
39
+ - Use signals for local component state
40
+ - Use `computed()` for derived state
41
+ - Keep state transformations pure and predictable
42
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
43
+
44
+ ## Templates
45
+
46
+ - Keep templates simple and avoid complex logic
47
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
48
+ - Use the async pipe to handle observables
49
+ - Do not assume globals like (`new Date()`) are available.
50
+
51
+ ## Services
52
+
53
+ - Design services around a single responsibility
54
+ - Use the `providedIn: 'root'` option for singleton services
55
+ - Use the `inject()` function instead of constructor injection
frontend/AGENTS.md ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
3
+
4
+ ## TypeScript Best Practices
5
+
6
+ - Use strict type checking
7
+ - Prefer type inference when the type is obvious
8
+ - Avoid the `any` type; use `unknown` when type is uncertain
9
+
10
+ ## Angular Best Practices
11
+
12
+ - Always use standalone components over NgModules
13
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
14
+ - Use signals for state management
15
+ - Implement lazy loading for feature routes
16
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
17
+ - Use `NgOptimizedImage` for all static images.
18
+ - `NgOptimizedImage` does not work for inline base64 images.
19
+
20
+ ## Accessibility Requirements
21
+
22
+ - It MUST pass all AXE checks.
23
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
24
+
25
+ ### Components
26
+
27
+ - Keep components small and focused on a single responsibility
28
+ - Use `input()` and `output()` functions instead of decorators
29
+ - Use `computed()` for derived state
30
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
31
+ - Prefer inline templates for small components
32
+ - Prefer Reactive forms instead of Template-driven ones
33
+ - Do NOT use `ngClass`, use `class` bindings instead
34
+ - Do NOT use `ngStyle`, use `style` bindings instead
35
+ - When using external templates/styles, use paths relative to the component TS file.
36
+
37
+ ## State Management
38
+
39
+ - Use signals for local component state
40
+ - Use `computed()` for derived state
41
+ - Keep state transformations pure and predictable
42
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
43
+
44
+ ## Templates
45
+
46
+ - Keep templates simple and avoid complex logic
47
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
48
+ - Use the async pipe to handle observables
49
+ - Do not assume globals like (`new Date()`) are available.
50
+
51
+ ## Services
52
+
53
+ - Design services around a single responsibility
54
+ - Use the `providedIn: 'root'` option for singleton services
55
+ - Use the `inject()` function instead of constructor injection
frontend/README.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Frontend
2
+
3
+ This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 21.2.3.
4
+
5
+ ## Development server
6
+
7
+ To start a local development server, run:
8
+
9
+ ```bash
10
+ ng serve
11
+ ```
12
+
13
+ Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
14
+
15
+ ## Code scaffolding
16
+
17
+ Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
18
+
19
+ ```bash
20
+ ng generate component component-name
21
+ ```
22
+
23
+ For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
24
+
25
+ ```bash
26
+ ng generate --help
27
+ ```
28
+
29
+ ## Building
30
+
31
+ To build the project run:
32
+
33
+ ```bash
34
+ ng build
35
+ ```
36
+
37
+ This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
38
+
39
+ ## Running unit tests
40
+
41
+ To execute unit tests with the [Vitest](https://vitest.dev/) test runner, use the following command:
42
+
43
+ ```bash
44
+ ng test
45
+ ```
46
+
47
+ ## Running end-to-end tests
48
+
49
+ For end-to-end (e2e) testing, run:
50
+
51
+ ```bash
52
+ ng e2e
53
+ ```
54
+
55
+ Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
56
+
57
+ ## Additional Resources
58
+
59
+ For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
frontend/angular.json ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+ "version": 1,
4
+ "cli": {
5
+ "packageManager": "npm"
6
+ },
7
+ "newProjectRoot": "projects",
8
+ "projects": {
9
+ "frontend": {
10
+ "projectType": "application",
11
+ "schematics": {
12
+ "@schematics/angular:component": {
13
+ "style": "scss",
14
+ "skipTests": true
15
+ },
16
+ "@schematics/angular:class": {
17
+ "skipTests": true
18
+ },
19
+ "@schematics/angular:directive": {
20
+ "skipTests": true
21
+ },
22
+ "@schematics/angular:guard": {
23
+ "skipTests": true
24
+ },
25
+ "@schematics/angular:interceptor": {
26
+ "skipTests": true
27
+ },
28
+ "@schematics/angular:pipe": {
29
+ "skipTests": true
30
+ },
31
+ "@schematics/angular:resolver": {
32
+ "skipTests": true
33
+ },
34
+ "@schematics/angular:service": {
35
+ "skipTests": true
36
+ }
37
+ },
38
+ "root": "",
39
+ "sourceRoot": "src",
40
+ "prefix": "app",
41
+ "architect": {
42
+ "build": {
43
+ "builder": "@angular/build:application",
44
+ "options": {
45
+ "browser": "src/main.ts",
46
+ "tsConfig": "tsconfig.app.json",
47
+ "inlineStyleLanguage": "scss",
48
+ "assets": [
49
+ {
50
+ "glob": "**/*",
51
+ "input": "public"
52
+ }
53
+ ],
54
+ "styles": [
55
+ "src/styles.scss"
56
+ ]
57
+ },
58
+ "configurations": {
59
+ "production": {
60
+ "budgets": [
61
+ {
62
+ "type": "initial",
63
+ "maximumWarning": "500kB",
64
+ "maximumError": "1MB"
65
+ },
66
+ {
67
+ "type": "anyComponentStyle",
68
+ "maximumWarning": "4kB",
69
+ "maximumError": "8kB"
70
+ }
71
+ ],
72
+ "outputHashing": "all"
73
+ },
74
+ "development": {
75
+ "optimization": false,
76
+ "extractLicenses": false,
77
+ "sourceMap": true
78
+ }
79
+ },
80
+ "defaultConfiguration": "production"
81
+ },
82
+ "serve": {
83
+ "builder": "@angular/build:dev-server",
84
+ "configurations": {
85
+ "production": {
86
+ "buildTarget": "frontend:build:production"
87
+ },
88
+ "development": {
89
+ "buildTarget": "frontend:build:development"
90
+ }
91
+ },
92
+ "defaultConfiguration": "development"
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
frontend/package-lock.json ADDED
The diff for this file is too large to render. See raw diff
 
frontend/package.json ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "frontend",
3
+ "version": "0.0.0",
4
+ "scripts": {
5
+ "ng": "ng",
6
+ "start": "ng serve",
7
+ "build": "ng build",
8
+ "watch": "ng build --watch --configuration development",
9
+ "test": "ng test"
10
+ },
11
+ "private": true,
12
+ "packageManager": "npm@10.9.4",
13
+ "dependencies": {
14
+ "@angular/cdk": "^21.2.3",
15
+ "@angular/common": "^21.2.0",
16
+ "@angular/compiler": "^21.2.0",
17
+ "@angular/core": "^21.2.0",
18
+ "@angular/forms": "^21.2.0",
19
+ "@angular/material": "^21.2.3",
20
+ "@angular/platform-browser": "^21.2.0",
21
+ "@angular/router": "^21.2.0",
22
+ "rxjs": "~7.8.0",
23
+ "tslib": "^2.3.0"
24
+ },
25
+ "devDependencies": {
26
+ "@angular/build": "^21.2.3",
27
+ "@angular/cli": "^21.2.3",
28
+ "@angular/compiler-cli": "^21.2.0",
29
+ "prettier": "^3.8.1",
30
+ "typescript": "~5.9.2"
31
+ }
32
+ }
frontend/public/favicon.ico ADDED
frontend/src/app/app.config.ts ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
2
+
3
+ export const appConfig: ApplicationConfig = {
4
+ providers: [
5
+ provideBrowserGlobalErrorListeners(),
6
+
7
+ ]
8
+ };
frontend/src/app/app.html ADDED
@@ -0,0 +1 @@
 
 
1
+ <app-dashboard />
frontend/src/app/app.scss ADDED
File without changes
frontend/src/app/app.ts ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component } from '@angular/core';
2
+ import { Dashboard } from './dashboard/dashboard';
3
+
4
+ @Component({
5
+ selector: 'app-root',
6
+ imports: [Dashboard],
7
+ templateUrl: './app.html',
8
+ styleUrl: './app.scss',
9
+ })
10
+ export class App {}
frontend/src/app/core/mocks/alerts.mock.ts ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export interface AlertData {
2
+ id: number;
3
+ timestamp: string;
4
+ severity: 'critical' | 'warning' | 'info';
5
+ message: string;
6
+ source: string;
7
+ }
8
+
9
+ export const ALERT_MOCKS: AlertData[] = [
10
+ {
11
+ id: 1,
12
+ timestamp: '2026-03-24T10:32:00Z',
13
+ severity: 'critical',
14
+ message: 'Node B-12 unresponsive for 5 minutes',
15
+ source: 'Network Monitor',
16
+ },
17
+ {
18
+ id: 2,
19
+ timestamp: '2026-03-24T10:28:00Z',
20
+ severity: 'warning',
21
+ message: 'CPU usage above 85% on Cluster A',
22
+ source: 'Resource Monitor',
23
+ },
24
+ {
25
+ id: 3,
26
+ timestamp: '2026-03-24T10:15:00Z',
27
+ severity: 'info',
28
+ message: 'AI detected anomalous traffic pattern in Zone 3',
29
+ source: 'AI Insights',
30
+ },
31
+ {
32
+ id: 4,
33
+ timestamp: '2026-03-24T09:58:00Z',
34
+ severity: 'warning',
35
+ message: 'SSL certificate expires in 7 days for api.example.com',
36
+ source: 'Cert Monitor',
37
+ },
38
+ {
39
+ id: 5,
40
+ timestamp: '2026-03-24T09:45:00Z',
41
+ severity: 'info',
42
+ message: 'Auto-scaling triggered: +2 instances in Region US-East',
43
+ source: 'AI Insights',
44
+ },
45
+ ];
frontend/src/app/core/mocks/kpi.mock.ts ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export interface KpiData {
2
+ title: string;
3
+ value: string;
4
+ unit?: string;
5
+ trend: 'up' | 'down' | 'stable';
6
+ trendLabel: string;
7
+ icon: string;
8
+ }
9
+
10
+ export const KPI_MOCKS: KpiData[] = [
11
+ {
12
+ title: 'Network Health',
13
+ value: '98.2',
14
+ unit: '%',
15
+ trend: 'up',
16
+ trendLabel: '+1.5% from last hour',
17
+ icon: 'hub',
18
+ },
19
+ {
20
+ title: 'Critical Incidents',
21
+ value: '3',
22
+ trend: 'down',
23
+ trendLabel: '-2 from yesterday',
24
+ icon: 'error_outline',
25
+ },
26
+ {
27
+ title: 'Threat Severity',
28
+ value: 'Low',
29
+ trend: 'stable',
30
+ trendLabel: 'No change',
31
+ icon: 'shield',
32
+ },
33
+ {
34
+ title: 'Site Availability',
35
+ value: '99.97',
36
+ unit: '%',
37
+ trend: 'up',
38
+ trendLabel: '+0.03% this week',
39
+ icon: 'cloud_done',
40
+ },
41
+ ];
frontend/src/app/dashboard/alert-list/alert-list.html ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <mat-card class="alert-card" appearance="outlined">
2
+ <mat-card-content>
3
+ <h3 class="alert-title">Recent Alerts &amp; AI Insights</h3>
4
+ <ul class="alert-list">
5
+ @for (alert of alerts(); track alert.id) {
6
+ <li class="alert-item">
7
+ <mat-icon [class]="'severity-icon severity-' + alert.severity">
8
+ {{ severityIcon(alert.severity) }}
9
+ </mat-icon>
10
+ <div class="alert-body">
11
+ <span class="alert-message">{{ alert.message }}</span>
12
+ <span class="alert-meta">
13
+ {{ alert.source }} · {{ alert.timestamp | date: 'HH:mm' }}
14
+ </span>
15
+ </div>
16
+ <span [class]="'severity-badge severity-' + alert.severity">
17
+ {{ alert.severity }}
18
+ </span>
19
+ </li>
20
+ }
21
+ </ul>
22
+ </mat-card-content>
23
+ </mat-card>
frontend/src/app/dashboard/alert-list/alert-list.scss ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ .alert-card {
6
+ border-radius: var(--pf-radius-md);
7
+ }
8
+
9
+ .alert-title {
10
+ font: var(--mat-sys-title-medium);
11
+ color: var(--mat-sys-on-surface);
12
+ margin: 0 0 var(--pf-spacing-md);
13
+ }
14
+
15
+ .alert-list {
16
+ list-style: none;
17
+ margin: 0;
18
+ padding: 0;
19
+ display: flex;
20
+ flex-direction: column;
21
+ gap: var(--pf-spacing-sm);
22
+ }
23
+
24
+ .alert-item {
25
+ display: flex;
26
+ align-items: flex-start;
27
+ gap: var(--pf-spacing-md);
28
+ padding: var(--pf-spacing-md);
29
+ border-radius: var(--pf-radius-sm);
30
+ background: var(--mat-sys-surface-container-low);
31
+ }
32
+
33
+ .severity-icon {
34
+ font-size: 20px;
35
+ width: 20px;
36
+ height: 20px;
37
+ flex-shrink: 0;
38
+ margin-top: 2px;
39
+
40
+ &.severity-critical {
41
+ color: var(--pf-severity-critical);
42
+ }
43
+
44
+ &.severity-warning {
45
+ color: var(--pf-severity-warning);
46
+ }
47
+
48
+ &.severity-info {
49
+ color: var(--pf-severity-info);
50
+ }
51
+ }
52
+
53
+ .alert-body {
54
+ flex: 1;
55
+ display: flex;
56
+ flex-direction: column;
57
+ gap: var(--pf-spacing-xs);
58
+ }
59
+
60
+ .alert-message {
61
+ font: var(--mat-sys-body-medium);
62
+ color: var(--mat-sys-on-surface);
63
+ }
64
+
65
+ .alert-meta {
66
+ font: var(--mat-sys-label-small);
67
+ color: var(--mat-sys-on-surface-variant);
68
+ }
69
+
70
+ .severity-badge {
71
+ flex-shrink: 0;
72
+ font: var(--mat-sys-label-small);
73
+ padding: var(--pf-spacing-xs) var(--pf-spacing-sm);
74
+ border-radius: var(--pf-radius-sm);
75
+ text-transform: uppercase;
76
+ letter-spacing: 0.5px;
77
+
78
+ &.severity-critical {
79
+ background: rgba(211, 47, 47, 0.1);
80
+ color: var(--pf-severity-critical);
81
+ }
82
+
83
+ &.severity-warning {
84
+ background: rgba(237, 108, 2, 0.1);
85
+ color: var(--pf-severity-warning);
86
+ }
87
+
88
+ &.severity-info {
89
+ background: rgba(2, 136, 209, 0.1);
90
+ color: var(--pf-severity-info);
91
+ }
92
+ }
frontend/src/app/dashboard/alert-list/alert-list.ts ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, input } from '@angular/core';
2
+ import { DatePipe } from '@angular/common';
3
+ import { MatCard, MatCardContent } from '@angular/material/card';
4
+ import { MatIcon } from '@angular/material/icon';
5
+ import { AlertData } from '../../core/mocks/alerts.mock';
6
+
7
+ @Component({
8
+ selector: 'app-alert-list',
9
+ imports: [DatePipe, MatCard, MatCardContent, MatIcon],
10
+ templateUrl: './alert-list.html',
11
+ styleUrl: './alert-list.scss',
12
+ })
13
+ export class AlertList {
14
+ alerts = input.required<AlertData[]>();
15
+
16
+ protected severityIcon(severity: AlertData['severity']): string {
17
+ const icons: Record<string, string> = {
18
+ critical: 'error',
19
+ warning: 'warning',
20
+ info: 'info',
21
+ };
22
+ return icons[severity];
23
+ }
24
+ }
frontend/src/app/dashboard/chart-placeholder/chart-placeholder.html ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ <mat-card class="chart-card" appearance="outlined">
2
+ <mat-card-content>
3
+ <h3 class="chart-title">{{ title() }}</h3>
4
+ <div class="chart-area">
5
+ <mat-icon class="chart-icon">bar_chart</mat-icon>
6
+ <span class="chart-label">Chart library not yet installed</span>
7
+ </div>
8
+ </mat-card-content>
9
+ </mat-card>
frontend/src/app/dashboard/chart-placeholder/chart-placeholder.scss ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ .chart-card {
6
+ height: 100%;
7
+ border-radius: var(--pf-radius-md);
8
+ }
9
+
10
+ .chart-title {
11
+ font: var(--mat-sys-title-medium);
12
+ color: var(--mat-sys-on-surface);
13
+ margin: 0 0 var(--pf-spacing-md);
14
+ }
15
+
16
+ .chart-area {
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: center;
20
+ justify-content: center;
21
+ min-height: 200px;
22
+ border: 2px dashed var(--mat-sys-outline-variant);
23
+ border-radius: var(--pf-radius-sm);
24
+ gap: var(--pf-spacing-sm);
25
+ }
26
+
27
+ .chart-icon {
28
+ font-size: 48px;
29
+ width: 48px;
30
+ height: 48px;
31
+ color: var(--mat-sys-outline);
32
+ }
33
+
34
+ .chart-label {
35
+ font: var(--mat-sys-body-medium);
36
+ color: var(--mat-sys-on-surface-variant);
37
+ }
frontend/src/app/dashboard/chart-placeholder/chart-placeholder.ts ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, input } from '@angular/core';
2
+ import { MatCard, MatCardContent } from '@angular/material/card';
3
+ import { MatIcon } from '@angular/material/icon';
4
+
5
+ @Component({
6
+ selector: 'app-chart-placeholder',
7
+ imports: [MatCard, MatCardContent, MatIcon],
8
+ templateUrl: './chart-placeholder.html',
9
+ styleUrl: './chart-placeholder.scss',
10
+ })
11
+ export class ChartPlaceholder {
12
+ title = input.required<string>();
13
+ }
frontend/src/app/dashboard/dashboard.html ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <section class="dashboard">
2
+ <header class="dashboard-header">
3
+ <h1 class="dashboard-title">PulseFabric Monitor</h1>
4
+ <p class="dashboard-subtitle">Real-time infrastructure monitoring dashboard</p>
5
+ </header>
6
+
7
+ <div class="kpi-grid">
8
+ @for (kpi of kpis; track kpi.title) {
9
+ <app-kpi-card
10
+ [title]="kpi.title"
11
+ [value]="kpi.value"
12
+ [unit]="kpi.unit ?? ''"
13
+ [trend]="kpi.trend"
14
+ [trendLabel]="kpi.trendLabel"
15
+ [icon]="kpi.icon"
16
+ />
17
+ }
18
+ </div>
19
+
20
+ <div class="chart-grid">
21
+ <app-chart-placeholder title="Network Traffic (24h)" />
22
+ <app-chart-placeholder title="Incident Trend (7d)" />
23
+ </div>
24
+
25
+ <app-alert-list [alerts]="alerts" />
26
+
27
+ <div id="ai-dropzone" class="ai-dropzone">
28
+ <span class="dropzone-label">AI Widget Drop Zone</span>
29
+ </div>
30
+ </section>
frontend/src/app/dashboard/dashboard.scss ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ .dashboard {
6
+ max-width: var(--pf-content-max-width);
7
+ margin: 0 auto;
8
+ padding: var(--pf-spacing-xl);
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: var(--pf-spacing-xl);
12
+ }
13
+
14
+ .dashboard-header {
15
+ padding: var(--pf-spacing-lg) 0;
16
+ }
17
+
18
+ .dashboard-title {
19
+ font: var(--mat-sys-headline-large);
20
+ color: var(--mat-sys-on-surface);
21
+ margin: 0;
22
+ }
23
+
24
+ .dashboard-subtitle {
25
+ font: var(--mat-sys-body-large);
26
+ color: var(--mat-sys-on-surface-variant);
27
+ margin: var(--pf-spacing-xs) 0 0;
28
+ }
29
+
30
+ .kpi-grid {
31
+ display: grid;
32
+ grid-template-columns: repeat(4, 1fr);
33
+ gap: var(--pf-spacing-lg);
34
+ }
35
+
36
+ .chart-grid {
37
+ display: grid;
38
+ grid-template-columns: repeat(2, 1fr);
39
+ gap: var(--pf-spacing-lg);
40
+ }
41
+
42
+ .ai-dropzone {
43
+ min-height: 120px;
44
+ border: 2px dashed var(--mat-sys-outline-variant);
45
+ border-radius: var(--pf-radius-md);
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ }
50
+
51
+ .dropzone-label {
52
+ font: var(--mat-sys-body-medium);
53
+ color: var(--mat-sys-outline);
54
+ }
55
+
56
+ @media (max-width: 1024px) {
57
+ .kpi-grid {
58
+ grid-template-columns: repeat(2, 1fr);
59
+ }
60
+ }
61
+
62
+ @media (max-width: 600px) {
63
+ .kpi-grid,
64
+ .chart-grid {
65
+ grid-template-columns: 1fr;
66
+ }
67
+
68
+ .dashboard {
69
+ padding: var(--pf-spacing-md);
70
+ }
71
+ }
frontend/src/app/dashboard/dashboard.ts ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component } from '@angular/core';
2
+ import { KpiCard } from './kpi-card/kpi-card';
3
+ import { ChartPlaceholder } from './chart-placeholder/chart-placeholder';
4
+ import { AlertList } from './alert-list/alert-list';
5
+ import { KPI_MOCKS } from '../core/mocks/kpi.mock';
6
+ import { ALERT_MOCKS } from '../core/mocks/alerts.mock';
7
+
8
+ @Component({
9
+ selector: 'app-dashboard',
10
+ imports: [KpiCard, ChartPlaceholder, AlertList],
11
+ templateUrl: './dashboard.html',
12
+ styleUrl: './dashboard.scss',
13
+ })
14
+ export class Dashboard {
15
+ protected readonly kpis = KPI_MOCKS;
16
+ protected readonly alerts = ALERT_MOCKS;
17
+ }
frontend/src/app/dashboard/kpi-card/kpi-card.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <mat-card class="kpi-card" appearance="outlined">
2
+ <mat-card-content>
3
+ <div class="kpi-header">
4
+ <mat-icon class="kpi-icon">{{ icon() }}</mat-icon>
5
+ <span class="kpi-title">{{ title() }}</span>
6
+ </div>
7
+ <div class="kpi-value">
8
+ {{ value() }}
9
+ @if (unit()) {
10
+ <span class="kpi-unit">{{ unit() }}</span>
11
+ }
12
+ </div>
13
+ <div class="kpi-trend" [class]="'kpi-trend trend-' + trend()">
14
+ <mat-icon class="trend-icon">{{ trendIcon() }}</mat-icon>
15
+ <span>{{ trendLabel() }}</span>
16
+ </div>
17
+ </mat-card-content>
18
+ </mat-card>
frontend/src/app/dashboard/kpi-card/kpi-card.scss ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :host {
2
+ display: block;
3
+ }
4
+
5
+ .kpi-card {
6
+ height: 100%;
7
+ border-radius: var(--pf-radius-md);
8
+ }
9
+
10
+ .kpi-header {
11
+ display: flex;
12
+ align-items: center;
13
+ gap: var(--pf-spacing-sm);
14
+ margin-bottom: var(--pf-spacing-md);
15
+ }
16
+
17
+ .kpi-icon {
18
+ color: var(--mat-sys-primary);
19
+ font-size: 20px;
20
+ width: 20px;
21
+ height: 20px;
22
+ }
23
+
24
+ .kpi-title {
25
+ font: var(--mat-sys-title-small);
26
+ color: var(--mat-sys-on-surface-variant);
27
+ }
28
+
29
+ .kpi-value {
30
+ font: var(--mat-sys-display-small);
31
+ color: var(--mat-sys-on-surface);
32
+ margin-bottom: var(--pf-spacing-sm);
33
+ }
34
+
35
+ .kpi-unit {
36
+ font: var(--mat-sys-title-medium);
37
+ color: var(--mat-sys-on-surface-variant);
38
+ }
39
+
40
+ .kpi-trend {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: var(--pf-spacing-xs);
44
+ font: var(--mat-sys-label-medium);
45
+ }
46
+
47
+ .trend-icon {
48
+ font-size: 16px;
49
+ width: 16px;
50
+ height: 16px;
51
+ }
52
+
53
+ .trend-up {
54
+ color: #2e7d32;
55
+ }
56
+
57
+ .trend-down {
58
+ color: var(--pf-severity-critical);
59
+ }
60
+
61
+ .trend-stable {
62
+ color: var(--mat-sys-on-surface-variant);
63
+ }
frontend/src/app/dashboard/kpi-card/kpi-card.ts ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Component, computed, input } from '@angular/core';
2
+ import { MatCard, MatCardContent } from '@angular/material/card';
3
+ import { MatIcon } from '@angular/material/icon';
4
+
5
+ @Component({
6
+ selector: 'app-kpi-card',
7
+ imports: [MatCard, MatCardContent, MatIcon],
8
+ templateUrl: './kpi-card.html',
9
+ styleUrl: './kpi-card.scss',
10
+ })
11
+ export class KpiCard {
12
+ title = input.required<string>();
13
+ value = input.required<string>();
14
+ unit = input<string>();
15
+ trend = input.required<'up' | 'down' | 'stable'>();
16
+ trendLabel = input.required<string>();
17
+ icon = input.required<string>();
18
+
19
+ protected trendIcon = computed(() => {
20
+ const icons: Record<string, string> = {
21
+ up: 'trending_up',
22
+ down: 'trending_down',
23
+ stable: 'trending_flat',
24
+ };
25
+ return icons[this.trend()];
26
+ });
27
+ }
frontend/src/app/shared/styles/_tokens.scss ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root {
2
+ // Spacing
3
+ --pf-spacing-xs: 4px;
4
+ --pf-spacing-sm: 8px;
5
+ --pf-spacing-md: 16px;
6
+ --pf-spacing-lg: 24px;
7
+ --pf-spacing-xl: 32px;
8
+ --pf-spacing-2xl: 48px;
9
+
10
+ // Border radius
11
+ --pf-radius-sm: 8px;
12
+ --pf-radius-md: 12px;
13
+ --pf-radius-lg: 16px;
14
+
15
+ // Shadows
16
+ --pf-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
17
+ --pf-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.1);
18
+
19
+ // Layout
20
+ --pf-content-max-width: 1400px;
21
+ --pf-header-height: 64px;
22
+
23
+ // Severity colors
24
+ --pf-severity-critical: #d32f2f;
25
+ --pf-severity-warning: #ed6c02;
26
+ --pf-severity-info: #0288d1;
27
+ }
frontend/src/index.html ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>PulseFabric Monitor</title>
6
+ <base href="/" />
7
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
8
+ <link rel="icon" type="image/x-icon" href="favicon.ico" />
9
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
10
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
11
+ <link
12
+ href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap"
13
+ rel="stylesheet"
14
+ />
15
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
16
+ </head>
17
+ <body>
18
+ <app-root></app-root>
19
+ </body>
20
+ </html>
frontend/src/main.ts ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import { bootstrapApplication } from '@angular/platform-browser';
2
+ import { appConfig } from './app/app.config';
3
+ import { App } from './app/app';
4
+
5
+ bootstrapApplication(App, appConfig)
6
+ .catch((err) => console.error(err));
frontend/src/styles.scss ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Include theming for Angular Material with `mat.theme()`.
2
+ // This Sass mixin will define CSS variables that are used for styling Angular Material
3
+ // components according to the Material 3 design spec.
4
+ // Learn more about theming and how to use it for your application's
5
+ // custom components at https://material.angular.dev/guide/theming
6
+ @use '@angular/material' as mat;
7
+ @use 'app/shared/styles/tokens';
8
+
9
+ html {
10
+ height: 100%;
11
+ @include mat.theme(
12
+ (
13
+ color: (
14
+ primary: mat.$violet-palette,
15
+ tertiary: mat.$blue-palette,
16
+ ),
17
+ typography: Roboto,
18
+ density: 0,
19
+ )
20
+ );
21
+ }
22
+
23
+ body {
24
+ // Default the application to a light color theme. This can be changed to
25
+ // `dark` to enable the dark color theme, or to `light dark` to defer to the
26
+ // user's system settings.
27
+ color-scheme: light;
28
+
29
+ // Set a default background, font and text colors for the application using
30
+ // Angular Material's system-level CSS variables. Learn more about these
31
+ // variables at https://material.angular.dev/guide/system-variables
32
+ background-color: var(--mat-sys-surface);
33
+ color: var(--mat-sys-on-surface);
34
+ font: var(--mat-sys-body-medium);
35
+
36
+ // Reset the user agent margin.
37
+ margin: 0;
38
+ height: 100%;
39
+ }
40
+ /* You can add global styles to this file, and also import other style files */
frontend/tsconfig.app.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2
+ /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3
+ {
4
+ "extends": "./tsconfig.json",
5
+ "compilerOptions": {
6
+ "outDir": "./out-tsc/app",
7
+ "types": []
8
+ },
9
+ "include": [
10
+ "src/**/*.ts"
11
+ ],
12
+ "exclude": [
13
+ "src/**/*.spec.ts"
14
+ ]
15
+ }
frontend/tsconfig.json ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2
+ /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3
+ {
4
+ "compileOnSave": false,
5
+ "compilerOptions": {
6
+ "strict": true,
7
+ "noImplicitOverride": true,
8
+ "noPropertyAccessFromIndexSignature": true,
9
+ "noImplicitReturns": true,
10
+ "noFallthroughCasesInSwitch": true,
11
+ "skipLibCheck": true,
12
+ "isolatedModules": true,
13
+ "experimentalDecorators": true,
14
+ "importHelpers": true,
15
+ "target": "ES2022",
16
+ "module": "preserve"
17
+ },
18
+ "angularCompilerOptions": {
19
+ "enableI18nLegacyMessageIdFormat": false,
20
+ "strictInjectionParameters": true,
21
+ "strictInputAccessModifiers": true,
22
+ "strictTemplates": true
23
+ },
24
+ "files": [],
25
+ "references": [
26
+ {
27
+ "path": "./tsconfig.app.json"
28
+ }
29
+ ]
30
+ }
frontend/tsconfig.spec.json ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
2
+ /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
3
+ {
4
+ "extends": "./tsconfig.json",
5
+ "compilerOptions": {
6
+ "outDir": "./out-tsc/spec",
7
+ "types": [
8
+ "vitest/globals"
9
+ ]
10
+ },
11
+ "include": [
12
+ "src/**/*.d.ts",
13
+ "src/**/*.spec.ts"
14
+ ]
15
+ }