src/app/signup/otp/otp.page.ts
OnInit
selector | app-otp |
styleUrls | ./otp.page.scss |
templateUrl | ./otp.page.html |
Properties |
Methods |
|
constructor(profileService: ProfileService, preference: SharedPreferences, _fb: FormBuilder, commonUtilService: CommonUtilService, tncUpdateHandlerService: TncUpdateHandlerService, location: Location, router: Router)
|
||||||||||||||||||||||||
Defined in src/app/signup/otp/otp.page.ts:26
|
||||||||||||||||||||||||
Parameters :
|
changeEvent | ||||
changeEvent(event)
|
||||
Defined in src/app/signup/otp/otp.page.ts:187
|
||||
Parameters :
Returns :
void
|
Async continue |
continue()
|
Defined in src/app/signup/otp/otp.page.ts:54
|
Returns :
any
|
goBack |
goBack()
|
Defined in src/app/signup/otp/otp.page.ts:41
|
Returns :
void
|
Async ngOnInit |
ngOnInit()
|
Defined in src/app/signup/otp/otp.page.ts:45
|
Returns :
any
|
redirectToLogin |
redirectToLogin()
|
Defined in src/app/signup/otp/otp.page.ts:183
|
Returns :
void
|
Async resendOTP |
resendOTP()
|
Defined in src/app/signup/otp/otp.page.ts:142
|
Returns :
any
|
acceptAgreement |
Default value : false
|
Defined in src/app/signup/otp/otp.page.ts:23
|
appName |
Type : string
|
Default value : ''
|
Defined in src/app/signup/otp/otp.page.ts:20
|
btnColor |
Type : string
|
Default value : '#8FC4FF'
|
Defined in src/app/signup/otp/otp.page.ts:17
|
contactNumber |
Type : string
|
Default value : ''
|
Defined in src/app/signup/otp/otp.page.ts:22
|
enableResend |
Default value : true
|
Defined in src/app/signup/otp/otp.page.ts:21
|
invalidOtp |
Default value : false
|
Defined in src/app/signup/otp/otp.page.ts:24
|
loader |
Type : any
|
Defined in src/app/signup/otp/otp.page.ts:26
|
Public otpInfoForm |
Type : FormGroup
|
Defined in src/app/signup/otp/otp.page.ts:18
|
remainingAttempts |
Type : any
|
Defined in src/app/signup/otp/otp.page.ts:25
|
Public router |
Type : Router
|
Defined in src/app/signup/otp/otp.page.ts:34
|
userData |
Type : any
|
Defined in src/app/signup/otp/otp.page.ts:19
|
import { Component, Inject, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { ProfileConstants, OTPTemplates, RouterLinks, PreferenceKey } from '@app/app/app.constant';
import { CommonUtilService } from '@app/services';
import { VerifyOtpRequest, HttpClientError, GenerateOtpRequest, ProfileService, SharedPreferences } from 'sunbird-sdk';
import { Location as SbLocation } from '@project-sunbird/client-services/models/location';
import { TncUpdateHandlerService } from '@app/services/handlers/tnc-update-handler.service';
import { Location } from '@angular/common';
@Component({
selector: 'app-otp',
templateUrl: './otp.page.html',
styleUrls: ['./otp.page.scss'],
})
export class OtpPage implements OnInit {
btnColor = '#8FC4FF';
public otpInfoForm: FormGroup;
userData: any;
appName = '';
enableResend = true;
contactNumber = '';
acceptAgreement = false;
invalidOtp = false;
remainingAttempts: any;
loader: any;
constructor(
@Inject('PROFILE_SERVICE') private profileService: ProfileService,
@Inject('SHARED_PREFERENCES') private preference: SharedPreferences,
private _fb: FormBuilder,
private commonUtilService: CommonUtilService,
private tncUpdateHandlerService: TncUpdateHandlerService,
private location: Location,
public router: Router) {
const extrasState = this.router.getCurrentNavigation().extras.state;
this.userData = extrasState.userData;
this.contactNumber = this.userData?.contactInfo?.phone ? (this.userData?.contactInfo?.phone).replace(/\d(?=\d{4})/g, '*')
: this.userData?.contactInfo?.email;
}
goBack() {
this.location.back();
}
async ngOnInit() {
this.otpInfoForm =
this._fb.group({
otp: ['', Validators.required],
});
this.appName = await this.commonUtilService.getAppName();
}
async continue() {
if (this.commonUtilService.networkInfo.isNetworkAvailable) {
this.loader = await this.commonUtilService.getLoader();
await this.loader.present();
let req: VerifyOtpRequest;
if (this.userData.contactInfo.type === ProfileConstants.CONTACT_TYPE_PHONE) {
req = {
key: this.userData.contactInfo.phone,
type: ProfileConstants.CONTACT_TYPE_PHONE,
otp: this.otpInfoForm.value.otp,
...(this.userData.contactInfo.phone &&
this.userData.contactInfo.phone.match(/(([a-z]|[A-Z])+[*]+([a-z]*[A-Z]*[0-9]*)*@)|([0-9]+[*]+[0-9]*)+/g) &&
{ userId: this.userData.userId })
};
} else {
req = {
key: this.userData.contactInfo.email,
type: ProfileConstants.CONTACT_TYPE_EMAIL,
otp: this.otpInfoForm.value.otp,
...(this.userData.contactInfo &&
this.userData.contactInfo.email.match(/(([a-z]|[A-Z])+[*]+([a-z]*[A-Z]*[0-9]*)*@)|([0-9]+[*]+[0-9]*)+/g) &&
{ userId: this.userData.userId })
};
}
this.profileService.verifyOTP(req).toPromise()
.then(() => {
const locationCodes = [];
for(const acc in this.userData.location) {
if (this.userData.location[acc]) {
const location: SbLocation = this.userData.location[acc] as SbLocation;
if (location.type) {
locationCodes.push({
type: location.type,
code: location.code
});
}
}
};
const profileReq = {
userId: this.userData.userId,
profileLocation: locationCodes,
firstName: this.userData.name,
lastName: '',
dob: this.userData.dob,
profileUserTypes: this.userData.profileUserTypes
};
this.profileService.updateServerProfile(profileReq).toPromise()
.then(async (data) => {
if (this.userData.profileUserTypes.length && this.userData.profileUserTypes[0].type) {
await this.preference.putString(PreferenceKey.SELECTED_USER_TYPE, this.userData.profileUserTypes[0].type).toPromise();
}
await this.loader.dismiss();
const categoriesProfileData = {
hasFilledLocation: true,
showOnlyMandatoryFields: true,
};
this.router.navigate([`/${RouterLinks.PROFILE}/${RouterLinks.CATEGORIES_EDIT}`], {
state: categoriesProfileData
});
}).catch(async (error) => {
console.error(error);
await this.loader.dismiss();
if (error.response.body.params.err === 'UOS_USRUPD0003') {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('SOMETHING_WENT_WRONG'));
}
});
})
.catch(error => {
this.loader.dismiss();
if (HttpClientError.isInstance(error)
&& error.response.responseCode === 400) {
if (typeof error.response.body === 'object') {
if (error.response.body.params.err === 'UOS_OTPVERFY0063' &&
error.response.body.result.remainingAttempt > 0) {
this.remainingAttempts = error.response.body.result.remainingAttempt;
this.otpInfoForm.value.otp = '';
this.invalidOtp = true;
} else {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('OTP_FAILED'));
}
}
}
});
} else {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('INTERNET_CONNECTIVITY_NEEDED'));
}
}
async resendOTP() {
if (this.commonUtilService.networkInfo.isNetworkAvailable) {
this.enableResend = !this.enableResend;
let req: GenerateOtpRequest;
if (this.userData.contactInfo.type === ProfileConstants.CONTACT_TYPE_PHONE) {
req = {
key: this.userData.contactInfo.phone,
type: ProfileConstants.CONTACT_TYPE_PHONE,
...(this.userData.contactInfo &&
this.userData.contactInfo.phone.match(/(([a-z]|[A-Z])+[*]+([a-z]*[A-Z]*[0-9]*)*@)|([0-9]+[*]+[0-9]*)+/g) &&
{ userId: this.userData.userId, templateId: OTPTemplates.EDIT_CONTACT_OTP_TEMPLATE })
};
} else {
req = {
key: this.userData.contactInfo.email,
type: ProfileConstants.CONTACT_TYPE_EMAIL,
...(this.userData.contactInfo.email &&
this.userData.contactInfo.email.match(/(([a-z]|[A-Z])+[*]+([a-z]*[A-Z]*[0-9]*)*@)|([0-9]+[*]+[0-9]*)+/g) &&
{ userId: this.userData.userId, templateId: OTPTemplates.EDIT_CONTACT_OTP_TEMPLATE })
};
}
let loader = await this.commonUtilService.getLoader();
await loader.present();
this.profileService.generateOTP(req).toPromise()
.then(async () => {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('OTP_RESENT'));
await loader.dismiss();
loader = undefined;
})
.catch(async (e) => {
if (loader) {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('SOMETHING_WENT_WRONG'));
await loader.dismiss();
loader = undefined;
}
});
} else {
this.commonUtilService.showToast(this.commonUtilService.translateMessage('INTERNET_CONNECTIVITY_NEEDED'));
}
}
redirectToLogin() {
this.router.navigate([RouterLinks.SIGN_IN]);
}
changeEvent(event) {
this.acceptAgreement = event.target.checked;
}
}
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button icon-only (click)="goBack()">
<ion-icon class="arrow-icon back-arrow" role="button" aria-label="back" name="arrow-back"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title role="heading" aria-level="1">{{'FRMELEMNTS_LBL_STEP' | translate:{'page_number': '4/4'} }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<div class="sign-up-div">
<div class="header">
<div class="logos">
<img src="assets/imgs/ic_launcher.png" alt="app">
</div>
<div class="ion-padding">
<h1 class="title">{{'APP_TITLE' | translate:{'%s': appName} }}</h1>
</div>
</div>
</div>
<div class="tablebox">
<table>
<tr>
<td>{{'NAME' | translate }}</td>
<td>{{userData?.name}}</td>
</tr>
<tr>
<td>{{'YOB_TITLE' | translate}}</td>
<td>{{userData?.dob}}</td>
</tr>
<tr>
<td>{{'STATE' | translate}}</td>
<td>{{userData?.location?.state?.name}}</td>
</tr>
<tr>
<td>{{'DISTRICT' | translate}}</td>
<td>{{userData?.location?.district?.name}}</td>
</tr>
<tr>
<td>{{'FRMELEMNTS_LBL_SCHOOL' | translate}}</td>
<td>{{userData?.location?.school?.name}}</td>
</tr>
<tr>
<td>{{'FRMELEMNTS_LBL_BLOCK' | translate}}</td>
<td>{{userData?.location?.block?.name}}</td>
</tr>
<tr>
<td>{{'FRMELEMNTS_LBL_CLUSTER' | translate}}</td>
<td>{{userData?.location?.cluster?.name}}</td>
</tr>
</table>
</div>
<div class="center">
<h5>{{'FRMELEMNTS_LBL_OTP_SENT_TO' | translate:{'contactNumber': contactNumber} }}</h5>
<span>{{'FRMELEMNTS_LBL_OTP_VALID_FOR' | translate}}</span>
<p>{{'FRMELEMNTS_LBL_OTP_PARENT_GUARDIAN' | translate}}</p>
</div>
<form [formGroup]="otpInfoForm" (ngSubmit)="continue()">
<ion-item lines="none">
<div size="12" class="text-center ion-no-padding" *ngIf="invalidOtp">
<p class="error">{{'ERROR_OTP' | translate:{'%s': remainingAttempts} }}</p>
</div>
<ion-label position="stacked">{{'FRMELEMNTS_LBL_OTP' | translate}}</ion-label>
<ion-input type="tel" placeholder="{{'ENTER_OTP' | translate}}" formControlName="otp"></ion-input>
</ion-item>
<div class="ion-padding-start danger"
*ngIf="otpInfoForm.controls.otp.touched && otpInfoForm.controls['otp'].errors && otpInfoForm.controls['otp'].errors.required">
{{'FRMELEMNTS_LBL_OTP_VALIDATION' | translate}}
</div>
<ion-item lines="none">
<ion-checkbox slot="start" name="agreement" (ionChange)="changeEvent($event)"></ion-checkbox>
<ion-text class="accepttext">{{'FRMELEMNTS_LBL_OTP_TERMS' | translate:{'app_name': appName} }}</ion-text>
</ion-item>
<div class="btn-info">
<ion-button expand="block"
[disabled]="otpInfoForm.value.otp && !acceptAgreement" (click)="continue()">
{{'FRMELEMNTS_LBL_CONTINUE' | translate}} <ion-icon class="mg-popup-btn-icon" name="arrow-forward" slot="end">
</ion-icon>
</ion-button>
</div>
</form>
<div class="center pb-40">
{{'FRMELEMNTS_LBL_OTP_NOT_RECEIVED' | translate}}<ion-button fill="clear" (click)="resendOTP();" [disabled]="!enableResend">{{'FRMELEMNTS_LBL_RESEND_OTP' | translate}}
</ion-button>
</div>
</ion-content>
<div class="footer">
<label>{{'FRMELEMNTS_LBL_HAVE_ACCOUNT' | translate }}</label>
<button class="login-info sb-btn sb-btn-normal sb-btn-outline-primary text-uppercase"
aria-label="Already have an account? Login here" tabindex="0" (click)="redirectToLogin()" type="submit">{{'SIGN_IN'
| translate}}</button>
</div>
./otp.page.scss
@import "src/assets/styles/base/_variables.scss";
@import "src/assets/styles/_variables.scss";
@import "src/assets/styles/_custom-mixins.scss";
.sign-up-div {
margin-top: 2vh;
.header {
text-align: center;
margin: auto;
.logos {
display: flex;
justify-content: center;
align-items: center;
img {
width: 4rem;
padding: 10px;
}
}
.title {
color: #005A9E;
font-weight: bold;
margin-top: 2px;
}
.subtitle {
font-weight: bold;
color: #333333;
}
}
}
ion-input,
section {
border: 1px solid gray;
border-radius: 16px;
margin: 10px auto;
padding-left: 1rem !important;
}
section {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 0 1rem;
ion-icon {
font-size: 23px;
color: gray;
}
}
ion-datetime {
width: 100%;
padding: 7px 0;
}
.important::after {
content: '*';
color: red;
margin-left: 5px;
}
.bold {
font-weight: bold;
}
.flex {
display: flex;
justify-content: space-between;
align-items: center;
}
.tablebox {
background: #F0F0F0;
padding: 10px;
margin-top: 7px;
}
table {
width: 100%;
tr {
td {
padding: 10px;
}
td:last-child {
font-weight: bold;
}
td:last-child::before {
content: ': ';
}
}
}
.center {
text-align: center;
}
.prb-3 {
padding-right: 7rem;
}
.pb-40{
padding-bottom: 40px;
}
.accepttext {
font-size: 12px;
}
.danger{
color: red;
}
.profile-info-section{
display: grid;
grid-template-columns: 100px 227px;
}
.profile-info{
color: map-get($colors, granite_gray);
font-family: "Noto Sans", sans-serif;
font-size: $font-size-base;
letter-spacing: 0;
}
.footer {
background: #F8FAFC;
border-top: 1px solid #d1d6dd;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
position: absolute;
bottom: 0;
width: 100%;
padding: 1rem;
a {
color: #005A9E;
}
}
.btn-info{
padding: .75rem;
}
ion-button{
height: 2.5rem;
}