src/app/modules/shared-feature/components/otp-popup/otp-popup.component.ts
OnInit
OnDestroy
selector | app-otp-popup |
styleUrls | ./otp-popup.component.scss |
templateUrl | ./otp-popup.component.html |
Properties |
|
Methods |
Inputs |
Outputs |
constructor(resourceService: ResourceService, tenantService: TenantService, deviceDetectorService: DeviceDetectorService, otpService: OtpService, userService: UserService, utilService: UtilService, configService: ConfigService, toasterService: ToasterService)
|
|||||||||||||||||||||||||||
Parameters :
|
otpData | |
Type : any
|
|
redirectToLogin | |
Type : boolean
|
|
closeContactForm | |
Type : EventEmitter
|
|
redirectToParent | |
Type : EventEmitter
|
|
verificationSuccess | |
Type : EventEmitter
|
|
enableSubmitButton |
enableSubmitButton()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
ngOnInit |
ngOnInit()
|
Returns :
void
|
redirectToParentComponent |
redirectToParentComponent()
|
Returns :
void
|
resendOTP |
resendOTP()
|
Returns :
boolean
|
resendOtpEnablePostTimer |
resendOtpEnablePostTimer()
|
Returns :
void
|
setInteractEventData |
setInteractEventData()
|
Returns :
void
|
verifyOTP |
verifyOTP()
|
Returns :
void
|
Public configService |
Type : ConfigService
|
counter |
Public deviceDetectorService |
Type : DeviceDetectorService
|
disableResendButton |
Default value : false
|
enableResendButton |
Default value : false
|
enableSubmitBtn |
Default value : false
|
errorMessage |
Type : string
|
infoMessage |
Type : string
|
logo |
Type : string
|
maxResendTry |
Type : number
|
Default value : 4
|
otpForm |
Type : UntypedFormGroup
|
Public otpService |
Type : OtpService
|
remainingAttempt |
resendOTPbtn |
resendOtpCounter |
Type : number
|
Default value : 0
|
resendOtpInteractEdata |
Type : IInteractEventEdata
|
Public resourceService |
Type : ResourceService
|
submitInteractEdata |
Type : IInteractEventEdata
|
telemetryInteractObject |
Type : IInteractEventObject
|
tenantDataSubscription |
Type : Subscription
|
tenantName |
Type : string
|
Public tenantService |
Type : TenantService
|
Public toasterService |
Type : ToasterService
|
Public unsubscribe |
Default value : new Subject<void>()
|
Public userService |
Type : UserService
|
Public utilService |
Type : UtilService
|
import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
import {ResourceService, ServerResponse, UtilService, ConfigService, ToasterService} from '@sunbird/shared';
import { Validators, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
import * as _ from 'lodash-es';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subscription, Subject } from 'rxjs';
import { TenantService, OtpService, UserService } from '@sunbird/core';
import { IInteractEventObject, IInteractEventEdata } from '@sunbird/telemetry';
@Component({
selector: 'app-otp-popup',
templateUrl: './otp-popup.component.html',
styleUrls: ['./otp-popup.component.scss']
})
export class OtpPopupComponent implements OnInit, OnDestroy {
@Input() otpData: any;
@Input() redirectToLogin: boolean;
@Output() redirectToParent = new EventEmitter();
@Output() verificationSuccess = new EventEmitter();
@Output() closeContactForm = new EventEmitter();
public unsubscribe = new Subject<void>();
otpForm: UntypedFormGroup;
enableSubmitBtn = false;
errorMessage: string;
infoMessage: string;
disableResendButton = false;
enableResendButton = false;
tenantDataSubscription: Subscription;
resendOTPbtn;
counter;
resendOtpCounter = 0;
maxResendTry = 4;
logo: string;
tenantName: string;
submitInteractEdata: IInteractEventEdata;
resendOtpInteractEdata: IInteractEventEdata;
telemetryInteractObject: IInteractEventObject;
remainingAttempt: 'string';
constructor(public resourceService: ResourceService, public tenantService: TenantService,
public deviceDetectorService: DeviceDetectorService, public otpService: OtpService, public userService: UserService,
public utilService: UtilService, public configService: ConfigService,
public toasterService: ToasterService) {
}
ngOnInit() {
this.tenantDataSubscription = this.tenantService.tenantData$.subscribe(
data => {
if (data && !data.err) {
this.logo = data.tenantData.logo;
this.tenantName = data.tenantData.titleName;
}
}
);
this.otpForm = new UntypedFormGroup({
otp: new UntypedFormControl('', [Validators.required])
});
this.resendOtpEnablePostTimer();
this.enableSubmitButton();
this.setInteractEventData();
}
resendOtpEnablePostTimer() {
this.counter = 20;
this.disableResendButton = false;
this.enableResendButton = false;
setTimeout(() => {
this.enableResendButton = true;
}, 22000);
const interval = setInterval(() => {
this.resendOTPbtn = this.resourceService.frmelmnts.lbl.resendOTP + ' (' + this.counter + ')';
this.counter--;
if (this.counter < 0) {
this.resendOTPbtn = this.resourceService.frmelmnts.lbl.resendOTP;
clearInterval(interval);
}
}, 1000);
}
verifyOTP() {
const wrongOTPMessage = this.otpData.type === 'phone' ? this.resourceService.frmelmnts.lbl.wrongPhoneOTP :
this.resourceService.frmelmnts.lbl.wrongEmailOTP;
this.enableSubmitBtn = false;
const request = {
'request': {
'key': this.otpData.value,
'type': this.otpData.type,
'otp': this.otpForm.controls.otp.value,
...( this.otpData.value && this.otpData.value.match(/(([a-z]|[A-Z])+[*]{1,}([a-z]*[A-Z]*[0-9]*)*@)|([*]{1,})+/g) &&
{ 'userId': this.userService.userid })
}
};
this.otpService.verifyOTP(request).subscribe(
(data: ServerResponse) => {
this.infoMessage = '';
this.errorMessage = '';
let emitData = {};
if (this.otpData.type === 'phone') {
emitData = {'phone': this.otpData.value, 'phoneVerified': true};
} else if (this.otpData.type === 'email') {
emitData = {'email': this.otpData.value, 'emailVerified': true};
}
this.verificationSuccess.emit(emitData);
},
(err) => {
if (_.get(err, 'error.result.remainingAttempt') === 0) {
if (this.redirectToLogin) {
this.utilService.redirectToLogin(this.resourceService.messages.emsg.m0050);
} else {
this.toasterService.error(this.resourceService.messages.emsg.m0050);
this.closeContactForm.emit('true');
}
} else {
this.otpForm.controls['otp'].setValue('');
this.enableSubmitBtn = true;
this.infoMessage = '';
this.remainingAttempt = _.get(err, 'error.result.remainingAttempt') || 1;
this.errorMessage =
_.get(err, 'error.params.status') === this.configService.constants.HTTP_STATUS_CODES.OTP_VERIFICATION_FAILED ?
_.get(this.resourceService, 'messages.imsg.m0086') : wrongOTPMessage;
}
}
);
}
resendOTP() {
this.disableResendButton = false;
this.enableResendButton = false;
this.resendOtpCounter = this.resendOtpCounter + 1 ;
if (this.resendOtpCounter >= this.maxResendTry) {
this.disableResendButton = false;
this.infoMessage = '';
this.errorMessage = this.resourceService.frmelmnts.lbl.OTPresendMaxretryreached;
return false;
}
this.otpForm.controls['otp'].setValue('');
const request = {
'request': {
'key': this.otpData.value,
'type': this.otpData.type,
...( this.otpData.value && this.otpData.value.match(/(([a-z]|[A-Z])+[*]{1,}([a-z]*[A-Z]*[0-9]*)*@)|([*]{1,})+/g) &&
{ userId: this.userService.userid, templateId: this.configService.appConfig.OTPTemplate.updateContactTemplate })
}
};
this.otpService.generateOTP(request).subscribe(
(data: ServerResponse) => {
this.resendOtpEnablePostTimer();
this.errorMessage = '';
this.infoMessage = this.resourceService.frmelmnts.lbl.resentOTP;
},
(err) => {
this.infoMessage = '';
this.errorMessage = this.resourceService.messages.fmsg.m0051;
}
);
}
enableSubmitButton() {
this.otpForm.valueChanges.subscribe(val => {
this.enableSubmitBtn = (this.otpForm.status === 'VALID');
});
}
redirectToParentComponent() {
this.redirectToParent.emit('true');
}
ngOnDestroy() {
if (this.tenantDataSubscription) {
this.tenantDataSubscription.unsubscribe();
}
this.unsubscribe.next();
this.unsubscribe.complete();
}
setInteractEventData() {
this.submitInteractEdata = {
id: 'submit-otp',
type: 'click',
pageid: 'profile-read'
};
this.resendOtpInteractEdata = {
id: 'resend-otp',
type: 'click',
pageid: 'profile-read'
};
this.telemetryInteractObject = {
id: this.userService.userid,
type: 'User',
ver: '1.0'
};
}
}
<!--Content-->
<div class="sb-mat__modal__content">
<div class="container-wrapper">
<div class="d-flex flex-jc-center">
<img class="image centered" alt={{tenantName}} height="45" src="{{logo}}">
</div>
<div class="mt-20">
<p *ngIf="!disableResendButton" class="line-height-1-3 grey text text-center mb-24">{{otpData?.instructions}}</p>
<div *ngIf="disableResendButton" class="grey text fs-1 text-center mb-30 line-height-1-3">{{otpData?.retryMessage}}<br><span
(click)="redirectToParentComponent()" class="fs-1 blue text font-weight-bold cursor-pointer" role="button" tabindex="0">{{resourceService?.frmelmnts?.lbl?.clickHere}}</span>
{{resourceService?.frmelmnts?.lbl?.toTryAgain}}</div>
<div class="fs-1 font-weight-bold text-center mb-16">{{resourceService?.frmelmnts?.lbl?.enterOTP}}</div>
<form class="sb-form borderd mb-16" [formGroup]="otpForm">
<label *ngIf="errorMessage" class="sb-text-error d-inline-block line-height-1-3">{{errorMessage | interpolate: '{remainingAttempt}': remainingAttempt}}</label>
<label *ngIf="infoMessage" class="text-center mb-10 d-inline-block line-height-1-3">{{infoMessage}}</label>
<div class="sb-field">
<input class="sb-form-control text-center" [ngClass]="{'orange-border': errorMessage}" formControlName="otp" type="text" name="otp">
</div>
</form>
<div appTelemetryInteract [telemetryInteractObject]="telemetryInteractObject"
[telemetryInteractEdata]="resendOtpInteractEdata" [ngClass]="{'grey cursor-pointerText': !enableResendButton}" (click)="resendOTP(); disableResendButton = true" class="fs-1 text-center blue text mb-30 cursor-pointer"
role="button" tabindex="0">{{resendOTPbtn}}</div>
</div>
</div>
</div>
<!--/Content-->
<!--Actions-->
<div class="sb-mat__modal__actions flex-jc-center">
<button appTelemetryInteract [telemetryInteractObject]="telemetryInteractObject"
[telemetryInteractEdata]="submitInteractEdata"
[ngClass]="{'sb-btn-disabled':!enableSubmitBtn}"
class="sb-btn sb-btn-normal sb-btn-primary" tabindex="0"
(click)="verifyOTP()">{{resourceService?.frmelmnts?.lbl?.submitOTP}}</button>
</div>
<!--/Actions-->
./otp-popup.component.scss
@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;
@use 'pages/sign_in_up' as *;
.orange-border {
border-color: var(--accessibility-red) !important;
}
.blue.text {
color: var(--primary-color);
}
input[type=number]::-webkit-outer-spin-button,
input[type=number]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.cursor-pointerText {
cursor: text;
pointer-events: none !important;
}