import { Component, OnInit, ViewChild } from '@angular/core'; import { CommonModule } from '@angular/common'; import { DialogModule, DialogService } from '@progress/kendo-angular-dialog'; import { ButtonsModule } from '@progress/kendo-angular-buttons'; import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms'; import { InputsModule } from '@progress/kendo-angular-inputs'; import { LabelModule } from '@progress/kendo-angular-label'; import { IndicatorsModule } from '@progress/kendo-angular-indicators'; import { MfaDialogComponent } from '../../shared/mfa-dialog/mfa-dialog.component'; import { AuthService, LoginCredentials, LoginResultType, TokenVerificationResult } from '../../shared/services/auth.service'; import { Router, ActivatedRoute } from '@angular/router'; @Component({ selector: 'app-login-page', standalone: true, imports: [ CommonModule, DialogModule, ButtonsModule, ReactiveFormsModule, InputsModule, LabelModule, IndicatorsModule, MfaDialogComponent ], templateUrl: './login-page.component.html', styleUrls: ['./login-page.component.scss'] }) export class LoginPage implements OnInit { @ViewChild('mfaDialog') mfaDialog!: MfaDialogComponent; activeTab: 'user' | 'admin' = 'user'; showLoginForm = false; loginForm: FormGroup; isProcessing = false; showError = false; errorMessage = ''; constructor( private dialogService: DialogService, private authService: AuthService, private router: Router, private route: ActivatedRoute, private fb: FormBuilder ) { this.loginForm = this.fb.group({ email: ['', [Validators.required, Validators.email]], password: ['', [Validators.required, Validators.minLength(6)]], rememberMe: [false] }); } ngOnInit(): void { // Check if user is already logged in if (this.authService.isAuthenticated()) { this.redirectToDashboard(); return; } // Check for token in URL parameters this.route.queryParams.subscribe(params => { const token = params['token']; if (token) { this.verifySecretLinkToken(token); } }); } setActiveTab(tab: 'user' | 'admin'): void { this.activeTab = tab; } copyToClipboard(text: string): void { navigator.clipboard.writeText(text).then(() => { // You could add a toast notification here console.log('Copied to clipboard:', text); }).catch(err => { console.error('Failed to copy text: ', err); }); } showLoginFormView(): void { this.showLoginForm = true; // Focus on email input when form appears setTimeout(() => { const emailInput = document.querySelector('input[formControlName="email"]') as HTMLInputElement; if (emailInput) { emailInput.focus(); } }, 100); } goBackToInitialState(): void { this.showLoginForm = false; this.loginForm.reset(); this.showError = false; this.errorMessage = ''; } onSubmit(): void { if (this.loginForm.valid && !this.isProcessing) { this.isProcessing = true; this.showError = false; const credentials: LoginCredentials = this.loginForm.value; this.authService.login(credentials).subscribe({ next: (result) => { this.isProcessing = false; if (result.result === LoginResultType.Success) { this.authService.setCurrentUser(result.responseData!); this.redirectToDashboard(); } else if (result.result === LoginResultType.MfaRequired) { this.showMfaDialog(credentials); } else { this.showError = true; this.errorMessage = result.message || 'Invalid email or password'; } }, error: (error) => { this.isProcessing = false; this.showError = true; this.errorMessage = 'An error occurred during login. Please try again.'; console.error('Login error:', error); } }); } } get emailControl() { return this.loginForm.get('email'); } get passwordControl() { return this.loginForm.get('password'); } private showMfaDialog(credentials: LoginCredentials): void { if (this.mfaDialog) { // Set the login data for MFA dialog (this.mfaDialog as any).loginData = credentials; // Show MFA dialog this.mfaDialog.show(); } } onMfaSuccess(userData: any): void { this.authService.setCurrentUser(userData); this.redirectToDashboard(); } onMfaCancel(): void { // Reset form and focus on email this.loginForm.reset(); setTimeout(() => { const emailInput = document.querySelector('input[formControlName="email"]') as HTMLInputElement; if (emailInput) { emailInput.focus(); } }, 100); } private verifySecretLinkToken(token: string): void { this.isProcessing = true; this.showError = false; // First check if token is expired locally if (this.authService.isTokenExpired(token)) { this.isProcessing = false; this.showError = true; this.errorMessage = 'This link has expired. Please request a new one.'; return; } this.authService.verifySecretLinkToken(token).subscribe({ next: (result: TokenVerificationResult) => { this.isProcessing = false; if (result.isValid && result.user) { // Token is valid, set user and redirect this.authService.setCurrentUser(result.user); this.redirectToDashboard(); } else { // Token verification failed this.showError = true; this.errorMessage = result.message || 'Invalid or expired link. Please request a new one.'; } }, error: (error) => { this.isProcessing = false; this.showError = true; this.errorMessage = 'An error occurred while verifying the link. Please try again.'; console.error('Token verification error:', error); } }); } private redirectToDashboard(): void { const redirectUrl = this.authService.getRedirectUrl(); this.router.navigate([redirectUrl || '/dashboard']); } }