diff --git a/eeg_frontend/src/app/app.config.ts b/eeg_frontend/src/app/app.config.ts index 7c1d66a..623aad2 100644 --- a/eeg_frontend/src/app/app.config.ts +++ b/eeg_frontend/src/app/app.config.ts @@ -4,13 +4,14 @@ import {routes} from './app.routes'; import {provideHttpClient, withFetch, withInterceptors} from '@angular/common/http'; import {BASE_PATH} from './api'; import {jwtInterceptor} from './interceptors/jwt.interceptor'; +import {errorInterceptor} from './interceptors/error.interceptor'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient(withFetch(), - withInterceptors([jwtInterceptor])), + withInterceptors([jwtInterceptor, errorInterceptor])), { provide: BASE_PATH, useValue: 'http://localhost:8080' } ] }; diff --git a/eeg_frontend/src/app/app.html b/eeg_frontend/src/app/app.html index 558b19c..52ecc9b 100644 --- a/eeg_frontend/src/app/app.html +++ b/eeg_frontend/src/app/app.html @@ -4,3 +4,4 @@
+ diff --git a/eeg_frontend/src/app/app.ts b/eeg_frontend/src/app/app.ts index 5fc4d88..4c9b6f8 100644 --- a/eeg_frontend/src/app/app.ts +++ b/eeg_frontend/src/app/app.ts @@ -1,10 +1,11 @@ import {Component, signal} from '@angular/core'; import {NavigationEnd, Router, RouterOutlet} from '@angular/router'; import {HeaderComponent} from './layout/header/header'; +import {ToastComponent} from './components/toast/toast'; @Component({ selector: 'app-root', - imports: [RouterOutlet, HeaderComponent], + imports: [RouterOutlet, HeaderComponent, ToastComponent], templateUrl: './app.html', styleUrl: './app.scss', }) diff --git a/eeg_frontend/src/app/components/toast/toast.ts b/eeg_frontend/src/app/components/toast/toast.ts new file mode 100644 index 0000000..b20eb37 --- /dev/null +++ b/eeg_frontend/src/app/components/toast/toast.ts @@ -0,0 +1,44 @@ +import { Component, inject } from '@angular/core'; +import { ToastService } from '../../services/toast'; + +@Component({ + selector: 'app-toast', + standalone: true, + template: ` +
+ @for (toast of toastService.toasts$(); track toast.id) { +
+ {{ toast.message }} + +
+ } +
+ `, + styles: [` + @keyframes slide-in { + from { transform: translateX(100%); opacity: 0; } + to { transform: translateX(0); opacity: 1; } + } + .animate-slide-in { + animation: slide-in 0.3s ease-out; + } + `] +}) +export class ToastComponent { + toastService = inject(ToastService); + + getToastClass(type: string): string { + switch (type) { + case 'success': return 'bg-green-500'; + case 'error': return 'bg-red-500'; + case 'warning': return 'bg-yellow-500'; + default: return 'bg-blue-500'; + } + } +} diff --git a/eeg_frontend/src/app/interceptors/error.interceptor.ts b/eeg_frontend/src/app/interceptors/error.interceptor.ts new file mode 100644 index 0000000..b53845f --- /dev/null +++ b/eeg_frontend/src/app/interceptors/error.interceptor.ts @@ -0,0 +1,31 @@ +import { HttpInterceptorFn } from '@angular/common/http'; +import { inject } from '@angular/core'; +import { Router } from '@angular/router'; +import { catchError, throwError } from 'rxjs'; +import { AuthService } from '../services/auth'; +import { ToastService } from '../services/toast'; + +export const errorInterceptor: HttpInterceptorFn = (req, next) => { + const router = inject(Router); + const authService = inject(AuthService); + const toastService = inject(ToastService); + + return next(req).pipe( + catchError(error => { + if (error.status === 401) { + // Unauthorized - auto logout + authService.logout(); + router.navigate(['/login']); + toastService.error('Sitzung abgelaufen. Bitte erneut einloggen.'); + } else if (error.status === 403) { + toastService.error('Keine Berechtigung für diese Aktion.'); + } else if (error.status === 404) { + toastService.error('Ressource nicht gefunden.'); + } else if (error.status >= 500) { + toastService.error('Ein Serverfehler ist aufgetreten. Bitte versuchen Sie es später erneut.'); + } + + return throwError(() => error); + }) + ); +}; diff --git a/eeg_frontend/src/app/layout/dashboard-layout/dashboard-layout.html b/eeg_frontend/src/app/layout/dashboard-layout/dashboard-layout.html index 2993266..de4f2c9 100644 --- a/eeg_frontend/src/app/layout/dashboard-layout/dashboard-layout.html +++ b/eeg_frontend/src/app/layout/dashboard-layout/dashboard-layout.html @@ -1,6 +1,15 @@
-