refactor: apply email format validator to LandingPageComponent
This commit is contained in:
parent
aaa2d11194
commit
a2cfe78445
3 changed files with 98 additions and 89 deletions
|
|
@ -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
|
||||||
>
|
formControlName="email"
|
||||||
<input
|
type="email"
|
||||||
type="email"
|
id="email"
|
||||||
id="email"
|
placeholder="Email Address"
|
||||||
name="email"
|
autocomplete="email"
|
||||||
#email="ngModel"
|
[class.error-border]="
|
||||||
placeholder="Email Address"
|
form.controls['email'].invalid && form.controls['email'].touched
|
||||||
class="custom-input"
|
"
|
||||||
autocomplete="email"
|
/>
|
||||||
[(ngModel)]="authData.email"
|
|
||||||
[class.error-border]="
|
|
||||||
(!email.valid && 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>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue