All files / app/authentication/register register.ts

90.38% Statements 47/52
93.33% Branches 28/30
77.77% Functions 7/9
89.58% Lines 43/48

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109                        87x 1x 1x 1x 1x   1x 1x   1x 1x 1x 1x   1x               133x             12x 12x 12x 12x   12x 4x 4x 2x   4x     8x   8x 8x 8x 5x 5x 5x     3x     3x   8x         467x 467x       5x             5x             41x 5x 5x     41x 5x 5x         29x      
import { Component, OnDestroy, computed, inject, signal } from '@angular/core';
import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { TranslocoModule, TranslocoService } from '@jsverse/transloco';
import { SupabaseConnector } from '../../services/supabase-connector';
 
@Component({
  selector: 'app-register',
  imports: [ReactiveFormsModule, TranslocoModule],
  templateUrl: './register.html',
  styleUrl: './register.scss',
})
export class Register implements OnDestroy {
  private readonly fb = inject(FormBuilder);
  private readonly supabaseService = inject(SupabaseConnector);
  private readonly router = inject(Router);
  private readonly transloco = inject(TranslocoService);
 
  private redirectTimeoutId: number | null = null;
  private redirectIntervalId: number | null = null;
 
  readonly isSubmitting = signal(false);
  readonly submitError = signal<string | null>(null);
  readonly registrationSucceeded = signal(false);
  readonly redirectCountdown = signal(5);
 
  readonly registerForm = this.fb.nonNullable.group({
    email: ['', [Validators.required, Validators.email]],
    username: ['', [Validators.required, Validators.minLength(3)]],
    password: ['', [Validators.required, Validators.minLength(8)]],
    confirmPassword: ['', [Validators.required]],
  });
 
  passwordsMatch(): boolean {
    return (
      this.registerForm.controls.password.value ===
      this.registerForm.controls.confirmPassword.value
    );
  }
 
  async onSubmit(): Promise<void> {
    this.clearRedirectTimers();
    this.submitError.set(null);
    this.registrationSucceeded.set(false);
    this.redirectCountdown.set(5);
 
    if (this.registerForm.invalid || !this.passwordsMatch()) {
      this.registerForm.markAllAsTouched();
      if (!this.passwordsMatch()) {
        this.submitError.set(this.transloco.translate('auth.register.passwordsMismatch'));
      }
      return;
    }
 
    this.isSubmitting.set(true);
 
    try {
      const { email, username, password } = this.registerForm.getRawValue();
      await this.supabaseService.register(email, username, password);
      this.registrationSucceeded.set(true);
      this.registerForm.reset();
      this.startRedirectCountdown();
    } catch (error) {
      const message =
        error instanceof Error
          ? error.message
          : this.transloco.translate('auth.register.submitFailed');
      this.submitError.set(message);
    } finally {
      this.isSubmitting.set(false);
    }
  }
 
  isInvalid(controlName: keyof typeof this.registerForm.controls): boolean {
    const control = this.registerForm.controls[controlName];
    return control.invalid && control.touched;
  }
 
  private startRedirectCountdown(): void {
    this.redirectIntervalId = window.setInterval(() => {
      const next = this.redirectCountdown() - 1;
      if (next >= 0) {
        this.redirectCountdown.set(next);
      }
    }, 1000);
 
    this.redirectTimeoutId = window.setTimeout(() => {
      this.clearRedirectTimers();
      this.router.navigateByUrl('/');
    }, 5000);
  }
 
  private clearRedirectTimers(): void {
    if (this.redirectIntervalId !== null) {
      window.clearInterval(this.redirectIntervalId);
      this.redirectIntervalId = null;
    }
 
    if (this.redirectTimeoutId !== null) {
      window.clearTimeout(this.redirectTimeoutId);
      this.redirectTimeoutId = null;
    }
  }
 
  ngOnDestroy(): void {
    this.clearRedirectTimers();
  }
}