From 3b8b62a8d6d9b8a218d1eae9b674e2480639f6fb Mon Sep 17 00:00:00 2001
From: Alexander Reifschneider <alexander.reifschneider@mgm-tp.com>
Date: Thu, 24 Apr 2025 11:00:21 +0200
Subject: [PATCH] OZG-7774 add statistic menu

Sub-Task: OZG-8104
---
 .../apps/admin/src/app/app.component.html     |  3 +
 .../apps/admin/src/app/app.component.ts       |  3 +-
 .../libs/admin/configuration/src/index.ts     |  1 +
 .../menu-container/menu/menu.component.html   |  5 --
 .../menu/menu.component.spec.ts               | 20 -------
 .../statistik-menu-container.component.html   |  1 +
 ...statistik-menu-container.component.spec.ts | 55 +++++++++++++++++++
 .../statistik-menu-container.component.ts     | 22 ++++++++
 .../statistik-menu.component.html             | 16 ++++++
 .../statistik-menu.component.spec.ts          | 53 ++++++++++++++++++
 .../statistik-menu.component.ts               | 19 +++++++
 .../libs/admin/shared/src/lib/routes.ts       |  6 +-
 .../nav-headline/nav-headline.component.ts    |  2 +-
 13 files changed, 176 insertions(+), 30 deletions(-)
 create mode 100644 alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.html
 create mode 100644 alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.spec.ts
 create mode 100644 alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.ts
 create mode 100644 alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.html
 create mode 100644 alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.spec.ts
 create mode 100644 alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.ts

diff --git a/alfa-client/apps/admin/src/app/app.component.html b/alfa-client/apps/admin/src/app/app.component.html
index e3f678a098..561a68601f 100644
--- a/alfa-client/apps/admin/src/app/app.component.html
+++ b/alfa-client/apps/admin/src/app/app.component.html
@@ -61,6 +61,9 @@
       @if (apiRoot | hasLink: apiRootLinkRel.CONFIGURATION) {
         <admin-menu-container data-test-id="menu-container"></admin-menu-container>
       }
+      @if (apiRoot | hasLink: apiRootLinkRel.CONFIGURATION) {
+        <admin-statistik-menu-container data-test-id="menu-container" />
+      }
     </ods-navbar>
     <main class="flex-1 overflow-y-auto bg-white px-6 py-4">
       <router-outlet
diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts
index 8cc01f4def..8aee55efef 100644
--- a/alfa-client/apps/admin/src/app/app.component.ts
+++ b/alfa-client/apps/admin/src/app/app.component.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { MenuContainerComponent } from '@admin-client/configuration';
+import { MenuContainerComponent, StatistikMenuContainerComponent } from '@admin-client/configuration';
 import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
 import { ROUTES } from '@admin-client/shared';
 import { KeycloakTokenService } from '@admin/keycloak-shared';
@@ -53,6 +53,7 @@ import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/
     UnavailablePageComponent,
     BuildInfoComponent,
     MenuContainerComponent,
+    StatistikMenuContainerComponent,
     RouterLink,
     HasLinkPipe,
   ],
diff --git a/alfa-client/libs/admin/configuration/src/index.ts b/alfa-client/libs/admin/configuration/src/index.ts
index 221b8b7376..63bd38c1b3 100644
--- a/alfa-client/libs/admin/configuration/src/index.ts
+++ b/alfa-client/libs/admin/configuration/src/index.ts
@@ -1 +1,2 @@
 export * from './lib/menu-container/menu-container.component';
+export * from './lib/statistik-menu-container/statistik-menu-container.component';
diff --git a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html
index 672cb8f71c..5d7b258f2f 100644
--- a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html
+++ b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.html
@@ -3,8 +3,3 @@
     <ods-icon icon name="mailbox" fill="text" />
   </ods-nav-item>
 }
-@if (configurationStateResource.resource | hasLink: configurationLinkRel.AGGREGATION_MAPPINGS) {
-  <ods-nav-item data-test-id="statistik-navigation" caption="Statistik" [path]="'/' + ROUTES.AGGREGATION_MAPPING">
-    <ods-icon icon name="statistic" fill="text" />
-  </ods-nav-item>
-}
diff --git a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts
index bc802c253d..5f5b3c7c54 100644
--- a/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts
+++ b/alfa-client/libs/admin/configuration/src/lib/menu-container/menu/menu.component.spec.ts
@@ -48,24 +48,4 @@ describe('MenuComponent', () => {
       notExistsAsHtmlElement(fixture, postfachNavigation);
     });
   });
-
-  describe('statistic navigation', () => {
-    it('should show if settings link is present', () => {
-      component.configurationStateResource = createStateResource(
-        createConfigurationResource([ConfigurationLinkRel.AGGREGATION_MAPPINGS]),
-      );
-
-      fixture.detectChanges();
-
-      existsAsHtmlElement(fixture, statistikNavigationSelector);
-    });
-
-    it('should hide if settings link is missing', () => {
-      component.configurationStateResource = createStateResource(createConfigurationResource());
-
-      fixture.detectChanges();
-
-      notExistsAsHtmlElement(fixture, statistikNavigationSelector);
-    });
-  });
 });
diff --git a/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.html b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.html
new file mode 100644
index 0000000000..5392d99854
--- /dev/null
+++ b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.html
@@ -0,0 +1 @@
+<admin-statistik-menu [configurationStateResource]="configurationStateResource$ | async" />
diff --git a/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.spec.ts b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.spec.ts
new file mode 100644
index 0000000000..8b521c1b5e
--- /dev/null
+++ b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.spec.ts
@@ -0,0 +1,55 @@
+import { ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
+import { createStateResource, StateResource } from '@alfa-client/tech-shared';
+import { getMockComponent, mock, Mock } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { MockComponent } from 'ng-mocks';
+import { of } from 'rxjs';
+import { createConfigurationResource } from '../../../../configuration-shared/test/configuration';
+import { StatistikMenuContainerComponent } from './statistik-menu-container.component';
+import { StatistikMenuComponent } from './statistik-menu/statistik-menu.component';
+
+describe('StatistikMenuContainerComponent', () => {
+  let component: StatistikMenuContainerComponent;
+  let fixture: ComponentFixture<StatistikMenuContainerComponent>;
+
+  let configurationService: Mock<ConfigurationService>;
+
+  const configurationStateResource: StateResource<ConfigurationResource> = createStateResource(createConfigurationResource());
+
+  beforeEach(async () => {
+    configurationService = { ...mock(ConfigurationService), get: jest.fn().mockReturnValue(of(configurationStateResource)) };
+
+    await TestBed.configureTestingModule({
+      imports: [StatistikMenuContainerComponent],
+      declarations: [MockComponent(StatistikMenuComponent)],
+      providers: [
+        {
+          provide: ConfigurationService,
+          useValue: configurationService,
+        },
+      ],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(StatistikMenuContainerComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('ngOnInit', () => {
+    it('should call service', () => {
+      component.ngOnInit();
+
+      expect(configurationService.get).toHaveBeenCalled();
+    });
+  });
+
+  it('should call menu', () => {
+    const menu: StatistikMenuComponent = getMockComponent(fixture, StatistikMenuComponent);
+
+    expect(menu.configurationStateResource).toBe(configurationStateResource);
+  });
+});
diff --git a/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.ts b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.ts
new file mode 100644
index 0000000000..3084cd0801
--- /dev/null
+++ b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu-container.component.ts
@@ -0,0 +1,22 @@
+import { ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
+import { StateResource } from '@alfa-client/tech-shared';
+import { CommonModule } from '@angular/common';
+import { Component, inject, OnInit } from '@angular/core';
+import { Observable } from 'rxjs';
+import { StatistikMenuComponent } from './statistik-menu/statistik-menu.component';
+
+@Component({
+  selector: 'admin-statistik-menu-container',
+  standalone: true,
+  imports: [CommonModule, StatistikMenuComponent],
+  templateUrl: './statistik-menu-container.component.html',
+})
+export class StatistikMenuContainerComponent implements OnInit {
+  private readonly configurationService = inject(ConfigurationService);
+
+  public configurationStateResource$: Observable<StateResource<ConfigurationResource>>;
+
+  ngOnInit(): void {
+    this.configurationStateResource$ = this.configurationService.get();
+  }
+}
diff --git a/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.html b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.html
new file mode 100644
index 0000000000..da11f79e80
--- /dev/null
+++ b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.html
@@ -0,0 +1,16 @@
+<ods-nav-headline label="Statistik" />
+@if (configurationStateResource.resource | hasLink: configurationLinkRel.AGGREGATION_MAPPINGS) {
+  <ods-nav-item data-test-id="statistik-navigation" caption="Auswertungen" [path]="'/' + ROUTES.AGGREGATION_MAPPING">
+    <ods-icon icon name="statistic" fill="text" />
+  </ods-nav-item>
+}
+<!-- @if (configurationStateResource.resource | hasLink: configurationLinkRel.**datenanfragen**) {
+  <ods-nav-item data-test-id="statistik-navigation" caption="Auswertungen" [path]="'/' + **datenanfragen**">
+    <ods-icon icon name="statistic" fill="text" />
+  </ods-nav-item>
+}
+@if (configurationStateResource.resource | hasLink: configurationLinkRel.**datenfreigaben**) {
+  <ods-nav-item data-test-id="statistik-navigation" caption="Auswertungen" [path]="'/' + **datenfreigaben**">
+    <ods-icon icon name="statistic" fill="text" />
+  </ods-nav-item>
+} -->
diff --git a/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.spec.ts b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.spec.ts
new file mode 100644
index 0000000000..805ffa7faf
--- /dev/null
+++ b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.spec.ts
@@ -0,0 +1,53 @@
+import { ConfigurationLinkRel } from '@admin-client/configuration-shared';
+import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@alfa-client/tech-shared';
+import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { IconComponent, NavItemComponent } from '@ods/system';
+import { createConfigurationResource } from 'libs/admin/configuration-shared/test/configuration';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
+import { MockComponent } from 'ng-mocks';
+import { StatistikMenuComponent } from './statistik-menu.component';
+
+describe('StatistikMenuComponent', () => {
+  let component: StatistikMenuComponent;
+  let fixture: ComponentFixture<StatistikMenuComponent>;
+
+  const postfachNavigation: string = getDataTestIdOf('postfach-navigation');
+  const statistikNavigationSelector: string = getDataTestIdOf('statistik-navigation');
+
+  beforeEach(async () => {
+    await TestBed.configureTestingModule({
+      imports: [StatistikMenuComponent, HasLinkPipe],
+      declarations: [MockComponent(NavItemComponent), MockComponent(IconComponent)],
+    }).compileComponents();
+
+    fixture = TestBed.createComponent(StatistikMenuComponent);
+    component = fixture.componentInstance;
+    component.configurationStateResource = createEmptyStateResource();
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+
+  describe('statistic navigation', () => {
+    it('should show if agregation mapping link is present', () => {
+      component.configurationStateResource = createStateResource(
+        createConfigurationResource([ConfigurationLinkRel.AGGREGATION_MAPPINGS]),
+      );
+
+      fixture.detectChanges();
+
+      existsAsHtmlElement(fixture, statistikNavigationSelector);
+    });
+
+    it('should hide if agregation mapping link is missing', () => {
+      component.configurationStateResource = createStateResource(createConfigurationResource());
+
+      fixture.detectChanges();
+
+      notExistsAsHtmlElement(fixture, statistikNavigationSelector);
+    });
+  });
+});
diff --git a/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.ts b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.ts
new file mode 100644
index 0000000000..75a8bab295
--- /dev/null
+++ b/alfa-client/libs/admin/configuration/src/lib/statistik-menu-container/statistik-menu/statistik-menu.component.ts
@@ -0,0 +1,19 @@
+import { ConfigurationLinkRel, ConfigurationResource } from '@admin-client/configuration-shared';
+import { ROUTES } from '@admin-client/shared';
+import { HasLinkPipe, StateResource } from '@alfa-client/tech-shared';
+import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
+import { IconComponent, NavHeadlineComponent, NavItemComponent } from '@ods/system';
+
+@Component({
+  selector: 'admin-statistik-menu',
+  standalone: true,
+  imports: [CommonModule, NavItemComponent, IconComponent, HasLinkPipe, NavHeadlineComponent],
+  templateUrl: './statistik-menu.component.html',
+})
+export class StatistikMenuComponent {
+  @Input() configurationStateResource: StateResource<ConfigurationResource>;
+
+  public readonly configurationLinkRel = ConfigurationLinkRel;
+  public readonly ROUTES = ROUTES;
+}
diff --git a/alfa-client/libs/admin/shared/src/lib/routes.ts b/alfa-client/libs/admin/shared/src/lib/routes.ts
index 9f1496843e..3f872ee122 100644
--- a/alfa-client/libs/admin/shared/src/lib/routes.ts
+++ b/alfa-client/libs/admin/shared/src/lib/routes.ts
@@ -28,7 +28,7 @@ export enum ROUTES {
   BENUTZER_ID = 'benutzer/:userid',
   ORGANISATIONSEINHEITEN = 'organisationseinheiten',
   UNAVAILABLE = 'unavailable',
-  AGGREGATION_MAPPING = 'auswertungen',
-  AGGREGATION_MAPPING_NEU = 'auswertungen/neu',
-  AGGREGATION_MAPPING_ID = 'auswertungen/:aggregationMappingId',
+  AGGREGATION_MAPPING = 'statistik/auswertungen',
+  AGGREGATION_MAPPING_NEU = 'statistik/auswertungen/neu',
+  AGGREGATION_MAPPING_ID = 'statistik/auswertungen/:aggregationMappingId',
 }
diff --git a/alfa-client/libs/design-system/src/lib/navbar/nav-headline/nav-headline.component.ts b/alfa-client/libs/design-system/src/lib/navbar/nav-headline/nav-headline.component.ts
index 052bc70128..a2f538b5db 100644
--- a/alfa-client/libs/design-system/src/lib/navbar/nav-headline/nav-headline.component.ts
+++ b/alfa-client/libs/design-system/src/lib/navbar/nav-headline/nav-headline.component.ts
@@ -5,7 +5,7 @@ import { Component, Input } from '@angular/core';
   selector: 'ods-nav-headline',
   standalone: true,
   imports: [CommonModule],
-  template: `<p class="mx-4 font-medium">{{ label }}</p>`,
+  template: `<p class="mx-4 my-2 font-medium">{{ label }}</p>`,
 })
 export class NavHeadlineComponent {
   @Input({ required: true }) label!: string;
-- 
GitLab