Files
ROLAC/APP/src/app/features/login-page/login-page.ts
T
Chris Chen d5648315a0 WIP
2026-05-25 17:32:18 -07:00

206 lines
6.0 KiB
TypeScript

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']);
}
}