diff --git a/src/app/app-module.ts b/src/app/app-module.ts
index 06cbe6a..803e39c 100644
--- a/src/app/app-module.ts
+++ b/src/app/app-module.ts
@@ -10,7 +10,8 @@ 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 { MatProgressBarModule } from '@angular/material/progress-bar';
+import { MatSnackBarModule } from '@angular/material/snack-bar';
import { HeaderComponent } from './header/header.component';
@@ -60,7 +61,8 @@ import { Header2Component } from './header-2/header-2.component';
MatIconModule,
MatTabsModule,
MatToolbarModule,
- MatProgressBarModule
+ MatProgressBarModule,
+ MatSnackBarModule
],
providers: [
provideBrowserGlobalErrorListeners(),
diff --git a/src/app/header-2/header-2.component.html b/src/app/header-2/header-2.component.html
index 8f1c08a..9545660 100644
--- a/src/app/header-2/header-2.component.html
+++ b/src/app/header-2/header-2.component.html
@@ -24,7 +24,9 @@
- @if (loading$ | async) {
+ @if (loadingService.error$ | async) {
+
+ } @else if (loadingService.loading$ | async){
(false);
- readonly loading$ = this._loading.asObservable();
+ private loadingSubject = new BehaviorSubject(false);
+ private errorSubject = new BehaviorSubject(false);
- show() {
- this._loading.next(true);
+ public loading$ = this.loadingSubject.asObservable();
+ public error$ = this.errorSubject.asObservable();
+
+ constructor(private snackBar: MatSnackBar) {}
+
+ show(): void {
+ this.loadingSubject.next(true);
+ this.errorSubject.next(false);
}
- hide() {
- this._loading.next(false);
+ hide(): void {
+ this.loadingSubject.next(false);
+ this.errorSubject.next(false);
+ }
+
+ showError(messageOrError?: string | HttpErrorResponse | any): void {
+ this.loadingSubject.next(false);
+ this.errorSubject.next(true);
+
+ if (!messageOrError) {
+ return;
+ }
+
+ const message = this.getErrorMessage(messageOrError);
+
+ const snackBarRef = this.snackBar.open(message, 'Schließen', {
+ duration: 0,
+ panelClass: ['error-snackbar'],
+ horizontalPosition: 'center',
+ verticalPosition: 'bottom'
+ });
+
+ snackBarRef.afterDismissed().subscribe(() => {
+ this.hide();
+ });
+ }
+
+ private getErrorMessage(error?: string | HttpErrorResponse | any): string {
+
+ if (typeof error === 'string') {
+ return error;
+ }
+
+ if (error instanceof HttpErrorResponse) {
+
+ if (error.status === 0) {
+ return 'Netzwerkfehler: Keine Verbindung zum Server möglich!';
+ }
+
+ if (error.status >= 500) {
+ return `Serverfehler (${error.status}): ${error.statusText || 'Interner Serverfehler'}`;
+ }
+
+ if (error.status >= 400) {
+ const errorMessage = error.error?.message || error.error?.error || error.statusText;
+ return `Fehler (${error.status}): ${errorMessage}`;
+ }
+
+ return `HTTP Fehler (${error.status}): ${error.statusText}`;
+ }
+
+ if (error.message) {
+ return error.message;
+ }
+
+ return 'Ein unbekannter Fehler ist aufgetreten!';
}
}
diff --git a/src/app/schedule/schedule.component.ts b/src/app/schedule/schedule.component.ts
index 7e89034..c7bbc7a 100644
--- a/src/app/schedule/schedule.component.ts
+++ b/src/app/schedule/schedule.component.ts
@@ -4,6 +4,7 @@ import { Vorstellung } from '@infinimotion/model-frontend';
import { Performance } from '../model/performance.model';
import { MovieGroup } from '../model/movie-group.model';
import { LoadingService } from '../loading.service';
+import { catchError, map, of, tap } from 'rxjs';
@Component({
selector: 'app-schedule',
@@ -47,14 +48,19 @@ export class ScheduleComponent implements OnInit {
loadPerformances() {
this.loading.show();
- this.http.getPerformaces().subscribe({
- next: (data) => {
- this.performaces = Array.isArray(data) ? data : [data];
+ this.http.getPerformaces().pipe(
+ map(data => Array.isArray(data) ? data : [data]),
+ tap(performaces => {
+ this.performaces = performaces;
this.assignPerformancesToDates();
- },
- error: (err) => console.error('Fehler beim Laden der Performances', err),
- complete: () => this.loading.hide()
- });
+ this.loading.hide();
+ }),
+ catchError(err => {
+ this.loading.showError(err);
+ console.error('Fehler beim Laden der Vorstellung', err);
+ return of([]);
+ })
+ ).subscribe();
}
assignPerformancesToDates() {
diff --git a/src/custom-theme.scss b/src/custom-theme.scss
index 6bdbd14..e55c90b 100644
--- a/src/custom-theme.scss
+++ b/src/custom-theme.scss
@@ -6,15 +6,30 @@
// custom components at https://material.angular.dev/guide/theming
@use '@angular/material' as mat;
- @include mat.progress-bar-overrides((
- active-indicator-color: white,
- track-color: transparent, // Transparent machen
- ));
+@include mat.progress-bar-overrides((
+ active-indicator-color: white,
+ track-color: transparent,
+));
+
+.mdc-linear-progress__buffer-bar {
+ background: linear-gradient(to right, #6366f1, #db2777) !important;
+}
+
+@include mat.snack-bar-overrides((
+ container-color: red,
+));
+
+
+
+.error-snackbar .mat-mdc-snack-bar-label {
+ color: white !important;
+}
+
+.error-snackbar .mat-mdc-button {
+ color: white !important;
+}
+
- // Gradient als Hintergrund
- .mdc-linear-progress__buffer-bar {
- background: linear-gradient(to right, #6366f1, #db2777) !important;
- }
html {
@include mat.theme((