import {Component, OnInit, OnDestroy} from '@angular/core'; import {FormBuilder, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms'; import {Router, ActivatedRoute} from '@angular/router'; import {Subject} from 'rxjs'; import {takeUntil} from 'rxjs/operators'; import {ApiService, LoginCredentials} from '../../services/api'; import {NgClass} from '@angular/common'; @Component({ selector: 'app-login', templateUrl: './login.component.html', imports: [ ReactiveFormsModule, NgClass ], styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit, OnDestroy { loginForm: FormGroup; loading = false; error = ''; success = ''; showPassword = false; returnUrl = ''; private destroy$ = new Subject(); constructor( private formBuilder: FormBuilder, private apiService: ApiService, private router: Router, private route: ActivatedRoute ) { // Redirect to dashboard if already logged in if (this.apiService.isAuthenticated) { this.router.navigate(['/dashboard']); } this.loginForm = this.formBuilder.group({ email: ['', [Validators.required, Validators.email]], password: ['', [Validators.required, Validators.minLength(6)]], rememberMe: [false] }); } ngOnInit(): void { // Get return url from route parameters or default to dashboard this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/dashboard'; // Clear any existing error messages this.clearMessages(); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); } // Getter for easy access to form fields get f() { return this.loginForm.controls; } // Get specific field error message getFieldError(fieldName: string): string { const field = this.loginForm.get(fieldName); if (field?.errors && field.touched) { if (field.errors['required']) { return `${this.capitalizeFirst(fieldName)} is required`; } if (field.errors['email']) { return 'Please enter a valid email address'; } if (field.errors['minlength']) { return `${this.capitalizeFirst(fieldName)} must be at least ${field.errors['minlength'].requiredLength} characters`; } } return ''; } // Check if field has error hasFieldError(fieldName: string): boolean { const field = this.loginForm.get(fieldName); return !!(field?.errors && field.touched); } // Capitalize first letter private capitalizeFirst(str: string): string { return str.charAt(0).toUpperCase() + str.slice(1); } // Toggle password visibility togglePasswordVisibility(): void { this.showPassword = !this.showPassword; } // Clear error and success messages clearMessages(): void { this.error = ''; this.success = ''; } // Handle form submission onSubmit(): void { this.clearMessages(); // Mark all fields as touched to show validation errors this.loginForm.markAllAsTouched(); if (this.loginForm.invalid) { return; } this.loading = true; const credentials: LoginCredentials = { email: this.f['email'].value, password: this.f['password'].value }; this.apiService.login(credentials) .pipe(takeUntil(this.destroy$)) .subscribe({ next: (response) => { this.loading = false; if (response.success) { this.success = 'Login successful! Redirecting...'; // Store remember me preference if needed if (this.f['rememberMe'].value) { localStorage.setItem('rememberMe', 'true'); } // Redirect after a short delay to show success message setTimeout(() => { this.router.navigate([this.returnUrl]); }, 1000); } else { this.error = response.message || 'Login failed. Please try again.'; } }, error: (error) => { this.loading = false; // Handle specific error cases if (error.status === 422 && error.error?.errors) { // Validation errors from server const serverErrors = error.error.errors; let errorMessages: string[] = []; Object.keys(serverErrors).forEach(key => { if (Array.isArray(serverErrors[key])) { errorMessages = errorMessages.concat(serverErrors[key]); } }); this.error = errorMessages.join(', '); } else if (error.status === 401) { this.error = 'Invalid email or password. Please try again.'; } else { this.error = error.userMessage || 'An error occurred. Please try again.'; } console.error('Login error:', error); } }); } // Navigate to register page goToRegister(): void { this.router.navigate(['/register'], { queryParams: {returnUrl: this.returnUrl} }); } // Navigate to forgot password page goToForgotPassword(): void { this.router.navigate(['/forgot-password']); } // Demo login (optional - for testing) demoLogin(): void { this.loginForm.patchValue({ email: 'demo@example.com', password: 'password123' }); } }