import { ChangeDetectorRef, Component, inject } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; import { ActivatedRoute, Router, RouterModule } from '@angular/router'; import { AuthService } from '../../../../core/services/auth/auth.service'; import { ReactiveFormsModule } from '@angular/forms'; import { ToastrService } from 'ngx-toastr'; import { catchError, finalize, of, switchMap, tap } from 'rxjs'; import { AppContextService } from '../../../../core/services/context/app-context.service'; @Component({ selector: 'app-login', standalone: true, imports: [RouterModule, ReactiveFormsModule], templateUrl: './login.html', styleUrl: './login.scss' }) export class Login { private readonly formBuilder = inject(FormBuilder); private readonly cdr = inject(ChangeDetectorRef); private readonly fallbackRoute = '/dashboards/crm'; public readonly adminLoginForm = this.formBuilder.nonNullable.group({ username: ['', [Validators.required, Validators.email]], password: ['', Validators.required], rememberMe: [false] }); public isSubmitting = false; public loginError = ''; public visibilityMap: Record = { Angular: false }; public iconMap: Record = { Angular: 'fe fe-eye-off' }; constructor( public authservice: AuthService, private appContextService: AppContextService, private route: ActivatedRoute, private router: Router, private toastr: ToastrService ) { } login() { this.loginError = ''; if (this.adminLoginForm.invalid) { this.adminLoginForm.markAllAsTouched(); return; } if (this.isSubmitting) { return; } this.isSubmitting = true; const { username, password, rememberMe } = this.adminLoginForm.getRawValue(); this.authservice.login({ email: username, password }, !!rememberMe) .pipe( switchMap(() => this.appContextService.ensureMenuInitialized(true).pipe( catchError(() => { this.authservice.logout(); this.loginError = 'Unable to load application context.'; return of(null); }) ) ), finalize(() => { this.isSubmitting = false; this.cdr.detectChanges(); }) ) .subscribe({ next: () => { if (this.loginError) { this.toastr.error(this.loginError); return; } void this.router.navigateByUrl(this.getSafeReturnUrl()); this.toastr.success('Login successful', username); }, error: (error) => { this.loginError = error?.error?.detail || error?.error?.message || 'Invalid email or password'; this.toastr.error(this.loginError); } }); } toggleVisibility(tab: string): void { this.visibilityMap[tab] = !this.visibilityMap[tab]; this.iconMap[tab] = this.visibilityMap[tab] ? 'fe fe-eye' : 'fe fe-eye-off'; } private getSafeReturnUrl(): string { const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl')?.trim() ?? ''; if (!returnUrl) { return this.fallbackRoute; } const lowerReturnUrl = returnUrl.toLowerCase(); const isSafeInternalUrl = returnUrl.startsWith('/') && !returnUrl.startsWith('//') && !returnUrl.includes('\\') && !lowerReturnUrl.includes('http://') && !lowerReturnUrl.includes('https://'); return isSafeInternalUrl ? returnUrl : this.fallbackRoute; } }