import { CommonModule } from '@angular/common'; import { Component, OnInit, inject, signal } from '@angular/core'; import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import { HttpErrorResponse } from '@angular/common/http'; import { Router, RouterLink } from '@angular/router'; import { AuthService } from '../../../core/services/auth.service'; import { NotificationService } from '../../../core/services/notification.service'; import { LoginDto } from '../../../core/models'; /** * Écran de connexion (`/login`) — Etape de session de l'authentification. * * Formulaire réactif (email + mot de passe). Sur succès, `AuthService.login` * stocke le JWT puis le composant navigue vers `/consultation` ; le routing et * la `profilConfigureGuard` redirigeront vers l'onboarding si le profil n'est * pas encore configuré. Sur 401, un message générique « Identifiants invalides. » * est affiché (Exigence 2.2). * * Contrainte zoneless : tout état async est exposé via des signals * (`soumissionEnCours`, `erreur`, `compteExiste`). * * _Requirements: 2.1, 2.3_ */ @Component({ selector: 'app-login', standalone: true, imports: [CommonModule, ReactiveFormsModule, RouterLink], templateUrl: './login.component.html', styleUrl: './login.component.scss' }) export class LoginComponent implements OnInit { private readonly fb = inject(FormBuilder); private readonly authService = inject(AuthService); private readonly router = inject(Router); private readonly notification = inject(NotificationService); form!: FormGroup; /** Vrai pendant l'appel de connexion (désactive le bouton). */ readonly soumissionEnCours = signal(false); /** Message d'erreur courant, ou null si aucune erreur. */ readonly erreur = signal(null); /** * Indique si un compte existe déjà. Le lien d'inscription n'est affiché que * lorsqu'aucun compte n'existe (application mono-utilisateur). */ readonly compteExiste = signal(true); ngOnInit(): void { this.form = this.fb.group({ email: ['', [Validators.required, Validators.email]], motDePasse: ['', [Validators.required, Validators.minLength(8)]] }); this.authService.compteExiste().subscribe({ next: (resultat) => this.compteExiste.set(resultat.existe), // En cas d'échec, on conserve la valeur par défaut (masque l'inscription). error: () => this.compteExiste.set(true) }); } /** Tente la connexion avec les identifiants saisis. */ seConnecter(): void { if (this.form.invalid || this.soumissionEnCours()) { this.form.markAllAsTouched(); return; } const valeur = this.form.getRawValue(); const dto: LoginDto = { email: (valeur.email ?? '').trim(), motDePasse: valeur.motDePasse ?? '' }; this.erreur.set(null); this.soumissionEnCours.set(true); this.authService.login(dto).subscribe({ next: () => { this.soumissionEnCours.set(false); // La cible protégée oriente ensuite vers l'onboarding si nécessaire. this.router.navigate(['/consultation']); }, error: (err: HttpErrorResponse) => { this.soumissionEnCours.set(false); if (err.status === 401) { const message = 'Identifiants invalides.'; this.erreur.set(message); this.notification.error(message); } else { const message = 'La connexion a échoué. Veuillez réessayer.'; this.erreur.set(message); this.notification.error(message); } } }); } }