File

src/app/modules/shared-feature/components/otp-popup/otp-popup.component.ts

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods
Inputs
Outputs

Constructor

constructor(resourceService: ResourceService, tenantService: TenantService, deviceDetectorService: DeviceDetectorService, otpService: OtpService, userService: UserService, utilService: UtilService, configService: ConfigService, toasterService: ToasterService)
Parameters :
Name Type Optional
resourceService ResourceService No
tenantService TenantService No
deviceDetectorService DeviceDetectorService No
otpService OtpService No
userService UserService No
utilService UtilService No
configService ConfigService No
toasterService ToasterService No

Inputs

otpData
Type : any
redirectToLogin
Type : boolean

Outputs

closeContactForm
Type : EventEmitter
redirectToParent
Type : EventEmitter
verificationSuccess
Type : EventEmitter

Methods

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

Properties

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;
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""