From 755163b9eb085e6e6cded0be2ace26d46dc5ad9d Mon Sep 17 00:00:00 2001 From: Amr Elsayyad Date: Sun, 14 Jul 2024 22:13:53 +0300 Subject: [PATCH] feat: support login using email (#14) --- src/app/components/login/login.component.html | 91 +++++++++++++------ src/app/components/login/login.component.ts | 6 +- src/app/components/otp/otp.component.html | 49 +++++++--- src/app/components/otp/otp.component.ts | 90 +++++++++--------- src/app/services/auth.service.ts | 28 ++++-- 5 files changed, 171 insertions(+), 93 deletions(-) diff --git a/src/app/components/login/login.component.html b/src/app/components/login/login.component.html index 66a6011..4d02dba 100644 --- a/src/app/components/login/login.component.html +++ b/src/app/components/login/login.component.html @@ -1,46 +1,85 @@
-
-

Login

+
+

+ Login +

- - -
- Account Number is required. + + +
+ Email / Account Number is required.
- +
- - + + [ngClass]="{ + 'fa-eye': showPassword, + 'fa-eye-slash': !showPassword + }" + >
-
+
Password is required.
- +
- -
-
\ No newline at end of file +
diff --git a/src/app/components/login/login.component.ts b/src/app/components/login/login.component.ts index 775360f..09dd9ff 100644 --- a/src/app/components/login/login.component.ts +++ b/src/app/components/login/login.component.ts @@ -32,16 +32,16 @@ export class LoginComponent implements OnInit { initLoginForm(): void { sessionStorage.clear(); this.loginForm = this.fb.group({ - accountNumber: ['', [Validators.required]], + identifier: ['', [Validators.required]], password: ['', [Validators.required]], }); } onSubmit(): void { if (this.loginForm.valid) { - const { accountNumber, password } = this.loginForm.value; + const { identifier, password } = this.loginForm.value; this.loader.show('Logging...'); - this.authService.login(accountNumber, password).subscribe({ + this.authService.login(identifier, password).subscribe({ next: (response: any) => { // Handle successful login here // Save the token from the response if needed diff --git a/src/app/components/otp/otp.component.html b/src/app/components/otp/otp.component.html index f2cd869..58b47c5 100644 --- a/src/app/components/otp/otp.component.html +++ b/src/app/components/otp/otp.component.html @@ -1,26 +1,41 @@
-
- +

OTP Verification

-
+
- - Email / Account Number + + placeholder="Email / Account Number" + />
-
@@ -31,16 +46,22 @@

- +
-

-
\ No newline at end of file +
diff --git a/src/app/components/otp/otp.component.ts b/src/app/components/otp/otp.component.ts index 3a67396..be6d9fb 100644 --- a/src/app/components/otp/otp.component.ts +++ b/src/app/components/otp/otp.component.ts @@ -1,11 +1,11 @@ import { ToastService } from 'angular-toastify'; +import { finalize } from 'rxjs'; import { AuthService } from 'src/app/services/auth.service'; import { LoadermodelService } from 'src/app/services/loadermodel.service'; import { environment } from 'src/environment/environment'; import { Component, ViewChild } from '@angular/core'; import { Router } from '@angular/router'; -import { finalize } from 'rxjs'; @Component({ selector: 'app-otp', @@ -13,7 +13,7 @@ import { finalize } from 'rxjs'; styleUrls: ['./otp.component.css'], }) export class OtpComponent { - accountNumber: string = ''; + identifier: string = ''; otp: string = ''; otpGenerated: boolean = false; authTokenName = environment.tokenName; @@ -23,13 +23,13 @@ export class OtpComponent { private toastService: ToastService, private router: Router, private loader: LoadermodelService - ) { } + ) {} ngOnInit() { // Check if the accountNumber exists in sessionStorage (on page refresh) const storedAccountNumber = sessionStorage.getItem('accountNumber'); if (storedAccountNumber) { - this.accountNumber = storedAccountNumber; + this.identifier = storedAccountNumber; this.otpGenerated = true; } } @@ -40,9 +40,9 @@ export class OtpComponent { length: 6, placeholder: '', inputStyles: { - 'width': '50px', - 'height': '50px' - } + width: '50px', + height: '50px', + }, }; onOtpChange(otp: string) { this.otp = otp; @@ -54,48 +54,54 @@ export class OtpComponent { generateOTP() { this.loader.show('Generating OTP...'); // Show the loader before making the API call - this.authService.generateOTP(this.accountNumber).pipe( - finalize(() => { - this.loader.hide(); // Hide the loader after API call completes (success or error) - }) - ).subscribe({ - next: (response: any) => { - this.toastService.success(response.message + ', Check Email'); - this.otpGenerated = true; - // Save the account number in sessionStorage - sessionStorage.setItem('accountNumber', this.accountNumber); - }, - error: (error: any) => { - this.toastService.error(error.error); - console.error(error); - }, - }); + this.authService + .generateOTP(this.identifier) + .pipe( + finalize(() => { + this.loader.hide(); // Hide the loader after API call completes (success or error) + }) + ) + .subscribe({ + next: (response: any) => { + this.toastService.success(response.message + ', Check Email'); + this.otpGenerated = true; + // Save the account number in sessionStorage + sessionStorage.setItem('accountNumber', this.identifier); + }, + error: (error: any) => { + this.toastService.error(error.error); + console.error(error); + }, + }); } verifyOTP() { this.loader.show('Verifying OTP...'); // Show the loader before making the API call const otpVerificationRequest = { - accountNumber: this.accountNumber, + identifier: this.identifier, otp: this.otp, }; - this.authService.verifyOTP(otpVerificationRequest).pipe( - finalize(() => { - // Hide the loader after API call completes (success or error) - this.loader.hide(); - }) - ).subscribe({ - next: (response: any) => { - console.log(response); - this.toastService.success('Account LoggedIn'); - const token = response.token; - localStorage.setItem(this.authTokenName, token); - this.router.navigate(['/dashboard']); - }, - error: (error: any) => { - this.toastService.error(error.error); - console.error(error); - }, - }); + this.authService + .verifyOTP(otpVerificationRequest) + .pipe( + finalize(() => { + // Hide the loader after API call completes (success or error) + this.loader.hide(); + }) + ) + .subscribe({ + next: (response: any) => { + console.log(response); + this.toastService.success('Account LoggedIn'); + const token = response.token; + localStorage.setItem(this.authTokenName, token); + this.router.navigate(['/dashboard']); + }, + error: (error: any) => { + this.toastService.error(error.error); + console.error(error); + }, + }); } } diff --git a/src/app/services/auth.service.ts b/src/app/services/auth.service.ts index 43be3bb..89225c9 100644 --- a/src/app/services/auth.service.ts +++ b/src/app/services/auth.service.ts @@ -14,7 +14,7 @@ export class AuthService { private baseUrl = environment.apiUrl; // Replace with your actual API base URL private authtokenName = environment.tokenName; - constructor(private http: HttpClient, private router: Router) { } + constructor(private http: HttpClient, private router: Router) {} registerUser(data: any): Observable { return this.http.post(`${this.baseUrl}/users/register`, data); @@ -27,8 +27,9 @@ export class AuthService { updateUserProfile(payload: any): Observable { return this.http.post(`${this.baseUrl}/users/update`, payload); } - generateOTP(accountNumber: string): Observable { - const body = { accountNumber: accountNumber }; + + generateOTP(identifier: string): Observable { + const body = { identifier: identifier }; return this.http.post(`${this.baseUrl}/users/generate-otp`, body); } @@ -39,9 +40,9 @@ export class AuthService { ); } - login(accountNumber: string, password: string): Observable { + login(identifier: string, password: string): Observable { const body = { - accountNumber: accountNumber, + identifier: identifier, password: password, }; return this.http.post(`${this.baseUrl}/users/login`, body); @@ -82,11 +83,22 @@ export class AuthService { verifyOtpForPasswordReset(identifier: string, otp: string): Observable { const body = { identifier: identifier, otp: otp }; - return this.http.post(`${this.baseUrl}/auth/password-reset/verify-otp`, body); + return this.http.post( + `${this.baseUrl}/auth/password-reset/verify-otp`, + body + ); } - resetPassword(identifier: string, resetToken: string, newPassword: string): Observable { - const body = { identifier: identifier, resetToken: resetToken, newPassword: newPassword }; + resetPassword( + identifier: string, + resetToken: string, + newPassword: string + ): Observable { + const body = { + identifier: identifier, + resetToken: resetToken, + newPassword: newPassword, + }; return this.http.post(`${this.baseUrl}/auth/password-reset`, body); } }