Add new header 2.0 component with loading service

Introduced Header2Component with a new design, external resource links, and a loading progress bar. Added LoadingService to manage loading state and integrated it into the schedule component. Updated main layout to use the new header and included related assets for external links. Changed API base URL in HttpService to use the production endpoint.
This commit is contained in:
2025-10-31 11:45:41 +01:00
parent 98626d11ed
commit 7549061fba
12 changed files with 103 additions and 6 deletions

View File

@@ -9,6 +9,9 @@ import { App } from './app';
import { MatIconModule } from '@angular/material/icon';
import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { HeaderComponent } from './header/header.component';
import { HomeComponent } from './home/home.component';
@@ -26,6 +29,7 @@ import { MovieScheduleInfoComponent } from './movie-schedule-info/movie-schedule
import { MovieScheduleTimesComponent } from './movie-schedule-times/movie-schedule-times.component';
import { MovieCategoryComponent } from './movie-category/movie-category.component';
import { MovieScheduleEmptyComponent } from './movie-schedule-empty/movie-schedule-empty.component';
import { Header2Component } from './header-2/header-2.component';
@NgModule({
@@ -45,7 +49,8 @@ import { MovieScheduleEmptyComponent } from './movie-schedule-empty/movie-schedu
MovieRatingComponent,
MovieDurationComponent,
MovieCategoryComponent,
MovieScheduleEmptyComponent
MovieScheduleEmptyComponent,
Header2Component
],
imports: [
AppRoutingModule,
@@ -53,8 +58,10 @@ import { MovieScheduleEmptyComponent } from './movie-schedule-empty/movie-schedu
CommonModule,
FormsModule,
MatIconModule,
MatTabsModule
],
MatTabsModule,
MatToolbarModule,
MatProgressBarModule
],
providers: [
provideBrowserGlobalErrorListeners(),
provideHttpClient(

View File

@@ -0,0 +1,16 @@
header {
width: 100%;
}
.header {
display: flex;
align-items: center;
justify-content: space-between;
background-color: white;
}
.redirect-img {
height: 2rem;
width: auto;
border-radius: 5px;
}

View File

@@ -0,0 +1,35 @@
<header>
<div class="header px-8 py-4 shadow-md">
<a routerLink="/" class="flex items-center space-x-4 hover:opacity-80 transition">
<img src="assets/logo.png" class="h-10 w-10 transform scale-175 translate-y-0.25" />
<h1 class="text-3xl font-semibold tracking-wide">InfiniMotion</h1>
</a>
<div class="absolute left-1/2 transform -translate-x-1/2 text-center">
<h2 class="text-3xl font-bold animate-fadeUp-delay bg-gradient-to-r from-indigo-500 to-pink-600 bg-clip-text text-transparent">
Absolut war gestern, Bewegung ist heute!
</h2>
</div>
<div class="flex items-center space-x-4">
<a href="https://git.infinimotion.de" target="_blank" rel="noopener noreferrer">
<img src="assets/logo-gitea.png" class="redirect-img hover:scale-110 transition" />
</a>
<a href="https://infinimotion.de/api/swagger" target="_blank" rel="noopener noreferrer">
<img src="assets/logo-quarkus.png" class="redirect-img hover:scale-110 transition" />
</a>
<a href="https://rc.infinimotion.de" target="_blank" rel="noopener noreferrer">
<img src="assets/logo-redpanda.jpeg" class="redirect-img hover:scale-110 transition border-orange-600 border-3" />
</a>
</div>
</div>
@if (loading$ | async) {
<mat-progress-bar
mode="indeterminate"
class="h-1 w-full"
></mat-progress-bar>
} @else {
<div class="h-1"></div>
}
</header>

View File

@@ -0,0 +1,15 @@
import { Component } from '@angular/core';
import { LoadingService } from '../loading.service';
@Component({
selector: 'app-header-2',
standalone: false,
templateUrl: './header-2.component.html',
styleUrl: './header-2.component.css'
})
export class Header2Component {
loading$;
constructor(private loadingService: LoadingService) {
this.loading$ = this.loadingService.loading$;
}
}

View File

@@ -3,10 +3,12 @@ import { HttpClient } from "@angular/common/http";
import { inject, Injectable } from "@angular/core";
import { Observable } from "rxjs";
@Injectable({providedIn: 'root'})
@Injectable({
providedIn: 'root'
})
export class HttpService {
private http = inject(HttpClient);
private baseUrl = '/api/';
private baseUrl = 'https://infinimotion.de/api/';
/* Kinosaal APIs */

View File

@@ -1,4 +1,4 @@
<app-header></app-header>
<app-header-2></app-header-2>
<div class="body">
<app-navbar></app-navbar>

View File

@@ -0,0 +1,18 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class LoadingService {
private _loading = new BehaviorSubject<boolean>(false);
readonly loading$ = this._loading.asObservable();
show() {
this._loading.next(true);
}
hide() {
this._loading.next(false);
}
}

View File

@@ -3,6 +3,7 @@ import { HttpService } from '../http.service';
import { Vorstellung } from '@infinimotion/model-frontend';
import { Performance } from '../model/performance.model';
import { MovieGroup } from '../model/movie-group.model';
import { LoadingService } from '../loading.service';
@Component({
selector: 'app-schedule',
@@ -15,6 +16,7 @@ export class ScheduleComponent implements OnInit {
performaces: Vorstellung[] = [];
private http = inject(HttpService);
private loading = inject(LoadingService)
constructor() {
this.generateDates();
@@ -44,12 +46,14 @@ export class ScheduleComponent implements OnInit {
}
loadPerformances() {
this.loading.show();
this.http.getPerformaces().subscribe({
next: (data) => {
this.performaces = Array.isArray(data) ? data : [data];
this.assignPerformancesToDates();
},
error: (err) => console.error('Fehler beim Laden der Performances', err),
complete: () => this.loading.hide()
});
}