digipay-utility-payment 0.0.7 → 0.0.9

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,20 +848,29 @@ 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();
783
856
  }
784
857
  getProviderCategories() {
785
- this.topupAndBillpaymentService.getTopupAndBillpaymentCategories().subscribe({
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;
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 [];
@@ -3668,8 +3781,12 @@ class ViewBillsComponent {
3668
3781
  }
3669
3782
  else {
3670
3783
  this.toasterService.error(this.translationService.translate(res?.error[0]));
3784
+ this.showLoader = false;
3671
3785
  }
3672
3786
  },
3787
+ error: () => {
3788
+ this.showLoader = false;
3789
+ }
3673
3790
  });
3674
3791
  }
3675
3792
  handleBillClick(data) {
@@ -3986,21 +4103,29 @@ class AuthService {
3986
4103
  const companyId = this.authProvider.getCompanyId();
3987
4104
  const userId = this.authProvider.getUserId();
3988
4105
  if (token)
3989
- headers['Authorization'] = token.startsWith('Bearer ') ? token : `${token}`;
4106
+ headers['Authorization'] = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
3990
4107
  if (companyId != null)
3991
4108
  headers['companyid'] = String(companyId);
3992
4109
  if (userId != null)
3993
4110
  headers['userid'] = String(userId);
3994
4111
  return headers;
3995
4112
  }
3996
- verifyOTP(_payload) {
3997
- 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 });
3998
4123
  }
3999
- sendOTP(_payload) {
4000
- return of({ success: false });
4124
+ sendOTP(payload) {
4125
+ return this.http.post(this.authUrl('sendOtp', '/auth/send_otp'), payload, { headers: this.defaultHeaders });
4001
4126
  }
4002
- createTransactionPin(_payload) {
4003
- return of({ success: false });
4127
+ createTransactionPin(payload) {
4128
+ return this.http.post(this.authUrl('createTransactionPin', '/auth/create_transaction_pin'), payload, { headers: this.defaultHeaders });
4004
4129
  }
4005
4130
  verifyTransactionPin(payload) {
4006
4131
  return this.http.post(`${this.baseUrl}/auth/verify_transaction_pin`, payload, { headers: this.defaultHeaders });
@@ -4411,7 +4536,18 @@ function openUtilityBootstrapModal(element) {
4411
4536
  return false;
4412
4537
  }
4413
4538
  }
4414
- /** 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. */
4415
4551
  function closeUtilityBootstrapModal(element) {
4416
4552
  if (!element) {
4417
4553
  return false;
@@ -4583,6 +4719,12 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4583
4719
  }
4584
4720
  });
4585
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
+ });
4586
4728
  this.dataService.adminUserDetails.pipe(takeUntil(this.destroy$)).subscribe((data) => {
4587
4729
  if (isNotNull(data)) {
4588
4730
  this.adminUserDetails = data;
@@ -4676,15 +4818,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4676
4818
  this.userDetail();
4677
4819
  }
4678
4820
  async calculatCharge() {
4821
+ this.showLoader = true;
4679
4822
  const cfg = (this.paymentsConfigService.getConfig() ?? {});
4680
4823
  const cfgHeaders = (cfg?.defaultHeaders ?? {});
4681
4824
  const userId = (cfgHeaders["userid"] ?? cfgHeaders["userId"] ?? cfg?.userId ?? "").toString().trim();
4682
- this.showLoader = true;
4683
4825
  let profileDetails = {
4684
4826
  "userProfileService": this.userprofileService,
4685
4827
  "userId": userId,
4686
4828
  "walletId": this.walletId,
4687
- "userType": USER_TYPES.AGENT,
4829
+ "userType": this.currentUserDetails?.user_type,
4688
4830
  "currencyId": this.currencyId,
4689
4831
  };
4690
4832
  if (this.vendorDetails?.vendor_code == "SOCHIETEL") {
@@ -4900,26 +5042,33 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4900
5042
  this.otpReset = false;
4901
5043
  if (this.otpForm.valid) {
4902
5044
  this.showLoader = true;
5045
+ const user = this.resolveCurrentUserDetails();
4903
5046
  const data = {
4904
- dial_code: this.currentUserDetails?.dial_code,
4905
- phone_number: this.currentUserDetails?.phone_number,
5047
+ dial_code: user?.dial_code,
5048
+ phone_number: user?.phone_number,
4906
5049
  otp: this.otpForm.value.otp,
4907
- 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,
4908
5052
  };
4909
5053
  this.authService.verifyOTP(data).subscribe({
4910
5054
  next: (response) => {
4911
5055
  this.showLoader = false;
4912
- if (response.success) {
5056
+ if (this.isApiSuccess(response)) {
4913
5057
  clearInterval(this.interval);
4914
5058
  this.hideModal("OTPVerification");
4915
- 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
+ }
4916
5063
  if (this.inValidTxnPin) {
4917
5064
  this.inValidTxnPin = false;
4918
5065
  this.isTxnPinCreated = false;
4919
- this.showModal("TransactionPIN");
5066
+ this.otpReset = true;
5067
+ setTimeout(() => this.showModal("TransactionPIN"), 200);
4920
5068
  }
4921
5069
  else if (this.isTpinSessionNeeded()) {
4922
- this.showModal("TransactionPIN");
5070
+ this.otpReset = true;
5071
+ setTimeout(() => this.showModal("TransactionPIN"), 200);
4923
5072
  }
4924
5073
  else {
4925
5074
  this.createIntent();
@@ -4927,11 +5076,12 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4927
5076
  this.otpReset = true;
4928
5077
  }
4929
5078
  else {
4930
- this.toasterService.error(this.translationService.translate(response?.error[0]));
5079
+ this.toasterService.error(this.getApiErrorMessage(response));
4931
5080
  }
4932
5081
  },
4933
- error: () => {
5082
+ error: (err) => {
4934
5083
  this.showLoader = false;
5084
+ this.toasterService.error(this.getApiErrorMessage(err?.error ?? err));
4935
5085
  },
4936
5086
  });
4937
5087
  }
@@ -4993,52 +5143,76 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
4993
5143
  this.otpForm.patchValue({ otp });
4994
5144
  }
4995
5145
  forgotTxnPin() {
4996
- this.hideModal("TransactionPIN");
4997
- this.sendOTPToAgent();
5146
+ this.sendOTPToAgent(true);
4998
5147
  }
4999
- 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
+ }
5000
5154
  this.showLoader = true;
5155
+ this.otpForm.reset();
5156
+ this.formErrors.otp = null;
5001
5157
  const data = {
5002
- dial_code: this.currentUserDetails?.dial_code,
5003
- phone_number: this.currentUserDetails?.phone_number,
5004
- // user_type: USER_TYPES.AGENT,
5005
- email: this.currentUserDetails?.email,
5006
- 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,
5007
5164
  };
5008
5165
  this.authService.sendOTP(data).subscribe({
5009
5166
  next: (response) => {
5010
5167
  this.showLoader = false;
5011
- if (response.success) {
5012
- this.toasterService.success(this.translationService.translate(response?.data?.message));
5013
- this.showModal("OTPVerification");
5014
- if (this.otpResendTime > 0) {
5015
- this.timer = this.otpResendTime;
5016
- this.interval = setInterval(() => {
5017
- if (this.timer > 0) {
5018
- this.timer--;
5019
- }
5020
- else {
5021
- clearInterval(this.interval);
5022
- }
5023
- }, 1000);
5168
+ if (this.isApiSuccess(response)) {
5169
+ const message = response?.data?.message;
5170
+ if (message) {
5171
+ this.toasterService.success(this.translationService.translate(message));
5024
5172
  }
5173
+ this.openOtpVerificationModal(restorePinModalOnFailure);
5174
+ this.startOtpResendTimer();
5025
5175
  }
5026
5176
  else {
5027
- this.toasterService.error(this.translationService.translate(response?.error[0]));
5177
+ this.toasterService.error(this.getApiErrorMessage(response));
5028
5178
  }
5029
5179
  },
5030
- error: () => {
5180
+ error: (err) => {
5031
5181
  this.showLoader = false;
5182
+ this.toasterService.error(this.getApiErrorMessage(err?.error ?? err));
5032
5183
  },
5033
5184
  });
5034
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
+ }
5035
5209
  enterTxnPin() {
5036
5210
  this.createIntent();
5037
5211
  }
5038
5212
  submitPINForm() {
5039
5213
  this.otpConfirm = true;
5040
5214
  this.formErrors = {};
5041
- this.showLoader = false;
5215
+ this.showLoader = true;
5042
5216
  if (this.txnPINForm.valid) {
5043
5217
  const pin = this.txnPINForm.value.pin;
5044
5218
  if (!this.isTxnPinCreated) {
@@ -5046,6 +5220,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5046
5220
  this.txnPINForm.reset();
5047
5221
  this.hideModal("TransactionPIN");
5048
5222
  this.showModal("ConfirmTransactionPIN");
5223
+ this.showLoader = true;
5049
5224
  }
5050
5225
  else {
5051
5226
  this.verifyTransactionPin(pin);
@@ -5064,6 +5239,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5064
5239
  this.hideModal("OTPVerification");
5065
5240
  this.otpReset = true;
5066
5241
  this.createIntent();
5242
+ this.showLoader = false;
5067
5243
  }
5068
5244
  else {
5069
5245
  this.otpReset = true;
@@ -5071,6 +5247,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5071
5247
  this.inValidTxnPin = true;
5072
5248
  const apiError = res?.error?.[0] || res?.error || this.translationService.translate("LABEL_SOMETHING_WENT_WRONG");
5073
5249
  this.toasterService.error(this.translationService.translate(apiError));
5250
+ this.showLoader = false;
5074
5251
  }
5075
5252
  },
5076
5253
  error: (error) => {
@@ -5106,12 +5283,12 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5106
5283
  this.hideModal("ConfirmTransactionPIN");
5107
5284
  }
5108
5285
  else {
5109
- this.toasterService.error(this.translationService.translate(res?.error[0]));
5286
+ this.toasterService.error(this.getApiErrorMessage(res));
5110
5287
  }
5111
5288
  },
5112
- error: () => {
5289
+ error: (err) => {
5113
5290
  this.showLoader = false;
5114
- this.toasterService.error(this.translationService.translate("LABEL_SOMETHING_WENT_WRONG"));
5291
+ this.toasterService.error(this.getApiErrorMessage(err?.error ?? err));
5115
5292
  },
5116
5293
  });
5117
5294
  }
@@ -5231,7 +5408,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5231
5408
  currency_id: this.currencyId,
5232
5409
  debit_type: TRANSFER_MODE.WALLET,
5233
5410
  debit_type_id: this.walletId,
5234
- debit_account_type: USER_TYPES.AGENT,
5411
+ debit_account_type: this.currentUserDetails?.user_type,
5235
5412
  debit_account_type_id: this.dataService.getWalletUserAccountId(),
5236
5413
  username: this.currentUserDetails?.first_name + " " + this.currentUserDetails?.last_name,
5237
5414
  },
@@ -5240,7 +5417,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5240
5417
  credit_type: TRANSFER_MODE.WALLET,
5241
5418
  credit_type_id: this.walletId,
5242
5419
  credit_account_type: USER_TYPES.VENDOR,
5243
- credit_account_type_id: this.adminUserDetails?.id,
5420
+ credit_account_type_id: this.vendorContractDetails?.user_id,
5244
5421
  username: this.vendorContractDetails?.contact_person_name,
5245
5422
  },
5246
5423
  txn_amount: (this.providerCode == 'DBA_PREPAID_ELECTRICITY' || this.providerCode == 'DBA_POSTPAID_ELECTRICITY') ? parseFloat(this.userAmountWithoutCharge) : txnAmount,
@@ -5324,7 +5501,6 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5324
5501
  return;
5325
5502
  }
5326
5503
  this.transactionService.initiateTopupBillPaymentTransaction(txnPayload).pipe(finalize(() => {
5327
- this.showLoader = false;
5328
5504
  })).subscribe({
5329
5505
  next: response => {
5330
5506
  if (response.success) {
@@ -5354,6 +5530,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5354
5530
  txnAmount: this.userAmount || txnAmount,
5355
5531
  txnDate: new Date().getTime(),
5356
5532
  };
5533
+ this.showLoader = false;
5357
5534
  this.topupAndBillpaymentService.saveTxnData(txnObj);
5358
5535
  this.showLoader = false;
5359
5536
  this.toasterService.success(this.translationService.translate(txnObj.message));
@@ -5361,7 +5538,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5361
5538
  }
5362
5539
  else {
5363
5540
  this.showLoader = false;
5364
- this.toasterService.error(this.translationService.translate(statusResponse?.error[0] || "LABEL_SOMETHING_WENT_WRONG"));
5541
+ this.toasterService.error(this.getApiErrorMessage(statusResponse));
5365
5542
  }
5366
5543
  },
5367
5544
  error: (statusError) => {
@@ -5483,15 +5660,28 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5483
5660
  }
5484
5661
  else {
5485
5662
  this.showLoader = false;
5486
- this.toasterService.error(this.translationService.translate(response?.error[0]));
5663
+ this.toasterService.error(this.getApiErrorMessage(response));
5487
5664
  }
5488
5665
  },
5489
5666
  error: (error) => {
5490
5667
  this.showLoader = false;
5491
- this.toasterService.error(this.translationService.translate(error?.error?.error));
5668
+ this.toasterService.error(this.getApiErrorMessage(error?.error ?? error));
5492
5669
  },
5493
5670
  });
5494
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
+ }
5495
5685
  buildPayBillPayload(txnId) {
5496
5686
  const currentAmount = this.userAmount || this.amount || this.billData?.selectedBill?.bill_amount || this.planData?.product_fixed_price || 0;
5497
5687
  const totalCharges = (parseFloat(this.calculateCharges?.total_charges) || 0) + (parseFloat(this.vendorCharge?.total_charges) || 0);
@@ -5564,7 +5754,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5564
5754
  };
5565
5755
  }
5566
5756
  goToMainAfterSuccessfulPayment() {
5567
- this.isTpinVerifiedForPayment = false;
5757
+ this.clearPaymentFlowState();
5568
5758
  if (this.sdkState?.isActive()) {
5569
5759
  this.sdkState.setStep("CATEGORY");
5570
5760
  }
@@ -5572,6 +5762,59 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5572
5762
  this.router.navigateByUrl("/operations/topup-and-billpayment");
5573
5763
  }
5574
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
+ }
5575
5818
  back() {
5576
5819
  this.isTpinVerifiedForPayment = false;
5577
5820
  if (this.sdkState?.isActive()) {
@@ -5668,14 +5911,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5668
5911
  const g = globalThis;
5669
5912
  const doc = g?.document;
5670
5913
  const el = doc?.getElementById(modalId) ?? null;
5671
- const jq = g?.$;
5672
- if (jq && typeof jq === "function") {
5673
- const modalEl = jq(`#${modalId}`);
5674
- if (modalEl?.length && typeof modalEl.modal === "function") {
5675
- modalEl.modal("show");
5676
- return;
5677
- }
5678
- }
5914
+ cleanupUtilityModalBackdrops();
5679
5915
  if (el && openUtilityBootstrapModal(el)) {
5680
5916
  return;
5681
5917
  }
@@ -5686,7 +5922,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5686
5922
  return;
5687
5923
  }
5688
5924
  catch {
5689
- /* 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;
5690
5934
  }
5691
5935
  }
5692
5936
  if (!el) {
@@ -5696,25 +5940,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5696
5940
  el.style.display = "block";
5697
5941
  el.removeAttribute("aria-hidden");
5698
5942
  el.setAttribute("aria-modal", "true");
5699
- if (!doc?.querySelector(".utility-payments-modal-backdrop")) {
5700
- const backdrop = doc.createElement("div");
5701
- backdrop.className = "modal-backdrop fade show utility-payments-modal-backdrop";
5702
- doc.body.appendChild(backdrop);
5703
- }
5943
+ const backdrop = doc.createElement("div");
5944
+ backdrop.className = "modal-backdrop fade show utility-payments-modal-backdrop";
5945
+ doc.body.appendChild(backdrop);
5704
5946
  doc.body.classList.add("modal-open");
5705
5947
  }
5706
5948
  hideModal(modalId) {
5707
5949
  const g = globalThis;
5708
5950
  const doc = g?.document;
5709
5951
  const el = doc?.getElementById(modalId) ?? null;
5710
- const jq = g?.$;
5711
- if (jq && typeof jq === "function") {
5712
- const modalEl = jq(`#${modalId}`);
5713
- if (modalEl?.length && typeof modalEl.modal === "function") {
5714
- modalEl.modal("hide");
5715
- return;
5716
- }
5717
- }
5718
5952
  if (el && closeUtilityBootstrapModal(el)) {
5719
5953
  return;
5720
5954
  }
@@ -5726,7 +5960,15 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5726
5960
  return;
5727
5961
  }
5728
5962
  catch {
5729
- /* 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;
5730
5972
  }
5731
5973
  }
5732
5974
  if (el) {
@@ -5735,11 +5977,10 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5735
5977
  el.setAttribute("aria-hidden", "true");
5736
5978
  el.removeAttribute("aria-modal");
5737
5979
  }
5738
- doc?.querySelectorAll(".utility-payments-modal-backdrop").forEach((node) => node.remove());
5739
- doc?.body.classList.remove("modal-open");
5980
+ cleanupUtilityModalBackdrops();
5740
5981
  }
5741
5982
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TopupAndBillpaymentReviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5742
- 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" }] });
5743
5984
  }
5744
5985
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TopupAndBillpaymentReviewComponent, decorators: [{
5745
5986
  type: Component,
@@ -5752,7 +5993,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
5752
5993
  FormlyBootstrapModule,
5753
5994
  FormlyModule,
5754
5995
  UtilityPaymentsUiModule
5755
- ], 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>" }]
5756
5997
  }], ctorParameters: () => [], propDecorators: { txnSummaryComp: [{
5757
5998
  type: ViewChild,
5758
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.7",
3
+ "version": "0.0.9",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.3.0",
6
6
  "@angular/core": "^20.3.0"