File

src/app/plugins/profile/components/submit-teacher-details/submit-teacher-details.component.ts

Implements

OnInit OnDestroy

Metadata

Index

Properties
Methods

Constructor

constructor(csUserService: CsUserService, activatedRoute: ActivatedRoute, telemetryService: TelemetryService, resourceService: ResourceService, toasterService: ToasterService, profileService: ProfileService, userService: UserService, formService: FormService, router: Router, navigationHelperService: NavigationHelperService, otpService: OtpService, tncService: TncService, utilService: UtilService, layoutService: LayoutService)
Parameters :
Name Type Optional
csUserService CsUserService No
activatedRoute ActivatedRoute No
telemetryService TelemetryService No
resourceService ResourceService No
toasterService ToasterService No
profileService ProfileService No
userService UserService No
formService FormService No
router Router No
navigationHelperService NavigationHelperService No
otpService OtpService No
tncService TncService No
utilService UtilService No
layoutService LayoutService No

Methods

Private assignDefaultValue
assignDefaultValue(childConfig: FieldConfig)
Parameters :
Name Type Optional
childConfig FieldConfig<any> No
Returns : FieldConfig<any>
closeConsentPopUp
closeConsentPopUp()
Returns : void
closeSuccessModal
closeSuccessModal()
Returns : void
declarationFormStatusChanges
declarationFormStatusChanges(event)
Parameters :
Name Optional
event No
Returns : void
declarationFormValueChanges
declarationFormValueChanges(event)
Parameters :
Name Optional
event No
Returns : void
emailVerificationAsyncFactory
emailVerificationAsyncFactory(formElement: FieldConfig, profile: any, initialEmailVal)
Parameters :
Name Type Optional
formElement FieldConfig<any> No
profile any No
initialEmailVal No
Returns : any
fetchTncData
fetchTncData()
Returns : void
generateOTP
generateOTP(fieldType, value)
Parameters :
Name Optional
fieldType No
value No
Returns : void
generateTelemetry
generateTelemetry(fieldType)
Parameters :
Name Optional
fieldType No
Returns : void
Private getDeclarationReqObject
getDeclarationReqObject(operation, declaredDetails, tenantPersonaDetails)
Parameters :
Name Optional
operation No
declaredDetails No
tenantPersonaDetails No
Returns : { operation: any; userId: any; orgId: any; persona: any; info: any; }
getFieldType
getFieldType(data)
Parameters :
Name Optional
data No
Returns : "declared-phone" | "declared-email"
getLocations
getLocations()
Returns : void
getPersonaTenant
getPersonaTenant()
Returns : void
getProfileInfo
getProfileInfo(declarations)
Parameters :
Name Optional
declarations No
Returns : void
getTeacherDetailsForm
getTeacherDetailsForm()
Returns : void
getUpdateTelemetry
getUpdateTelemetry()
goBack
goBack()
Returns : void
initializeFormData
initializeFormData(formConfig)
Parameters :
Name Optional
formConfig No
Returns : void
linkClicked
linkClicked(event)
Parameters :
Name Optional
event No
Returns : void
logAuditEvent
logAuditEvent()
Returns : void
mobileVerificationAsyncFactory
mobileVerificationAsyncFactory(formElement: FieldConfig, profile: any, initialMobileVal)
Parameters :
Name Type Optional
formElement FieldConfig<any> No
profile any No
initialMobileVal No
Returns : any
navigateToProfile
navigateToProfile()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
onOtpPopupClose
onOtpPopupClose()
Returns : void
onOtpVerificationError
onOtpVerificationError(data)
Parameters :
Name Optional
data No
Returns : void
onVerificationSuccess
onVerificationSuccess(event)
Parameters :
Name Optional
event No
Returns : void
prepareOtpData
prepareOtpData(fieldType, value)
Parameters :
Name Optional
fieldType No
value No
Returns : any
setOtpValidation
setOtpValidation(valueToSet)
Parameters :
Name Optional
valueToSet No
Returns : void
setTelemetryData
setTelemetryData()
Returns : void
showAndHidePopup
showAndHidePopup(mode: boolean)
Parameters :
Name Type Optional
mode boolean No
Returns : void
Async submit
submit()
Returns : any
telemetryImpressionEvent
telemetryImpressionEvent()
Returns : void
tenantPersonaFormStatusChanges
tenantPersonaFormStatusChanges(event)
Parameters :
Name Optional
event No
Returns : void
tenantPersonaFormValueChanges
tenantPersonaFormValueChanges(event)
Parameters :
Name Optional
event No
Returns : void
updateProfile
updateProfile(data)
Parameters :
Name Optional
data No
Returns : void
updateUserConsent
updateUserConsent(currentOrgId, previousOrgId?)
Parameters :
Name Optional
currentOrgId No
previousOrgId Yes
Returns : void

Properties

cancelInteractEdata
Type : IInteractEventEdata
consentConfig
Type : literal type
declaredDetails
Type : any
declaredLatestFormValue
forChanges
Type : object
Default value : { prevPersonaValue: '', prevTenantValue: '', prevPhoneValue: '', prevEmailValue: '' }
formAction
Type : string
formGroupObj
Type : object
Default value : {}
Public formService
Type : FormService
globalConsent
Type : string
Default value : 'global-consent'
instance
Type : string
isDeclarationFormValid
Default value : false
isglobalConsent
Default value : true
isOtpVerificationRequired
Default value : false
isTenantChanged
Default value : false
isTenantPersonaFormValid
Default value : false
layoutConfiguration
Type : any
Public layoutService
Type : LayoutService
modal
Decorators :
@ViewChild('modal')
Public navigationHelperService
Type : NavigationHelperService
otpConfirm
otpData
Public otpService
Type : OtpService
previousOrgId
profileInfo
Type : literal type
Public profileService
Type : ProfileService
Public resourceService
Type : ResourceService
Public router
Type : Router
selectedDistrict
selectedState
selectedStateCode
Type : any
selectedTenant
Type : string
Default value : ''
showGlobalConsentPopUpSection
Default value : false
showLoader
Default value : true
showSuccessModal
Default value : false
showTncPopup
Default value : false
submitDetailsInteractEdata
Type : IInteractEventEdata
submitInteractEdata
Type : IInteractEventEdata
teacherDetailsForm
telemetryInteractObject
Type : IInteractEventObject
tenantPersonaForm
tenantPersonaLatestFormValue
termsAndConditionLink
Type : any
tncLatestVersion
Type : any
Public tncService
Type : TncService
Public toasterService
Type : ToasterService
unsubscribe
Default value : new Subject<void>()
userProfile
Type : any
Public userService
Type : UserService
Public utilService
Type : UtilService
validationType
Type : object
Default value : { 'declared-phone': { isVerified: false, isVerificationRequired: false }, 'declared-email': { isVerified: false, isVerificationRequired: false } }
import { Component, Inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { UntypedFormControl, ValidationErrors } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { FormService, OtpService, TncService, UserService } from '@sunbird/core';
import { Consent, ConsentStatus } from '@project-sunbird/client-services/models';
import { CsUserService } from '@project-sunbird/client-services/services/user/interface';
import {
  IUserData,
  NavigationHelperService,
  ResourceService,
  ServerResponse,
  ToasterService,
  UtilService, LayoutService
} from '@sunbird/shared';
import { IInteractEventEdata, IInteractEventObject, TelemetryService } from '@sunbird/telemetry';
import { FieldConfig } from '@project-sunbird/common-form-elements-full';
import * as _ from 'lodash-es';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { ProfileService } from './../../services';

@Component({
  selector: 'app-submit-teacher-details',
  templateUrl: './submit-teacher-details.component.html',
  styleUrls: ['./submit-teacher-details.component.scss']
})
export class SubmitTeacherDetailsComponent implements OnInit, OnDestroy {

  @ViewChild('modal') modal;
  showSuccessModal = false;
  userProfile: any;
  formAction: string;
  unsubscribe = new Subject<void>();
  layoutConfiguration: any;
  selectedState;
  selectedDistrict;
  forChanges = {
    prevPersonaValue: '',
    prevTenantValue: '',
    prevPhoneValue: '',
    prevEmailValue: ''
  };
  showLoader = true;
  submitInteractEdata: IInteractEventEdata;
  submitDetailsInteractEdata: IInteractEventEdata;
  cancelInteractEdata: IInteractEventEdata;
  telemetryInteractObject: IInteractEventObject;
  instance: string;
  showTncPopup = false;
  tncLatestVersion: any;
  termsAndConditionLink: any;
  otpData;
  isOtpVerificationRequired = false;
  validationType = {
    'declared-phone': {
      isVerified: false,
      isVerificationRequired: false
    },
    'declared-email': {
      isVerified: false,
      isVerificationRequired: false
    }
  };
  formGroupObj = {};
  declaredDetails: any;
  tenantPersonaForm;
  teacherDetailsForm;
  tenantPersonaLatestFormValue;
  declaredLatestFormValue;
  selectedTenant = '';
  selectedStateCode: any;
  isDeclarationFormValid = false;
  isTenantPersonaFormValid = false;
  otpConfirm;
  globalConsent = 'global-consent';
  isglobalConsent = true;
  consentConfig: { tncLink: string; tncText: any; };
  showGlobalConsentPopUpSection = false;
  profileInfo: {};
  isTenantChanged = false;
  previousOrgId;

  constructor(
    @Inject('CS_USER_SERVICE') private csUserService: CsUserService,
    private activatedRoute: ActivatedRoute,
    private telemetryService: TelemetryService,
    public resourceService: ResourceService,
    public toasterService: ToasterService,
    public profileService: ProfileService,
    public userService: UserService,
    public formService: FormService,
    public router: Router,
    public navigationHelperService: NavigationHelperService,
    public otpService: OtpService,
    public tncService: TncService,
    public utilService: UtilService, public layoutService: LayoutService) { }

  ngOnInit() {

    this.layoutConfiguration = this.layoutService.initlayoutConfig();
    this.layoutService.switchableLayout().
      pipe(takeUntil(this.unsubscribe)).subscribe(layoutConfig => {
        if (layoutConfig != null) {
          this.layoutConfiguration = layoutConfig.layout;
        }
      });

    this.instance = _.upperCase(this.resourceService.instance || 'SUNBIRD');
    this.consentConfig = { tncLink: this.resourceService.frmelmnts.lbl.tncLabelLink,
       tncText: this.resourceService.frmelmnts.lbl.nonCustodianTC };
    this.fetchTncData();
    const queryParams = this.activatedRoute.snapshot.queryParams;
    this.formAction = queryParams.formaction;
    this.telemetryImpressionEvent();
    this.userService.userData$.pipe(takeUntil(this.unsubscribe)).subscribe((user: IUserData) => {
      if (user.userProfile) {
        this.userProfile = user.userProfile;
        this.getLocations();
        if (_.get(this.userProfile, 'declarations.length')) {
          this.declaredDetails = _.get(this.userProfile, 'declarations')[0] || '';
          this.forChanges.prevPersonaValue = _.get(this.declaredDetails, 'persona');
          this.forChanges.prevTenantValue = _.get(this.declaredDetails, 'orgId');
        }
        this.getPersonaTenant();
        this.showLoader = false;
      }
    });
    this.setTelemetryData();
  }

  fetchTncData() {
    this.tncService.getTncConfig().pipe(takeUntil(this.unsubscribe)).subscribe((data: ServerResponse) => {
      const response = _.get(data, 'result.response.value');
      if (response) {
        try {
          const tncConfig = this.utilService.parseJson(response);
          this.tncLatestVersion = _.get(tncConfig, 'latestVersion') || {};
          this.termsAndConditionLink = tncConfig[this.tncLatestVersion].url;
        } catch (e) {
          this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
        }
      }
    }, (err) => {
      this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0004'));
    }
    );
  }

  showAndHidePopup(mode: boolean) {
    this.showTncPopup = mode;
  }

  telemetryImpressionEvent() {
    this.telemetryService.impression({
      context: {
        env: this.activatedRoute.snapshot.data.telemetry.env
      },
      edata: {
        type: this.activatedRoute.snapshot.data.telemetry.type,
        subtype: this.formAction,
        pageid: this.activatedRoute.snapshot.data.telemetry.pageid,
        uri: this.activatedRoute.snapshot.data.telemetry.uri,
        duration: this.navigationHelperService.getPageLoadTime()
      }
    });
  }

  setTelemetryData() {
    this.submitInteractEdata = {
      id: 'submit-teacher-details',
      type: 'click',
      pageid: this.activatedRoute.snapshot.data.telemetry.pageid
    };
    this.cancelInteractEdata = {
      id: `cancel-${this.formAction}-teacher-details`,
      type: 'click',
      pageid: this.activatedRoute.snapshot.data.telemetry.pageid
    };
    this.submitDetailsInteractEdata = {
      id: `teacher-details-submit-success`,
      type: 'click',
      pageid: this.activatedRoute.snapshot.data.telemetry.pageid
    };
  }

  generateTelemetry(fieldType) {
    const interactData = {
      context: {
        env: this.activatedRoute.snapshot.data.telemetry.env,
        cdata: []
      },
      edata: {
        id: `validate-${fieldType}-${this.formAction}-teacher-details`,
        type: 'click',
        pageid: this.activatedRoute.snapshot.data.telemetry.pageid
      }
    };
    this.telemetryService.interact(interactData);
  }

  generateOTP(fieldType, value) {
    this.generateTelemetry(fieldType);
    const request = {
      request: {
        key: value.toString(),
        type: fieldType === 'declared-phone' ? 'phone' : 'email'
      }
    };
    this.otpService.generateOTP(request).pipe(takeUntil(this.unsubscribe)).subscribe((data: ServerResponse) => {
      this.otpData = this.prepareOtpData(fieldType, value);
      this.setOtpValidation(true);
    },
      (err) => {
        this.toasterService.error(this.resourceService.messages.fmsg.m0051);
      }
    );
  }

  onVerificationSuccess(event) {
    this.setOtpValidation(false);
    this.otpConfirm.next(true);
    this.otpConfirm.complete();
  }

  getFieldType(data) {
    return _.get(data, 'phone') ? 'declared-phone' : 'declared-email';
  }

  onOtpPopupClose() {
    this.setOtpValidation(false);
  }

  setOtpValidation(valueToSet) {
    this.isOtpVerificationRequired = valueToSet;
  }

  onOtpVerificationError(data) {
    this.setOtpValidation(false);
  }

  prepareOtpData(fieldType, value) {
    const otpData: any = {};
    switch (fieldType) {
      case 'declared-phone':
        otpData.instructions = this.resourceService.frmelmnts.instn.t0083;
        otpData.retryMessage = this.resourceService.frmelmnts.lbl.unableToUpdateMobile;
        otpData.wrongOtpMessage = this.resourceService.frmelmnts.lbl.wrongPhoneOTP;
        break;
      case 'declared-email':
        otpData.instructions = this.resourceService.frmelmnts.instn.t0084;
        otpData.retryMessage = this.resourceService.frmelmnts.lbl.unableToUpdateEmail;
        otpData.wrongOtpMessage = this.resourceService.frmelmnts.lbl.wrongEmailOTP;
        break;
    }
    otpData.type = fieldType === 'declared-phone' ? 'phone' : 'email';
    otpData.value = value;
    return otpData;
  }

  getLocations() {
    _.map(this.userProfile.userLocations, (locations) => {
      if (locations.type === 'state') {
        this.selectedState = locations.name;
      }
      if (locations.type === 'district') {
        this.selectedDistrict = locations.name;
      }
    });
  }

  getUpdateTelemetry() {
    const fieldsChanged = [];
    if (this.forChanges.prevPersonaValue !== _.get(this.tenantPersonaLatestFormValue, 'persona')) { fieldsChanged.push('Persona'); }
    if (this.forChanges.prevTenantValue !== _.get(this.tenantPersonaLatestFormValue, 'tenant')) { fieldsChanged.push('Tenant'); }
    if (this.declaredDetails && _.get(this.declaredLatestFormValue, 'children.externalIds')) {
      const userDeclaredValues = _.get(this.declaredLatestFormValue, 'children.externalIds');
      for (const [key, value] of Object.entries(userDeclaredValues)) {
        if (!_.includes(['state', 'district', 'name'], key) &&
          this.declaredDetails.info[key] !== this.declaredLatestFormValue.children.externalIds[key]) {
          fieldsChanged.push(key);
        }
      }
    }

    const updateInteractEdata: IInteractEventEdata = {
      id: 'update-teacher-details',
      type: 'click',
      pageid: this.activatedRoute.snapshot.data.telemetry.pageid
    };
    if (!_.isEmpty(fieldsChanged)) {
      updateInteractEdata['extra'] = { fieldsChanged };
    }
    return updateInteractEdata;
  }

  closeSuccessModal() {
    this.modal.deny();
    this.showSuccessModal = false;
    this.navigateToProfile();
  }


  updateProfile(data) {
    this.profileService.declarations(data).pipe(takeUntil(this.unsubscribe)).subscribe(res => {
      if (this.formAction === 'update') {
        this.toasterService.success(this.resourceService.messages.smsg.m0037);
        this.navigateToProfile();
      } else {
        if (_.get(this.declaredLatestFormValue, 'tnc')) {
          this.logAuditEvent();
        }
        this.showSuccessModal = true;
      }
    }, err => {
      this.navigateToProfile();
      this.toasterService.error(this.formAction === 'submit' ? this.resourceService.messages.emsg.m0051 :
        this.resourceService.messages.emsg.m0052);
    });
  }

  goBack() {
    this.navigationHelperService.goBack();
  }


  logAuditEvent() {
    this.telemetryService.audit({
      context: {
        env: this.activatedRoute.snapshot.data.telemetry.env,
        cdata: [{ id: 'teacher-self-declaration', type: 'FromPage' }]
      },
      object: { id: 'data-sharing', type: 'TnC', ver: this.tncLatestVersion },
      edata: { state: 'Updated', props: [], prevstate: '', type: 'tnc-data-sharing' }
    });
  }

  navigateToProfile() {
    this.router.navigate(['/profile']);
  }

  getPersonaTenant() {
    this.profileService.getPersonaTenantForm().pipe(takeUntil(this.unsubscribe)).subscribe(response => {
      this.selectedTenant = (_.get(this.userProfile, 'declarations[0].orgId')) || '';

      response.forEach(config => {
        if (config.code === 'persona') {
          config.default = _.get(this.userProfile, 'declarations[0].persona');
        } else if (config.code === 'tenant') {
          config.default = _.get(this.userProfile, 'declarations[0].orgId');
        }
      });

      this.tenantPersonaForm = response;
      if (this.selectedTenant) {
        this.getTeacherDetailsForm();
      }
    }, error => {
      console.error('Unable to fetch form', error);
      this.toasterService.error(_.get(this.resourceService, 'messages.emsg.m0005'));
      this.navigateToProfile();
    });
  }

  tenantPersonaFormValueChanges(event) {
    this.tenantPersonaLatestFormValue = event;
    if (_.get(event, 'tenant')) {
      if (!this.selectedTenant || event.tenant !== this.selectedTenant) {
        this.previousOrgId = this.selectedTenant;
        this.isTenantChanged = this.selectedTenant ? true : false;
        this.selectedTenant = event.tenant;
        this.getTeacherDetailsForm();
      }
    }
  }

  linkClicked(event) {
    if (_.get(event, 'event.preventDefault')) {
      event.event.preventDefault();
      this.showTncPopup = true;
    }
  }

  declarationFormValueChanges(event) {
    this.declaredLatestFormValue = event;
    if (_.get(event, 'children.externalIds')) {
      if (!this.selectedStateCode && _.get(event, 'children.externalIds.declared-state')) {
        this.selectedStateCode = event.children.externalIds['declared-state'];
      }
      if (_.get(event, 'children.externalIds["declared-state"]') && this.selectedStateCode !== _.get(event, 'children.externalIds.declared-state')) {
        this.selectedStateCode = event.children.externalIds['declared-state'];
      }
    }
  }

  tenantPersonaFormStatusChanges(event) {
    this.isTenantPersonaFormValid = event.isValid || event.valid;
  }

  declarationFormStatusChanges(event) {
    this.isDeclarationFormValid = event.isValid;
  }

  getTeacherDetailsForm() {
    this.profileService.getSelfDeclarationForm(this.selectedTenant).pipe(takeUntil(this.unsubscribe)).subscribe(formConfig => {
      console.log('formConfig', formConfig);
      this.initializeFormData(formConfig);
    }, error => {
      console.error('Unable to fetch form', error);
      this.toasterService.error(_.get(this.resourceService, 'messages.emsg.m0005'));
    });
  }

  initializeFormData(formConfig) {
    this.teacherDetailsForm = formConfig.map((config: FieldConfig<any>) => {
      switch (config.code) {
        case 'name':
          config.templateOptions.labelHtml.values['$1'] = this.userProfile.firstName;
          break;
        case 'state':
          config.templateOptions.labelHtml.values['$1'] = this.selectedState || 'Enter location from Profile page';
          break;
        case 'district':
          config.templateOptions.labelHtml.values['$1'] = this.selectedDistrict || 'Enter location from Profile page';
          break;
        case 'externalIds':
          config.children = (config.children as FieldConfig<any>[]).map((childConfig: FieldConfig<any>) => {

            if (_.get(childConfig, `templateOptions['dataSrc'].marker`) === 'LOCATION_LIST') {
              if (childConfig.templateOptions['dataSrc'].params.id === 'state') {
                let stateCode;
                if (this.selectedState) {
                  stateCode = this.selectedState;
                } else {
                  let stateDetails;
                  if (_.get(this.userProfile, `declarations[0].info[${childConfig.code}]`)) {
                    stateDetails = this.userProfile.declarations[0].info[childConfig.code];
                  }
                  stateCode = _.get(stateDetails, 'id');
                }
              } else if (_.get(childConfig, 'templateOptions["dataSrc"].params.id') === 'district') {
                let districtDetails;
                if (_.get(this.userProfile, `declarations[0].info[${childConfig.code}]`)) {
                  districtDetails = this.userProfile.declarations[0].info[childConfig.code];
                }
              }
              return childConfig;
            }

            this.assignDefaultValue(childConfig);
            if (childConfig.asyncValidation) {
              childConfig = this.assignDefaultValue(childConfig);

              if (_.get(childConfig, 'asyncValidation.marker') === 'MOBILE_OTP_VALIDATION') {
                childConfig.asyncValidation.asyncValidatorFactory = this.mobileVerificationAsyncFactory(childConfig, this.userProfile, childConfig.default);
              } else if (_.get(childConfig, 'asyncValidation.marker') === 'EMAIL_OTP_VALIDATION') {
                childConfig.asyncValidation.asyncValidatorFactory = this.emailVerificationAsyncFactory(childConfig, this.userProfile, childConfig.default);
              }
              return childConfig;
            }
            return childConfig;
          });
          break;
        case 'tnc':
          if (this.formAction === 'update') {
            config = undefined;
          }
          break;
      }
      return config;
    }).filter((formData) => formData);
  }

  private assignDefaultValue(childConfig: FieldConfig<any>) {
    if (_.get(this.userProfile, `declarations[0].info[${childConfig.code}]`)) {
      childConfig.default = this.userProfile.declarations[0].info[childConfig.code];
    }

    if (this.formAction === 'submit') {
      if (childConfig.code === 'declared-phone') {
        childConfig.default = this.userProfile['maskedPhone'];
      }

      if (childConfig.code === 'declared-email') {
        childConfig.default = this.userProfile['maskedEmail'];
      }
    }

    return childConfig;
  }



  mobileVerificationAsyncFactory(formElement: FieldConfig<any>, profile: any, initialMobileVal): any {
    return (marker: string, trigger: HTMLElement) => {
      if (marker === 'MOBILE_OTP_VALIDATION') {
        return async (control: UntypedFormControl) => {
          if ((control && !control.value) || (initialMobileVal && initialMobileVal === control.value)) {
            return null;
          }
          return new Promise<ValidationErrors | null>(resolve => {
            if (trigger) {
              const that = this;
              this.otpConfirm = new Subject();
              trigger.onclick = (async () => {
                try {
                  that.generateOTP('declared-phone', control.value);
                  const isOtpVerified: boolean = await that.otpConfirm.toPromise();
                  if (isOtpVerified) {
                    resolve(null);
                  } else {
                    resolve({ asyncValidation: 'error' });
                  }
                } catch (e) {
                  console.error(e);
                }
              }).bind(this);
              return;
            }
            resolve(null);
          });
        };
      }
      return async () => null;
    };
  }

  emailVerificationAsyncFactory(formElement: FieldConfig<any>, profile: any, initialEmailVal): any {
    return (marker: string, trigger: HTMLElement) => {
      if (marker === 'EMAIL_OTP_VALIDATION') {
        return async (control: UntypedFormControl) => {
          if ((control && !control.value) || (initialEmailVal && initialEmailVal === control.value)) {
            return null;
          }
          return new Promise<ValidationErrors | null>(resolve => {
            if (trigger) {
              const that = this;
              this.otpConfirm = new Subject();
              trigger.onclick = (async () => {
                try {
                  that.generateOTP('declared-email', control.value);
                  const isOtpVerified: boolean = await that.otpConfirm.toPromise();
                  if (isOtpVerified) {
                    resolve(null);
                  } else {
                    resolve({ asyncValidation: 'error' });
                  }
                } catch (e) {
                  console.error(e);
                }
              }).bind(this);
              return;
            }
            resolve(null);
          });
        };
      }
      return async () => null;
    };
  }

  closeConsentPopUp() {
    this.showGlobalConsentPopUpSection = false;
    this.isglobalConsent = false;
    this.globalConsent = '';
  }

  async submit() {
    if (!this.declaredLatestFormValue || !this.tenantPersonaLatestFormValue) {
      this.toasterService.error(_.get(this.resourceService, 'messages.fmsg.m0051'));
      return;
    }
    const formValue = this.declaredLatestFormValue.children.externalIds;
    const declarations = [];
    const declaredDetails = this.declaredLatestFormValue.children && this.declaredLatestFormValue.children.externalIds;
    let operation = '';
    if (!this.userProfile.declarations || !_.get(this.userProfile, 'declarations.length')) {
      operation = 'add';
    } else if (this.tenantPersonaLatestFormValue.tenant === this.userProfile.declarations[0].orgId) {
      operation = 'edit';
    } else if (this.tenantPersonaLatestFormValue.tenant !== this.userProfile.declarations[0].orgId) {
      const tenantPersonaData = { persona: this.userProfile.declarations[0].persona, tenant: this.userProfile.declarations[0].orgId };
      declarations.push(this.getDeclarationReqObject('remove', this.userProfile.declarations[0].info, tenantPersonaData));
      operation = 'add';
    }
    declarations.push(this.getDeclarationReqObject(operation, declaredDetails, this.tenantPersonaLatestFormValue));

    const data = { declarations };
    this.getProfileInfo(declarations);
    this.updateProfile(data);
    if (this.formAction === 'submit') {
      this.updateUserConsent(declarations[0].orgId);
    } else if (this.formAction === 'update' && this.isTenantChanged) {
      this.updateUserConsent(declarations[1].orgId, this.previousOrgId);
    }
  }

  updateUserConsent(currentOrgId, previousOrgId?) {
    if (this.isTenantChanged && !!previousOrgId) {
      const requestFoRevoked: Consent = {
        status: ConsentStatus.REVOKED,
        userId: this.userService.userid,
        consumerId: previousOrgId,
        objectId: previousOrgId,
        objectType: 'Organisation'
      };
      this.csUserService.updateConsent(requestFoRevoked, { apiPath: '/learner/user/v1' })
        .pipe(takeUntil(this.unsubscribe))
        .subscribe((response) => {
         // this.toasterService.success(_.get(this.resourceService, 'messages.smsg.dataSettingSubmitted'));
          if (response && response.consent) {
            this.isTenantChanged = false;
            const requestForActive: Consent = {
              status: ConsentStatus.ACTIVE,
              userId: this.userService.userid,
              consumerId: currentOrgId,
              objectId: currentOrgId,
              objectType: 'Organisation'
            };
            this.csUserService.updateConsent(requestForActive, { apiPath: '/learner/user/v1' })
              .pipe(takeUntil(this.unsubscribe))
              .subscribe(() => {
                this.toasterService.success(_.get(this.resourceService, 'messages.smsg.dataSettingSubmitted'));
              }, error => {
                this.toasterService.error(_.get(this.resourceService, 'messages.emsg.m0005'));
                console.error('Error while updating user consent', error);
              });
          }
        }, error => {
          this.toasterService.error(_.get(this.resourceService, 'messages.emsg.m0005'));
          console.error('Error while updating user consent', error);
        });
    } else {
      const request: Consent = {
        status: ConsentStatus.ACTIVE,
        userId: this.userService.userid,
        consumerId: currentOrgId,
        objectId: currentOrgId,
        objectType: 'Organisation'
      };
      this.csUserService.updateConsent(request, { apiPath: '/learner/user/v1' })
        .pipe(takeUntil(this.unsubscribe))
        .subscribe(() => {
          this.toasterService.success(_.get(this.resourceService, 'messages.smsg.dataSettingSubmitted'));
        }, error => {
          this.toasterService.error(_.get(this.resourceService, 'messages.emsg.m0005'));
          console.error('Error while updating user consent', error);
        });
    }
  }

  getProfileInfo(declarations) {
    this.profileInfo = {
      emailId: '',
      phone: '',
      schoolId: '',
      schoolName: ''
    };
    for (const [key, value] of Object.entries(declarations[0].info)) {
      switch (key) {
        case 'declared-email':
          this.profileInfo['emailId'] = value;
          break;
        case 'declared-phone':
          this.profileInfo['phone'] = value;
          break;
        case 'declared-school-udise-code':
          this.profileInfo['schoolId'] = value;
          break;
        case 'declared-school-name':
          this.profileInfo['schoolName'] = value;
          break;
      }
    }
  }

  private getDeclarationReqObject(operation, declaredDetails, tenantPersonaDetails) {
    return {
      operation,
      userId: this.userProfile.userId,
      orgId: tenantPersonaDetails.tenant,
      persona: tenantPersonaDetails.persona,
      info: declaredDetails
    };
  }

  ngOnDestroy() {
    this.unsubscribe.next();
    this.unsubscribe.complete();
    if (_.get(this.modal, 'deny')) {
      this.modal.deny();
    }
  }
}
<div [ngClass]="layoutConfiguration ? 'sb-back-actionbar' : 'sb-bg-white cc-player__btn-back'" class="relative position mt-0">
  <div class="ui container py-0 px-0 d-flex flex-ai-center">
    <button type="button" (click)="goBack()" [ngClass]="layoutConfiguration ? 'sb-btn-primary sb-btn-round' : 'sb-btn-link sb-btn-link-primary sb-left-icon-btn px-0'" class="sb-btn sb-btn-normal" tabindex="0" attr.aria-label="{{resourceService?.frmelmnts?.btn?.back}}">
    <i class="icon-svg icon-svg--xxs icon-back mr-4"><svg class="icon icon-svg--primary">
        <use xlink:href="assets/images/sprite.svg#arrow-long-left"></use>
      </svg></i>
   <span>{{resourceService?.frmelmnts?.btn?.back}}</span>
  </button>
    <div class="content-header__content w-100 ml-16">
      <div class="d-flex flex-dc flex-basis-1 mr-32 min-w-0 content-header__content__title">
        <div class="content-header__title font-weight-bold ellipsis text-left"  tabindex="0" role="heading" aria-level="2">
          <span *ngIf="formAction === 'submit'">{{resourceService?.frmelmnts?.lbl?.provideTeacherDetails}} </span>
    <span *ngIf="formAction === 'update'">{{resourceService?.frmelmnts?.lbl?.updateDetails}}</span>
  </div>
      </div>
    </div>
  </div>
</div>

<div [ngClass]="layoutConfiguration ? 'sbt-inside-page-container' : ''">
<div class="mt-24 sb-md-container">
  <div class="sb-modal-header teacher-header font-weight-bold px-24 py-16">
    <span *ngIf="formAction === 'submit'">{{resourceService?.frmelmnts?.lbl?.provideTeacherDetails}} </span>
    <span *ngIf="formAction === 'update'">{{resourceService?.frmelmnts?.lbl?.updateDetails}}</span>
  </div>

  <div class="py-16 px-32">
    <div *ngIf="showLoader">
      <app-loader></app-loader>
    </div>

    <div *ngIf="!showLoader">
      <sb-form *ngIf="tenantPersonaForm" [config]="tenantPersonaForm" [platform]="'web'"
        (initialize)="tenantPersonaFormValueChanges($event?.value); tenantPersonaFormStatusChanges($event);"
        (valueChanges)="tenantPersonaFormValueChanges($event)" (statusChanges)="tenantPersonaFormStatusChanges($event)">
      </sb-form>

      <sb-form *ngIf=" teacherDetailsForm?.length" [config]="teacherDetailsForm" [platform]="'web'"
        (valueChanges)="declarationFormValueChanges($event)" (statusChanges)="declarationFormStatusChanges($event)"
        (linkClicked)="linkClicked($event)">
      </sb-form>

      <div class="teacher-buttons text-right">
        <button *ngIf="formAction === 'submit'" appTelemetryInteract [telemetryInteractEdata]="submitInteractEdata"
          [ngClass]="{'sb-btn-disabled': !isTenantPersonaFormValid || !isDeclarationFormValid}"
          class="sb-btn sb-btn-normal sb-btn-primary" [disabled]="!isTenantPersonaFormValid || !isDeclarationFormValid"
          (click)="submit()" tabindex="0">
          {{resourceService?.frmelmnts?.btn?.submit}}
        </button>
        <button *ngIf="formAction === 'update'" appTelemetryInteract [telemetryInteractEdata]="getUpdateTelemetry()"
          [ngClass]="{'sb-btn-disabled': !isTenantPersonaFormValid || !isDeclarationFormValid}"
          class="sb-btn sb-btn-normal sb-btn-primary" [disabled]="!isTenantPersonaFormValid || !isDeclarationFormValid"
          (click)="submit()" tabindex="0">
          {{resourceService?.frmelmnts?.btn?.update}}
        </button>
      </div>
    </div>
  </div>
</div>
</div>
<!-- information submitted modal in TEACHER Profile-->
<app-modal-wrapper *ngIf="showSuccessModal" [config]="{disableClose: true, size: 'small'}"
  (dismiss)="closeSuccessModal()" #modal>
  <ng-template sbModalContent>
    <div class="sb-modal">
      <div class="transition ui dimmer page modals active visible">
        <div class="ui modal transition active visible small">

          <div class="sb-modal-header font-weight-normal">
            {{resourceService?.frmelmnts?.lbl?.thankyouForSubmittingDetails}}
          </div>
          <div class="sb-modal-content text-center">
            <div class="my-16">{{resourceService?.frmelmnts?.lbl?.editProfileInfo}}</div>
          </div>
          <div class="sb-modal-actions">
            <button class="sb-btn sb-btn-normal sb-btn-success" appTelemetryInteract
              [telemetryInteractEdata]="submitDetailsInteractEdata" tabindex="0" (click)="closeSuccessModal()">
              {{resourceService?.frmelmnts?.btn?.ok}}
            </button>
          </div>
        </div>
      </div>
    </div>
  </ng-template>
</app-modal-wrapper>

<app-tnc-popup (close)="showAndHidePopup(false)" [tncUrl]="termsAndConditionLink" *ngIf="showTncPopup">
</app-tnc-popup>
<app-modal-wrapper *ngIf="isOtpVerificationRequired" [config]="{disableClose: true, size: 'small'}"
  (dismiss)="onOtpPopupClose()" #modal>
  <ng-template sbModalContent>
    <div class="sb-modal">
      <div class="transition ui dimmer page modals active visible">
        <div class="ui modal transition active visible small">

          <app-otp-popup [otpData]="otpData" [redirectToLogin]="false"
            (verificationSuccess)="onVerificationSuccess($event)" (closeContactForm)="onOtpPopupClose()"
            (redirectToParent)="onOtpVerificationError($event)">
          </app-otp-popup>
        </div>
      </div>
    </div>
  </ng-template>
</app-modal-wrapper>

./submit-teacher-details.component.scss

@use "@project-sunbird/sb-styles/assets/mixins/mixins" as *;

:host{
  .sb-md-container {
    max-width: calculateRem(720px);
    width: calc(100% - 2rem);
    background: var(--white);
    margin: 0 auto;
    border-radius: calculateRem(4px);
  
    .teacher-header{
      border-bottom: calculateRem(0.5px) solid var(--gray-200);
    }
    
    .is-invalid {
      border-color: var(--red-400) !important;
    }
    
    .invalid-msg {
      color: var(--red-400);
    }
    
    .primary.text {
      color: var(--info-color);
    }
    
    .ui.stackable.grid>.wide.column {
      padding: 0rem !important;
    }
    
    .sb-btn-border {
      border-radius: calculateRem(40px);
      text-transform: none;
    }
    
    .success-icon {
      position: absolute;
      right: calculateRem(8px);
      bottom: calculateRem(6px);
  
      html[dir="rtl"] & {
        left: calculateRem(8px);
         right:0px;
      }
    }

    .warning-icon {
      position: absolute;
      right: calculateRem(8px);
      top: calculateRem(2px);
      html[dir="rtl"] & {
        left: calculateRem(8px);
        right:0px;
      }
    }

    .phone-code{
      position: absolute;
      z-index: 1;
      top: calculateRem(8px);
      left: calculateRem(4px);
      font-size: calculateRem(12px);
      font-family: inherit;
      font-weight: bold;
      html[dir="rtl"] & {
        right: calculateRem(6px);
      }
    }
    
    .sb-field .ui.selection.dropdown {
      font-weight: bold;
      position: relative;
    }
    .sb-field .ui.selection.dropdown.phone-code-space {
      padding-left: 2rem;
      padding-right: inherit;
  
      html[dir="rtl"] & {
        padding-right: 2.5rem;
        padding-left: inherit;
      }
    }
  }
}
.sb-field {
  margin-bottom: calculateRem(16px) 0px;
  width: 100%;
  .sb-field-label{
    width:calculateRem(72px);
  }
}


Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""