digipay-utility-payment 0.0.12 → 0.0.14

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
@@ -736,7 +736,8 @@ class TranslationService {
736
736
  COMMON_LABEL_CLOSE: 'Close',
737
737
  COMMON_LABEL_AMOUNT_MUST_NOT_EXCEED_BILL_AMOUNT: 'Amount must not be greater than the bill amount',
738
738
  LABEL_NO_PROVIDERS_AVAILABLE: 'No providers available',
739
- LABEL_ENTER_4_DIGIT_TRANSACTION_PIN: 'Enter your 4-digit transaction PIN'
739
+ LABEL_ENTER_4_DIGIT_TRANSACTION_PIN: 'Enter your 4-digit transaction PIN',
740
+ AUTH_INVALID_TRANSACTION_PIN: "Invalid transaction PIN",
740
741
  };
741
742
  translate(key) {
742
743
  return TranslationService.LABELS[key] ?? key;
@@ -1104,7 +1105,6 @@ function utilityPaymentsSdkDebug(event, detail) {
1104
1105
  if (!always && !utilityPaymentsSdkIsVerboseDebug()) {
1105
1106
  return;
1106
1107
  }
1107
- console.info(LOG_PREFIX, event, { tag: UTILITY_PAYMENTS_SDK_BUILD_TAG, ...detail });
1108
1108
  }
1109
1109
 
1110
1110
  class VendorProvidersComponent {
@@ -2277,239 +2277,231 @@ class BillWorkflowComponent {
2277
2277
  };
2278
2278
  this.topupAndBillpaymentService.saveWorkflowData(workflowState);
2279
2279
  }
2280
- getExtraFieldsToShow(field) {
2281
- if (!field)
2282
- return undefined; // Early return for falsy field
2283
- let isReadOnly = false;
2284
- if (field?.external_field_key === "dial_code") {
2285
- isReadOnly = true;
2286
- this.fieldsModel = { "dial_code": this.currentUserDetails?.dial_code };
2287
- }
2288
- const validations = field?.field_validation || [];
2289
- let isRequired = false;
2290
- let minLength;
2291
- let maxLength;
2292
- let minValue;
2293
- let maxValue;
2294
- const validationMessages = {};
2295
- validations.forEach((validation) => {
2296
- const fieldType = validation?.field_types;
2297
- const fieldValue = validation?.field_values;
2298
- const fieldError = validation?.field_error;
2299
- if (fieldType === 1) {
2300
- isRequired = fieldValue === "true" || fieldValue === true || fieldValue === "1";
2301
- }
2302
- else if (fieldType === 2) {
2303
- maxLength = parseInt(fieldValue);
2304
- if (fieldError)
2305
- validationMessages.maxlength = fieldError;
2306
- }
2307
- else if (fieldType === 3) {
2308
- minValue = parseFloat(fieldValue);
2309
- if (fieldError)
2310
- validationMessages.min = fieldError;
2311
- }
2312
- else if (fieldType === 4) {
2313
- minLength = parseInt(fieldValue);
2314
- if (fieldError)
2315
- validationMessages.minlength = fieldError;
2316
- if (!isRequired)
2317
- isRequired = true;
2318
- }
2319
- else if (fieldType === 5) {
2320
- maxValue = parseFloat(fieldValue);
2321
- if (fieldError)
2322
- validationMessages.max = fieldError;
2323
- }
2324
- });
2325
- let res = {
2326
- key: field.external_field_key,
2327
- templateOptions: {},
2328
- className: "col-sm-6",
2329
- wrappers: ["form-field-horizontal"],
2330
- type: "input",
2331
- modelOptions: { updateOn: 'change' },
2332
- expressionProperties: {
2333
- 'templateOptions.disabled': 'formState.disabled',
2334
- },
2335
- hooks: {
2336
- onInit: (field) => {
2337
- const control = field.formControl;
2338
- if (control) {
2339
- control.valueChanges.subscribe(() => {
2340
- if (control.invalid && control.value !== null && control.value !== '') {
2341
- control.markAsTouched();
2342
- }
2343
- });
2344
- }
2345
- }
2346
- }
2347
- };
2348
- if (isRequired) {
2349
- validationMessages.required = `${field.field_title} ${this.translationService.translate("LABEL_IS_REQUIRED")}`;
2350
- }
2351
- if (Object.keys(validationMessages).length > 0) {
2352
- res["validation"] = { messages: validationMessages };
2353
- }
2354
- if (field.field_type == TOPUP_BILL_PAYMENT_FIELD_TYPE.TEXT_BOX) {
2355
- res["templateOptions"] = {
2356
- label: `${field.field_title} `,
2357
- placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2358
- required: isRequired,
2359
- minLength: minLength,
2360
- maxLength: maxLength,
2361
- readonly: isReadOnly,
2362
- };
2363
- }
2364
- else if (field.field_type == TOPUP_BILL_PAYMENT_FIELD_TYPE.NUMERIC) {
2365
- res["templateOptions"] = {
2366
- label: `${field.field_title} `,
2367
- placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2368
- required: isRequired,
2369
- min: minValue,
2370
- max: maxValue,
2371
- minLength: minLength,
2372
- maxLength: maxLength,
2373
- };
2374
- res["type"] = "number-field";
2375
- }
2376
- return res; // Always reached now
2377
- }
2378
- // getExtraFieldsToShow(field: any): FormlyFieldConfig | null {
2379
- // if (field) {
2380
- // let isReadOnly = false;
2381
- // let fieldValue: any = null;
2382
- // let customValidators: any = {};
2383
- // if (field?.external_field_key === "dial_code") {
2384
- // isReadOnly = true;
2385
- // fieldValue = this.currentUserDetails?.dial_code;
2386
- // this.fieldsModel = { "dial_code": fieldValue };
2280
+ // getExtraFieldsToShow(field: any): FormlyFieldConfig | undefined {
2281
+ // if (!field) return undefined; // Early return for falsy field
2282
+ // let isReadOnly = false;
2283
+ // if (field?.external_field_key === "dial_code") {
2284
+ // isReadOnly = true;
2285
+ // this.fieldsModel = { "dial_code": this.currentUserDetails?.dial_code };
2286
+ // }
2287
+ // const validations: Array<any> = field?.field_validation || [];
2288
+ // let isRequired: boolean = false;
2289
+ // let minLength: number | undefined;
2290
+ // let maxLength: number | undefined;
2291
+ // let minValue: number | undefined;
2292
+ // let maxValue: number | undefined;
2293
+ // const validationMessages: any = {};
2294
+ // validations.forEach((validation: any) => {
2295
+ // const fieldType = validation?.field_types;
2296
+ // const fieldValue = validation?.field_values;
2297
+ // const fieldError = validation?.field_error;
2298
+ // if (fieldType === 1) {
2299
+ // isRequired = fieldValue === "true" || fieldValue === true || fieldValue === "1";
2300
+ // } else if (fieldType === 2) {
2301
+ // maxLength = parseInt(fieldValue);
2302
+ // if (fieldError) validationMessages.maxlength = fieldError;
2303
+ // } else if (fieldType === 3) {
2304
+ // minValue = parseFloat(fieldValue);
2305
+ // if (fieldError) validationMessages.min = fieldError;
2306
+ // } else if (fieldType === 4) {
2307
+ // minLength = parseInt(fieldValue);
2308
+ // if (fieldError) validationMessages.minlength = fieldError;
2309
+ // if (!isRequired) isRequired = true;
2310
+ // } else if (fieldType === 5) {
2311
+ // maxValue = parseFloat(fieldValue);
2312
+ // if (fieldError) validationMessages.max = fieldError;
2387
2313
  // }
2388
- // // Check if this is an amount field and we have a selected product
2389
- // const isAmountField = field?.external_field_key?.toLowerCase().includes("amount") ||
2390
- // field?.field_title?.toLowerCase().includes("amount");
2391
- // if (isAmountField && this.selectedProduct) {
2392
- // if (this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.FIXED) {
2393
- // // Fixed price: make field readonly and set the fixed price
2394
- // isReadOnly = true;
2395
- // fieldValue = this.selectedProduct?.product_fixed_price || 0;
2396
- // if (this.fieldsModel) {
2397
- // this.fieldsModel[field.external_field_key] = fieldValue;
2398
- // } else {
2399
- // this.fieldsModel = { [field.external_field_key]: fieldValue };
2314
+ // });
2315
+ // let res: FormlyFieldConfig = {
2316
+ // key: field.external_field_key,
2317
+ // templateOptions: {} as FormlyTemplateOptions,
2318
+ // className: "col-sm-6",
2319
+ // wrappers: ["form-field-horizontal"],
2320
+ // type: "input",
2321
+ // modelOptions: { updateOn: 'change' },
2322
+ // expressionProperties: {
2323
+ // 'templateOptions.disabled': 'formState.disabled',
2324
+ // },
2325
+ // hooks: {
2326
+ // onInit: (field: FormlyFieldConfig) => {
2327
+ // const control = field.formControl;
2328
+ // if (control) {
2329
+ // control.valueChanges.subscribe(() => {
2330
+ // if (control.invalid && control.value !== null && control.value !== '') {
2331
+ // control.markAsTouched();
2332
+ // }
2333
+ // });
2400
2334
  // }
2401
- // } else if (this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.RANGE) {
2402
- // const rangeMin = Number(this.selectedProduct?.product_range_price?.min) || 0;
2403
- // const rangeMax = Number(this.selectedProduct?.product_range_price?.max) || 0;
2404
- // customValidators = {
2405
- // // Range validator - checks if value is within the allowed range
2406
- // // Allows typing leading zeros (e.g., "01", "08") but validates the numeric value
2407
- // range: {
2408
- // expression: (control: any) => {
2409
- // const value = control?.value;
2410
- // if (value === null || value === undefined || value === '') {
2411
- // return true; // No error if empty
2412
- // }
2413
- // const valueStr = String(value).trim();
2414
- // // Convert string to number (handles leading zeros: "01" becomes 1, "08" becomes 8)
2415
- // const numValue = Number(valueStr);
2416
- // if (isNaN(numValue) || !isFinite(numValue)) {
2417
- // return true; // Skip validation for invalid numbers
2418
- // }
2419
- // // Return true if value is IN range (no error), false if out of range (error)
2420
- // return numValue >= rangeMin && numValue <= rangeMax;
2421
- // },
2422
- // message: () => `${this.translationService.translate("COMMON_LABEL_AMOUNT_MUST_BE_BETWEEN")} ${rangeMin} ${this.translationService.translate("COMMON_LABEL_AND")} ${rangeMax}`
2423
- // }
2424
- // };
2425
2335
  // }
2426
2336
  // }
2427
- // const validations: Array<any> = field?.field_validation || [];
2428
- // const normalizedFieldType = this.normalizeFieldType(field?.field_type);
2429
- // const normalizedValidations = this.normalizeValidations(validations);
2430
- // const isRequired: boolean = normalizedValidations.isRequired;
2431
- // const minLength: number | undefined = normalizedValidations.minLength;
2432
- // const maxLength: number | undefined = normalizedValidations.maxLength;
2433
- // let minValue: number | undefined = normalizedValidations.minValue;
2434
- // let maxValue: number | undefined = normalizedValidations.maxValue;
2435
- // // For range products, don't set HTML5 min/max to allow typing any value
2436
- // // We'll validate using custom validator only
2437
- // // This prevents HTML5 from blocking input before validation
2438
- // if (isAmountField && this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.RANGE) {
2439
- // // Don't override min/max - let custom validator handle it
2440
- // // This allows users to type any value, then validate on blur/submit
2441
- // }
2442
- // let res: FormlyFieldConfig = {
2443
- // key: field.external_field_key,
2444
- // templateOptions: {} as any,
2445
- // className: "col-12",
2446
- // wrappers: ["form-field-horizontal"],
2447
- // type: "input",
2448
- // // Enable real-time validation on change/input
2449
- // modelOptions: {
2450
- // updateOn: 'change'
2451
- // },
2452
- // // Show errors in real-time (even when not touched)
2453
- // expressionProperties: {
2454
- // 'templateOptions.disabled': 'formState.disabled',
2455
- // },
2456
- // // Mark field as touched on value change to show errors immediately
2457
- // hooks: {
2458
- // onInit: (field: FormlyFieldConfig) => {
2459
- // const control = field.formControl;
2460
- // if (control) {
2461
- // // Subscribe to value changes and mark as touched to show errors immediately
2462
- // control.valueChanges.subscribe(() => {
2463
- // if (control.invalid && control.value !== null && control.value !== '') {
2464
- // control.markAsTouched();
2465
- // }
2466
- // });
2467
- // }
2468
- // }
2469
- // }
2337
+ // };
2338
+ // if (isRequired) {
2339
+ // validationMessages.required = `${field.field_title} ${this.translationService.translate("LABEL_IS_REQUIRED")}`;
2340
+ // }
2341
+ // if (Object.keys(validationMessages).length > 0) {
2342
+ // res["validation"] = { messages: validationMessages };
2343
+ // }
2344
+ // if (field.field_type == TOPUP_BILL_PAYMENT_FIELD_TYPE.TEXT_BOX) {
2345
+ // res["templateOptions"] = {
2346
+ // label: `${field.field_title} `,
2347
+ // placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2348
+ // required: isRequired,
2349
+ // minLength: minLength,
2350
+ // maxLength: maxLength,
2351
+ // readonly: isReadOnly,
2470
2352
  // };
2471
- // // Add custom validators if any
2472
- // if (Object.keys(customValidators).length > 0) {
2473
- // res["validators"] = customValidators;
2474
- // }
2475
- // if (normalizedFieldType == TOPUP_BILL_PAYMENT_FIELD_TYPE.TEXT_BOX) {
2476
- // res["templateOptions"] = {
2477
- // label: `${field.field_title} `,
2478
- // placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2479
- // required: isRequired,
2480
- // minLength: minLength,
2481
- // maxLength: maxLength,
2482
- // readonly: isReadOnly,
2483
- // };
2484
- // if (fieldValue !== null) {
2485
- // res["defaultValue"] = fieldValue;
2486
- // }
2487
- // } else if (normalizedFieldType == TOPUP_BILL_PAYMENT_FIELD_TYPE.NUMERIC) {
2488
- // // For range products, don't set min/max in templateOptions to allow typing
2489
- // // Custom validator will handle validation
2490
- // const templateOptions: any = {
2491
- // label: `${field.field_title} `,
2492
- // placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2493
- // required: isRequired,
2494
- // minLength: minLength,
2495
- // maxLength: maxLength,
2496
- // readonly: isReadOnly,
2497
- // };
2498
- // // Only set min/max if NOT a range product (to allow typing any value for range products)
2499
- // if (!(isAmountField && this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.RANGE)) {
2500
- // templateOptions.min = minValue;
2501
- // templateOptions.max = maxValue;
2502
- // }
2503
- // res["templateOptions"] = templateOptions;
2504
- // res["type"] = "number-field";
2505
- // if (fieldValue !== null) {
2506
- // res["defaultValue"] = fieldValue;
2507
- // }
2508
- // }
2509
- // return res;
2353
+ // } else if (field.field_type == TOPUP_BILL_PAYMENT_FIELD_TYPE.NUMERIC) {
2354
+ // res["templateOptions"] = {
2355
+ // label: `${field.field_title} `,
2356
+ // placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2357
+ // required: isRequired,
2358
+ // min: minValue,
2359
+ // max: maxValue,
2360
+ // minLength: minLength,
2361
+ // maxLength: maxLength,
2362
+ // };
2363
+ // res["type"] = "number-field";
2510
2364
  // }
2511
- // return null;
2365
+ // return res; // Always reached now
2512
2366
  // }
2367
+ getExtraFieldsToShow(field) {
2368
+ if (field) {
2369
+ let isReadOnly = false;
2370
+ let fieldValue = null;
2371
+ let customValidators = {};
2372
+ if (field?.external_field_key === "dial_code") {
2373
+ isReadOnly = true;
2374
+ fieldValue = this.currentUserDetails?.dial_code;
2375
+ this.fieldsModel = { "dial_code": fieldValue };
2376
+ }
2377
+ // Check if this is an amount field and we have a selected product
2378
+ const isAmountField = field?.external_field_key?.toLowerCase().includes("amount") ||
2379
+ field?.field_title?.toLowerCase().includes("amount");
2380
+ if (isAmountField && this.selectedProduct) {
2381
+ if (this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.FIXED) {
2382
+ // Fixed price: make field readonly and set the fixed price
2383
+ isReadOnly = true;
2384
+ fieldValue = this.selectedProduct?.product_fixed_price || 0;
2385
+ if (this.fieldsModel) {
2386
+ this.fieldsModel[field.external_field_key] = fieldValue;
2387
+ }
2388
+ else {
2389
+ this.fieldsModel = { [field.external_field_key]: fieldValue };
2390
+ }
2391
+ }
2392
+ else if (this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.RANGE) {
2393
+ const rangeMin = Number(this.selectedProduct?.product_range_price?.min) || 0;
2394
+ const rangeMax = Number(this.selectedProduct?.product_range_price?.max) || 0;
2395
+ customValidators = {
2396
+ // Range validator - checks if value is within the allowed range
2397
+ // Allows typing leading zeros (e.g., "01", "08") but validates the numeric value
2398
+ range: {
2399
+ expression: (control) => {
2400
+ const value = control?.value;
2401
+ if (value === null || value === undefined || value === '') {
2402
+ return true; // No error if empty
2403
+ }
2404
+ const valueStr = String(value).trim();
2405
+ // Convert string to number (handles leading zeros: "01" becomes 1, "08" becomes 8)
2406
+ const numValue = Number(valueStr);
2407
+ if (isNaN(numValue) || !isFinite(numValue)) {
2408
+ return true; // Skip validation for invalid numbers
2409
+ }
2410
+ // Return true if value is IN range (no error), false if out of range (error)
2411
+ return numValue >= rangeMin && numValue <= rangeMax;
2412
+ },
2413
+ message: () => `${this.translationService.translate("COMMON_LABEL_AMOUNT_MUST_BE_BETWEEN")} ${rangeMin} ${this.translationService.translate("COMMON_LABEL_AND")} ${rangeMax}`
2414
+ }
2415
+ };
2416
+ }
2417
+ }
2418
+ const validations = field?.field_validation || [];
2419
+ const normalizedFieldType = this.normalizeFieldType(field?.field_type);
2420
+ const normalizedValidations = this.normalizeValidations(validations);
2421
+ const isRequired = normalizedValidations.isRequired || true;
2422
+ const minLength = normalizedValidations.minLength;
2423
+ const maxLength = normalizedValidations.maxLength;
2424
+ let minValue = normalizedValidations.minValue;
2425
+ let maxValue = normalizedValidations.maxValue;
2426
+ // For range products, don't set HTML5 min/max to allow typing any value
2427
+ // We'll validate using custom validator only
2428
+ // This prevents HTML5 from blocking input before validation
2429
+ if (isAmountField && this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.RANGE) {
2430
+ // Don't override min/max - let custom validator handle it
2431
+ // This allows users to type any value, then validate on blur/submit
2432
+ }
2433
+ let res = {
2434
+ key: field.external_field_key,
2435
+ templateOptions: {},
2436
+ className: "col-12",
2437
+ wrappers: ["form-field-horizontal"],
2438
+ type: "input",
2439
+ // Enable real-time validation on change/input
2440
+ modelOptions: {
2441
+ updateOn: 'change'
2442
+ },
2443
+ // Show errors in real-time (even when not touched)
2444
+ expressionProperties: {
2445
+ 'templateOptions.disabled': 'formState.disabled',
2446
+ },
2447
+ // Mark field as touched on value change to show errors immediately
2448
+ hooks: {
2449
+ onInit: (field) => {
2450
+ const control = field.formControl;
2451
+ if (control) {
2452
+ // Subscribe to value changes and mark as touched to show errors immediately
2453
+ control.valueChanges.subscribe(() => {
2454
+ if (control.invalid && control.value !== null && control.value !== '') {
2455
+ control.markAsTouched();
2456
+ }
2457
+ });
2458
+ }
2459
+ }
2460
+ }
2461
+ };
2462
+ // Add custom validators if any
2463
+ if (Object.keys(customValidators).length > 0) {
2464
+ res["validators"] = customValidators;
2465
+ }
2466
+ if (normalizedFieldType == TOPUP_BILL_PAYMENT_FIELD_TYPE.TEXT_BOX) {
2467
+ res["templateOptions"] = {
2468
+ label: `${field.field_title} `,
2469
+ placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2470
+ required: isRequired,
2471
+ minLength: minLength,
2472
+ maxLength: maxLength,
2473
+ readonly: isReadOnly,
2474
+ };
2475
+ if (fieldValue !== null) {
2476
+ res["defaultValue"] = fieldValue;
2477
+ }
2478
+ }
2479
+ else if (normalizedFieldType == TOPUP_BILL_PAYMENT_FIELD_TYPE.NUMERIC) {
2480
+ // For range products, don't set min/max in templateOptions to allow typing
2481
+ // Custom validator will handle validation
2482
+ const templateOptions = {
2483
+ label: `${field.field_title} `,
2484
+ placeholder: `${this.translationService.translate("COMMON_LABEL_PLEASE_ENTER")} ${field.field_title}`,
2485
+ required: isRequired,
2486
+ minLength: minLength,
2487
+ maxLength: maxLength,
2488
+ readonly: isReadOnly,
2489
+ };
2490
+ // Only set min/max if NOT a range product (to allow typing any value for range products)
2491
+ if (!(isAmountField && this.selectedProduct?.product_price_type === PRODUCT_PRICE_TYPE.RANGE)) {
2492
+ templateOptions.min = minValue;
2493
+ templateOptions.max = maxValue;
2494
+ }
2495
+ res["templateOptions"] = templateOptions;
2496
+ res["type"] = "number-field";
2497
+ if (fieldValue !== null) {
2498
+ res["defaultValue"] = fieldValue;
2499
+ }
2500
+ }
2501
+ return res;
2502
+ }
2503
+ return null;
2504
+ }
2513
2505
  ngOnDestroy() {
2514
2506
  this.destroy$.next(true);
2515
2507
  this.destroy$.unsubscribe();
@@ -3065,6 +3057,21 @@ class WorkFlowComponent {
3065
3057
  return TOPUP_BILL_PAYMENT_FIELD_TYPE.BUTTON;
3066
3058
  return fieldTypeValue;
3067
3059
  }
3060
+ isFormIncomplete() {
3061
+ if (!this.detailsForm)
3062
+ return true;
3063
+ let hasEmptyFields = false;
3064
+ this.fieldsArray.forEach((field) => {
3065
+ const isRequired = field?.templateOptions?.required;
3066
+ const fieldKey = field.key != null ? String(field.key) : '';
3067
+ const formControl = this.detailsForm.get(fieldKey);
3068
+ const fieldValue = formControl?.value;
3069
+ if ((!fieldValue || fieldValue === '' || fieldValue === null || fieldValue === undefined)) {
3070
+ hasEmptyFields = true;
3071
+ }
3072
+ });
3073
+ return hasEmptyFields || !this.detailsForm.valid;
3074
+ }
3068
3075
  normalizeFieldAction(action) {
3069
3076
  const actionValue = String(action ?? "").trim().toUpperCase();
3070
3077
  if (actionValue === "GET_BILL_SCREEN")
@@ -3116,7 +3123,7 @@ class WorkFlowComponent {
3116
3123
  },
3117
3124
  ],
3118
3125
  }),
3119
- ], ngImport: i0, template: "\n\n@if (showWorkflowComponent) {\n \n <sdk-bill-workflow \n [selectedBill]=\"selectedBillForWorkflow\"\n (workflowCompleted)=\"onWorkflowCompleted($event)\">\n </sdk-bill-workflow>\n \n \n}@else { \n <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>{{ 'LABEL_UTILITIES' | translate }}</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\">{{ vendorProvider?.provider_name }}\n </h4>\n </div>\n <div class=\"tab-content\">\n <div class=\"tab-pane fadeIn active show\">\n <form role=\"form\" class=\"form-horizontal\" [formGroup]=\"detailsForm\" (ngSubmit)=\"submitForm()\">\n <div class=\"card-body\">\n <div class=\"mt-3\">\n @if (fieldsArray.length > 0) {\n <div class=\"row\">\n <div class=\"col-xl-5 offset-xl-3\">\n <!-- <div class=\"form-group form-row\">\n <label\n class=\"control-label text-md-right col-md-4 col-lg-3\">Provider</label>\n <div class=\"col-md-5\">\n <ng-select placeholder=\"Select Provider\" bindLabel=\"provider_name\"\n bindValue=\"id\" [items]=\"vendorProviders\"\n (change)=\"changeVendorProvider($event)\">\n </ng-select>\n </div>\n </div> -->\n <!-- <pre>{{fieldsArray|json}}</pre> -->\n <formly-form [fields]=\"fieldsArray\" [model]=\"fieldsModel\" [form]=\"detailsForm\">\n </formly-form>\n </div>\n </div>\n }\n \n @if (fieldsArray.length === 0) {\n <sdk-no-data title=\"LABEL_FIELDS_NOT_AVAILABLE\"></sdk-no-data>\n }\n </div>\n </div>\n <div class=\"card-footer bg-light text-right\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"back()\">\n {{'COMMON_LABEL_CANCEL' | translate}}\n </button>\n @if (buttonData) {\n <button type=\"submit\" class=\"btn btn-primary\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\"\n [disabled]=\"showLoader\">\n {{ buttonData?.field_title }}\n </button>\n }\n </div>\n </form>\n </div>\n </div>\n </div>\n </section>\n </div>\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: "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: "component", type: i1$2.LegacyFormlyForm, selector: "formly-form" }, { kind: "component", type: NoDataComponent, selector: "sdk-no-data", inputs: ["title", "icon"] }, { kind: "component", type: BillWorkflowComponent, selector: "sdk-bill-workflow", inputs: ["billData", "selectedBill"], outputs: ["workflowCompleted"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3126
+ ], ngImport: i0, template: "\n\n@if (showWorkflowComponent) {\n \n <sdk-bill-workflow \n [selectedBill]=\"selectedBillForWorkflow\"\n (workflowCompleted)=\"onWorkflowCompleted($event)\">\n </sdk-bill-workflow>\n \n \n}@else { \n <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>{{ 'LABEL_UTILITIES' | translate }}</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\">{{ vendorProvider?.provider_name }}\n </h4>\n </div>\n <div class=\"tab-content\">\n <div class=\"tab-pane fadeIn active show\">\n <form role=\"form\" class=\"form-horizontal\" [formGroup]=\"detailsForm\" (ngSubmit)=\"submitForm()\">\n <div class=\"card-body\">\n <div class=\"mt-3\">\n @if (fieldsArray.length > 0) {\n <div class=\"row\">\n <div class=\"col-xl-5 offset-xl-3\">\n <!-- <div class=\"form-group form-row\">\n <label\n class=\"control-label text-md-right col-md-4 col-lg-3\">Provider</label>\n <div class=\"col-md-5\">\n <ng-select placeholder=\"Select Provider\" bindLabel=\"provider_name\"\n bindValue=\"id\" [items]=\"vendorProviders\"\n (change)=\"changeVendorProvider($event)\">\n </ng-select>\n </div>\n </div> -->\n <!-- <pre>{{fieldsArray|json}}</pre> -->\n <formly-form [fields]=\"fieldsArray\" [model]=\"fieldsModel\" [form]=\"detailsForm\">\n </formly-form>\n </div>\n </div>\n }\n \n @if (fieldsArray.length === 0) {\n <sdk-no-data title=\"LABEL_FIELDS_NOT_AVAILABLE\"></sdk-no-data>\n }\n </div>\n </div>\n <div class=\"card-footer bg-light text-right\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"back()\">\n {{'COMMON_LABEL_CANCEL' | translate}}\n </button>\n @if (buttonData) {\n <button type=\"submit\" class=\"btn btn-primary\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\"\n [disabled]=\"showLoader || isFormIncomplete()\">\n {{ buttonData?.field_title }}\n </button>\n }\n </div>\n </form>\n </div>\n </div>\n </div>\n </section>\n </div>\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: "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: "component", type: i1$2.LegacyFormlyForm, selector: "formly-form" }, { kind: "component", type: NoDataComponent, selector: "sdk-no-data", inputs: ["title", "icon"] }, { kind: "component", type: BillWorkflowComponent, selector: "sdk-bill-workflow", inputs: ["billData", "selectedBill"], outputs: ["workflowCompleted"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
3120
3127
  }
3121
3128
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: WorkFlowComponent, decorators: [{
3122
3129
  type: Component,
@@ -3166,7 +3173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
3166
3173
  },
3167
3174
  ],
3168
3175
  }),
3169
- ], template: "\n\n@if (showWorkflowComponent) {\n \n <sdk-bill-workflow \n [selectedBill]=\"selectedBillForWorkflow\"\n (workflowCompleted)=\"onWorkflowCompleted($event)\">\n </sdk-bill-workflow>\n \n \n}@else { \n <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>{{ 'LABEL_UTILITIES' | translate }}</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\">{{ vendorProvider?.provider_name }}\n </h4>\n </div>\n <div class=\"tab-content\">\n <div class=\"tab-pane fadeIn active show\">\n <form role=\"form\" class=\"form-horizontal\" [formGroup]=\"detailsForm\" (ngSubmit)=\"submitForm()\">\n <div class=\"card-body\">\n <div class=\"mt-3\">\n @if (fieldsArray.length > 0) {\n <div class=\"row\">\n <div class=\"col-xl-5 offset-xl-3\">\n <!-- <div class=\"form-group form-row\">\n <label\n class=\"control-label text-md-right col-md-4 col-lg-3\">Provider</label>\n <div class=\"col-md-5\">\n <ng-select placeholder=\"Select Provider\" bindLabel=\"provider_name\"\n bindValue=\"id\" [items]=\"vendorProviders\"\n (change)=\"changeVendorProvider($event)\">\n </ng-select>\n </div>\n </div> -->\n <!-- <pre>{{fieldsArray|json}}</pre> -->\n <formly-form [fields]=\"fieldsArray\" [model]=\"fieldsModel\" [form]=\"detailsForm\">\n </formly-form>\n </div>\n </div>\n }\n \n @if (fieldsArray.length === 0) {\n <sdk-no-data title=\"LABEL_FIELDS_NOT_AVAILABLE\"></sdk-no-data>\n }\n </div>\n </div>\n <div class=\"card-footer bg-light text-right\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"back()\">\n {{'COMMON_LABEL_CANCEL' | translate}}\n </button>\n @if (buttonData) {\n <button type=\"submit\" class=\"btn btn-primary\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\"\n [disabled]=\"showLoader\">\n {{ buttonData?.field_title }}\n </button>\n }\n </div>\n </form>\n </div>\n </div>\n </div>\n </section>\n </div>\n}" }]
3176
+ ], template: "\n\n@if (showWorkflowComponent) {\n \n <sdk-bill-workflow \n [selectedBill]=\"selectedBillForWorkflow\"\n (workflowCompleted)=\"onWorkflowCompleted($event)\">\n </sdk-bill-workflow>\n \n \n}@else { \n <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>{{ 'LABEL_UTILITIES' | translate }}</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\">{{ vendorProvider?.provider_name }}\n </h4>\n </div>\n <div class=\"tab-content\">\n <div class=\"tab-pane fadeIn active show\">\n <form role=\"form\" class=\"form-horizontal\" [formGroup]=\"detailsForm\" (ngSubmit)=\"submitForm()\">\n <div class=\"card-body\">\n <div class=\"mt-3\">\n @if (fieldsArray.length > 0) {\n <div class=\"row\">\n <div class=\"col-xl-5 offset-xl-3\">\n <!-- <div class=\"form-group form-row\">\n <label\n class=\"control-label text-md-right col-md-4 col-lg-3\">Provider</label>\n <div class=\"col-md-5\">\n <ng-select placeholder=\"Select Provider\" bindLabel=\"provider_name\"\n bindValue=\"id\" [items]=\"vendorProviders\"\n (change)=\"changeVendorProvider($event)\">\n </ng-select>\n </div>\n </div> -->\n <!-- <pre>{{fieldsArray|json}}</pre> -->\n <formly-form [fields]=\"fieldsArray\" [model]=\"fieldsModel\" [form]=\"detailsForm\">\n </formly-form>\n </div>\n </div>\n }\n \n @if (fieldsArray.length === 0) {\n <sdk-no-data title=\"LABEL_FIELDS_NOT_AVAILABLE\"></sdk-no-data>\n }\n </div>\n </div>\n <div class=\"card-footer bg-light text-right\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"back()\">\n {{'COMMON_LABEL_CANCEL' | translate}}\n </button>\n @if (buttonData) {\n <button type=\"submit\" class=\"btn btn-primary\"\n [ngClass]=\"{'qt-loader qt-loader-mini qt-loader-left': showLoader}\"\n [disabled]=\"showLoader || isFormIncomplete()\">\n {{ buttonData?.field_title }}\n </button>\n }\n </div>\n </form>\n </div>\n </div>\n </div>\n </section>\n </div>\n}" }]
3170
3177
  }], ctorParameters: () => [] });
3171
3178
 
3172
3179
  const REGION_COMMUNE_DATA = {
@@ -3775,7 +3782,6 @@ class ViewBillsComponent {
3775
3782
  this.topupAndBillpaymentService.workFlowUserInput.pipe(takeUntil(this.destroy$)).subscribe((data) => {
3776
3783
  if (isNotNull(data)) {
3777
3784
  this.workFlowUserInput = data;
3778
- console.log("workFlowUserInput==>", this.workFlowUserInput);
3779
3785
  if (data?.length > 1) {
3780
3786
  const latestNumericValue = data?.find((element) => element['value'] && typeof element['value'] === 'number')?.value || null;
3781
3787
  this.userAmount = latestNumericValue;
@@ -3835,6 +3841,7 @@ class ViewBillsComponent {
3835
3841
  this.showLoader = false;
3836
3842
  if (res?.success) {
3837
3843
  this.billsData = res?.data;
3844
+ this.showLoader = false;
3838
3845
  }
3839
3846
  else {
3840
3847
  this.toasterService.error(this.translationService.translate(res?.error[0]));
@@ -5906,6 +5913,7 @@ class TopupAndBillpaymentReviewComponent extends TransactionClass {
5906
5913
  this.back();
5907
5914
  }
5908
5915
  }).catch(() => undefined);
5916
+ this.topupAndBillpaymentService?.deleteWorkflowUserInput();
5909
5917
  }
5910
5918
  removeunderScore(value) {
5911
5919
  return value.replace(/_/g, ' ').split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
package/package.json CHANGED
@@ -1,9 +1,15 @@
1
1
  {
2
2
  "name": "digipay-utility-payment",
3
- "version": "0.0.12",
3
+ "version": "0.0.14",
4
4
  "peerDependencies": {
5
- "@angular/common": "^20.3.0",
6
- "@angular/core": "^20.3.0"
5
+ "@angular/common": "^20.0.0",
6
+ "@angular/core": "^20.0.0",
7
+ "@ng-select/ng-select": "^15.1.3",
8
+ "@ngx-formly/bootstrap": "^7.0.0",
9
+ "@ngx-formly/core": "^7.0.0",
10
+ "ngx-toastr": "^19.0.0",
11
+ "lodash": "^4.17.21",
12
+ "rxjs": "^7.8.0"
7
13
  },
8
14
  "dependencies": {
9
15
  "@popperjs/core": "^2.11.8",