digipay-utility-payment 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, InjectionToken, inject, Pipe, NgModule, Component, ChangeDetectorRef, Input, EventEmitter, Output, signal, ViewChildren, ViewChild } from '@angular/core';
2
+ import { Injectable, InjectionToken, inject, Pipe, NgModule, Input, Component, ChangeDetectorRef, EventEmitter, Output, signal, ViewChildren, ViewChild } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule } from '@angular/common';
5
5
  import * as i2 from '@angular/forms';
@@ -305,9 +305,23 @@ const PRODUCT_MASTER_DICT = {
305
305
  RCG: 'RCG',
306
306
  BP: 'BP',
307
307
  };
308
- const OTP_TYPES = {
309
- OTP_TYPE_ADD_CASH_MANUALLY: 'OTP_TYPE_ADD_CASH_MANUALLY',
310
- };
308
+ var OTP_TYPES;
309
+ (function (OTP_TYPES) {
310
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_REGISTRATION"] = 1] = "OTP_TYPE_REGISTRATION";
311
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_FORGOT_LOGIN_PIN"] = 2] = "OTP_TYPE_FORGOT_LOGIN_PIN";
312
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_FORGOT_TRANSACTION_PIN"] = 3] = "OTP_TYPE_FORGOT_TRANSACTION_PIN";
313
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_FORGOT_PASSWORD"] = 4] = "OTP_TYPE_FORGOT_PASSWORD";
314
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_COMMON"] = 5] = "OTP_TYPE_COMMON";
315
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_EMAIL"] = 6] = "OTP_TYPE_EMAIL";
316
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_LOGIN"] = 7] = "OTP_TYPE_LOGIN";
317
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_OLD_PHONE"] = 8] = "OTP_TYPE_OLD_PHONE";
318
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_NEW_PHONE"] = 9] = "OTP_TYPE_NEW_PHONE";
319
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_PAYMENT_LINK_VERIFICATION"] = 10] = "OTP_TYPE_PAYMENT_LINK_VERIFICATION";
320
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_ADD_CASH_MANUALLY"] = 11] = "OTP_TYPE_ADD_CASH_MANUALLY";
321
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_MERCHANT_SCAN_CUSTOMER_QR_OR_CARD"] = 12] = "OTP_TYPE_MERCHANT_SCAN_CUSTOMER_QR_OR_CARD";
322
+ OTP_TYPES[OTP_TYPES["OTY_TYPE_CASH_IN"] = 14] = "OTY_TYPE_CASH_IN";
323
+ OTP_TYPES[OTP_TYPES["OTP_TYPE_CASH_OUT"] = 15] = "OTP_TYPE_CASH_OUT";
324
+ })(OTP_TYPES || (OTP_TYPES = {}));
311
325
  const KAFKA_QUEUE_TYPE = {
312
326
  TOPUP_BILL_PAYMENT_PAYMENT_EXTERNAL_SYC: 'TOPUP_BILL_PAYMENT_PAYMENT_EXTERNAL_SYC',
313
327
  };
@@ -585,6 +599,18 @@ class TopupAndBillpaymentService {
585
599
  deleteWorkflowData() {
586
600
  this.workflowDataSubject.next(null);
587
601
  }
602
+ /** Clears all bill-payment flow state after a completed or abandoned session. */
603
+ clearAllSessionState() {
604
+ this.deleteVendorCategory();
605
+ this.deleteVendorProvider();
606
+ this.deleteVendorPlan();
607
+ this.deleteWorkflowUserInput();
608
+ this.deleteBillData();
609
+ this.deleteTxnData();
610
+ this.deleteWorkflowScreens();
611
+ this.deleteWorkflowData();
612
+ this.setCurrentScreenStep(0);
613
+ }
588
614
  // API wrappers
589
615
  getVendorDetailsById(id) {
590
616
  return this.api.getVendorDetailsById(id);
@@ -703,7 +729,14 @@ class TranslationService {
703
729
  COMMON_LABEL_AND: 'and',
704
730
  STATUS_UPDATED_SUCCESSFULLY: 'Status updated successfully',
705
731
  TOP_UP_COMPANY_BILL_PAYMENT_WORKFLOW_SCREEN_MAPPING_DATA_NOT_FOUND: 'Top-up company bill payment workflow screen mapping data not found',
706
- BILL_NOT_FOUND: 'Bill not found'
732
+ BILL_NOT_FOUND: 'Bill not found',
733
+ LABEL_BILL_OVER_DUE: 'Bill is overdue',
734
+ LABEL_DEBITED_FROM: 'Debited From',
735
+ LABEL_TRANSACTION_PIN: 'Transaction PIN',
736
+ COMMON_LABEL_CLOSE: 'Close',
737
+ COMMON_LABEL_AMOUNT_MUST_NOT_EXCEED_BILL_AMOUNT: 'Amount must not be greater than the bill amount',
738
+ LABEL_NO_PROVIDERS_AVAILABLE: 'No providers available',
739
+ LABEL_ENTER_4_DIGIT_TRANSACTION_PIN: 'Enter your 4-digit transaction PIN'
707
740
  };
708
741
  translate(key) {
709
742
  return TranslationService.LABELS[key] ?? key;
@@ -770,6 +803,44 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
770
803
  }]
771
804
  }] });
772
805
 
806
+ class NoDataComponent {
807
+ title = 'No data available';
808
+ icon;
809
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: NoDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
810
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: NoDataComponent, isStandalone: true, selector: "sdk-no-data", inputs: { title: "title", icon: "icon" }, ngImport: i0, template: `
811
+ <div class="text-center py-4">
812
+ @if (icon) {
813
+ <div class="mb-2">
814
+ <i class="la" [class.icon]="icon"></i>
815
+ </div>
816
+ }
817
+ <p class="text-muted">{{ title | translate }}</p>
818
+ </div>
819
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: SharedModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
820
+ }
821
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: NoDataComponent, decorators: [{
822
+ type: Component,
823
+ args: [{
824
+ selector: 'sdk-no-data',
825
+ template: `
826
+ <div class="text-center py-4">
827
+ @if (icon) {
828
+ <div class="mb-2">
829
+ <i class="la" [class.icon]="icon"></i>
830
+ </div>
831
+ }
832
+ <p class="text-muted">{{ title | translate }}</p>
833
+ </div>
834
+ `,
835
+ standalone: true,
836
+ imports: [SharedModule],
837
+ }]
838
+ }], propDecorators: { title: [{
839
+ type: Input
840
+ }], icon: [{
841
+ type: Input
842
+ }] } });
843
+
773
844
  class UtilitiesComponent {
774
845
  topupAndBillpaymentService = inject(TopupAndBillpaymentService);
775
846
  router = inject(Router);
@@ -777,6 +848,8 @@ class UtilitiesComponent {
777
848
  translationService = inject(TranslationService);
778
849
  sdkState = inject(SdkStateService, { optional: true });
779
850
  providerCategories = [];
851
+ categoriesLoaded = false;
852
+ hasCategories = false;
780
853
  constructor() { }
781
854
  ngOnInit() {
782
855
  this.getProviderCategories();
@@ -784,13 +857,20 @@ class UtilitiesComponent {
784
857
  getProviderCategories() {
785
858
  this.topupAndBillpaymentService.getTopupAndBillpaymentCategories({ is_active: true }).subscribe({
786
859
  next: (res) => {
860
+ this.categoriesLoaded = true;
787
861
  if (res?.success) {
788
- this.providerCategories = res?.data?.provider_category_master?.filter((data) => data?.is_active);
862
+ const master = res?.data?.provider_category_master ?? [];
863
+ this.hasCategories = master.length > 0;
864
+ this.providerCategories = master.filter((item) => item.is_active);
789
865
  }
790
866
  else {
867
+ this.hasCategories = false;
791
868
  this.providerCategories = [];
792
869
  }
793
870
  }, error: () => {
871
+ this.categoriesLoaded = true;
872
+ this.hasCategories = false;
873
+ this.providerCategories = [];
794
874
  this.toastrService.error(this.translationService.translate("LABEL_SOMETHING_WENT_WRONG"));
795
875
  }
796
876
  });
@@ -810,7 +890,7 @@ class UtilitiesComponent {
810
890
  }
811
891
  }
812
892
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: UtilitiesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
813
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: UtilitiesComponent, isStandalone: true, selector: "sdk-utilities", ngImport: i0, template: "<div class=\"utilities-content\">\n <header class=\"utilities-header-section\">\n <h1 class=\"utilities-title\">{{ 'LABEL_UTILITIES' | translate }}</h1>\n </header>\n\n <section class=\"utilities-section\">\n <div class=\"utilities-card\">\n <div class=\"utilities-card-header\">\n <h4 class=\"utilities-card-title\">{{ 'LABEL_RECHARGE_AND_PAY_BILLS' | translate }}</h4>\n </div>\n <div class=\"utilities-card-body\">\n <div class=\"utilities-grid\">\n @for (item of providerCategories; track item?.id ?? item?.category_name) {\n <a class=\"utility-card\" (click)=\"navigateToVendorProvider(item)\" role=\"button\" tabindex=\"0\">\n <div class=\"utility-card-inner\">\n <div class=\"utility-icon\">\n @if (item?.image) {\n <img loading=\"lazy\" [src]=\"item.image\" [alt]=\"item?.category_name ?? ''\" />\n } @else {\n <span class=\"utility-icon-placeholder\">{{ (item?.category_name ?? '') | slice:0:1 }}</span>\n }\n </div>\n <h5 class=\"utility-name\">{{ item?.category_name }}</h5>\n </div>\n </a>\n }\n </div>\n </div>\n </div>\n </section>\n</div>\n", styles: [".utilities-content{overflow:visible;min-height:120px;background:#f8f9fa;margin:0 -.25rem;padding:.35rem .25rem 1.25rem;border-radius:0}.utilities-header-section{margin-bottom:1rem;padding:0 .15rem}.utilities-title{font-size:1.875rem;font-weight:700;color:#1e3557;margin:0;line-height:1.2;letter-spacing:-.02em}.utilities-section{padding:0}.utilities-card{background:#fff;border:1px solid #dee2e6;border-radius:8px;box-shadow:0 1px 2px #1e35570a;overflow:hidden}.utilities-card-header{padding:.85rem 1.25rem;border-bottom:1px solid #e9ecef;background:#fff}.utilities-card-title{font-size:1.125rem;font-weight:600;margin:0;color:#1e3557}.utilities-card-body{padding:1.25rem 1.25rem 1.35rem}.utilities-grid{display:flex;flex-wrap:wrap;gap:1rem 1.1rem}.utility-card{display:block;text-decoration:none;color:inherit;cursor:pointer;border-radius:8px;overflow:visible;width:140px;flex:0 0 auto;transition:transform .12s ease,box-shadow .12s ease}.utility-card:hover{transform:translateY(-1px)}.utility-card:focus-visible{outline:2px solid #0d6efd;outline-offset:2px}.utility-card-inner{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:1rem .6rem .85rem;text-align:center;min-height:132px;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;box-sizing:border-box}.utility-card:hover .utility-card-inner{border-color:#cbd5e1;box-shadow:0 2px 8px #1e355712}.utility-icon{width:56px;height:56px;margin-bottom:.75rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;background:#f1ffff;border-radius:50%;border:1px solid #e2e8f0;box-sizing:border-box}.utility-icon img{max-width:36px;max-height:36px;object-fit:contain}.utility-icon-placeholder{width:100%;height:100%;border-radius:999px;background:#f1ffff;color:#5b7a8c;font-size:1.125rem;font-weight:600;display:flex;align-items:center;justify-content:center;text-transform:uppercase}.utility-name{font-size:.8125rem;font-weight:600;color:#212529;margin:0;line-height:1.25;word-break:break-word;max-width:100%}@media (max-width: 767px){.utilities-content{margin:0;padding:.25rem 0 1rem}.utilities-title{font-size:1.5rem}.utilities-grid{gap:.65rem;justify-content:flex-start}.utility-card{width:calc(50% - .35rem);max-width:160px}.utility-card-inner{min-height:120px}.utilities-card-body{padding:1rem}}\n"], dependencies: [{ kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: NgSelectModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormlyBootstrapModule }, { kind: "ngmodule", type: FormlyModule }, { kind: "pipe", type: i1.SlicePipe, name: "slice" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
893
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: UtilitiesComponent, isStandalone: true, selector: "sdk-utilities", ngImport: i0, template: "<div class=\"utilities-content\">\n <header class=\"utilities-header-section\">\n <h1 class=\"utilities-title\">{{ 'LABEL_UTILITIES' | translate }}</h1>\n </header>\n\n <section class=\"utilities-section\">\n <div class=\"utilities-card\">\n <div class=\"utilities-card-header\">\n <h4 class=\"utilities-card-title\">{{ 'LABEL_RECHARGE_AND_PAY_BILLS' | translate }}</h4>\n </div>\n <div class=\"utilities-card-body\">\n <div class=\"utilities-grid\">\n @if (categoriesLoaded && !hasCategories) {\n <sdk-no-data title=\"LABEL_NO_PROVIDERS_AVAILABLE\"></sdk-no-data>\n } @else {\n @for (item of providerCategories; track item?.id ?? item?.category_name) {\n <a class=\"utility-card\" (click)=\"navigateToVendorProvider(item)\" role=\"button\" tabindex=\"0\">\n <div class=\"utility-card-inner\">\n <div class=\"utility-icon\">\n @if (item?.image) {\n <img loading=\"lazy\" [src]=\"item.image\" [alt]=\"item?.category_name ?? ''\" />\n } @else {\n <span class=\"utility-icon-placeholder\">{{ (item?.category_name ?? '') | slice:0:1 }}</span>\n }\n </div>\n <h5 class=\"utility-name\">{{ item?.category_name }}</h5>\n </div>\n </a>\n }\n }\n </div>\n </div>\n </div>\n </section>\n</div>", styles: [".utilities-content{overflow:visible;min-height:120px;background:#f8f9fa;margin:0 -.25rem;padding:.35rem .25rem 1.25rem;border-radius:0}.utilities-header-section{margin-bottom:1rem;padding:0 .15rem}.utilities-title{font-size:1.875rem;font-weight:700;color:#1e3557;margin:0;line-height:1.2;letter-spacing:-.02em}.utilities-section{padding:0}.utilities-card{background:#fff;border:1px solid #dee2e6;border-radius:8px;box-shadow:0 1px 2px #1e35570a;overflow:hidden}.utilities-card-header{padding:.85rem 1.25rem;border-bottom:1px solid #e9ecef;background:#fff}.utilities-card-title{font-size:1.125rem;font-weight:600;margin:0;color:#1e3557}.utilities-card-body{padding:1.25rem 1.25rem 1.35rem}.utilities-grid{display:flex;flex-wrap:wrap;gap:1rem 1.1rem}.utility-card{display:block;text-decoration:none;color:inherit;cursor:pointer;border-radius:8px;overflow:visible;width:140px;flex:0 0 auto;transition:transform .12s ease,box-shadow .12s ease}.utility-card:hover{transform:translateY(-1px)}.utility-card:focus-visible{outline:2px solid #0d6efd;outline-offset:2px}.utility-card-inner{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:1rem .6rem .85rem;text-align:center;min-height:132px;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;box-sizing:border-box}.utility-card:hover .utility-card-inner{border-color:#cbd5e1;box-shadow:0 2px 8px #1e355712}.utility-icon{width:56px;height:56px;margin-bottom:.75rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;background:#f1ffff;border-radius:50%;border:1px solid #e2e8f0;box-sizing:border-box}.utility-icon img{max-width:36px;max-height:36px;object-fit:contain}.utility-icon-placeholder{width:100%;height:100%;border-radius:999px;background:#f1ffff;color:#5b7a8c;font-size:1.125rem;font-weight:600;display:flex;align-items:center;justify-content:center;text-transform:uppercase}.utility-name{font-size:.8125rem;font-weight:600;color:#212529;margin:0;line-height:1.25;word-break:break-word;max-width:100%}@media (max-width: 767px){.utilities-content{margin:0;padding:.25rem 0 1rem}.utilities-title{font-size:1.5rem}.utilities-grid{gap:.65rem;justify-content:flex-start}.utility-card{width:calc(50% - .35rem);max-width:160px}.utility-card-inner{min-height:120px}.utilities-card-body{padding:1rem}}\n"], dependencies: [{ kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: NgSelectModule }, { kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: FormlyBootstrapModule }, { kind: "ngmodule", type: FormlyModule }, { kind: "component", type: NoDataComponent, selector: "sdk-no-data", inputs: ["title", "icon"] }, { kind: "pipe", type: i1.SlicePipe, name: "slice" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
814
894
  }
815
895
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: UtilitiesComponent, decorators: [{
816
896
  type: Component,
@@ -820,8 +900,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
820
900
  FormsModule,
821
901
  ReactiveFormsModule,
822
902
  FormlyBootstrapModule,
823
- FormlyModule
824
- ], template: "<div class=\"utilities-content\">\n <header class=\"utilities-header-section\">\n <h1 class=\"utilities-title\">{{ 'LABEL_UTILITIES' | translate }}</h1>\n </header>\n\n <section class=\"utilities-section\">\n <div class=\"utilities-card\">\n <div class=\"utilities-card-header\">\n <h4 class=\"utilities-card-title\">{{ 'LABEL_RECHARGE_AND_PAY_BILLS' | translate }}</h4>\n </div>\n <div class=\"utilities-card-body\">\n <div class=\"utilities-grid\">\n @for (item of providerCategories; track item?.id ?? item?.category_name) {\n <a class=\"utility-card\" (click)=\"navigateToVendorProvider(item)\" role=\"button\" tabindex=\"0\">\n <div class=\"utility-card-inner\">\n <div class=\"utility-icon\">\n @if (item?.image) {\n <img loading=\"lazy\" [src]=\"item.image\" [alt]=\"item?.category_name ?? ''\" />\n } @else {\n <span class=\"utility-icon-placeholder\">{{ (item?.category_name ?? '') | slice:0:1 }}</span>\n }\n </div>\n <h5 class=\"utility-name\">{{ item?.category_name }}</h5>\n </div>\n </a>\n }\n </div>\n </div>\n </div>\n </section>\n</div>\n", styles: [".utilities-content{overflow:visible;min-height:120px;background:#f8f9fa;margin:0 -.25rem;padding:.35rem .25rem 1.25rem;border-radius:0}.utilities-header-section{margin-bottom:1rem;padding:0 .15rem}.utilities-title{font-size:1.875rem;font-weight:700;color:#1e3557;margin:0;line-height:1.2;letter-spacing:-.02em}.utilities-section{padding:0}.utilities-card{background:#fff;border:1px solid #dee2e6;border-radius:8px;box-shadow:0 1px 2px #1e35570a;overflow:hidden}.utilities-card-header{padding:.85rem 1.25rem;border-bottom:1px solid #e9ecef;background:#fff}.utilities-card-title{font-size:1.125rem;font-weight:600;margin:0;color:#1e3557}.utilities-card-body{padding:1.25rem 1.25rem 1.35rem}.utilities-grid{display:flex;flex-wrap:wrap;gap:1rem 1.1rem}.utility-card{display:block;text-decoration:none;color:inherit;cursor:pointer;border-radius:8px;overflow:visible;width:140px;flex:0 0 auto;transition:transform .12s ease,box-shadow .12s ease}.utility-card:hover{transform:translateY(-1px)}.utility-card:focus-visible{outline:2px solid #0d6efd;outline-offset:2px}.utility-card-inner{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:1rem .6rem .85rem;text-align:center;min-height:132px;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;box-sizing:border-box}.utility-card:hover .utility-card-inner{border-color:#cbd5e1;box-shadow:0 2px 8px #1e355712}.utility-icon{width:56px;height:56px;margin-bottom:.75rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;background:#f1ffff;border-radius:50%;border:1px solid #e2e8f0;box-sizing:border-box}.utility-icon img{max-width:36px;max-height:36px;object-fit:contain}.utility-icon-placeholder{width:100%;height:100%;border-radius:999px;background:#f1ffff;color:#5b7a8c;font-size:1.125rem;font-weight:600;display:flex;align-items:center;justify-content:center;text-transform:uppercase}.utility-name{font-size:.8125rem;font-weight:600;color:#212529;margin:0;line-height:1.25;word-break:break-word;max-width:100%}@media (max-width: 767px){.utilities-content{margin:0;padding:.25rem 0 1rem}.utilities-title{font-size:1.5rem}.utilities-grid{gap:.65rem;justify-content:flex-start}.utility-card{width:calc(50% - .35rem);max-width:160px}.utility-card-inner{min-height:120px}.utilities-card-body{padding:1rem}}\n"] }]
903
+ FormlyModule,
904
+ NoDataComponent
905
+ ], template: "<div class=\"utilities-content\">\n <header class=\"utilities-header-section\">\n <h1 class=\"utilities-title\">{{ 'LABEL_UTILITIES' | translate }}</h1>\n </header>\n\n <section class=\"utilities-section\">\n <div class=\"utilities-card\">\n <div class=\"utilities-card-header\">\n <h4 class=\"utilities-card-title\">{{ 'LABEL_RECHARGE_AND_PAY_BILLS' | translate }}</h4>\n </div>\n <div class=\"utilities-card-body\">\n <div class=\"utilities-grid\">\n @if (categoriesLoaded && !hasCategories) {\n <sdk-no-data title=\"LABEL_NO_PROVIDERS_AVAILABLE\"></sdk-no-data>\n } @else {\n @for (item of providerCategories; track item?.id ?? item?.category_name) {\n <a class=\"utility-card\" (click)=\"navigateToVendorProvider(item)\" role=\"button\" tabindex=\"0\">\n <div class=\"utility-card-inner\">\n <div class=\"utility-icon\">\n @if (item?.image) {\n <img loading=\"lazy\" [src]=\"item.image\" [alt]=\"item?.category_name ?? ''\" />\n } @else {\n <span class=\"utility-icon-placeholder\">{{ (item?.category_name ?? '') | slice:0:1 }}</span>\n }\n </div>\n <h5 class=\"utility-name\">{{ item?.category_name }}</h5>\n </div>\n </a>\n }\n }\n </div>\n </div>\n </div>\n </section>\n</div>", styles: [".utilities-content{overflow:visible;min-height:120px;background:#f8f9fa;margin:0 -.25rem;padding:.35rem .25rem 1.25rem;border-radius:0}.utilities-header-section{margin-bottom:1rem;padding:0 .15rem}.utilities-title{font-size:1.875rem;font-weight:700;color:#1e3557;margin:0;line-height:1.2;letter-spacing:-.02em}.utilities-section{padding:0}.utilities-card{background:#fff;border:1px solid #dee2e6;border-radius:8px;box-shadow:0 1px 2px #1e35570a;overflow:hidden}.utilities-card-header{padding:.85rem 1.25rem;border-bottom:1px solid #e9ecef;background:#fff}.utilities-card-title{font-size:1.125rem;font-weight:600;margin:0;color:#1e3557}.utilities-card-body{padding:1.25rem 1.25rem 1.35rem}.utilities-grid{display:flex;flex-wrap:wrap;gap:1rem 1.1rem}.utility-card{display:block;text-decoration:none;color:inherit;cursor:pointer;border-radius:8px;overflow:visible;width:140px;flex:0 0 auto;transition:transform .12s ease,box-shadow .12s ease}.utility-card:hover{transform:translateY(-1px)}.utility-card:focus-visible{outline:2px solid #0d6efd;outline-offset:2px}.utility-card-inner{background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:1rem .6rem .85rem;text-align:center;min-height:132px;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;box-sizing:border-box}.utility-card:hover .utility-card-inner{border-color:#cbd5e1;box-shadow:0 2px 8px #1e355712}.utility-icon{width:56px;height:56px;margin-bottom:.75rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;background:#f1ffff;border-radius:50%;border:1px solid #e2e8f0;box-sizing:border-box}.utility-icon img{max-width:36px;max-height:36px;object-fit:contain}.utility-icon-placeholder{width:100%;height:100%;border-radius:999px;background:#f1ffff;color:#5b7a8c;font-size:1.125rem;font-weight:600;display:flex;align-items:center;justify-content:center;text-transform:uppercase}.utility-name{font-size:.8125rem;font-weight:600;color:#212529;margin:0;line-height:1.25;word-break:break-word;max-width:100%}@media (max-width: 767px){.utilities-content{margin:0;padding:.25rem 0 1rem}.utilities-title{font-size:1.5rem}.utilities-grid{gap:.65rem;justify-content:flex-start}.utility-card{width:calc(50% - .35rem);max-width:160px}.utility-card-inner{min-height:120px}.utilities-card-body{padding:1rem}}\n"] }]
825
906
  }], ctorParameters: () => [] });
826
907
 
827
908
  function isNotNull(value) {
@@ -1215,44 +1296,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
1215
1296
  ], template: "<div class=\"content\">\n <header class=\"page-header\">\n <div class=\"d-flex align-items-center flex-wrap\">\n <div class=\"mr-auto\">\n <h1>Utilities</h1>\n </div>\n </div>\n </header>\n\n <section class=\"page-content container-fluid\">\n\n <div class=\"card m-0 border-0\">\n <div class=\"card-header p-t-25 p-b-20\">\n <h4 class=\"card-title font-weight-600 font-size-18 m-0 text-dark\">{{vendorCategory?.category_name}}</h4>\n </div>\n <div class=\"tab-content\">\n <div class=\"tab-pane fadeIn active show\">\n <form role=\"form\" class=\"form-horizontal\">\n <div class=\"card-body\">\n <div class=\"mt-3\">\n <div class=\"row\">\n <div class=\"col-xl-10 offset-xl-1\">\n @if (loadingState) {\n <div class=\"form-group form-row\">\n <div class=\"control-label text-md-right col-md-4 col-lg-3\">\n <div class=\"shimmer shimmer-effect\" style=\"height: 20px; width: 80px; margin-top: 8px;\"></div>\n </div>\n <div class=\"col-md-5\">\n <div class=\"shimmer shimmer-effect\" style=\"height: 38px; width: 100%;\"></div>\n </div>\n </div>\n } @else {\n @if (currentVendorKey == \"airtime_credit\" || currentVendorKey == \"airtime_data\" ) {\n <div class=\"form-group form-row\">\n <label\n class=\"control-label text-md-right col-md-4 col-lg-3\">\n {{'LABEL_OPERATOR' | translate}}\n </label>\n <div class=\"col-md-5\">\n <ng-select \n [placeholder]=\"'LABEL_SELECT_OPERATOR' | translate\" \n bindLabel=\"provider_name\"\n bindValue=\"id\" \n [items]=\"vendorProviders\"\n (change)=\"changeVendorProvider($event)\">\n </ng-select>\n </div>\n </div>\n } @else {\n <div class=\"form-group form-row\">\n <label\n class=\"control-label text-md-right col-md-4 col-lg-3\">\n {{'LABEL_PROVIDER' | translate}}\n </label>\n <div class=\"col-md-5\">\n <ng-select \n [placeholder]=\"'LABEL_SELECT_PROVIDER' | translate\" \n bindLabel=\"provider_name\"\n bindValue=\"id\" \n [items]=\"vendorProviders\"\n (change)=\"changeVendorProvider($event)\">\n </ng-select>\n </div>\n </div>\n }\n }\n </div>\n\n @if (recentTxnArray.length > 0) {\n <div class=\"col-xl-12\">\n <div class=\"border-bottom p-t-25 p-b-20\">\n <h4 class=\"card-title font-weight-600 font-size-18 m-0 text-dark\">\n {{'LABEL_RECENT_TRANSACTIONS' | translate}}</h4>\n </div>\n </div>\n <div class=\"row\">\n @for (obj of recentTxnArray; track obj) {\n <a (click)=\"handleRecentTxnClick(obj)\">\n <div class=\"card services-box text-center equal-height\">\n <div class=\"card-body\">\n <div class=\"icon\">\n @if (obj?.payment_request?.vendor_provider_image) {\n <img loading=\"lazy\"\n style=\"width: 50px; height: 50px; border-radius: 50%;\"\n [src]=\"obj?.payment_request?.vendor_provider_image\"\n alt=\"\" />\n } @else {\n <i class=\"align-middle fa fa-2x fa-bookmark\"></i>\n }\n </div>\n <h5 class=\"font-weight-600 mb-2 mt-3\">{{\n obj?.payment_request?.provider_name || \"-\" }}</h5>\n <h6 class=\"m-0 mb-1 text-muted\">{{\n obj?.payment_request?.account_number }}</h6>\n <h6 class=\"m-0 text-muted\">{{obj?.receiver_amount || 0.00 |\n price: { currency } }}</h6>\n </div>\n </div>\n </a>\n }\n </div>\n }\n </div>\n </div>\n </div>\n <div class=\"card-footer bg-light text-right\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"back()\">{{'COMMON_LABEL_CANCEL' | translate}}</button>\n <button type=\"button\" (click)=\"navigateToWorkFlow()\"\n class=\"btn btn-primary\">{{'COMMON_LABEL_NEXT' |translate}}</button>\n </div>\n </form>\n </div>\n </div>\n </div>\n </section>\n</div>\n\n<style>\n .shimmer-effect {\n border-radius: 10px;\n background-color: #F6F7F8;\n background-image: linear-gradient(to right, #F6F7F8 0, #EDEEF1 20%, #F6F7F8 40%, #F6F7F8 100%);\n background-position: 0 0;\n background-repeat: no-repeat;\n background-size: 1000px 1000px;\n animation: shimmerEffect 1s linear infinite forwards;\n }\n\n .shimmer {\n display: inline-block;\n width: 100%;\n height: 12px;\n }\n\n @keyframes shimmerEffect {\n 0% {\n background-position: -1000px 0;\n }\n 100% {\n background-position: 1000px 0;\n }\n }\n</style>" }]
1216
1297
  }], ctorParameters: () => [] });
1217
1298
 
1218
- class NoDataComponent {
1219
- title = 'No data available';
1220
- icon;
1221
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: NoDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1222
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: NoDataComponent, isStandalone: true, selector: "sdk-no-data", inputs: { title: "title", icon: "icon" }, ngImport: i0, template: `
1223
- <div class="text-center py-4">
1224
- @if (icon) {
1225
- <div class="mb-2">
1226
- <i class="la" [class.icon]="icon"></i>
1227
- </div>
1228
- }
1229
- <p class="text-muted">{{ title | translate }}</p>
1230
- </div>
1231
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: SharedModule }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
1232
- }
1233
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: NoDataComponent, decorators: [{
1234
- type: Component,
1235
- args: [{
1236
- selector: 'sdk-no-data',
1237
- template: `
1238
- <div class="text-center py-4">
1239
- @if (icon) {
1240
- <div class="mb-2">
1241
- <i class="la" [class.icon]="icon"></i>
1242
- </div>
1243
- }
1244
- <p class="text-muted">{{ title | translate }}</p>
1245
- </div>
1246
- `,
1247
- standalone: true,
1248
- imports: [SharedModule],
1249
- }]
1250
- }], propDecorators: { title: [{
1251
- type: Input
1252
- }], icon: [{
1253
- type: Input
1254
- }] } });
1255
-
1256
1299
  class FormlyHorizontalWrapperComponent extends FieldWrapper {
1257
1300
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FormlyHorizontalWrapperComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1258
1301
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: FormlyHorizontalWrapperComponent, isStandalone: true, selector: "sdk-formly-wrapper-form-field-horizontal", usesInheritance: true, ngImport: i0, template: `
@@ -1885,16 +1928,19 @@ class BillWorkflowComponent {
1885
1928
  this.topupAndBillpaymentService.vendorProvider.pipe(takeUntil(this.destroy$)).subscribe(data => {
1886
1929
  if (isNotNull(data)) {
1887
1930
  this.vendorProvider = data;
1931
+ console.log("vendorProvider==>", this.vendorProvider);
1888
1932
  }
1889
1933
  });
1890
1934
  this.topupAndBillpaymentService.workFlowUserInput.pipe(takeUntil(this.destroy$)).subscribe((data) => {
1891
1935
  if (isNotNull(data)) {
1892
1936
  this.workFlowUserInput = data;
1937
+ console.log("workFlowUserInput==>", this.workFlowUserInput);
1893
1938
  }
1894
1939
  });
1895
1940
  this.topupAndBillpaymentService.vendorPlan.pipe(takeUntil(this.destroy$)).subscribe((data) => {
1896
1941
  if (isNotNull(data)) {
1897
1942
  this.selectedProduct = data;
1943
+ console.log("selectedProduct==>", this.selectedProduct);
1898
1944
  }
1899
1945
  });
1900
1946
  this.topupAndBillpaymentService.currentScreenStep.pipe(takeUntil(this.destroy$)).subscribe((index) => {
@@ -1913,6 +1959,7 @@ class BillWorkflowComponent {
1913
1959
  this.topupAndBillpaymentService.workflowData.pipe(takeUntil(this.destroy$)).subscribe((data) => {
1914
1960
  if (isNotNull(data)) {
1915
1961
  this.allWorkflowData = data;
1962
+ console.log("allWorkflowData==>", this.allWorkflowData);
1916
1963
  }
1917
1964
  });
1918
1965
  // Create form with updateOn: 'change' for real-time validation
@@ -2040,6 +2087,9 @@ class BillWorkflowComponent {
2040
2087
  }
2041
2088
  }
2042
2089
  submitForm() {
2090
+ if (!this.validateEnteredAmountAgainstBill()) {
2091
+ return;
2092
+ }
2043
2093
  // Validate amount range for products with range price type
2044
2094
  if (this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.RANGE) {
2045
2095
  const amountField = this.fieldsArray.find((field) => {
@@ -2231,6 +2281,7 @@ class BillWorkflowComponent {
2231
2281
  const rangeMin = Number(this.selectedProduct?.product_range_price?.min) || 0;
2232
2282
  const rangeMax = Number(this.selectedProduct?.product_range_price?.max) || 0;
2233
2283
  customValidators = {
2284
+ ...customValidators,
2234
2285
  // Range validator - checks if value is within the allowed range
2235
2286
  // Allows typing leading zeros (e.g., "01", "08") but validates the numeric value
2236
2287
  range: {
@@ -2253,6 +2304,24 @@ class BillWorkflowComponent {
2253
2304
  };
2254
2305
  }
2255
2306
  }
2307
+ if (isAmountField) {
2308
+ const billAmount = this.getBillAmount();
2309
+ if (billAmount !== null) {
2310
+ customValidators = {
2311
+ ...customValidators,
2312
+ billAmountMax: {
2313
+ expression: (control) => {
2314
+ const enteredAmount = this.parseFormAmount(control?.value);
2315
+ if (enteredAmount === null) {
2316
+ return true;
2317
+ }
2318
+ return enteredAmount <= billAmount;
2319
+ },
2320
+ message: () => this.translationService.translate("COMMON_LABEL_AMOUNT_MUST_NOT_EXCEED_BILL_AMOUNT"),
2321
+ },
2322
+ };
2323
+ }
2324
+ }
2256
2325
  const validations = field?.field_validation || [];
2257
2326
  const normalizedFieldType = this.normalizeFieldType(field?.field_type);
2258
2327
  const normalizedValidations = this.normalizeValidations(validations);
@@ -2344,6 +2413,50 @@ class BillWorkflowComponent {
2344
2413
  this.destroy$.next(true);
2345
2414
  this.destroy$.unsubscribe();
2346
2415
  }
2416
+ getSelectedBill() {
2417
+ return this.allWorkflowData?.selectedBill ?? this.selectedBill ?? null;
2418
+ }
2419
+ getBillAmount() {
2420
+ const billAmount = Number(this.getSelectedBill()?.bill_amount);
2421
+ if (isNaN(billAmount) || billAmount <= 0) {
2422
+ return null;
2423
+ }
2424
+ return billAmount;
2425
+ }
2426
+ findAmountField() {
2427
+ return this.fieldsArray.find((field) => {
2428
+ const keyStr = String(field?.key || "").toLowerCase();
2429
+ const labelStr = String(field?.templateOptions?.label || "").toLowerCase();
2430
+ return keyStr.includes("amount") || labelStr.includes("amount");
2431
+ });
2432
+ }
2433
+ parseFormAmount(value) {
2434
+ if (value === null || value === undefined || value === "") {
2435
+ return null;
2436
+ }
2437
+ const amount = typeof value === "number" ? value : parseFloat(String(value));
2438
+ return isNaN(amount) ? null : amount;
2439
+ }
2440
+ validateEnteredAmountAgainstBill() {
2441
+ const billAmount = this.getBillAmount();
2442
+ if (billAmount === null) {
2443
+ return true;
2444
+ }
2445
+ const amountField = this.findAmountField();
2446
+ if (!amountField?.key) {
2447
+ return true;
2448
+ }
2449
+ const fieldKey = String(amountField.key);
2450
+ const enteredAmount = this.parseFormAmount(this.detailsForm?.value[fieldKey]);
2451
+ if (enteredAmount === null || enteredAmount <= billAmount) {
2452
+ return true;
2453
+ }
2454
+ this.toasterService.error(this.translationService.translate("COMMON_LABEL_AMOUNT_MUST_NOT_EXCEED_BILL_AMOUNT"));
2455
+ const control = this.detailsForm.get(fieldKey);
2456
+ control?.setErrors({ ...(control.errors ?? {}), billAmountMax: true });
2457
+ control?.markAsTouched();
2458
+ return false;
2459
+ }
2347
2460
  normalizeWorkflowDetails(workflowDetails) {
2348
2461
  if (!Array.isArray(workflowDetails))
2349
2462
  return [];
@@ -3990,21 +4103,29 @@ class AuthService {
3990
4103
  const companyId = this.authProvider.getCompanyId();
3991
4104
  const userId = this.authProvider.getUserId();
3992
4105
  if (token)
3993
- headers['Authorization'] = token.startsWith('Bearer ') ? token : `${token}`;
4106
+ headers['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
3994
4107
  if (companyId != null)
3995
4108
  headers['companyid'] = String(companyId);
3996
4109
  if (userId != null)
3997
4110
  headers['userid'] = String(userId);
3998
4111
  return headers;
3999
4112
  }
4000
- verifyOTP(_payload) {
4001
- return of({ success: false });
4113
+ authUrl(pathKey, defaultPath) {
4114
+ const cfg = this.config.getConfig();
4115
+ const custom = cfg?.authPaths?.[pathKey];
4116
+ if (custom) {
4117
+ return custom.startsWith('http') ? custom : `${this.baseUrl}${custom.startsWith('/') ? custom : `/${custom}`}`;
4118
+ }
4119
+ return `${this.baseUrl}${defaultPath}`;
4120
+ }
4121
+ verifyOTP(payload) {
4122
+ return this.http.post(this.authUrl('verifyOtp', '/auth/verify_otp'), payload, { headers: this.defaultHeaders });
4002
4123
  }
4003
- sendOTP(_payload) {
4004
- return of({ success: false });
4124
+ sendOTP(payload) {
4125
+ return this.http.post(this.authUrl('sendOtp', '/auth/send_otp'), payload, { headers: this.defaultHeaders });
4005
4126
  }
4006
- createTransactionPin(_payload) {
4007
- return of({ success: false });
4127
+ createTransactionPin(payload) {
4128
+ return this.http.post(this.authUrl('createTransactionPin', '/auth/create_transaction_pin'), payload, { headers: this.defaultHeaders });
4008
4129
  }
4009
4130
  verifyTransactionPin(payload) {
4010
4131
  return this.http.post(`${this.baseUrl}/auth/verify_transaction_pin`, payload, { headers: this.defaultHeaders });
@@ -4415,7 +4536,18 @@ function openUtilityBootstrapModal(element) {
4415
4536
  return false;
4416
4537
  }
4417
4538
  }
4418
- /** Hides a modal that was opened with this SDK’s bundled Bootstrap `Modal` instance. */
4539
+ /** Removes stray backdrops / body lock left by mixed Bootstrap or jQuery modals. */
4540
+ function cleanupUtilityModalBackdrops() {
4541
+ const doc = globalThis.document;
4542
+ if (!doc?.body) {
4543
+ return;
4544
+ }
4545
+ doc.querySelectorAll('.modal-backdrop').forEach((node) => node.remove());
4546
+ doc.body.classList.remove('modal-open');
4547
+ doc.body.style.removeProperty('padding-right');
4548
+ doc.body.style.removeProperty('overflow');
4549
+ }
4550
+ /** Hides a modal that was opened with this SDK's bundled Bootstrap `Modal` instance. */
4419
4551
  function closeUtilityBootstrapModal(element) {
4420
4552
  if (!element) {
4421
4553
  return false;
@@ -4587,6 +4719,12 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4587
4719
  }
4588
4720
  });
4589
4721
  this.loadCurrentUserDetailsFromApi();
4722
+ this.dataService.currentUserDetails.pipe(takeUntil(this.destroy$)).subscribe((data) => {
4723
+ if (isNotNull(data)) {
4724
+ this.currentUserDetails = data;
4725
+ this.isTxnPinCreated = Boolean(data?.transaction_pin);
4726
+ }
4727
+ });
4590
4728
  this.dataService.adminUserDetails.pipe(takeUntil(this.destroy$)).subscribe((data) => {
4591
4729
  if (isNotNull(data)) {
4592
4730
  this.adminUserDetails = data;
@@ -4680,15 +4818,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4680
4818
  this.userDetail();
4681
4819
  }
4682
4820
  async calculatCharge() {
4821
+ this.showLoader = true;
4683
4822
  const cfg = (this.paymentsConfigService.getConfig() ?? {});
4684
4823
  const cfgHeaders = (cfg?.defaultHeaders ?? {});
4685
4824
  const userId = (cfgHeaders["userid"] ?? cfgHeaders["userId"] ?? cfg?.userId ?? "").toString().trim();
4686
- this.showLoader = true;
4687
4825
  let profileDetails = {
4688
4826
  "userProfileService": this.userprofileService,
4689
4827
  "userId": userId,
4690
4828
  "walletId": this.walletId,
4691
- "userType": USER_TYPES.AGENT,
4829
+ "userType": this.currentUserDetails?.user_type,
4692
4830
  "currencyId": this.currencyId,
4693
4831
  };
4694
4832
  if (this.vendorDetails?.vendor_code == "SOCHIETEL") {
@@ -4708,7 +4846,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4708
4846
  productCode: PRODUCT_MASTER_DICT.BP,
4709
4847
  amount: this.userAmount || this.amount || this.billData?.selectedBill?.bill_amount || this.planData?.product_fixed_price,
4710
4848
  currencyId: this.currencyId,
4711
- userType: USER_TYPES.AGENT,
4849
+ userType: this.currentUserDetails?.user_type,
4712
4850
  walletId: this.walletId,
4713
4851
  };
4714
4852
  if (this.vendorDetails?.vendor_code == "SOCHIETEL") {
@@ -4904,26 +5042,33 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4904
5042
  this.otpReset = false;
4905
5043
  if (this.otpForm.valid) {
4906
5044
  this.showLoader = true;
5045
+ const user = this.resolveCurrentUserDetails();
4907
5046
  const data = {
4908
- dial_code: this.currentUserDetails?.dial_code,
4909
- phone_number: this.currentUserDetails?.phone_number,
5047
+ dial_code: user?.dial_code,
5048
+ phone_number: user?.phone_number,
4910
5049
  otp: this.otpForm.value.otp,
4911
- otp_type: OTP_TYPES.OTP_TYPE_ADD_CASH_MANUALLY,
5050
+ user_type: this.currentUserDetails?.user_type,
5051
+ otp_type: OTP_TYPES.OTP_TYPE_FORGOT_TRANSACTION_PIN,
4912
5052
  };
4913
5053
  this.authService.verifyOTP(data).subscribe({
4914
5054
  next: (response) => {
4915
5055
  this.showLoader = false;
4916
- if (response.success) {
5056
+ if (this.isApiSuccess(response)) {
4917
5057
  clearInterval(this.interval);
4918
5058
  this.hideModal("OTPVerification");
4919
- this.toasterService.success(this.translationService.translate(response?.data?.message));
5059
+ const message = response?.data?.message;
5060
+ if (message) {
5061
+ this.toasterService.success(this.translationService.translate(message));
5062
+ }
4920
5063
  if (this.inValidTxnPin) {
4921
5064
  this.inValidTxnPin = false;
4922
5065
  this.isTxnPinCreated = false;
4923
- this.showModal("TransactionPIN");
5066
+ this.otpReset = true;
5067
+ setTimeout(() => this.showModal("TransactionPIN"), 200);
4924
5068
  }
4925
5069
  else if (this.isTpinSessionNeeded()) {
4926
- this.showModal("TransactionPIN");
5070
+ this.otpReset = true;
5071
+ setTimeout(() => this.showModal("TransactionPIN"), 200);
4927
5072
  }
4928
5073
  else {
4929
5074
  this.createIntent();
@@ -4931,11 +5076,12 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4931
5076
  this.otpReset = true;
4932
5077
  }
4933
5078
  else {
4934
- this.toasterService.error(this.translationService.translate(response?.error[0]));
5079
+ this.toasterService.error(this.getApiErrorMessage(response));
4935
5080
  }
4936
5081
  },
4937
- error: () => {
5082
+ error: (err) => {
4938
5083
  this.showLoader = false;
5084
+ this.toasterService.error(this.getApiErrorMessage(err?.error ?? err));
4939
5085
  },
4940
5086
  });
4941
5087
  }
@@ -4997,45 +5143,69 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4997
5143
  this.otpForm.patchValue({ otp });
4998
5144
  }
4999
5145
  forgotTxnPin() {
5000
- this.hideModal("TransactionPIN");
5001
- this.sendOTPToAgent();
5146
+ this.sendOTPToAgent(true);
5002
5147
  }
5003
- sendOTPToAgent() {
5148
+ sendOTPToAgent(restorePinModalOnFailure = false) {
5149
+ const user = this.resolveCurrentUserDetails();
5150
+ if (!user?.dial_code || !user?.phone_number) {
5151
+ this.toasterService.error(this.translationService.translate("LABEL_SOMETHING_WENT_WRONG"));
5152
+ return;
5153
+ }
5004
5154
  this.showLoader = true;
5155
+ this.otpForm.reset();
5156
+ this.formErrors.otp = null;
5005
5157
  const data = {
5006
- dial_code: this.currentUserDetails?.dial_code,
5007
- phone_number: this.currentUserDetails?.phone_number,
5008
- // user_type: USER_TYPES.AGENT,
5009
- email: this.currentUserDetails?.email,
5010
- otp_type: OTP_TYPES.OTP_TYPE_ADD_CASH_MANUALLY,
5158
+ dial_code: user.dial_code,
5159
+ phone_number: user.phone_number,
5160
+ email: user?.email,
5161
+ user_id: user?.id,
5162
+ user_type: this.currentUserDetails?.user_type,
5163
+ otp_type: OTP_TYPES.OTP_TYPE_FORGOT_TRANSACTION_PIN,
5011
5164
  };
5012
5165
  this.authService.sendOTP(data).subscribe({
5013
5166
  next: (response) => {
5014
5167
  this.showLoader = false;
5015
- if (response.success) {
5016
- this.toasterService.success(this.translationService.translate(response?.data?.message));
5017
- this.showModal("OTPVerification");
5018
- if (this.otpResendTime > 0) {
5019
- this.timer = this.otpResendTime;
5020
- this.interval = setInterval(() => {
5021
- if (this.timer > 0) {
5022
- this.timer--;
5023
- }
5024
- else {
5025
- clearInterval(this.interval);
5026
- }
5027
- }, 1000);
5168
+ if (this.isApiSuccess(response)) {
5169
+ const message = response?.data?.message;
5170
+ if (message) {
5171
+ this.toasterService.success(this.translationService.translate(message));
5028
5172
  }
5173
+ this.openOtpVerificationModal(restorePinModalOnFailure);
5174
+ this.startOtpResendTimer();
5029
5175
  }
5030
5176
  else {
5031
- this.toasterService.error(this.translationService.translate(response?.error[0]));
5177
+ this.toasterService.error(this.getApiErrorMessage(response));
5032
5178
  }
5033
5179
  },
5034
- error: () => {
5180
+ error: (err) => {
5035
5181
  this.showLoader = false;
5182
+ this.toasterService.error(this.getApiErrorMessage(err?.error ?? err));
5036
5183
  },
5037
5184
  });
5038
5185
  }
5186
+ openOtpVerificationModal(hideTransactionPinModal) {
5187
+ if (hideTransactionPinModal) {
5188
+ this.hideModal("TransactionPIN");
5189
+ }
5190
+ setTimeout(() => {
5191
+ this.showModal("OTPVerification");
5192
+ }, 200);
5193
+ }
5194
+ startOtpResendTimer() {
5195
+ if (this.otpResendTime <= 0) {
5196
+ return;
5197
+ }
5198
+ this.timer = this.otpResendTime;
5199
+ clearInterval(this.interval);
5200
+ this.interval = setInterval(() => {
5201
+ if (this.timer > 0) {
5202
+ this.timer--;
5203
+ }
5204
+ else {
5205
+ clearInterval(this.interval);
5206
+ }
5207
+ }, 1000);
5208
+ }
5039
5209
  enterTxnPin() {
5040
5210
  this.createIntent();
5041
5211
  }
@@ -5113,12 +5283,12 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5113
5283
  this.hideModal("ConfirmTransactionPIN");
5114
5284
  }
5115
5285
  else {
5116
- this.toasterService.error(this.translationService.translate(res?.error[0]));
5286
+ this.toasterService.error(this.getApiErrorMessage(res));
5117
5287
  }
5118
5288
  },
5119
- error: () => {
5289
+ error: (err) => {
5120
5290
  this.showLoader = false;
5121
- this.toasterService.error(this.translationService.translate("LABEL_SOMETHING_WENT_WRONG"));
5291
+ this.toasterService.error(this.getApiErrorMessage(err?.error ?? err));
5122
5292
  },
5123
5293
  });
5124
5294
  }
@@ -5238,7 +5408,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5238
5408
  currency_id: this.currencyId,
5239
5409
  debit_type: TRANSFER_MODE.WALLET,
5240
5410
  debit_type_id: this.walletId,
5241
- debit_account_type: USER_TYPES.AGENT,
5411
+ debit_account_type: this.currentUserDetails?.user_type,
5242
5412
  debit_account_type_id: this.dataService.getWalletUserAccountId(),
5243
5413
  username: this.currentUserDetails?.first_name + " " + this.currentUserDetails?.last_name,
5244
5414
  },
@@ -5247,7 +5417,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5247
5417
  credit_type: TRANSFER_MODE.WALLET,
5248
5418
  credit_type_id: this.walletId,
5249
5419
  credit_account_type: USER_TYPES.VENDOR,
5250
- credit_account_type_id: this.adminUserDetails?.id,
5420
+ credit_account_type_id: this.vendorContractDetails?.user_id,
5251
5421
  username: this.vendorContractDetails?.contact_person_name,
5252
5422
  },
5253
5423
  txn_amount: (this.providerCode == 'DBA_PREPAID_ELECTRICITY' || this.providerCode == 'DBA_POSTPAID_ELECTRICITY') ? parseFloat(this.userAmountWithoutCharge) : txnAmount,
@@ -5331,7 +5501,6 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5331
5501
  return;
5332
5502
  }
5333
5503
  this.transactionService.initiateTopupBillPaymentTransaction(txnPayload).pipe(finalize(() => {
5334
- this.showLoader = false;
5335
5504
  })).subscribe({
5336
5505
  next: response => {
5337
5506
  if (response.success) {
@@ -5361,6 +5530,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5361
5530
  txnAmount: this.userAmount || txnAmount,
5362
5531
  txnDate: new Date().getTime(),
5363
5532
  };
5533
+ this.showLoader = false;
5364
5534
  this.topupAndBillpaymentService.saveTxnData(txnObj);
5365
5535
  this.showLoader = false;
5366
5536
  this.toasterService.success(this.translationService.translate(txnObj.message));
@@ -5368,7 +5538,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5368
5538
  }
5369
5539
  else {
5370
5540
  this.showLoader = false;
5371
- this.toasterService.error(this.translationService.translate(statusResponse?.error[0] || "LABEL_SOMETHING_WENT_WRONG"));
5541
+ this.toasterService.error(this.getApiErrorMessage(statusResponse));
5372
5542
  }
5373
5543
  },
5374
5544
  error: (statusError) => {
@@ -5490,15 +5660,28 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5490
5660
  }
5491
5661
  else {
5492
5662
  this.showLoader = false;
5493
- this.toasterService.error(this.translationService.translate(response?.error[0]));
5663
+ this.toasterService.error(this.getApiErrorMessage(response));
5494
5664
  }
5495
5665
  },
5496
5666
  error: (error) => {
5497
5667
  this.showLoader = false;
5498
- this.toasterService.error(this.translationService.translate(error?.error?.error));
5668
+ this.toasterService.error(this.getApiErrorMessage(error?.error ?? error));
5499
5669
  },
5500
5670
  });
5501
5671
  }
5672
+ resolveCurrentUserDetails() {
5673
+ return this.currentUserDetails ?? this.dataService.currentUserDetails?.value ?? null;
5674
+ }
5675
+ isApiSuccess(response) {
5676
+ return response?.success === true || response?.success === 1;
5677
+ }
5678
+ getApiErrorMessage(response, fallbackKey = "LABEL_SOMETHING_WENT_WRONG") {
5679
+ const raw = response?.error?.[0]
5680
+ ?? (typeof response?.error === "string" ? response.error : null)
5681
+ ?? response?.message
5682
+ ?? fallbackKey;
5683
+ return this.translationService.translate(raw);
5684
+ }
5502
5685
  buildPayBillPayload(txnId) {
5503
5686
  const currentAmount = this.userAmount || this.amount || this.billData?.selectedBill?.bill_amount || this.planData?.product_fixed_price || 0;
5504
5687
  const totalCharges = (parseFloat(this.calculateCharges?.total_charges) || 0) + (parseFloat(this.vendorCharge?.total_charges) || 0);
@@ -5571,7 +5754,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5571
5754
  };
5572
5755
  }
5573
5756
  goToMainAfterSuccessfulPayment() {
5574
- this.isTpinVerifiedForPayment = false;
5757
+ this.clearPaymentFlowState();
5575
5758
  if (this.sdkState?.isActive()) {
5576
5759
  this.sdkState.setStep("CATEGORY");
5577
5760
  }
@@ -5579,6 +5762,59 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5579
5762
  this.router.navigateByUrl("/operations/topup-and-billpayment");
5580
5763
  }
5581
5764
  }
5765
+ clearPaymentFlowState() {
5766
+ clearInterval(this.interval);
5767
+ this.interval = null;
5768
+ this.timer = 0;
5769
+ this.otpForm?.reset();
5770
+ this.txnPINForm?.reset();
5771
+ this.formErrors = { otp: null, pin: null, confirmPin: null };
5772
+ this.otpReset = false;
5773
+ this.otpConfirm = false;
5774
+ this.inValidTxnPin = false;
5775
+ this.isTpinVerifiedForPayment = false;
5776
+ this.enteredPIN = null;
5777
+ this.showLoader = false;
5778
+ this.hideModal("TransactionPIN");
5779
+ this.hideModal("OTPVerification");
5780
+ this.hideModal("ConfirmTransactionPIN");
5781
+ this.workFlowUserInput = [];
5782
+ this.billData = null;
5783
+ this.planData = null;
5784
+ this.amount = undefined;
5785
+ this.userAmount = null;
5786
+ this.userAmountWithoutCharge = null;
5787
+ this.paybleAmount = null;
5788
+ this.calculateCharges = null;
5789
+ this.vendorCharge = null;
5790
+ this.chargeData = null;
5791
+ this.taxData = null;
5792
+ this.cashTransferAmount = 0;
5793
+ this.latestTransactionPayload = null;
5794
+ this.txnData = {};
5795
+ this.txnAmount = null;
5796
+ this.senderReceiverStore = {};
5797
+ this.isBillReview = false;
5798
+ this.isPlanReview = false;
5799
+ this.proceedToPayment = true;
5800
+ this.communeId = null;
5801
+ this.regionName = null;
5802
+ this.regionId = null;
5803
+ this.communeName = null;
5804
+ this.kwh = null;
5805
+ this.meterName = null;
5806
+ this.vendorDetails = null;
5807
+ this.providerCode = null;
5808
+ this.vendorContractDetails = null;
5809
+ this.revenueConfigDetails = null;
5810
+ this.companyShareValue = 0;
5811
+ this.vendorShareValue = 0;
5812
+ this.vendorUserDetails = null;
5813
+ this.vendorProvider = null;
5814
+ this.vendorCategory = null;
5815
+ this.intentedData.set(null);
5816
+ this.topupAndBillpaymentService.clearAllSessionState();
5817
+ }
5582
5818
  back() {
5583
5819
  this.isTpinVerifiedForPayment = false;
5584
5820
  if (this.sdkState?.isActive()) {
@@ -5675,14 +5911,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5675
5911
  const g = globalThis;
5676
5912
  const doc = g?.document;
5677
5913
  const el = doc?.getElementById(modalId) ?? null;
5678
- const jq = g?.$;
5679
- if (jq && typeof jq === "function") {
5680
- const modalEl = jq(`#${modalId}`);
5681
- if (modalEl?.length && typeof modalEl.modal === "function") {
5682
- modalEl.modal("show");
5683
- return;
5684
- }
5685
- }
5914
+ cleanupUtilityModalBackdrops();
5686
5915
  if (el && openUtilityBootstrapModal(el)) {
5687
5916
  return;
5688
5917
  }
@@ -5693,7 +5922,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5693
5922
  return;
5694
5923
  }
5695
5924
  catch {
5696
- /* fall through to DOM */
5925
+ /* fall through */
5926
+ }
5927
+ }
5928
+ const jq = g?.$;
5929
+ if (jq && typeof jq === "function") {
5930
+ const modalEl = jq(`#${modalId}`);
5931
+ if (modalEl?.length && typeof modalEl.modal === "function") {
5932
+ modalEl.modal("show");
5933
+ return;
5697
5934
  }
5698
5935
  }
5699
5936
  if (!el) {
@@ -5703,25 +5940,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5703
5940
  el.style.display = "block";
5704
5941
  el.removeAttribute("aria-hidden");
5705
5942
  el.setAttribute("aria-modal", "true");
5706
- if (!doc?.querySelector(".utility-payments-modal-backdrop")) {
5707
- const backdrop = doc.createElement("div");
5708
- backdrop.className = "modal-backdrop fade show utility-payments-modal-backdrop";
5709
- doc.body.appendChild(backdrop);
5710
- }
5943
+ const backdrop = doc.createElement("div");
5944
+ backdrop.className = "modal-backdrop fade show utility-payments-modal-backdrop";
5945
+ doc.body.appendChild(backdrop);
5711
5946
  doc.body.classList.add("modal-open");
5712
5947
  }
5713
5948
  hideModal(modalId) {
5714
5949
  const g = globalThis;
5715
5950
  const doc = g?.document;
5716
5951
  const el = doc?.getElementById(modalId) ?? null;
5717
- const jq = g?.$;
5718
- if (jq && typeof jq === "function") {
5719
- const modalEl = jq(`#${modalId}`);
5720
- if (modalEl?.length && typeof modalEl.modal === "function") {
5721
- modalEl.modal("hide");
5722
- return;
5723
- }
5724
- }
5725
5952
  if (el && closeUtilityBootstrapModal(el)) {
5726
5953
  return;
5727
5954
  }
@@ -5733,7 +5960,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5733
5960
  return;
5734
5961
  }
5735
5962
  catch {
5736
- /* fall through to DOM */
5963
+ /* fall through */
5964
+ }
5965
+ }
5966
+ const jq = g?.$;
5967
+ if (jq && typeof jq === "function") {
5968
+ const modalEl = jq(`#${modalId}`);
5969
+ if (modalEl?.length && typeof modalEl.modal === "function") {
5970
+ modalEl.modal("hide");
5971
+ return;
5737
5972
  }
5738
5973
  }
5739
5974
  if (el) {
@@ -5742,11 +5977,10 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5742
5977
  el.setAttribute("aria-hidden", "true");
5743
5978
  el.removeAttribute("aria-modal");
5744
5979
  }
5745
- doc?.querySelectorAll(".utility-payments-modal-backdrop").forEach((node) => node.remove());
5746
- doc?.body.classList.remove("modal-open");
5980
+ cleanupUtilityModalBackdrops();
5747
5981
  }
5748
5982
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TopupAndBillpaymentReviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5749
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: TopupAndBillpaymentReviewComponent, isStandalone: true, selector: "sdk-topup-and-billpayment-review", viewQueries: [{ propertyName: "txnSummaryComp", first: true, predicate: TransactionSummaryComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"content review-payment-page\">\n <header class=\"page-header\">\n <div class=\"d-flex align-items-center flex-wrap\">\n <div class=\"mr-auto\">\n <h1>{{ 'LABEL_REVIEW_PAYMENT' | translate }}</h1>\n </div>\n </div>\n </header>\n\n <section class=\"page-content container-fluid review-payment-section\">\n <div class=\"card m-0 border-0 review-payment-shell\">\n <form role=\"form\">\n <div class=\"card-body review-payment-body\">\n <div class=\"review-payment-content\">\n <div class=\"row g-3\">\n <div class=\"col-xl-8\">\n <h5 class=\"border-bottom pb-3 font-weight-600 section-heading\"> {{ 'LABEL_PAYMENT_SUMMARY' | translate\n }} </h5>\n <div class=\"border-bottom table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_CATEGORY_TYPE' | translate }}</td>\n <td class=\"text-right\">{{\n providerCategoryTypes[vendorCategory?.category_type] || \"-\" |\n translate}}</td>\n </tr> -->\n @if(providerCode != \"SOCHIETEL\"){\n <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n @if (providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number || \"-\" }}</td>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_code || \"-\" }}</td>\n }\n </tr>\n }\n <tr>\n <td>{{ 'LABEL_PROVIDER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorProvider?.provider_name || \"-\" }}</td>\n </tr>\n <!-- <tr>\n <td>{{ 'LABEL_VENDOR_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorDetails?.vendor_name }}</td>\n </tr> -->\n <!-- @if(providerCode == \"SOCHIETEL\"){ -->\n @if( vendorCategory?.category_key == \"airtime_data\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name || \"-\" }}</td>\n </tr>\n }\n\n @if(vendorCategory?.category_key == \"road_tax\" || vendorCategory?.category_key == \"ROAD_TAX\"){\n @if (billData?.selectedBill?.meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.meta_data); track key) {\n <tr>\n <td>{{ removeunderScore(key) }}</td>\n <td class=\"text-right\">\n {{ \n (billData?.selectedBill?.meta_data[key] == 0 ? (0 | price: { currency }): billData?.selectedBill?.meta_data[key]) \n ?? \"-\"}}\n </td>\n </tr>\n }\n }\n }\n\n <!-- } -->\n <!-- <tr>\n <td>{{ 'COMMON_LABEL_DESCRIPTION' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_description || \"-\" }}</td>\n </tr> -->\n @if(mobileNumberInput){\n <tr>\n <td>{{ mobileNumberInput?.label || \"-\" }}</td>\n <td class=\"text-right\">{{ mobileNumberInput?.value || \"-\" }}</td>\n </tr>\n }\n @if(planData?.product_price_type == 1){\n <tr>\n <td>{{ 'LABEL_AMOUNT' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_fixed_price || 0.0 | price: { currency } }}</td>\n </tr>\n }@if(planData?.product_price_type == 2){\n <tr>\n <td>{{ 'LABEL_MINIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.min || 0.0 | price: { currency } }}</td>\n </tr>\n <tr>\n <td>{{ 'LABEL_MAXIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.max || 0.0 | price: { currency } }}</td>\n </tr>\n }\n @if(kwh){\n <tr>\n <td>{{ 'LABEL_KWH' | translate }}</td>\n <td class=\"text-right\">{{ kwh }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h5 class=\"border-bottom pb-3 mb-4 font-weight-600 mt-3 section-heading\">\n {{'Debited From'}}\n </h5>\n <div class=\"media d-user align-items-center\">\n <img loading=\"lazy\" [src]=\"companyDetail?.logo ? companyDetail?.logo : 'assets/avatars/profile.jpg'\"\n alt=\"\" class=\"h-50 w-50 rounded-circle mr-3\" />\n <div class=\"media-body\">\n <h5 class=\"mb-1 fontsize14 font-weight-600\">{{ walletData?.wallet_name }}\n </h5>\n <span class=\"text-muted\"> {{\"LABEL_AVAILABLE_BALANCE\" | translate}} :\n {{agentUserWallet?.wallet_balance | price : {currency} }}</span>\n </div>\n </div>\n\n <!-- <ng-container *ngIf=\"calculateCharges?.charges?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'COMMON_LABEL_CHARGES'\n |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngFor=\"let obj of calculateCharges?.charges\">\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n <!-- <ng-container *ngIf=\"workFlowUserInput?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'LABEL_USER_INPUT' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngIf=\"meterName?.customer_name\">\n <td>{{ 'LABEL_METER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ meterName?.customer_name }}</td>\n </tr>\n <tr *ngFor=\"let obj of workFlowUserInput\">\n <td>{{ obj?.label }}</td>\n <td class=\"text-right\">{{ obj?.value }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n @if (isPlanReview && planData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_PLAN_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n @if( vendorCategory?.category_key != \"airtime_credit\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name }}</td>\n </tr>\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n planData?.product_fixed_price || this.amount || 0.0| price: {\n currency } }}</td>\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || planData?.product_fixed_price || 0.0 |\n price: { currency }\n }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n }\n\n @if (isBillReview && billData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_BILL_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number }}\n </td>\n </tr> -->\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}\n </td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || 0.0 |\n price: { currency }\n }}\n </td>\n } -->\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n } -->\n </tr>\n @if (billData?.selectedBill?.bill_meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.bill_meta_data); track key) {\n <tr>\n <td class=\"font-weight-600\"> {{ removeunderScore(key) }}</td>\n <td class=\"font-weight-600 text-right\">\n {{ billData?.selectedBill?.bill_meta_data[key] || \"-\"}}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n\n <div class=\"col-xl-4\">\n <div\n class=\"card review-amount-card equal-height d-flex align-items-center justify-content-center m-0 shadow-none border\">\n <div class=\"card-body d-flex align-items-center py-4\">\n <div class=\"text-center\">\n @if (isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_BILL_AMOUNT' | translate }}\n </h6>\n @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n }\n @if (isPlanReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_PLAN_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || planData?.product_fixed_price || 0.0 | price: { currency } }} </h2>\n }\n @if (!isPlanReview && !isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'COMMON_LABEL_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{ amount || 0.0 | price:\n { currency } }} </h2>\n\n }\n \n\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-footer review-payment-footer text-right\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"cancel()\">{{ 'COMMON_LABEL_CANCEL' |\n translate }}</button>\n <button type=\"button\" class=\"btn btn-primary btn-sm\" [disabled]=\"showLoader\" (click)=\"enterTxnPin()\">{{\n 'COMMON_LABEL_SUBMIT' | translate }}</button>\n </div>\n </form>\n </div>\n </section>\n</div>\n\n<style>\n .review-payment-page .page-header h1 {\n font-size: 1.35rem;\n font-weight: 700;\n color: #1e3a5f;\n margin-bottom: 0.25rem;\n }\n\n .review-payment-section {\n padding-left: 0;\n padding-right: 0;\n }\n\n .review-payment-shell {\n border: 1px solid #dce3eb !important;\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n }\n\n .review-payment-body {\n padding: 1.1rem 1.2rem 0.8rem;\n }\n\n .review-payment-content {\n margin-top: 0.2rem;\n }\n\n .section-heading {\n color: #1e3a5f;\n font-size: 0.95rem;\n font-weight: 700;\n margin-bottom: 0.7rem !important;\n }\n\n .review-table table td {\n font-size: 0.8rem;\n color: #264563;\n padding: 0.5rem 0.25rem;\n vertical-align: middle;\n border-top-color: #edf1f5;\n }\n\n .review-amount-card {\n min-height: 100%;\n border: 1px solid #dce3eb !important;\n border-radius: 6px;\n background: #f6f8fa;\n }\n\n .amount-label {\n color: #7b8fa6 !important;\n font-weight: 600;\n letter-spacing: 0.01em;\n margin-bottom: 0.55rem !important;\n }\n\n .review-amount-card h2 {\n color: #1e3a5f;\n font-size: 2rem !important;\n font-weight: 700;\n }\n\n .review-payment-footer {\n border-top: 1px solid #e4e9ef;\n background: #fff;\n padding: 0.65rem 1rem;\n }\n\n .review-payment-footer .btn {\n min-width: 86px;\n margin-left: 0.45rem;\n }\n\n .txn-pin-modal-dialog {\n max-width: 420px;\n }\n\n .txn-pin-modal-content {\n border: 1px solid #e8edf3;\n border-radius: 12px;\n box-shadow: 0 0.5rem 1.5rem rgba(15, 34, 58, 0.12);\n overflow: hidden;\n }\n\n .txn-pin-modal-header {\n padding: 0.75rem 1rem;\n border-bottom: 1px solid #eef2f6;\n }\n\n .txn-pin-title {\n margin: 0;\n font-size: 1.05rem;\n font-weight: 700;\n color: #1f3f66;\n }\n\n .txn-pin-modal-body {\n padding: 0.9rem 1rem 0.75rem;\n }\n\n .txn-pin-subtitle {\n margin: 0 0 0.75rem;\n font-size: 0.8rem;\n color: #8d9fb2;\n }\n\n .txn-pin-modal-footer {\n border-top: 1px solid #eef2f6;\n padding: 0.55rem 0.85rem;\n gap: 0.5rem;\n justify-content: flex-end;\n }\n\n .txn-pin-close-btn,\n .txn-pin-submit-btn {\n min-width: 74px;\n padding: 0.22rem 0.85rem;\n font-size: 0.75rem;\n border-radius: 4px;\n }\n\n .txn-pin-forgot-btn {\n margin-right: auto;\n font-size: 0.76rem;\n color: #0d6efd;\n text-decoration: none;\n }\n</style>\n\n@if (showLoader) {\n<sdk-common-loader message=\"{{ 'LABEL_PLEASE_WAIT' | translate }}...\"></sdk-common-loader>\n}\n<div id=\"OTPVerification\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"OTPVerificationLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog\" role=\"document\">\n <form [formGroup]=\"otpForm\" (ngSubmit)=\"submitOTPForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\"> {{'LABEL_OTP_VERIFICATION' |translate}} </h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{'LABEL_ENTER_4_DIGIT_NUMBER_SENT_TO'|translate}}\n <span class=\"font-weight-600 ml-1 text-dark\">{{ currentUserDetails?.dial_code + \" \" +\n currentUserDetails?.phone_number }}</span>\n </p>\n <label for=\"inputOTP\" class=\"sr-only\">{{'LABEL_OTP' |translate}}</label>\n <sdk-otp-input (inputChange)=\"onOtpChange($event)\" [length]=\"pinLength\"\n [isPassword]=\"true\"> </sdk-otp-input>\n @if (formErrors.otp) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.otp\"></span>\n }\n\n @if (otpResendTime > 0) {\n @if (timer === 0) {\n <button type=\"button\" class=\"p-2 mt-1 btn-link\" (click)=\"sendOTPToAgent()\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n </button>\n } @else {\n <p class=\"p-2 mt-1 text-muted\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n <span class=\"font-weight-600\">{{ getTimerString(timer) }}</span>\n </p>\n }\n }\n </div>\n <button type=\"submit\" class=\"btn btn-primary btn-block btn-lg mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{'COMMON_LABEL_CONFIRM'\n |translate}}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n\n<!-- Transaction PIN Modal -->\n<div id=\"TransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"TransactionPINLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog txn-pin-modal-dialog\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content txn-pin-modal-content\">\n <div class=\"modal-header txn-pin-modal-header\">\n <h3 class=\"modal-title txn-pin-title\">Transaction Pin</h3>\n </div>\n <div class=\"modal-body txn-pin-modal-body\">\n <div class=\"form-group mb-0\">\n <p class=\"txn-pin-subtitle\">Enter your transaction Pin to proceed</p>\n <label for=\"inputOTP\" class=\"sr-only\">{{'LABEL_PIN' |translate}}</label>\n @if (otpReset) {\n <sdk-otp-input\n class=\"txn-pin-input\"\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.pin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.pin\"></span>\n }\n </div>\n </div>\n <div class=\"modal-footer txn-pin-modal-footer\">\n <!-- @if (inValidTxnPin) {\n <button type=\"button\" class=\"btn btn-link txn-pin-forgot-btn px-0\" (click)=\"forgotTxnPin()\">\n {{ 'LABEL_FORGOT_TXN_PIN' | translate }}\n </button>\n } -->\n <button type=\"button\" class=\"btn btn-light btn-sm txn-pin-close-btn\" (click)=\"closeTransactionPinModal()\">\n Close\n </button>\n <button type=\"submit\" class=\"btn btn-primary btn-sm txn-pin-submit-btn\" [disabled]=\"showLoader\">\n Submit\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n<!-- Confirm Transaction PIN Modal -->\n<div id=\"ConfirmTransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"ConfirmTransactionPINLabel\"\n data-backdrop=\"static\" data-keyboard=\"false\">\n <div class=\"modal-dialog modal-md\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitConfirmPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">{{ 'LABEL_CONFIRM_TRANSACTION_PIN' | translate }}</h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{ 'LABEL_REENTER_4_DIGIT_TRANSACTION_PIN' | translate }}</p>\n @if (otpConfirm) {\n <sdk-otp-input\n #otpInputComp\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.confirmPin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.confirmPin\"></span>\n }\n </div>\n <!-- <p\n class=\"card bg-light text-center p-2 flex-row justify-content-center flex-wrap rounded mt-4 mb-3\">\n {{'LABEL_YOU_ARE_SENDING_MONEY_TO' |translate}} <span class=\"font-weight-600 ml-2\"> {{\n senderReceiverStore?.receiver?.first_name + \" \" +\n senderReceiverStore?.receiver?.last_name }}</span></p> -->\n <button type=\"submit\" class=\"btn btn-primary btn-block btn-lg mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_CONFIRM' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>", styles: [".review-payment-page .page-header h1{font-size:1.35rem;font-weight:700;color:#1e3a5f;margin-bottom:.25rem}.review-payment-section{padding-left:0;padding-right:0}.review-payment-shell{border:1px solid #dce3eb!important;border-radius:8px;background:#fff;overflow:hidden}.review-payment-body{padding:1.1rem 1.2rem .8rem}.review-payment-content{margin-top:.2rem}.section-heading{color:#1e3a5f;font-size:.95rem;font-weight:700;margin-bottom:.7rem!important}.review-table table td{font-size:.8rem;color:#264563;padding:.5rem .25rem;vertical-align:middle;border-top-color:#edf1f5}.review-amount-card{min-height:100%;border:1px solid #dce3eb!important;border-radius:6px;background:#f6f8fa}.amount-label{color:#7b8fa6!important;font-weight:600;letter-spacing:.01em;margin-bottom:.55rem!important}.review-amount-card h2{color:#1e3a5f;font-size:2rem!important;font-weight:700}.review-payment-footer{border-top:1px solid #e4e9ef;background:#fff;padding:.65rem 1rem}.review-payment-footer .btn{min-width:86px;margin-left:.45rem}.txn-pin-modal-dialog{max-width:420px}.txn-pin-modal-content{border:1px solid #e8edf3;border-radius:12px;box-shadow:0 .5rem 1.5rem #0f223a1f;overflow:hidden}.txn-pin-modal-header{padding:.75rem 1rem;border-bottom:1px solid #eef2f6}.txn-pin-title{margin:0;font-size:1.05rem;font-weight:700;color:#1f3f66}.txn-pin-modal-body{padding:.9rem 1rem .75rem}.txn-pin-subtitle{margin:0 0 .75rem;font-size:.8rem;color:#8d9fb2}.txn-pin-modal-footer{border-top:1px solid #eef2f6;padding:.55rem .85rem;gap:.5rem;justify-content:flex-end}.txn-pin-close-btn,.txn-pin-submit-btn{min-width:74px;padding:.22rem .85rem;font-size:.75rem;border-radius:4px}.txn-pin-forgot-btn{margin-right:auto;font-size:.76rem;color:#0d6efd;text-decoration:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: NgSelectModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormlyBootstrapModule }, { kind: "ngmodule", type: FormlyModule }, { kind: "ngmodule", type: UtilityPaymentsUiModule }, { kind: "component", type: OtpInputComponent, selector: "sdk-otp-input", inputs: ["length", "placeholder", "isPassword", "segmented", "autoFocus"], outputs: ["inputChange", "otpChange"] }, { kind: "component", type: CommonLoaderComponent, selector: "sdk-common-loader", inputs: ["message"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: PricePipe, name: "price" }] });
5983
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: TopupAndBillpaymentReviewComponent, isStandalone: true, selector: "sdk-topup-and-billpayment-review", viewQueries: [{ propertyName: "txnSummaryComp", first: true, predicate: TransactionSummaryComponent, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"content review-payment-page\">\n <header class=\"page-header\">\n <div class=\"d-flex align-items-center flex-wrap\">\n <div class=\"mr-auto\">\n <h1>{{ 'LABEL_REVIEW_PAYMENT' | translate }}</h1>\n </div>\n </div>\n </header>\n\n <section class=\"page-content container-fluid review-payment-section\">\n <div class=\"card m-0 border-0 review-payment-shell\">\n <form role=\"form\">\n <div class=\"card-body review-payment-body\">\n <div class=\"review-payment-content\">\n <div class=\"row g-3\">\n <div class=\"col-xl-8\">\n <h5 class=\"border-bottom pb-3 font-weight-600 section-heading\"> {{ 'LABEL_PAYMENT_SUMMARY' | translate\n }} </h5>\n <div class=\"border-bottom table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_CATEGORY_TYPE' | translate }}</td>\n <td class=\"text-right\">{{\n providerCategoryTypes[vendorCategory?.category_type] || \"-\" |\n translate}}</td>\n </tr> -->\n @if(providerCode != \"SOCHIETEL\"){\n <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n @if (providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number || \"-\" }}</td>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_code || \"-\" }}</td>\n }\n </tr>\n }\n <tr>\n <td>{{ 'LABEL_PROVIDER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorProvider?.provider_name || \"-\" }}</td>\n </tr>\n <!-- <tr>\n <td>{{ 'LABEL_VENDOR_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorDetails?.vendor_name }}</td>\n </tr> -->\n <!-- @if(providerCode == \"SOCHIETEL\"){ -->\n @if( vendorCategory?.category_key == \"airtime_data\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name || \"-\" }}</td>\n </tr>\n }\n\n @if(vendorCategory?.category_key == \"road_tax\" || vendorCategory?.category_key == \"ROAD_TAX\"){\n @if (billData?.selectedBill?.meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.meta_data); track key) {\n <tr>\n <td>{{ removeunderScore(key) }}</td>\n <td class=\"text-right\">\n {{ \n (billData?.selectedBill?.meta_data[key] == 0 ? (0 | price: { currency }): billData?.selectedBill?.meta_data[key]) \n ?? \"-\"}}\n </td>\n </tr>\n }\n }\n }\n\n <!-- } -->\n <!-- <tr>\n <td>{{ 'COMMON_LABEL_DESCRIPTION' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_description || \"-\" }}</td>\n </tr> -->\n @if(mobileNumberInput){\n <tr>\n <td>{{ mobileNumberInput?.label || \"-\" }}</td>\n <td class=\"text-right\">{{ mobileNumberInput?.value || \"-\" }}</td>\n </tr>\n }\n @if(planData?.product_price_type == 1){\n <tr>\n <td>{{ 'LABEL_AMOUNT' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_fixed_price || 0.0 | price: { currency } }}</td>\n </tr>\n }@if(planData?.product_price_type == 2){\n <tr>\n <td>{{ 'LABEL_MINIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.min || 0.0 | price: { currency } }}</td>\n </tr>\n <tr>\n <td>{{ 'LABEL_MAXIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.max || 0.0 | price: { currency } }}</td>\n </tr>\n }\n @if(kwh){\n <tr>\n <td>{{ 'LABEL_KWH' | translate }}</td>\n <td class=\"text-right\">{{ kwh }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h5 class=\"border-bottom pb-3 mb-4 font-weight-600 mt-3 section-heading\">\n {{ 'LABEL_DEBITED_FROM' | translate }}\n </h5>\n <div class=\"media d-user align-items-center\">\n <img loading=\"lazy\" [src]=\"companyDetail?.logo ? companyDetail?.logo : 'assets/avatars/profile.jpg'\"\n alt=\"\" class=\"h-50 w-50 rounded-circle mr-3\" />\n <div class=\"media-body\">\n <h5 class=\"mb-1 fontsize14 font-weight-600\">{{ walletData?.wallet_name }}\n </h5>\n <span class=\"text-muted\"> {{\"LABEL_AVAILABLE_BALANCE\" | translate}} :\n {{agentUserWallet?.wallet_balance | price : {currency} }}</span>\n </div>\n </div>\n\n <!-- <ng-container *ngIf=\"calculateCharges?.charges?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'COMMON_LABEL_CHARGES'\n |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngFor=\"let obj of calculateCharges?.charges\">\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n <!-- <ng-container *ngIf=\"workFlowUserInput?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'LABEL_USER_INPUT' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngIf=\"meterName?.customer_name\">\n <td>{{ 'LABEL_METER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ meterName?.customer_name }}</td>\n </tr>\n <tr *ngFor=\"let obj of workFlowUserInput\">\n <td>{{ obj?.label }}</td>\n <td class=\"text-right\">{{ obj?.value }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n @if (isPlanReview && planData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_PLAN_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n @if( vendorCategory?.category_key != \"airtime_credit\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name }}</td>\n </tr>\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n planData?.product_fixed_price || this.amount || 0.0| price: {\n currency } }}</td>\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || planData?.product_fixed_price || 0.0 |\n price: { currency }\n }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n }\n\n @if (isBillReview && billData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_BILL_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number }}\n </td>\n </tr> -->\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}\n </td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || 0.0 |\n price: { currency }\n }}\n </td>\n } -->\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n } -->\n </tr>\n @if (billData?.selectedBill?.bill_meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.bill_meta_data); track key) {\n <tr>\n <td class=\"font-weight-600\"> {{ removeunderScore(key) }}</td>\n <td class=\"font-weight-600 text-right\">\n {{ billData?.selectedBill?.bill_meta_data[key] || \"-\"}}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n\n <div class=\"col-xl-4\">\n <div\n class=\"card review-amount-card equal-height d-flex align-items-center justify-content-center m-0 shadow-none border\">\n <div class=\"card-body d-flex align-items-center py-4\">\n <div class=\"text-center\">\n @if (isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_BILL_AMOUNT' | translate }}\n </h6>\n @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n }\n @if (isPlanReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_PLAN_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || planData?.product_fixed_price || 0.0 | price: { currency } }} </h2>\n }\n @if (!isPlanReview && !isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'COMMON_LABEL_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{ amount || 0.0 | price:\n { currency } }} </h2>\n\n }\n \n\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-footer review-payment-footer text-right\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"cancel()\">{{ 'COMMON_LABEL_CANCEL' |\n translate }}</button>\n <button type=\"button\" class=\"btn btn-primary btn-sm\" [disabled]=\"showLoader\" (click)=\"enterTxnPin()\">{{\n 'COMMON_LABEL_SUBMIT' | translate }}</button>\n </div>\n </form>\n </div>\n </section>\n</div>\n\n<style>\n .review-payment-page .page-header h1 {\n font-size: 1.35rem;\n font-weight: 700;\n color: #1e3a5f;\n margin-bottom: 0.25rem;\n }\n\n .review-payment-section {\n padding-left: 0;\n padding-right: 0;\n }\n\n .review-payment-shell {\n border: 1px solid #dce3eb !important;\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n }\n\n .review-payment-body {\n padding: 1.1rem 1.2rem 0.8rem;\n }\n\n .review-payment-content {\n margin-top: 0.2rem;\n }\n\n .section-heading {\n color: #1e3a5f;\n font-size: 0.95rem;\n font-weight: 700;\n margin-bottom: 0.7rem !important;\n }\n\n .review-table table td {\n font-size: 0.8rem;\n color: #264563;\n padding: 0.5rem 0.25rem;\n vertical-align: middle;\n border-top-color: #edf1f5;\n }\n\n .review-amount-card {\n min-height: 100%;\n border: 1px solid #dce3eb !important;\n border-radius: 6px;\n background: #f6f8fa;\n }\n\n .amount-label {\n color: #7b8fa6 !important;\n font-weight: 600;\n letter-spacing: 0.01em;\n margin-bottom: 0.55rem !important;\n }\n\n .review-amount-card h2 {\n color: #1e3a5f;\n font-size: 2rem !important;\n font-weight: 700;\n }\n\n .review-payment-footer {\n border-top: 1px solid #e4e9ef;\n background: #fff;\n padding: 0.65rem 1rem;\n }\n\n .review-payment-footer .btn {\n min-width: 86px;\n margin-left: 0.45rem;\n }\n\n .txn-pin-modal-dialog {\n max-width: 420px;\n }\n\n .txn-pin-modal-content {\n border: 1px solid #e8edf3;\n border-radius: 12px;\n box-shadow: 0 0.5rem 1.5rem rgba(15, 34, 58, 0.12);\n overflow: hidden;\n }\n\n .txn-pin-modal-header {\n padding: 0.75rem 1rem;\n border-bottom: 1px solid #eef2f6;\n }\n\n .txn-pin-title {\n margin: 0;\n font-size: 1.05rem;\n font-weight: 700;\n color: #1f3f66;\n }\n\n .txn-pin-modal-body {\n padding: 0.9rem 1rem 0.75rem;\n }\n\n .txn-pin-subtitle {\n margin: 0 0 0.75rem;\n font-size: 0.8rem;\n color: #8d9fb2;\n }\n\n .txn-pin-modal-footer {\n border-top: 1px solid #eef2f6;\n padding: 0.55rem 0.85rem;\n gap: 0.5rem;\n justify-content: flex-end;\n }\n\n .txn-pin-close-btn,\n .txn-pin-submit-btn {\n min-width: 74px;\n padding: 0.22rem 0.85rem;\n font-size: 0.75rem;\n border-radius: 4px;\n }\n\n .txn-pin-forgot-btn {\n margin-right: auto;\n font-size: 0.76rem;\n color: #0d6efd;\n text-decoration: none;\n }\n</style>\n\n@if (showLoader) {\n<sdk-common-loader message=\"{{ 'LABEL_PLEASE_WAIT' | translate }}...\"></sdk-common-loader>\n}\n<div id=\"OTPVerification\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"OTPVerificationLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog\" role=\"document\">\n <form [formGroup]=\"otpForm\" (ngSubmit)=\"submitOTPForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">{{ 'LABEL_OTP_VERIFICATION' | translate }}</h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{ 'LABEL_ENTER_4_DIGIT_NUMBER_SENT_TO' | translate }}\n <span class=\"font-weight-600 ml-1 text-dark\">{{ currentUserDetails?.dial_code + \" \" +\n currentUserDetails?.phone_number }}</span>\n </p>\n <label for=\"inputOTP\" class=\"sr-only\">{{ 'LABEL_OTP' | translate }}</label>\n <sdk-otp-input (inputChange)=\"onOtpChange($event)\" [length]=\"pinLength\"\n [isPassword]=\"true\"> </sdk-otp-input>\n @if (formErrors.otp) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.otp\"></span>\n }\n\n @if (otpResendTime > 0) {\n @if (timer === 0) {\n <button type=\"button\" class=\"p-2 mt-1 btn-link\" (click)=\"sendOTPToAgent()\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n </button>\n } @else {\n <p class=\"p-2 mt-1 text-muted\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n <span class=\"font-weight-600\">{{ getTimerString(timer) }}</span>\n </p>\n }\n }\n </div>\n <button type=\"submit\" class=\"btn btn-primary btn-block mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_CONFIRM' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n\n<!-- Transaction PIN Modal -->\n<div id=\"TransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"TransactionPINLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog txn-pin-modal-dialog\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content txn-pin-modal-content\">\n <div class=\"modal-header txn-pin-modal-header\">\n <h3 class=\"modal-title txn-pin-title\">{{ 'LABEL_TRANSACTION_PIN' | translate }}</h3>\n </div>\n <div class=\"modal-body txn-pin-modal-body\">\n <div class=\"form-group mb-0\">\n <p class=\"txn-pin-subtitle\">{{ 'LABEL_ENTER_4_DIGIT_TRANSACTION_PIN' | translate }}</p>\n <label for=\"inputOTP\" class=\"sr-only\">{{ 'LABEL_PIN' | translate }}</label>\n @if (otpReset) {\n <sdk-otp-input\n class=\"txn-pin-input\"\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.pin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.pin\"></span>\n }\n </div>\n </div>\n <div class=\"modal-footer txn-pin-modal-footer\">\n <!-- @if (inValidTxnPin) {\n <button type=\"button\" class=\"btn btn-link txn-pin-forgot-btn px-0\" (click)=\"forgotTxnPin()\">\n {{ 'LABEL_FORGOT_TXN_PIN' | translate }}\n </button>\n } -->\n <button type=\"button\" class=\"btn btn-light btn-sm txn-pin-close-btn\" (click)=\"closeTransactionPinModal()\">\n {{ 'COMMON_LABEL_CLOSE' | translate }}\n </button>\n <button type=\"submit\" class=\"btn btn-primary btn-sm txn-pin-submit-btn\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_SUBMIT' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n<!-- Confirm Transaction PIN Modal -->\n<div id=\"ConfirmTransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"ConfirmTransactionPINLabel\"\n data-backdrop=\"static\" data-keyboard=\"false\">\n <div class=\"modal-dialog modal-md\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitConfirmPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">{{ 'LABEL_CONFIRM_TRANSACTION_PIN' | translate }}</h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{ 'LABEL_REENTER_4_DIGIT_TRANSACTION_PIN' | translate }}</p>\n @if (otpConfirm) {\n <sdk-otp-input\n #otpInputComp\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.confirmPin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.confirmPin\"></span>\n }\n </div>\n <!-- <p\n class=\"card bg-light text-center p-2 flex-row justify-content-center flex-wrap rounded mt-4 mb-3\">\n {{'LABEL_YOU_ARE_SENDING_MONEY_TO' |translate}} <span class=\"font-weight-600 ml-2\"> {{\n senderReceiverStore?.receiver?.first_name + \" \" +\n senderReceiverStore?.receiver?.last_name }}</span></p> -->\n <button type=\"submit\" class=\"btn btn-primary btn-block btn-lg mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_CONFIRM' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>", styles: [".review-payment-page .page-header h1{font-size:1.35rem;font-weight:700;color:#1e3a5f;margin-bottom:.25rem}.review-payment-section{padding-left:0;padding-right:0}.review-payment-shell{border:1px solid #dce3eb!important;border-radius:8px;background:#fff;overflow:hidden}.review-payment-body{padding:1.1rem 1.2rem .8rem}.review-payment-content{margin-top:.2rem}.section-heading{color:#1e3a5f;font-size:.95rem;font-weight:700;margin-bottom:.7rem!important}.review-table table td{font-size:.8rem;color:#264563;padding:.5rem .25rem;vertical-align:middle;border-top-color:#edf1f5}.review-amount-card{min-height:100%;border:1px solid #dce3eb!important;border-radius:6px;background:#f6f8fa}.amount-label{color:#7b8fa6!important;font-weight:600;letter-spacing:.01em;margin-bottom:.55rem!important}.review-amount-card h2{color:#1e3a5f;font-size:2rem!important;font-weight:700}.review-payment-footer{border-top:1px solid #e4e9ef;background:#fff;padding:.65rem 1rem}.review-payment-footer .btn{min-width:86px;margin-left:.45rem}.txn-pin-modal-dialog{max-width:420px}.txn-pin-modal-content{border:1px solid #e8edf3;border-radius:12px;box-shadow:0 .5rem 1.5rem #0f223a1f;overflow:hidden}.txn-pin-modal-header{padding:.75rem 1rem;border-bottom:1px solid #eef2f6}.txn-pin-title{margin:0;font-size:1.05rem;font-weight:700;color:#1f3f66}.txn-pin-modal-body{padding:.9rem 1rem .75rem}.txn-pin-subtitle{margin:0 0 .75rem;font-size:.8rem;color:#8d9fb2}.txn-pin-modal-footer{border-top:1px solid #eef2f6;padding:.55rem .85rem;gap:.5rem;justify-content:flex-end}.txn-pin-close-btn,.txn-pin-submit-btn{min-width:74px;padding:.22rem .85rem;font-size:.75rem;border-radius:4px}.txn-pin-forgot-btn{margin-right:auto;font-size:.76rem;color:#0d6efd;text-decoration:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: SharedModule }, { kind: "ngmodule", type: NgSelectModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormlyBootstrapModule }, { kind: "ngmodule", type: FormlyModule }, { kind: "ngmodule", type: UtilityPaymentsUiModule }, { kind: "component", type: OtpInputComponent, selector: "sdk-otp-input", inputs: ["length", "placeholder", "isPassword", "segmented", "autoFocus"], outputs: ["inputChange", "otpChange"] }, { kind: "component", type: CommonLoaderComponent, selector: "sdk-common-loader", inputs: ["message"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "pipe", type: PricePipe, name: "price" }] });
5750
5984
  }
5751
5985
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TopupAndBillpaymentReviewComponent, decorators: [{
5752
5986
  type: Component,
@@ -5759,7 +5993,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
5759
5993
  FormlyBootstrapModule,
5760
5994
  FormlyModule,
5761
5995
  UtilityPaymentsUiModule
5762
- ], template: "<div class=\"content review-payment-page\">\n <header class=\"page-header\">\n <div class=\"d-flex align-items-center flex-wrap\">\n <div class=\"mr-auto\">\n <h1>{{ 'LABEL_REVIEW_PAYMENT' | translate }}</h1>\n </div>\n </div>\n </header>\n\n <section class=\"page-content container-fluid review-payment-section\">\n <div class=\"card m-0 border-0 review-payment-shell\">\n <form role=\"form\">\n <div class=\"card-body review-payment-body\">\n <div class=\"review-payment-content\">\n <div class=\"row g-3\">\n <div class=\"col-xl-8\">\n <h5 class=\"border-bottom pb-3 font-weight-600 section-heading\"> {{ 'LABEL_PAYMENT_SUMMARY' | translate\n }} </h5>\n <div class=\"border-bottom table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_CATEGORY_TYPE' | translate }}</td>\n <td class=\"text-right\">{{\n providerCategoryTypes[vendorCategory?.category_type] || \"-\" |\n translate}}</td>\n </tr> -->\n @if(providerCode != \"SOCHIETEL\"){\n <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n @if (providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number || \"-\" }}</td>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_code || \"-\" }}</td>\n }\n </tr>\n }\n <tr>\n <td>{{ 'LABEL_PROVIDER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorProvider?.provider_name || \"-\" }}</td>\n </tr>\n <!-- <tr>\n <td>{{ 'LABEL_VENDOR_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorDetails?.vendor_name }}</td>\n </tr> -->\n <!-- @if(providerCode == \"SOCHIETEL\"){ -->\n @if( vendorCategory?.category_key == \"airtime_data\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name || \"-\" }}</td>\n </tr>\n }\n\n @if(vendorCategory?.category_key == \"road_tax\" || vendorCategory?.category_key == \"ROAD_TAX\"){\n @if (billData?.selectedBill?.meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.meta_data); track key) {\n <tr>\n <td>{{ removeunderScore(key) }}</td>\n <td class=\"text-right\">\n {{ \n (billData?.selectedBill?.meta_data[key] == 0 ? (0 | price: { currency }): billData?.selectedBill?.meta_data[key]) \n ?? \"-\"}}\n </td>\n </tr>\n }\n }\n }\n\n <!-- } -->\n <!-- <tr>\n <td>{{ 'COMMON_LABEL_DESCRIPTION' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_description || \"-\" }}</td>\n </tr> -->\n @if(mobileNumberInput){\n <tr>\n <td>{{ mobileNumberInput?.label || \"-\" }}</td>\n <td class=\"text-right\">{{ mobileNumberInput?.value || \"-\" }}</td>\n </tr>\n }\n @if(planData?.product_price_type == 1){\n <tr>\n <td>{{ 'LABEL_AMOUNT' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_fixed_price || 0.0 | price: { currency } }}</td>\n </tr>\n }@if(planData?.product_price_type == 2){\n <tr>\n <td>{{ 'LABEL_MINIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.min || 0.0 | price: { currency } }}</td>\n </tr>\n <tr>\n <td>{{ 'LABEL_MAXIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.max || 0.0 | price: { currency } }}</td>\n </tr>\n }\n @if(kwh){\n <tr>\n <td>{{ 'LABEL_KWH' | translate }}</td>\n <td class=\"text-right\">{{ kwh }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h5 class=\"border-bottom pb-3 mb-4 font-weight-600 mt-3 section-heading\">\n {{'Debited From'}}\n </h5>\n <div class=\"media d-user align-items-center\">\n <img loading=\"lazy\" [src]=\"companyDetail?.logo ? companyDetail?.logo : 'assets/avatars/profile.jpg'\"\n alt=\"\" class=\"h-50 w-50 rounded-circle mr-3\" />\n <div class=\"media-body\">\n <h5 class=\"mb-1 fontsize14 font-weight-600\">{{ walletData?.wallet_name }}\n </h5>\n <span class=\"text-muted\"> {{\"LABEL_AVAILABLE_BALANCE\" | translate}} :\n {{agentUserWallet?.wallet_balance | price : {currency} }}</span>\n </div>\n </div>\n\n <!-- <ng-container *ngIf=\"calculateCharges?.charges?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'COMMON_LABEL_CHARGES'\n |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngFor=\"let obj of calculateCharges?.charges\">\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n <!-- <ng-container *ngIf=\"workFlowUserInput?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'LABEL_USER_INPUT' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngIf=\"meterName?.customer_name\">\n <td>{{ 'LABEL_METER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ meterName?.customer_name }}</td>\n </tr>\n <tr *ngFor=\"let obj of workFlowUserInput\">\n <td>{{ obj?.label }}</td>\n <td class=\"text-right\">{{ obj?.value }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n @if (isPlanReview && planData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_PLAN_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n @if( vendorCategory?.category_key != \"airtime_credit\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name }}</td>\n </tr>\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n planData?.product_fixed_price || this.amount || 0.0| price: {\n currency } }}</td>\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || planData?.product_fixed_price || 0.0 |\n price: { currency }\n }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n }\n\n @if (isBillReview && billData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_BILL_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number }}\n </td>\n </tr> -->\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}\n </td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || 0.0 |\n price: { currency }\n }}\n </td>\n } -->\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n } -->\n </tr>\n @if (billData?.selectedBill?.bill_meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.bill_meta_data); track key) {\n <tr>\n <td class=\"font-weight-600\"> {{ removeunderScore(key) }}</td>\n <td class=\"font-weight-600 text-right\">\n {{ billData?.selectedBill?.bill_meta_data[key] || \"-\"}}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n\n <div class=\"col-xl-4\">\n <div\n class=\"card review-amount-card equal-height d-flex align-items-center justify-content-center m-0 shadow-none border\">\n <div class=\"card-body d-flex align-items-center py-4\">\n <div class=\"text-center\">\n @if (isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_BILL_AMOUNT' | translate }}\n </h6>\n @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n }\n @if (isPlanReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_PLAN_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || planData?.product_fixed_price || 0.0 | price: { currency } }} </h2>\n }\n @if (!isPlanReview && !isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'COMMON_LABEL_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{ amount || 0.0 | price:\n { currency } }} </h2>\n\n }\n \n\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-footer review-payment-footer text-right\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"cancel()\">{{ 'COMMON_LABEL_CANCEL' |\n translate }}</button>\n <button type=\"button\" class=\"btn btn-primary btn-sm\" [disabled]=\"showLoader\" (click)=\"enterTxnPin()\">{{\n 'COMMON_LABEL_SUBMIT' | translate }}</button>\n </div>\n </form>\n </div>\n </section>\n</div>\n\n<style>\n .review-payment-page .page-header h1 {\n font-size: 1.35rem;\n font-weight: 700;\n color: #1e3a5f;\n margin-bottom: 0.25rem;\n }\n\n .review-payment-section {\n padding-left: 0;\n padding-right: 0;\n }\n\n .review-payment-shell {\n border: 1px solid #dce3eb !important;\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n }\n\n .review-payment-body {\n padding: 1.1rem 1.2rem 0.8rem;\n }\n\n .review-payment-content {\n margin-top: 0.2rem;\n }\n\n .section-heading {\n color: #1e3a5f;\n font-size: 0.95rem;\n font-weight: 700;\n margin-bottom: 0.7rem !important;\n }\n\n .review-table table td {\n font-size: 0.8rem;\n color: #264563;\n padding: 0.5rem 0.25rem;\n vertical-align: middle;\n border-top-color: #edf1f5;\n }\n\n .review-amount-card {\n min-height: 100%;\n border: 1px solid #dce3eb !important;\n border-radius: 6px;\n background: #f6f8fa;\n }\n\n .amount-label {\n color: #7b8fa6 !important;\n font-weight: 600;\n letter-spacing: 0.01em;\n margin-bottom: 0.55rem !important;\n }\n\n .review-amount-card h2 {\n color: #1e3a5f;\n font-size: 2rem !important;\n font-weight: 700;\n }\n\n .review-payment-footer {\n border-top: 1px solid #e4e9ef;\n background: #fff;\n padding: 0.65rem 1rem;\n }\n\n .review-payment-footer .btn {\n min-width: 86px;\n margin-left: 0.45rem;\n }\n\n .txn-pin-modal-dialog {\n max-width: 420px;\n }\n\n .txn-pin-modal-content {\n border: 1px solid #e8edf3;\n border-radius: 12px;\n box-shadow: 0 0.5rem 1.5rem rgba(15, 34, 58, 0.12);\n overflow: hidden;\n }\n\n .txn-pin-modal-header {\n padding: 0.75rem 1rem;\n border-bottom: 1px solid #eef2f6;\n }\n\n .txn-pin-title {\n margin: 0;\n font-size: 1.05rem;\n font-weight: 700;\n color: #1f3f66;\n }\n\n .txn-pin-modal-body {\n padding: 0.9rem 1rem 0.75rem;\n }\n\n .txn-pin-subtitle {\n margin: 0 0 0.75rem;\n font-size: 0.8rem;\n color: #8d9fb2;\n }\n\n .txn-pin-modal-footer {\n border-top: 1px solid #eef2f6;\n padding: 0.55rem 0.85rem;\n gap: 0.5rem;\n justify-content: flex-end;\n }\n\n .txn-pin-close-btn,\n .txn-pin-submit-btn {\n min-width: 74px;\n padding: 0.22rem 0.85rem;\n font-size: 0.75rem;\n border-radius: 4px;\n }\n\n .txn-pin-forgot-btn {\n margin-right: auto;\n font-size: 0.76rem;\n color: #0d6efd;\n text-decoration: none;\n }\n</style>\n\n@if (showLoader) {\n<sdk-common-loader message=\"{{ 'LABEL_PLEASE_WAIT' | translate }}...\"></sdk-common-loader>\n}\n<div id=\"OTPVerification\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"OTPVerificationLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog\" role=\"document\">\n <form [formGroup]=\"otpForm\" (ngSubmit)=\"submitOTPForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\"> {{'LABEL_OTP_VERIFICATION' |translate}} </h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{'LABEL_ENTER_4_DIGIT_NUMBER_SENT_TO'|translate}}\n <span class=\"font-weight-600 ml-1 text-dark\">{{ currentUserDetails?.dial_code + \" \" +\n currentUserDetails?.phone_number }}</span>\n </p>\n <label for=\"inputOTP\" class=\"sr-only\">{{'LABEL_OTP' |translate}}</label>\n <sdk-otp-input (inputChange)=\"onOtpChange($event)\" [length]=\"pinLength\"\n [isPassword]=\"true\"> </sdk-otp-input>\n @if (formErrors.otp) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.otp\"></span>\n }\n\n @if (otpResendTime > 0) {\n @if (timer === 0) {\n <button type=\"button\" class=\"p-2 mt-1 btn-link\" (click)=\"sendOTPToAgent()\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n </button>\n } @else {\n <p class=\"p-2 mt-1 text-muted\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n <span class=\"font-weight-600\">{{ getTimerString(timer) }}</span>\n </p>\n }\n }\n </div>\n <button type=\"submit\" class=\"btn btn-primary btn-block btn-lg mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{'COMMON_LABEL_CONFIRM'\n |translate}}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n\n<!-- Transaction PIN Modal -->\n<div id=\"TransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"TransactionPINLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog txn-pin-modal-dialog\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content txn-pin-modal-content\">\n <div class=\"modal-header txn-pin-modal-header\">\n <h3 class=\"modal-title txn-pin-title\">Transaction Pin</h3>\n </div>\n <div class=\"modal-body txn-pin-modal-body\">\n <div class=\"form-group mb-0\">\n <p class=\"txn-pin-subtitle\">Enter your transaction Pin to proceed</p>\n <label for=\"inputOTP\" class=\"sr-only\">{{'LABEL_PIN' |translate}}</label>\n @if (otpReset) {\n <sdk-otp-input\n class=\"txn-pin-input\"\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.pin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.pin\"></span>\n }\n </div>\n </div>\n <div class=\"modal-footer txn-pin-modal-footer\">\n <!-- @if (inValidTxnPin) {\n <button type=\"button\" class=\"btn btn-link txn-pin-forgot-btn px-0\" (click)=\"forgotTxnPin()\">\n {{ 'LABEL_FORGOT_TXN_PIN' | translate }}\n </button>\n } -->\n <button type=\"button\" class=\"btn btn-light btn-sm txn-pin-close-btn\" (click)=\"closeTransactionPinModal()\">\n Close\n </button>\n <button type=\"submit\" class=\"btn btn-primary btn-sm txn-pin-submit-btn\" [disabled]=\"showLoader\">\n Submit\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n<!-- Confirm Transaction PIN Modal -->\n<div id=\"ConfirmTransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"ConfirmTransactionPINLabel\"\n data-backdrop=\"static\" data-keyboard=\"false\">\n <div class=\"modal-dialog modal-md\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitConfirmPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">{{ 'LABEL_CONFIRM_TRANSACTION_PIN' | translate }}</h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{ 'LABEL_REENTER_4_DIGIT_TRANSACTION_PIN' | translate }}</p>\n @if (otpConfirm) {\n <sdk-otp-input\n #otpInputComp\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.confirmPin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.confirmPin\"></span>\n }\n </div>\n <!-- <p\n class=\"card bg-light text-center p-2 flex-row justify-content-center flex-wrap rounded mt-4 mb-3\">\n {{'LABEL_YOU_ARE_SENDING_MONEY_TO' |translate}} <span class=\"font-weight-600 ml-2\"> {{\n senderReceiverStore?.receiver?.first_name + \" \" +\n senderReceiverStore?.receiver?.last_name }}</span></p> -->\n <button type=\"submit\" class=\"btn btn-primary btn-block btn-lg mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_CONFIRM' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>" }]
5996
+ ], template: "<div class=\"content review-payment-page\">\n <header class=\"page-header\">\n <div class=\"d-flex align-items-center flex-wrap\">\n <div class=\"mr-auto\">\n <h1>{{ 'LABEL_REVIEW_PAYMENT' | translate }}</h1>\n </div>\n </div>\n </header>\n\n <section class=\"page-content container-fluid review-payment-section\">\n <div class=\"card m-0 border-0 review-payment-shell\">\n <form role=\"form\">\n <div class=\"card-body review-payment-body\">\n <div class=\"review-payment-content\">\n <div class=\"row g-3\">\n <div class=\"col-xl-8\">\n <h5 class=\"border-bottom pb-3 font-weight-600 section-heading\"> {{ 'LABEL_PAYMENT_SUMMARY' | translate\n }} </h5>\n <div class=\"border-bottom table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_CATEGORY_TYPE' | translate }}</td>\n <td class=\"text-right\">{{\n providerCategoryTypes[vendorCategory?.category_type] || \"-\" |\n translate}}</td>\n </tr> -->\n @if(providerCode != \"SOCHIETEL\"){\n <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n @if (providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number || \"-\" }}</td>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_code || \"-\" }}</td>\n }\n </tr>\n }\n <tr>\n <td>{{ 'LABEL_PROVIDER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorProvider?.provider_name || \"-\" }}</td>\n </tr>\n <!-- <tr>\n <td>{{ 'LABEL_VENDOR_NAME' | translate }}</td>\n <td class=\"text-right\">{{ vendorDetails?.vendor_name }}</td>\n </tr> -->\n <!-- @if(providerCode == \"SOCHIETEL\"){ -->\n @if( vendorCategory?.category_key == \"airtime_data\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name || \"-\" }}</td>\n </tr>\n }\n\n @if(vendorCategory?.category_key == \"road_tax\" || vendorCategory?.category_key == \"ROAD_TAX\"){\n @if (billData?.selectedBill?.meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.meta_data); track key) {\n <tr>\n <td>{{ removeunderScore(key) }}</td>\n <td class=\"text-right\">\n {{ \n (billData?.selectedBill?.meta_data[key] == 0 ? (0 | price: { currency }): billData?.selectedBill?.meta_data[key]) \n ?? \"-\"}}\n </td>\n </tr>\n }\n }\n }\n\n <!-- } -->\n <!-- <tr>\n <td>{{ 'COMMON_LABEL_DESCRIPTION' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_description || \"-\" }}</td>\n </tr> -->\n @if(mobileNumberInput){\n <tr>\n <td>{{ mobileNumberInput?.label || \"-\" }}</td>\n <td class=\"text-right\">{{ mobileNumberInput?.value || \"-\" }}</td>\n </tr>\n }\n @if(planData?.product_price_type == 1){\n <tr>\n <td>{{ 'LABEL_AMOUNT' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_fixed_price || 0.0 | price: { currency } }}</td>\n </tr>\n }@if(planData?.product_price_type == 2){\n <tr>\n <td>{{ 'LABEL_MINIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.min || 0.0 | price: { currency } }}</td>\n </tr>\n <tr>\n <td>{{ 'LABEL_MAXIMUM_AMOUNT' | translate }}: </td>\n <td class=\"text-right\">{{ planData?.product_range_price?.max || 0.0 | price: { currency } }}</td>\n </tr>\n }\n @if(kwh){\n <tr>\n <td>{{ 'LABEL_KWH' | translate }}</td>\n <td class=\"text-right\">{{ kwh }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n\n <h5 class=\"border-bottom pb-3 mb-4 font-weight-600 mt-3 section-heading\">\n {{ 'LABEL_DEBITED_FROM' | translate }}\n </h5>\n <div class=\"media d-user align-items-center\">\n <img loading=\"lazy\" [src]=\"companyDetail?.logo ? companyDetail?.logo : 'assets/avatars/profile.jpg'\"\n alt=\"\" class=\"h-50 w-50 rounded-circle mr-3\" />\n <div class=\"media-body\">\n <h5 class=\"mb-1 fontsize14 font-weight-600\">{{ walletData?.wallet_name }}\n </h5>\n <span class=\"text-muted\"> {{\"LABEL_AVAILABLE_BALANCE\" | translate}} :\n {{agentUserWallet?.wallet_balance | price : {currency} }}</span>\n </div>\n </div>\n\n <!-- <ng-container *ngIf=\"calculateCharges?.charges?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'COMMON_LABEL_CHARGES'\n |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngFor=\"let obj of calculateCharges?.charges\">\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n <!-- <ng-container *ngIf=\"workFlowUserInput?.length > 0\">\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600\"> {{ 'LABEL_USER_INPUT' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <tr *ngIf=\"meterName?.customer_name\">\n <td>{{ 'LABEL_METER_NAME' | translate }}</td>\n <td class=\"text-right\">{{ meterName?.customer_name }}</td>\n </tr>\n <tr *ngFor=\"let obj of workFlowUserInput\">\n <td>{{ obj?.label }}</td>\n <td class=\"text-right\">{{ obj?.value }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n </ng-container> -->\n\n @if (isPlanReview && planData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_PLAN_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n @if( vendorCategory?.category_key != \"airtime_credit\"){\n <tr>\n <td>{{ 'LABEL_PRODUCT_NAME' | translate }}</td>\n <td class=\"text-right\">{{ planData?.product_name }}</td>\n </tr>\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n planData?.product_fixed_price || this.amount || 0.0| price: {\n currency } }}</td>\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || planData?.product_fixed_price || 0.0 |\n price: { currency }\n }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n }\n\n @if (isBillReview && billData) {\n <h5 class=\"border-bottom pb-3 mb-3 mt-3 font-weight-600 section-heading\"> {{ 'LABEL_BILL_DETAILS' |\n translate }} </h5>\n <div class=\"table-responsive payment-summary-table review-table\">\n <table aria-label class=\"table m-0\">\n <tbody>\n <!-- <tr>\n <td>{{ 'LABEL_BILL_NUMBER' | translate }}</td>\n <td class=\"text-right\">{{ billData?.selectedBill?.bill_number }}\n </td>\n </tr> -->\n <tr>\n <td class=\"font-weight-600\">{{ 'COMMON_LABEL_AMOUNT' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}\n </td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\">{{\n userAmountWithoutCharge || 0.0 |\n price: { currency }\n }}\n </td>\n } -->\n </tr>\n @if (calculateCharges?.charges?.length > 0) {\n @for (obj of calculateCharges?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n @if (vendorCharge?.charges?.length > 0) {\n @for (obj of vendorCharge?.charges; track obj) {\n <tr>\n <td>{{ obj?.charge_name }}</td>\n <td class=\"text-right\">{{ obj?.final_charge || 0.0 | price: {\n currency } }}</td>\n </tr>\n }\n }\n <tr>\n <td class=\"font-weight-600\">{{ 'LABEL_PAYABLE' | translate }}\n </td>\n <!-- @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') { -->\n <td class=\"font-weight-600 text-right\">{{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n <!-- } -->\n <!-- @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <td class=\"font-weight-600 text-right\" >{{\n userAmount || billData?.selectedBill?.bill_amount || 0.0 |\n price: { currency }\n }}</td>\n } -->\n </tr>\n @if (billData?.selectedBill?.bill_meta_data) {\n @for (key of objectKeys(billData?.selectedBill?.bill_meta_data); track key) {\n <tr>\n <td class=\"font-weight-600\"> {{ removeunderScore(key) }}</td>\n <td class=\"font-weight-600 text-right\">\n {{ billData?.selectedBill?.bill_meta_data[key] || \"-\"}}\n </td>\n </tr>\n }\n }\n </tbody>\n </table>\n </div>\n }\n </div>\n\n <div class=\"col-xl-4\">\n <div\n class=\"card review-amount-card equal-height d-flex align-items-center justify-content-center m-0 shadow-none border\">\n <div class=\"card-body d-flex align-items-center py-4\">\n <div class=\"text-center\">\n @if (isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_BILL_AMOUNT' | translate }}\n </h6>\n @if (providerCode != 'DBA_PREPAID_ELECTRICITY' && providerCode != 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || billData?.selectedBill?.bill_amount || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_PREPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n @if (providerCode == 'DBA_POSTPAID_ELECTRICITY') {\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n userAmountWithoutCharge || 0.0 | price:\n { currency } }}\n </h2>\n }\n }\n @if (isPlanReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'LABEL_PLAN_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{\n paybleAmount || planData?.product_fixed_price || 0.0 | price: { currency } }} </h2>\n }\n @if (!isPlanReview && !isBillReview) {\n <h6 class=\"d-block m-b-15 text-grey font-size-16 amount-label\"> {{\n 'COMMON_LABEL_AMOUNT' | translate }}\n </h6>\n <h2 class=\"mb-0 font-size-26 font-weight-600\"> {{ amount || 0.0 | price:\n { currency } }} </h2>\n\n }\n \n\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"card-footer review-payment-footer text-right\">\n <button type=\"button\" class=\"btn btn-outline-secondary btn-sm\" (click)=\"cancel()\">{{ 'COMMON_LABEL_CANCEL' |\n translate }}</button>\n <button type=\"button\" class=\"btn btn-primary btn-sm\" [disabled]=\"showLoader\" (click)=\"enterTxnPin()\">{{\n 'COMMON_LABEL_SUBMIT' | translate }}</button>\n </div>\n </form>\n </div>\n </section>\n</div>\n\n<style>\n .review-payment-page .page-header h1 {\n font-size: 1.35rem;\n font-weight: 700;\n color: #1e3a5f;\n margin-bottom: 0.25rem;\n }\n\n .review-payment-section {\n padding-left: 0;\n padding-right: 0;\n }\n\n .review-payment-shell {\n border: 1px solid #dce3eb !important;\n border-radius: 8px;\n background: #fff;\n overflow: hidden;\n }\n\n .review-payment-body {\n padding: 1.1rem 1.2rem 0.8rem;\n }\n\n .review-payment-content {\n margin-top: 0.2rem;\n }\n\n .section-heading {\n color: #1e3a5f;\n font-size: 0.95rem;\n font-weight: 700;\n margin-bottom: 0.7rem !important;\n }\n\n .review-table table td {\n font-size: 0.8rem;\n color: #264563;\n padding: 0.5rem 0.25rem;\n vertical-align: middle;\n border-top-color: #edf1f5;\n }\n\n .review-amount-card {\n min-height: 100%;\n border: 1px solid #dce3eb !important;\n border-radius: 6px;\n background: #f6f8fa;\n }\n\n .amount-label {\n color: #7b8fa6 !important;\n font-weight: 600;\n letter-spacing: 0.01em;\n margin-bottom: 0.55rem !important;\n }\n\n .review-amount-card h2 {\n color: #1e3a5f;\n font-size: 2rem !important;\n font-weight: 700;\n }\n\n .review-payment-footer {\n border-top: 1px solid #e4e9ef;\n background: #fff;\n padding: 0.65rem 1rem;\n }\n\n .review-payment-footer .btn {\n min-width: 86px;\n margin-left: 0.45rem;\n }\n\n .txn-pin-modal-dialog {\n max-width: 420px;\n }\n\n .txn-pin-modal-content {\n border: 1px solid #e8edf3;\n border-radius: 12px;\n box-shadow: 0 0.5rem 1.5rem rgba(15, 34, 58, 0.12);\n overflow: hidden;\n }\n\n .txn-pin-modal-header {\n padding: 0.75rem 1rem;\n border-bottom: 1px solid #eef2f6;\n }\n\n .txn-pin-title {\n margin: 0;\n font-size: 1.05rem;\n font-weight: 700;\n color: #1f3f66;\n }\n\n .txn-pin-modal-body {\n padding: 0.9rem 1rem 0.75rem;\n }\n\n .txn-pin-subtitle {\n margin: 0 0 0.75rem;\n font-size: 0.8rem;\n color: #8d9fb2;\n }\n\n .txn-pin-modal-footer {\n border-top: 1px solid #eef2f6;\n padding: 0.55rem 0.85rem;\n gap: 0.5rem;\n justify-content: flex-end;\n }\n\n .txn-pin-close-btn,\n .txn-pin-submit-btn {\n min-width: 74px;\n padding: 0.22rem 0.85rem;\n font-size: 0.75rem;\n border-radius: 4px;\n }\n\n .txn-pin-forgot-btn {\n margin-right: auto;\n font-size: 0.76rem;\n color: #0d6efd;\n text-decoration: none;\n }\n</style>\n\n@if (showLoader) {\n<sdk-common-loader message=\"{{ 'LABEL_PLEASE_WAIT' | translate }}...\"></sdk-common-loader>\n}\n<div id=\"OTPVerification\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"OTPVerificationLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog\" role=\"document\">\n <form [formGroup]=\"otpForm\" (ngSubmit)=\"submitOTPForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">{{ 'LABEL_OTP_VERIFICATION' | translate }}</h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{ 'LABEL_ENTER_4_DIGIT_NUMBER_SENT_TO' | translate }}\n <span class=\"font-weight-600 ml-1 text-dark\">{{ currentUserDetails?.dial_code + \" \" +\n currentUserDetails?.phone_number }}</span>\n </p>\n <label for=\"inputOTP\" class=\"sr-only\">{{ 'LABEL_OTP' | translate }}</label>\n <sdk-otp-input (inputChange)=\"onOtpChange($event)\" [length]=\"pinLength\"\n [isPassword]=\"true\"> </sdk-otp-input>\n @if (formErrors.otp) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.otp\"></span>\n }\n\n @if (otpResendTime > 0) {\n @if (timer === 0) {\n <button type=\"button\" class=\"p-2 mt-1 btn-link\" (click)=\"sendOTPToAgent()\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n </button>\n } @else {\n <p class=\"p-2 mt-1 text-muted\">\n {{ 'LABEL_RESEND_OTP' | translate }}\n <span class=\"font-weight-600\">{{ getTimerString(timer) }}</span>\n </p>\n }\n }\n </div>\n <button type=\"submit\" class=\"btn btn-primary btn-block mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_CONFIRM' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n\n<!-- Transaction PIN Modal -->\n<div id=\"TransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"TransactionPINLabel\" data-backdrop=\"static\"\n data-keyboard=\"false\">\n <div class=\"modal-dialog txn-pin-modal-dialog\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content txn-pin-modal-content\">\n <div class=\"modal-header txn-pin-modal-header\">\n <h3 class=\"modal-title txn-pin-title\">{{ 'LABEL_TRANSACTION_PIN' | translate }}</h3>\n </div>\n <div class=\"modal-body txn-pin-modal-body\">\n <div class=\"form-group mb-0\">\n <p class=\"txn-pin-subtitle\">{{ 'LABEL_ENTER_4_DIGIT_TRANSACTION_PIN' | translate }}</p>\n <label for=\"inputOTP\" class=\"sr-only\">{{ 'LABEL_PIN' | translate }}</label>\n @if (otpReset) {\n <sdk-otp-input\n class=\"txn-pin-input\"\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.pin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.pin\"></span>\n }\n </div>\n </div>\n <div class=\"modal-footer txn-pin-modal-footer\">\n <!-- @if (inValidTxnPin) {\n <button type=\"button\" class=\"btn btn-link txn-pin-forgot-btn px-0\" (click)=\"forgotTxnPin()\">\n {{ 'LABEL_FORGOT_TXN_PIN' | translate }}\n </button>\n } -->\n <button type=\"button\" class=\"btn btn-light btn-sm txn-pin-close-btn\" (click)=\"closeTransactionPinModal()\">\n {{ 'COMMON_LABEL_CLOSE' | translate }}\n </button>\n <button type=\"submit\" class=\"btn btn-primary btn-sm txn-pin-submit-btn\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_SUBMIT' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>\n\n<!-- Confirm Transaction PIN Modal -->\n<div id=\"ConfirmTransactionPIN\" class=\"modal fade\" role=\"dialog\" aria-labelledby=\"ConfirmTransactionPINLabel\"\n data-backdrop=\"static\" data-keyboard=\"false\">\n <div class=\"modal-dialog modal-md\" role=\"document\">\n <form [formGroup]=\"txnPINForm\" (ngSubmit)=\"submitConfirmPINForm()\" role=\"form\" aria-label>\n <div class=\"modal-content\">\n <div class=\"modal-header\">\n <h3 class=\"modal-title\">{{ 'LABEL_CONFIRM_TRANSACTION_PIN' | translate }}</h3>\n </div>\n <div class=\"modal-body py-4\">\n <div class=\"form-group\">\n <p class=\"m-b-20 text-muted\">{{ 'LABEL_REENTER_4_DIGIT_TRANSACTION_PIN' | translate }}</p>\n @if (otpConfirm) {\n <sdk-otp-input\n #otpInputComp\n [segmented]=\"true\"\n [autoFocus]=\"true\"\n (inputChange)=\"onTxnPinChange($event)\"\n [length]=\"pinLength\"\n [isPassword]=\"true\"\n ></sdk-otp-input>\n }\n @if (formErrors.confirmPin) {\n <span class=\"help-block\" [innerHTML]=\"formErrors.confirmPin\"></span>\n }\n </div>\n <!-- <p\n class=\"card bg-light text-center p-2 flex-row justify-content-center flex-wrap rounded mt-4 mb-3\">\n {{'LABEL_YOU_ARE_SENDING_MONEY_TO' |translate}} <span class=\"font-weight-600 ml-2\"> {{\n senderReceiverStore?.receiver?.first_name + \" \" +\n senderReceiverStore?.receiver?.last_name }}</span></p> -->\n <button type=\"submit\" class=\"btn btn-primary btn-block btn-lg mt-2\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\" [disabled]=\"showLoader\">\n {{ 'COMMON_LABEL_CONFIRM' | translate }}\n </button>\n </div>\n </div>\n </form>\n </div>\n</div>" }]
5763
5997
  }], ctorParameters: () => [], propDecorators: { txnSummaryComp: [{
5764
5998
  type: ViewChild,
5765
5999
  args: [TransactionSummaryComponent]
package/index.d.ts CHANGED
@@ -22,9 +22,17 @@ declare class SdkStateService {
22
22
  * Runtime configuration passed from any host app into `<sdk-utility-payments [config]="...">`.
23
23
  * The SDK does not depend on a specific host project — only this shape + optional auth provider.
24
24
  */
25
+ interface UtilityPaymentsAuthPaths {
26
+ /** Relative to baseUrl, e.g. `/auth/send_otp` */
27
+ sendOtp?: string;
28
+ verifyOtp?: string;
29
+ createTransactionPin?: string;
30
+ }
25
31
  interface UtilityPaymentsConfigInput {
26
32
  baseUrl: string;
27
33
  defaultHeaders?: Record<string, string>;
34
+ /** Override auth paths when your Java API differs from SDK defaults */
35
+ authPaths?: UtilityPaymentsAuthPaths;
28
36
  }
29
37
 
30
38
  /**
@@ -169,6 +177,8 @@ declare class TopupAndBillpaymentService {
169
177
  setCurrentScreenStep(index: number): void;
170
178
  saveWorkflowData(data: any): void;
171
179
  deleteWorkflowData(): void;
180
+ /** Clears all bill-payment flow state after a completed or abandoned session. */
181
+ clearAllSessionState(): void;
172
182
  getVendorDetailsById(id: string): Observable<any>;
173
183
  getTopupAndBillpaymentCategories(params?: any): Observable<any>;
174
184
  getTopupAndBillpaymentCategoryById(id: string): Observable<any>;
@@ -255,4 +265,4 @@ declare function utilityPaymentsSdkIsVerboseDebug(): boolean;
255
265
  declare function utilityPaymentsSdkDebug(event: string, detail?: Record<string, unknown>): void;
256
266
 
257
267
  export { DataService, PaymentsApiService, PaymentsConfigService, SdkStateService, TopupAndBillpaymentService, TransactionService, TranslationService, UTILITY_PAYMENTS_AUTH_PROVIDER, UTILITY_PAYMENTS_SDK_BUILD_TAG, UtilityPaymentsContainerComponent, UtilityPaymentsModule, WorkflowStateService, utilityPaymentsSdkDebug, utilityPaymentsSdkIsVerboseDebug };
258
- export type { UtilityPaymentsAuthProvider, UtilityPaymentsConfigInput };
268
+ export type { UtilityPaymentsAuthPaths, UtilityPaymentsAuthProvider, UtilityPaymentsConfigInput };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "digipay-utility-payment",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.3.0",
6
6
  "@angular/core": "^20.3.0"