refactor: apply email format validator to LandingPageComponent

This commit is contained in:
Chneemann 2025-05-09 09:36:47 +02:00
parent aaa2d11194
commit a2cfe78445
3 changed files with 98 additions and 89 deletions

View file

@ -1,48 +1,42 @@
<section class="home-background"> <section class="home-background">
<div class="headline"> <div class="headline">
<p>Movies, TV shows, and more</p> <p class="title">Movies, TV shows, and more</p>
<p>Watch whenever you want wherever you want</p> <p class="subtitle">Watch whenever you want wherever you want</p>
<p>Enter your email to create or restart your subscription.</p> <p class="note">Enter your email to create or restart your subscription.</p>
</div> </div>
<form
#taskForm="ngForm" <form [formGroup]="form" (ngSubmit)="onSubmit()">
(ngSubmit)="onSubmit(taskForm, email)" <div class="email-field">
onsubmit="return false"
>
<input <input
formControlName="email"
type="email" type="email"
id="email" id="email"
name="email"
#email="ngModel"
placeholder="Email Address" placeholder="Email Address"
class="custom-input"
autocomplete="email" autocomplete="email"
[(ngModel)]="authData.email"
[class.error-border]=" [class.error-border]="
(!email.valid && email.touched) || form.controls['email'].invalid && form.controls['email'].touched
(email.touched &&
!isUserEmailValid(authData.email) &&
authData.email.length > 0)
" "
required
/> />
<div class="error-msg">
@if (!email.valid && email.touched) {
<p>Please enter your email</p>
} @else { @if (email.touched && authData.email.length > 0 &&
!isUserEmailValid(authData.email)) {
<p>This is not a valid email format</p>
}}
</div> </div>
<div class="error-container">
@if (form.controls['email'].touched && form.controls['email'].invalid) {
<div class="error-msg">
@if (form.controls['email'].errors?.['required']) {
<p role="alert">Please enter your email</p>
} @if (form.controls['email'].errors?.['invalidEmailFormat'] &&
form.value.email) {
<p role="alert">This is not a valid email format</p>
}
</div>
}
</div>
<app-btn-large <app-btn-large
[value]="'Sign Up'" [value]="'Sign Up'"
[imgPath]="'play'"
[imgPath]="'arrow_right'" [imgPath]="'arrow_right'"
[imgReverse]="true" [imgReverse]="true"
[disabled]=" [disabled]="form.invalid || form.disabled"
(!isUserEmailValid(authData.email) && authData.email.length > 0) ||
authData.send
"
></app-btn-large> ></app-btn-large>
</form> </form>
</section> </section>

View file

@ -4,20 +4,25 @@
@use "./../../../../assets/style/auth-layout.scss" as *; @use "./../../../../assets/style/auth-layout.scss" as *;
.headline { .headline {
p:nth-child(1) { display: flex;
flex-direction: column;
text-align: center;
max-width: 90%;
gap: 12px;
.title {
font-size: 48px; font-size: 48px;
font-weight: 700; font-weight: 700;
padding: 12px;
} }
p:nth-child(2) {
.subtitle {
font-size: 24px; font-size: 24px;
font-weight: 500; font-weight: 500;
padding: 12px;
} }
p:nth-child(3) {
.note {
font-size: 18px; font-size: 18px;
font-weight: 400; font-weight: 400;
padding: 12px;
} }
} }
@ -26,24 +31,29 @@ form {
position: relative; position: relative;
width: 500px; width: 500px;
padding: 24px; padding: 24px;
input { input {
width: 65%; width: 100%;
padding: 12px 18px; padding: 12px 24px !important;
margin: 8px 0; margin: 8px 0;
color: $white;
border: 2px solid $white; border: 2px solid $white;
border-radius: 24px; border-radius: 24px;
font-size: 18px;
&::placeholder { &::placeholder {
color: rgba($white, 0.6); color: rgba($white, 0.6);
} }
} }
.error-border { .error-border {
border: 2px solid $red; border: 2px solid $red;
} }
app-btn-large {
margin-left: 24px;
width: 230px;
}
} }
.error-msg { .error-container {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
padding: 6px; padding: 6px;
@ -56,28 +66,36 @@ form {
form { form {
flex-direction: column; flex-direction: column;
width: 90%; width: 90%;
input { input {
width: 100%; width: 100%;
} }
app-btn-large {
margin-left: 0;
width: fit-content;
}
} }
.error-msg { .error-container {
position: relative; position: relative;
padding: 0; padding: 0;
height: 12px; height: 12px;
margin-bottom: 8px; margin-bottom: 12px;
} }
} }
@media screen and (max-width: 500px) { @media screen and (max-width: 500px) {
.headline { .headline {
p:nth-child(1) { .title {
font-size: 36px; font-size: 36px;
} }
p:nth-child(2) {
.subtitle {
font-size: 20px; font-size: 20px;
} }
p:nth-child(3) {
.note {
font-size: 16px; font-size: 16px;
} }
} }

View file

@ -1,79 +1,76 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms'; import {
FormBuilder,
FormGroup,
FormsModule,
NgForm,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { BtnLargeComponent } from '../../../shared/components/buttons/btn-large/btn-large.component'; import { BtnLargeComponent } from '../../../shared/components/buttons/btn-large/btn-large.component';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ErrorService } from '../../../services/error.service'; import { ErrorService } from '../../../services/error.service';
import { AuthService } from '../../../services/auth.service'; import { AuthService } from '../../../services/auth.service';
import { emailFormatValidator } from '../../../validators/email-format.validator';
@Component({ @Component({
selector: 'app-landing-page', selector: 'app-landing-page',
standalone: true, standalone: true,
imports: [CommonModule, BtnLargeComponent, FormsModule], imports: [CommonModule, BtnLargeComponent, FormsModule, ReactiveFormsModule],
templateUrl: './landing-page.component.html', templateUrl: './landing-page.component.html',
styleUrl: './landing-page.component.scss', styleUrl: './landing-page.component.scss',
}) })
export class LandingPageComponent { export class LandingPageComponent {
authData = { form: FormGroup = new FormGroup({});
email: '',
send: false,
};
/** /**
* Initializes the LandingPageComponent with Router, AuthService, and ErrorService. * Initializes the LandingPageComponent with Router, FormBuilder, AuthService, and ErrorService.
*/ */
constructor( constructor(
private router: Router, private router: Router,
private fb: FormBuilder,
private authService: AuthService, private authService: AuthService,
public errorService: ErrorService public errorService: ErrorService
) {} ) {}
/** /**
* Validates the given email address. * Initializes the component by setting up necessary data.
* Converts to lowercase before checking against the regex.
*
* @param emailValue The email address to validate.
* @returns True if the email format is valid, false otherwise.
*/ */
isUserEmailValid(emailValue: string): boolean { ngOnInit(): void {
const emailRegex = /^[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,}$/; this.createForm();
return emailRegex.test(emailValue.toLowerCase());
} }
/** /**
* Handles form submission. * Initializes the form with required fields and validators.
* If the form is valid, checks for duplicate email addresses.
*
* @param ngForm The submitted form.
* @param emailInput The input field for the email.
*/ */
async onSubmit(ngForm: NgForm, emailInput: any): Promise<void> { private createForm(): void {
if (ngForm.submitted && ngForm.form.valid) { this.form = this.fb.group({
await this.checkDuplicatesEmail(); email: ['', [Validators.required, emailFormatValidator()]],
} else { });
emailInput.control.markAsTouched();
}
} }
/** /**
* Checks whether the entered email already exists. * Handles the submission of the registration form.
* Navigates to the registration page if it's available. * Validates the form, sends a check if user already exists request,
* Handles UI state and errors accordingly. * and navigates to the registration page if the user does not exist.
*
* @returns A Promise that resolves when the registration process is complete.
*/ */
private async checkDuplicatesEmail(): Promise<void> { async onSubmit(): Promise<void> {
const email = this.authData.email.trim().toLowerCase(); if (this.form.invalid) return;
if (!email) return;
this.authData.send = true; this.form.disable();
const email = this.form.value.email?.toLowerCase().trim();
try { try {
await this.authService.checkAuthUserEmail({ email }); await this.authService.checkAuthUserEmail({ email });
this.errorService.clearError(); this.router.navigate(['/register'], { queryParams: { email } });
this.router.navigate(['/register'], { queryParams: { email: email } }); this.form.reset();
} catch (error) { } catch (error) {
this.errorService.handleError(error); this.errorService.handleError(error);
} finally { } finally {
this.authData.send = false; this.form.enable();
} }
} }
} }