import { Component } from '@angular/core'; import { CommonModule } from '@angular/common'; import { ReactiveFormsModule, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Router, ActivatedRoute } from '@angular/router'; import { AuthService } from '../auth/auth.service'; @Component({ selector: 'app-login', standalone: true, imports: [CommonModule, ReactiveFormsModule], template: `

Sign In

Username is required
Password is required

{{ errorMessage }}

`, styles: [` .login-page { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px; background: var(--bg); } .login-card { width: 100%; max-width: 400px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 40px 32px; } h1 { margin-bottom: 28px; font-size: 1.5rem; } .field { margin-bottom: 20px; } label { display: block; margin-bottom: 6px; font-size: 0.9rem; color: var(--text-muted); } input[type="text"], input[type="password"] { width: 100%; padding: 10px 12px; background: var(--bg); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); font-size: 1rem; transition: border-color var(--transition); } input:focus { outline: none; border-color: var(--border-focus); } .validation-error { display: block; margin-top: 4px; font-size: 0.8rem; color: var(--danger); } .error-message { margin-bottom: 16px; color: var(--danger); font-size: 0.9rem; } button[type="submit"] { width: 100%; padding: 11px; background: var(--accent); color: var(--accent-text); border: none; border-radius: var(--radius); font-size: 1rem; font-weight: 600; cursor: pointer; transition: opacity var(--transition); } button[type="submit"]:disabled { opacity: 0.5; cursor: default; } `], }) export class LoginComponent { form: FormGroup; loading = false; errorMessage = ''; constructor( private fb: FormBuilder, private auth: AuthService, private router: Router, private route: ActivatedRoute, ) { this.form = this.fb.group({ username: ['', Validators.required], password: ['', Validators.required], }); } onSubmit(): void { if (this.form.invalid) { this.form.markAllAsTouched(); return; } this.loading = true; this.errorMessage = ''; const { username, password } = this.form.value; const returnUrl = this.route.snapshot.queryParamMap.get('returnUrl') ?? '/'; this.auth.login(username, password).subscribe({ next: () => { this.loading = false; this.router.navigateByUrl(returnUrl); }, error: () => { this.loading = false; this.errorMessage = 'Invalid username or password'; }, }); } }