From b759195e1bb7b83747a726a75877cab2daec257f Mon Sep 17 00:00:00 2001
From: Lennard Strohmeyer <lennard.strohmeyer@digitallearning.gmbh>
Date: Thu, 20 Mar 2025 00:14:02 +0100
Subject: [PATCH] Visual and structural changes of administration area and
 expand panels

---
 src/frontend/src/app/app-routing.module.ts    |  2 +
 src/frontend/src/app/app.module.ts            | 80 ++++++++++---------
 .../consent-history.component.html            |  4 +-
 .../provider-setting.component.html           |  2 +-
 .../schema-change.component.html              |  2 +-
 .../verb-groups/verb-groups.component.html    |  4 +-
 .../wizard/wizard.component.html              |  2 +-
 .../control-center.component.html             | 61 ++++++--------
 .../control-center.component.scss             | 23 ++----
 .../control-center.component.ts               | 70 ++++++++--------
 .../app/dashboard/dashboard.component.html    | 22 +++++
 .../app/dashboard/dashboard.component.scss    | 16 ++++
 .../app/dashboard/dashboard.component.spec.ts | 23 ++++++
 .../src/app/dashboard/dashboard.component.ts  | 53 ++++++++++++
 .../navigation/header/header.component.html   | 25 ++++--
 src/frontend/src/locale/messages.de.xlf       | 10 ++-
 src/frontend/src/locale/messages.xlf          |  7 +-
 17 files changed, 262 insertions(+), 144 deletions(-)
 create mode 100644 src/frontend/src/app/dashboard/dashboard.component.html
 create mode 100644 src/frontend/src/app/dashboard/dashboard.component.scss
 create mode 100644 src/frontend/src/app/dashboard/dashboard.component.spec.ts
 create mode 100644 src/frontend/src/app/dashboard/dashboard.component.ts

diff --git a/src/frontend/src/app/app-routing.module.ts b/src/frontend/src/app/app-routing.module.ts
index 6948d65..0e12790 100644
--- a/src/frontend/src/app/app-routing.module.ts
+++ b/src/frontend/src/app/app-routing.module.ts
@@ -16,9 +16,11 @@ import { AnalyticsTokensComponent } from './analytics-tokens/analytics-tokens.co
 import { AnalyticsEngineComponent } from './analytics-engine/analytics-engine.component'
 import { ConsentHistoryComponent } from './consent-management/consent-history/consent-history.component'
 import { ControlCenterComponent } from './control-center/control-center.component'
+import { DashboardComponent } from './dashboard/dashboard.component'
 
 const routes: Routes = [
   { path: 'home', component: HomeComponent },
+  { path: 'dashboard', component: DashboardComponent },
   { path: 'consent-management', component: ConsentManagementComponent, canActivate: [AuthGuard] },
   { path: 'consent-history', component: ConsentHistoryComponent, canActivate: [AuthGuard] },
   { path: 'control-center', component: ControlCenterComponent, canActivate: [AuthGuard]},
diff --git a/src/frontend/src/app/app.module.ts b/src/frontend/src/app/app.module.ts
index 5cffa71..a99fa7b 100644
--- a/src/frontend/src/app/app.module.ts
+++ b/src/frontend/src/app/app.module.ts
@@ -1,5 +1,6 @@
 import { NgModule, APP_INITIALIZER } from '@angular/core'
 import { BrowserModule } from '@angular/platform-browser'
+import { CommonModule } from '@angular/common';
 
 import { AppRoutingModule } from './app-routing.module'
 import { AppComponent } from './app.component'
@@ -82,6 +83,7 @@ import { NzRadioModule } from 'ng-zorro-antd/radio'
 import { PrivacyPolicyDialog } from './dialogs/privacy-policy-dialog/privacy-policy-dialog'
 import { MarkdownEditorComponent } from './helper-components/markdown-editor/markdown-editor.component'
 import { ResultToolsComponent } from './control-center/result-tools/result-tools.component'
+import { DashboardComponent } from './dashboard/dashboard.component'
 
 registerLocaleData(de)
 
@@ -118,46 +120,48 @@ registerLocaleData(de)
     PrivacyPolicyDialog,
     MarkdownEditorComponent,
     ResultToolsComponent,
+    DashboardComponent
   ],
     imports: [
-        BrowserModule,
-        AppRoutingModule,
-        LayoutModule,
-        FormsModule,
-        ReactiveFormsModule,
-        HttpClientModule,
-        BrowserAnimationsModule,
-        NzTabsModule,
-        NzGridModule,
-        NzCardModule,
-        NzButtonModule,
-        FontAwesomeModule,
-        NzLayoutModule,
-        NgOptimizedImage,
-        NzMenuModule,
-        NzAffixModule,
-        NzSwitchModule,
-        NzDropDownModule,
-        NzCollapseModule,
-        NzListModule,
-        NzToolTipModule,
-        NzSelectModule,
-        NzInputModule,
-        NzSpaceModule,
-        NzFormModule,
-        NzBadgeModule,
-        NzTagModule,
-        NzTableModule,
-        NzCheckboxModule,
-        NzProgressModule,
-        NzAlertModule,
-        NzModalModule,
-        NzSpinModule,
-        NzDatePickerModule,
-        MarkdownModule.forRoot(),
-        NzRadioModule,
-        NzStatisticModule,
-        NzIconModule
+      CommonModule,
+      BrowserModule,
+      AppRoutingModule,
+      LayoutModule,
+      FormsModule,
+      ReactiveFormsModule,
+      HttpClientModule,
+      BrowserAnimationsModule,
+      NzTabsModule,
+      NzGridModule,
+      NzCardModule,
+      NzButtonModule,
+      FontAwesomeModule,
+      NzLayoutModule,
+      NgOptimizedImage,
+      NzMenuModule,
+      NzAffixModule,
+      NzSwitchModule,
+      NzDropDownModule,
+      NzCollapseModule,
+      NzListModule,
+      NzToolTipModule,
+      NzSelectModule,
+      NzInputModule,
+      NzSpaceModule,
+      NzFormModule,
+      NzBadgeModule,
+      NzTagModule,
+      NzTableModule,
+      NzCheckboxModule,
+      NzProgressModule,
+      NzAlertModule,
+      NzModalModule,
+      NzSpinModule,
+      NzDatePickerModule,
+      MarkdownModule.forRoot(),
+      NzRadioModule,
+      NzStatisticModule,
+      NzIconModule
     ],
   providers: [
     {
diff --git a/src/frontend/src/app/consent-management/consent-history/consent-history.component.html b/src/frontend/src/app/consent-management/consent-history/consent-history.component.html
index 94d5fce..57cb987 100644
--- a/src/frontend/src/app/consent-management/consent-history/consent-history.component.html
+++ b/src/frontend/src/app/consent-management/consent-history/consent-history.component.html
@@ -5,7 +5,7 @@
 </p>
 <p>&nbsp;</p>
 
-<nz-collapse>
+<nz-collapse nzExpandIconPosition="right">
   <nz-collapse-panel [nzHeader]="faqPauseHeader">
     <ng-template #faqPauseHeader>
       Was passiert, wenn ich die Datenübertragung pausiere?
@@ -39,7 +39,7 @@
 
 <h2>Deine Einwilligungen</h2>
 
-<nz-collapse *ngFor="let group_data of consentHistory">
+<nz-collapse *ngFor="let group_data of consentHistory" nzExpandIconPosition="right">
   <nz-collapse-panel [nzHeader]="groupConsentPanelHeader">
     <ng-template #groupConsentPanelHeader>
       <div class="consent-header">
diff --git a/src/frontend/src/app/consent-management/provider-settings/provider-setting.component.html b/src/frontend/src/app/consent-management/provider-settings/provider-setting.component.html
index 08575b2..1b5ea37 100644
--- a/src/frontend/src/app/consent-management/provider-settings/provider-setting.component.html
+++ b/src/frontend/src/app/consent-management/provider-settings/provider-setting.component.html
@@ -16,7 +16,7 @@
       [ngClass]="{ inactive: !consentGroup.isDefault && isGroupActive(consentGroup) }" *ngIf="consentGroup.showVerbDetails">
       <nz-collapse-panel [nzActive]="consentGroup.isDefault" nzHeader="Details">
 
-        <nz-collapse>
+        <nz-collapse nzExpandIconPosition="right">
           <nz-collapse-panel *ngFor="let verb of consentGroup.verbs | orderBy:'label'; index as fieldIdx" [nzHeader]="headerTemplate">
             <ng-template #headerTemplate>
               <div class="setting">
diff --git a/src/frontend/src/app/consent-management/schema-change/schema-change.component.html b/src/frontend/src/app/consent-management/schema-change/schema-change.component.html
index f07f8e0..fd618f2 100644
--- a/src/frontend/src/app/consent-management/schema-change/schema-change.component.html
+++ b/src/frontend/src/app/consent-management/schema-change/schema-change.component.html
@@ -1,4 +1,4 @@
-<nz-collapse>
+<nz-collapse nzExpandIconPosition="right">
   <nz-collapse-panel [nzHeader]="panelHeader">
     <ng-template #panelHeader>
       <span i18n="Schema Changes | Header @@schemaChanges">
diff --git a/src/frontend/src/app/consent-management/verb-groups/verb-groups.component.html b/src/frontend/src/app/consent-management/verb-groups/verb-groups.component.html
index 29e706a..1382071 100644
--- a/src/frontend/src/app/consent-management/verb-groups/verb-groups.component.html
+++ b/src/frontend/src/app/consent-management/verb-groups/verb-groups.component.html
@@ -1,4 +1,4 @@
-<nz-collapse>
+<nz-collapse nzExpandIconPosition="right">
   <nz-collapse-panel [nzHeader]="panelHeader">
     <ng-template #panelHeader>
       <span i18n="Verb Groups | Header @@groups">
@@ -6,7 +6,7 @@
       </span>
     </ng-template>
 
-    <nz-collapse>
+    <nz-collapse nzExpandIconPosition="right">
       <nz-collapse-panel *ngFor="let group of verbGroups.concat(additionalVerbGroups)" [nzHeader]="group.label">
         <p class="subheader" i18n="Description @@description">>
           Description
diff --git a/src/frontend/src/app/consent-management/wizard/wizard.component.html b/src/frontend/src/app/consent-management/wizard/wizard.component.html
index 013677f..efe2078 100644
--- a/src/frontend/src/app/consent-management/wizard/wizard.component.html
+++ b/src/frontend/src/app/consent-management/wizard/wizard.component.html
@@ -28,7 +28,7 @@
         {{ getSelectedProvider()?.name }}
       </h2>
       <div *ngFor="let group_data of getSelectedProvider()?.groups">
-        <nz-collapse *ngIf="Object.keys(groupsToConsent).includes(String(group_data.id))">
+        <nz-collapse *ngIf="Object.keys(groupsToConsent).includes(String(group_data.id))" nzExpandIconPosition="right">
           <nz-collapse-panel [nzHeader]="groupConsentPanelHeader">
             <ng-template #groupConsentPanelHeader>
               <div class="consent-header">
diff --git a/src/frontend/src/app/control-center/control-center.component.html b/src/frontend/src/app/control-center/control-center.component.html
index 8aa4e85..3ed7c26 100644
--- a/src/frontend/src/app/control-center/control-center.component.html
+++ b/src/frontend/src/app/control-center/control-center.component.html
@@ -7,43 +7,26 @@
 <nz-tabset>
 
 
-  <nz-tab [nzTitle]="tabTitleOverview">
-    <ng-template i18n="Overview @@Overview" #tabTitleOverview>
-      Übersicht
-    </ng-template>
-
-    <div class="statistic-container">
-      <nz-card class="statistic-card" [nzBordered]="true">
-      <nz-statistic [nzTitle]="'Number of Users'" [nzValue]="this.statistics?.user_count"></nz-statistic>
-    </nz-card>
-    <nz-card class="statistic-card" [nzBordered]="true">
-      <nz-statistic [nzTitle]="'Number of Statements'" [nzValue]="this.statistics?.statement_count"></nz-statistic>
-    </nz-card>
-    <nz-card class="statistic-card" [nzBordered]="true">
-      <nz-statistic [nzTitle]="'Number of Results'" [nzValue]="this.statistics?.result_count"></nz-statistic>
-    </nz-card>
-
-    <nz-card class="statistic-card" [nzBordered]="true">
-      <div class="chart-container">
-        <canvas #chartCanvas></canvas>
-      </div>
-    </nz-card>
-
-  </div>
-
-  </nz-tab>
-
   <nz-tab [nzTitle]="tabTitleUsers">
     <ng-template i18n="Users @@usersAndRoles" #tabTitleUsers>
       Users
     </ng-template>
+
+    <div class="table-header">
+      <input
+        nz-input
+        [(ngModel)]="userSearchText"
+        (ngModelChange)="onUserSearch()"
+        placeholder="Nutzer*in suchen..."
+      >
+    </div>
+
     <nz-table
       #userTable
-      [nzData]="this.users"
+      [nzData]="this.filteredUsers"
     >
       <thead>
       <tr>
-        <th></th>
         <th>#</th>
         <th>Vorname</th>
         <th>Nachname</th>
@@ -51,13 +34,12 @@
         <th>Admin</th>
         <th>Pausiert</th>
         <th>Datenschutzerklärung</th>
+        <th></th>
       </tr>
       </thead>
       <tbody>
       <ng-container *ngFor="let user of userTable.data">
         <tr>
-          <td [nzExpand]="expandSet.has(user.id)"
-              (nzExpandChange)="onExpandChange(user.id, $event)"></td>
           <td>{{user.id}}</td>
           <td>{{user.first_name}}</td>
           <td>{{user.last_name}}</td>
@@ -65,15 +47,22 @@
           <td>{{user.is_superuser ? "ja" : "nein"}}</td>
           <td>{{user.paused_data_recording ? "ja" : "nein"}}</td>
           <td>{{user.general_privacy_policy ? "ja" : "nein"}}</td>
+          <td [nzExpand]="expandSet.has(user.id)"
+              (nzExpandChange)="onExpandChange(user.id, $event)"></td>
         </tr>
         <tr [nzExpand]="expandSet.has(user.id)">
           <td [attr.colspan]="8">
             <nz-tabset>
-              <nz-tab nzTitle="Rollen">
+              <nz-tab nzTitle="Rollen verwalten">
                 <h3>Rollen</h3>
                 <nz-checkbox-group [(ngModel)]="user_group_checkboxes[user.id]" (ngModelChange)="user_permissions_changed[user.id] = true">
                 </nz-checkbox-group>
-                <button nz-button [disabled]="!user_permissions_changed[user.id]" style="float: right" (click)="saveUserPermissions(user.id)">Speichern</button>
+                <p></p>
+                <button nz-button nzType="primary" [disabled]="!user_permissions_changed[user.id]" style="float: right" (click)="saveUserPermissions(user.id)">Speichern</button>
+              </nz-tab>
+
+              <nz-tab nzTitle="Datenauskunft erstellen">
+                ...
               </nz-tab>
             </nz-tabset>
 
@@ -124,7 +113,7 @@
       <button *nzSpaceItem nz-button nzType="default" (click)="generateStatement()">Generate Statement</button>
       </nz-space>
       <div class="response-container" *ngIf="this.responseMessage">
-        
+
         <nz-alert [nzType]="this.responseType" [nzMessage]="this.responseMessage" nzShowIcon></nz-alert>
       </div>
     </div>
@@ -134,7 +123,7 @@
       xAPI Statement Filter Debugger
     </h3>
     <p i18n="@@controlCenterDescription">
-      Select an analytics from the list to execute the statement fetch that can be done by the analytics  
+      Select an analytics from the list to execute the statement fetch that can be done by the analytics
     </p>
     <nz-select [(ngModel)]="selectedAnalysis" placeholder="Select Analytics">
       <nz-option *ngFor="let provider of this.analyticsToken" [nzValue]="provider" [nzLabel]="provider.name"></nz-option>
@@ -144,7 +133,7 @@
     <button *nzSpaceItem nz-button nzType="primary" (click)="sendFilter()">Get statements</button>
     </nz-space>
     <div class="response-container" *ngIf="this.responseStatementMessage">
-        
+
       <nz-alert [nzType]="this.responseStatementType" [nzMessage]="this.responseStatementMessage" nzShowIcon></nz-alert>
     </div>
     </div>
@@ -157,6 +146,6 @@
       Analytics Result Tools
     </ng-template>
      <app-result-tools></app-result-tools>
-  </nz-tab>  
+  </nz-tab>
 
 </nz-tabset>
diff --git a/src/frontend/src/app/control-center/control-center.component.scss b/src/frontend/src/app/control-center/control-center.component.scss
index 7433511..7fd8275 100644
--- a/src/frontend/src/app/control-center/control-center.component.scss
+++ b/src/frontend/src/app/control-center/control-center.component.scss
@@ -1,25 +1,18 @@
 .control-center {
   padding: 20px;
 }
-.statistic-container {
+.table-header {
   display: flex;
-  gap: 20px;
-  justify-content: center;
-}
-.statistic-card {
-  width: 300px;
-  text-align: center;
-  background-color: white !important;
-  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
-  border-radius: 8px;
-}
-.chart-container {
-  width: 100%;
-  height: 200px;
+  justify-content: flex-end;
+  margin-bottom: 10px;
+  input[nz-input] {
+    width: 250px;
+  }
 }
+
 .xapi-tools-container {
   display: flex;
   flex-direction: column;
   gap: 10px;
   padding: 20px;
-}
\ No newline at end of file
+}
diff --git a/src/frontend/src/app/control-center/control-center.component.ts b/src/frontend/src/app/control-center/control-center.component.ts
index 1944e95..2704c27 100644
--- a/src/frontend/src/app/control-center/control-center.component.ts
+++ b/src/frontend/src/app/control-center/control-center.component.ts
@@ -6,6 +6,7 @@ import { Chart, registerables } from 'chart.js';
 import { catchError } from 'rxjs/operators';
 import { of, forkJoin } from 'rxjs';
 
+
 Chart.register(...registerables);
 
 interface AuthGroupCheckbox {
@@ -23,10 +24,12 @@ type UserPermissionChangeMap = Record<number, boolean>;
 })
 export class ControlCenterComponent implements OnInit {
   protected users: AuthUser[] = [];
+  protected filteredUsers: AuthUser[] = [];
+  protected userSearchText: string = "";
+
   protected auth_permissions: AuthPermission[] = [];
   protected auth_groups: AuthGroup[] = [];
   protected privacy_policy: string = "";
-  protected statistics?: Statistics;
   protected selectedProvider?: ApplicationTokens;
   protected providers: ApplicationTokens[] = [];
   protected xapiStatement: string = '';
@@ -59,19 +62,17 @@ export class ControlCenterComponent implements OnInit {
       permissions: this._apiService.getPermissions(),
       users: this._apiService.getUsers(),
       privacy: this._apiService.getPrivacyPolicy(),
-      statistics: this._apiService.getStatistics(),
       providers: this._apiService.getApplicationTokens(),
       analyticsTokens: this._apiService.getAnalyticsTokens()
     })
-    .subscribe(({ groups, permissions, users, privacy, statistics, providers, analyticsTokens }) => {
+    .subscribe(({ groups, permissions, users, privacy, providers, analyticsTokens }) => {
       this.auth_groups = groups;
       this.auth_permissions = permissions;
       this.users = users;
+      this.filteredUsers = [...users];
       this.privacy_policy = privacy?.content || "";
-      this.statistics = statistics;
       this.providers = providers;
       this.analyticsToken = analyticsTokens;
-      this.renderChart();
 
       // Process user checkboxes
       const newGroupCheckboxes: UserGroupCheckboxMap = {};
@@ -97,36 +98,6 @@ export class ControlCenterComponent implements OnInit {
     });
   }
 
-  renderChart() {
-    // Ensure a canvas is available before rendering the chart.
-    const canvas = document.querySelector('canvas');
-    if (!canvas) return;
-    const ctx = canvas.getContext('2d');
-    if (!ctx) return;
-
-    new Chart(ctx, {
-      type: 'line',
-      data: {
-        labels: this.statistics?.statement_history.map((_, i) => `Day ${i + 1}`),
-        datasets: [{
-          label: 'Statements Over Time',
-          data: this.statistics?.statement_history,
-          borderColor: 'blue',
-          backgroundColor: 'rgba(0, 0, 255, 0.1)',
-          fill: true,
-        }]
-      },
-      options: {
-        responsive: true,
-        maintainAspectRatio: false,
-        scales: {
-          y: {
-            beginAtZero: true
-          }
-        }
-      }
-    });
-  }
 
   onExpandChange(id: number, checked: boolean): void {
     if (checked) {
@@ -137,6 +108,35 @@ export class ControlCenterComponent implements OnInit {
     }
   }
 
+
+  isFuzzyMatch(text: string, query: string): boolean {
+    let queryIndex = 0;
+
+    for (const char of text) {
+      if (char === query[queryIndex]) {
+        queryIndex++;
+      }
+      if (queryIndex === query.length) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  onUserSearch(): void {
+    const query = this.userSearchText.toLowerCase().trim();
+
+    if (!query) {
+      this.filteredUsers = [...this.users];
+      return;
+    }
+
+    this.filteredUsers = this.users.filter(item =>
+      this.isFuzzyMatch(item.first_name.toLowerCase(), query) ||
+      this.isFuzzyMatch(item.last_name.toLowerCase(), query)
+    );
+  }
+
   saveUserPermissions(user_id: number): void {
     this._apiService.saveUserPermissions(
       user_id,
diff --git a/src/frontend/src/app/dashboard/dashboard.component.html b/src/frontend/src/app/dashboard/dashboard.component.html
new file mode 100644
index 0000000..71ae241
--- /dev/null
+++ b/src/frontend/src/app/dashboard/dashboard.component.html
@@ -0,0 +1,22 @@
+<h1>Willkommen im Administrationsbereich von POLARIS.</h1>
+
+<p></p>
+
+<div class="statistic-container">
+  <nz-card class="statistic-card" [nzBordered]="true">
+    <nz-statistic [nzTitle]="'Number of Users'" [nzValue]="this.statistics?.user_count"></nz-statistic>
+  </nz-card>
+  <nz-card class="statistic-card" [nzBordered]="true">
+    <nz-statistic [nzTitle]="'Number of Statements'" [nzValue]="this.statistics?.statement_count"></nz-statistic>
+  </nz-card>
+  <nz-card class="statistic-card" [nzBordered]="true">
+    <nz-statistic [nzTitle]="'Number of Results'" [nzValue]="this.statistics?.result_count"></nz-statistic>
+  </nz-card>
+
+  <nz-card class="statistic-card" [nzBordered]="true">
+    <div class="chart-container">
+      <canvas #chartCanvas></canvas>
+    </div>
+  </nz-card>
+
+</div>
diff --git a/src/frontend/src/app/dashboard/dashboard.component.scss b/src/frontend/src/app/dashboard/dashboard.component.scss
new file mode 100644
index 0000000..4bff4b1
--- /dev/null
+++ b/src/frontend/src/app/dashboard/dashboard.component.scss
@@ -0,0 +1,16 @@
+.statistic-container {
+  display: flex;
+  gap: 20px;
+  justify-content: center;
+}
+.statistic-card {
+  width: 300px;
+  text-align: center;
+  background-color: white !important;
+  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+  border-radius: 8px;
+}
+.chart-container {
+  width: 100%;
+  height: 200px;
+}
diff --git a/src/frontend/src/app/dashboard/dashboard.component.spec.ts b/src/frontend/src/app/dashboard/dashboard.component.spec.ts
new file mode 100644
index 0000000..a5e2332
--- /dev/null
+++ b/src/frontend/src/app/dashboard/dashboard.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DashboardComponent } from './dashboard.component';
+
+describe('DashboardComponent', () => {
+  let component: DashboardComponent;
+  let fixture: ComponentFixture<DashboardComponent>;
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      declarations: [ DashboardComponent ]
+    })
+      .compileComponents();
+
+    fixture = TestBed.createComponent(DashboardComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/src/frontend/src/app/dashboard/dashboard.component.ts b/src/frontend/src/app/dashboard/dashboard.component.ts
new file mode 100644
index 0000000..c2e5f04
--- /dev/null
+++ b/src/frontend/src/app/dashboard/dashboard.component.ts
@@ -0,0 +1,53 @@
+import { Component, OnInit } from '@angular/core'
+import { ApiService, Statistics } from '../services/api.service'
+import { NzMessageService } from 'ng-zorro-antd/message'
+import { NzModalService } from 'ng-zorro-antd/modal'
+import { Chart } from 'chart.js'
+
+@Component({
+  selector: 'app-dashboard',
+  templateUrl: './dashboard.component.html',
+  styleUrls: ['./dashboard.component.scss']
+})
+export class DashboardComponent implements OnInit {
+  protected statistics?: Statistics;
+  constructor(
+    private _messageService: NzMessageService,
+    private _apiService: ApiService,
+    public dialog: NzModalService
+  ) {}
+  ngOnInit() {
+    this._apiService.getStatistics().subscribe(statistics => {this.statistics = statistics; this.renderChart();})
+  }
+
+  renderChart() {
+    // Ensure a canvas is available before rendering the chart.
+    const canvas = document.querySelector('canvas');
+    if (!canvas) return;
+    const ctx = canvas.getContext('2d');
+    if (!ctx) return;
+
+    new Chart(ctx, {
+      type: 'line',
+      data: {
+        labels: this.statistics?.statement_history.map((_, i) => `Day ${i + 1}`),
+        datasets: [{
+          label: 'Statements Over Time',
+          data: this.statistics?.statement_history,
+          borderColor: 'blue',
+          backgroundColor: 'rgba(0, 0, 255, 0.1)',
+          fill: true,
+        }]
+      },
+      options: {
+        responsive: true,
+        maintainAspectRatio: false,
+        scales: {
+          y: {
+            beginAtZero: true
+          }
+        }
+      }
+    });
+  }
+}
diff --git a/src/frontend/src/app/navigation/header/header.component.html b/src/frontend/src/app/navigation/header/header.component.html
index 69a17f5..c3cf179 100644
--- a/src/frontend/src/app/navigation/header/header.component.html
+++ b/src/frontend/src/app/navigation/header/header.component.html
@@ -38,6 +38,15 @@
       Merge Data
     </li>
 
+    <li nz-menu-item
+        routerLink="/dashboard"
+        *ngIf="loggedIn?.isProvider"
+        [nzMatchRouter]="true"
+        i18n="Dashboard | Header Entry @@dashboardHeader"
+    >
+      Dashboard
+    </li>
+
     <li nz-menu-item
         routerLink="/provider"
         *ngIf="loggedIn?.isProvider"
@@ -83,21 +92,21 @@
           {{ loggedIn.email }}
           <i nz-icon nzType="down" nzTheme="outline"></i>
         </a>
-    
+
       <nz-dropdown-menu #menu="nzDropdownMenu">
         <ul nz-menu>
           <li nz-menu-item routerLink="/profil">
             <span class="menu-item">
               <fa-icon [icon]="faUser" class="menu-icon"></fa-icon>
-              <span class="menu-text" 
+              <span class="menu-text"
                     i18n="Profile | Header profile dropdown entry @@profileProfileDropDown">
                 Profile
               </span>
             </span>
           </li>
-    
-          <li nz-menu-item 
-              routerLink="/data-disclosure" 
+
+          <li nz-menu-item
+              routerLink="/data-disclosure"
               *ngIf="environment.pageVisibility.data_disclosure && !loggedIn?.isProvider">
             <span class="menu-item">
               <fa-icon [icon]="faDownload" class="menu-icon"></fa-icon>
@@ -107,7 +116,7 @@
               </span>
             </span>
           </li>
-    
+
           <li nz-menu-item routerLink="/data-removal" *ngIf="!loggedIn?.isProvider">
             <span class="menu-item">
               <fa-icon [icon]="faTrash" class="menu-icon"></fa-icon>
@@ -117,7 +126,7 @@
               </span>
             </span>
           </li>
-    
+
           <li nz-menu-item (click)="logout()">
             <span class="menu-item">
               <fa-icon [icon]="faSignOutAlt" class="menu-icon"></fa-icon>
@@ -129,6 +138,6 @@
           </li>
         </ul>
       </nz-dropdown-menu>
-    </div>    
+    </div>
   </div>
 </nz-header>
diff --git a/src/frontend/src/locale/messages.de.xlf b/src/frontend/src/locale/messages.de.xlf
index 6e68616..bbc8a22 100644
--- a/src/frontend/src/locale/messages.de.xlf
+++ b/src/frontend/src/locale/messages.de.xlf
@@ -1960,10 +1960,10 @@
         <note priority="1" from="meaning">Analytics Tokens </note>
       </trans-unit>
       <trans-unit id="controlCenter" datatype="html">
-        <source>Control Center</source>
-        <target>Systemsteuerung</target>
+        <source>Administration</source>
+        <target>Administration</target>
         <note priority="1" from="description"> Header Entry </note>
-        <note priority="1" from="meaning">Control Center</note>
+        <note priority="1" from="meaning">Administration</note>
       </trans-unit>
       <trans-unit id="profileProfileDropDown" datatype="html">
         <source>Profile</source>
@@ -2101,6 +2101,10 @@
         <source>pause</source>
         <target>pausieren</target>
       </trans-unit>
+      <trans-unit id="dashboardHeader" datatype="html">
+        <source>Dashboard</source>
+        <target>Dashboard</target>
+      </trans-unit>
     </body>
   </file>
 </xliff>
diff --git a/src/frontend/src/locale/messages.xlf b/src/frontend/src/locale/messages.xlf
index 40d749b..8cdd208 100644
--- a/src/frontend/src/locale/messages.xlf
+++ b/src/frontend/src/locale/messages.xlf
@@ -1175,9 +1175,9 @@
         <note priority="1" from="meaning">Analytics Tokens </note>
       </trans-unit>
       <trans-unit id="controlCenter" datatype="html">
-        <source>Control Center</source>
+        <source>Administration</source>
         <note priority="1" from="description"> Header Entry </note>
-        <note priority="1" from="meaning">Control Center</note>
+        <note priority="1" from="meaning">Administration</note>
       </trans-unit>
       <trans-unit id="profileProfileDropDown" datatype="html">
         <source>Profile</source>
@@ -1293,6 +1293,9 @@
       <trans-unit id="pauseConfirmationText" datatype="html">
         <source>pause</source>
       </trans-unit>
+      <trans-unit id="dashboardHeader" datatype="html">
+        <source>Dashboard</source>
+      </trans-unit>
     </body>
   </file>
 </xliff>
-- 
GitLab