Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Login using Email #14

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 65 additions & 26 deletions src/app/components/login/login.component.html
Original file line number Diff line number Diff line change
@@ -1,46 +1,85 @@
<div class="h-full flex items-center justify-center coverparentspace">
<div class="max-w-md w-full">
<div class="border-none md:border border-gray-300 px-4 py-3 mb-8 bg-white rounded-lg shadow-none md:shadow-md">
<h2 class="my-3 text-center text-3xl font-extrabold text-gray-900">Login</h2>
<div
class="border-none md:border border-gray-300 px-4 py-3 mb-8 bg-white rounded-lg shadow-none md:shadow-md"
>
<h2 class="my-3 text-center text-3xl font-extrabold text-gray-900">
Login
</h2>
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="mb-4">
<label for="accountNumber" class="block text-sm font-bold mb-2">Account Number:</label>
<input formControlName="accountNumber" type="text" id="accountNumber"
class="w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:border-indigo-500" />
<div *ngIf="loginForm.get('accountNumber')?.invalid && loginForm.get('accountNumber')?.touched"
class="text-red-500 text-sm mt-1">
Account Number is required.
<label for="identifier" class="block text-sm font-bold mb-2"
>Email / Account Number:</label
>
<input
formControlName="identifier"
type="text"
id="identifier"
class="w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:border-indigo-500"
/>
<div
*ngIf="
loginForm.get('identifier')?.invalid &&
loginForm.get('identifier')?.touched
"
class="text-red-500 text-sm mt-1"
>
Email / Account Number is required.
</div>
</div>
<div class="mb-6">
<label for="password" class="block text-sm font-bold mb-2">Password:</label>
<label for="password" class="block text-sm font-bold mb-2"
>Password:</label
>
<div class="relative">
<input formControlName="password" type="{{ showPassword ? 'text' : 'password' }}" id="password"
class="w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:border-indigo-500" />
<span class="fa fa-eye-slash absolute right-3 top-1/2 transform -translate-y-1/2 cursor-pointer"
<input
formControlName="password"
type="{{ showPassword ? 'text' : 'password' }}"
id="password"
class="w-full px-3 py-2 border rounded-lg shadow-sm focus:outline-none focus:border-indigo-500"
/>
<span
class="fa fa-eye-slash absolute right-3 top-1/2 transform -translate-y-1/2 cursor-pointer"
(click)="togglePasswordVisibility()"
[ngClass]="{ 'fa-eye': showPassword, 'fa-eye-slash': !showPassword }"></span>
[ngClass]="{
'fa-eye': showPassword,
'fa-eye-slash': !showPassword
}"
></span>
</div>
<div *ngIf="loginForm.get('password')?.invalid && loginForm.get('password')?.touched"
class="text-red-500 text-sm mt-1">
<div
*ngIf="
loginForm.get('password')?.invalid &&
loginForm.get('password')?.touched
"
class="text-red-500 text-sm mt-1"
>
Password is required.
</div>
</div>
<div class="flex items-center justify-between">
<button type="submit" [disabled]="loginForm.invalid"
class="group relative w-full flex justify-center py-2 px-4 bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-3 px-6 rounded focus:outline-none focus:shadow-outline disabled:opacity-50 disabled:cursor-not-allowed">Login</button>
<button
type="submit"
[disabled]="loginForm.invalid"
class="group relative w-full flex justify-center py-2 px-4 bg-indigo-500 hover:bg-indigo-700 text-white font-bold py-3 px-6 rounded focus:outline-none focus:shadow-outline disabled:opacity-50 disabled:cursor-not-allowed"
>
Login
</button>
</div>
</form>

<div class="flex justify-between">
<a class="block mt-4 font-semibold leading-6 text-indigo-600 hover:text-indigo-500" routerLink="/login/otp">Login
via
Otp</a>
<a class="block mt-4 font-semibold leading-6 text-indigo-600 hover:text-indigo-500" routerLink="/forget-password">Forget Password?
</a>

<div class="flex justify-between">
<a
class="block mt-4 font-semibold leading-6 text-indigo-600 hover:text-indigo-500"
routerLink="/login/otp"
>Login via Otp</a
>
<a
class="block mt-4 font-semibold leading-6 text-indigo-600 hover:text-indigo-500"
routerLink="/forget-password"
>Forget Password?
</a>
</div>

</div>
</div>
</div>
</div>
6 changes: 3 additions & 3 deletions src/app/components/login/login.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
49 changes: 35 additions & 14 deletions src/app/components/otp/otp.component.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,41 @@
<div class="h-full flex items-center justify-center coverparentspace">
<div class="max-w-md w-full">
<div class="border-none md:border border-gray-300 px-4 py-3 mb-8 bg-white rounded-lg shadow-none md:shadow-md">

<div
class="border-none md:border border-gray-300 px-4 py-3 mb-8 bg-white rounded-lg shadow-none md:shadow-md"
>
<h2 class="my-3 text-center text-3xl font-extrabold text-gray-900">
OTP Verification
</h2>

<ng-container *ngIf="!otpGenerated; else verifyOtpSection">
<!-- OTP Generation Section -->
<form class="mt-8 space-y-6" (ngSubmit)="generateOTP()" #otpForm="ngForm">
<form
class="mt-8 space-y-6"
(ngSubmit)="generateOTP()"
#otpForm="ngForm"
>
<div class="rounded-md shadow-sm -space-y-px">
<div>
<label for="accountNumber" class="sr-only">Account Number</label>
<input id="accountNumber" name="accountNumber" type="text" [(ngModel)]="accountNumber" required
<label for="identifier" class="block text-sm font-bold mb-2"
>Email / Account Number</label
>
<input
id="identifier"
name="identifier"
type="text"
[(ngModel)]="identifier"
required
class="appearance-none rounded-none relative block w-full px-3 py-2 border text-gray-700 placeholder-gray-400 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
placeholder="Account Number" />
placeholder="Email / Account Number"
/>
</div>
</div>

<div>
<button type="submit"
class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<button
type="submit"
class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
>
Generate OTP
</button>
</div>
Expand All @@ -31,16 +46,22 @@ <h2 class="my-3 text-center text-3xl font-extrabold text-gray-900">
<ng-template #verifyOtpSection>
<div class="mt-8 space-y-6">
<div class="flex justify-center">
<ng-otp-input #ngOtpInput (onInputChange)="onOtpChange($event)" [config]="config"></ng-otp-input>
<ng-otp-input
#ngOtpInput
(onInputChange)="onOtpChange($event)"
[config]="config"
></ng-otp-input>
</div>
<button type="submit"
(click)="verifyOTP()"
[disabled]="otp.length !== 6"
class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-indigo-200 disabled:cursor-not-allowed">
<button
type="submit"
(click)="verifyOTP()"
[disabled]="otp.length !== 6"
class="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:bg-indigo-200 disabled:cursor-not-allowed"
>
Verify OTP
</button>
</div>
</ng-template>
</div>
</div>
</div>
</div>
90 changes: 48 additions & 42 deletions src/app/components/otp/otp.component.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
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',
templateUrl: './otp.component.html',
styleUrls: ['./otp.component.css'],
})
export class OtpComponent {
accountNumber: string = '';
identifier: string = '';
otp: string = '';
otpGenerated: boolean = false;
authTokenName = environment.tokenName;
Expand All @@ -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;
}
}
Expand All @@ -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;
Expand All @@ -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);
},
});
}
}
Loading