@splpi/estore-shared-components 7.0.3 → 7.0.4

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.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
+ import * as axios from 'axios';
4
+ import { AxiosRequestConfig } from 'axios';
3
5
  import { IconType } from 'react-icons';
4
6
 
5
7
  interface IPersonalInfo {
@@ -154,10 +156,10 @@ type SharedLifePlanApplicationProps = {
154
156
  onPaymentError?: (error: unknown) => void;
155
157
  /**
156
158
  * Called on the payment step with the cart items and application data.
157
- * Must return the checkout URL (e.g. from PayMongoService.createNewSalesCheckout).
159
+ * Must return the checkout URL. Defaults to the built-in PayMongoService (test account).
158
160
  */
159
161
  onCheckout?: (request: NewSalesCheckoutRequest) => Promise<string | undefined>;
160
- /** Optional address parser used to fill the address form from the scanned ID. */
162
+ /** Address parser used to fill the address form from the scanned ID. Defaults to GeoApifyService.parseAddress. */
161
163
  parseAddress?: (addressLine: string) => Promise<IParsedAddress>;
162
164
  };
163
165
  declare const SharedLifePlanApplication: ({ title, description, onPaymentError, onCheckout, parseAddress, }: SharedLifePlanApplicationProps) => react_jsx_runtime.JSX.Element;
@@ -190,8 +192,8 @@ declare function useOcr(scanIdFn: ScanIdFn): {
190
192
 
191
193
  type GetStartedNotifyType = "info" | "error";
192
194
  type GetStartedProps = {
193
- /** Host app's ID scanner, e.g. `OcrService.scanId`. The result is saved for form autofill. */
194
- scanId: ScanIdFn;
195
+ /** ID scanner. Defaults to the built-in `OcrService.scanId`. The result is saved for form autofill. */
196
+ scanId?: ScanIdFn;
195
197
  /** Called on Skip / Continue in the Referral Agent dialog, e.g. `() => router.push("/lifeplan-application")`. */
196
198
  onContinue?: () => void;
197
199
  /** Shows a message to the user, e.g. `(type, msg) => toast[type](msg)`. Defaults to console. */
@@ -229,6 +231,81 @@ declare function DocumentUploadCard({ config, onStatusChange, onProcess, onError
229
231
  onError?: (message: string) => void;
230
232
  }): react_jsx_runtime.JSX.Element;
231
233
 
234
+ declare class APIError extends Error {
235
+ status?: number | undefined;
236
+ constructor(message: string, status?: number);
237
+ }
238
+ declare const apiClient: axios.AxiosInstance;
239
+ /** Sets the API base URL used by the shared services (OCR, address, PayMongo). */
240
+ declare const configureApi: (options: {
241
+ baseUrl: string;
242
+ }) => void;
243
+ declare const api: {
244
+ get: <TResponse>(url: string, params?: Record<string, unknown>, config?: AxiosRequestConfig) => Promise<TResponse>;
245
+ post: <TResponse, TPayload = unknown>(url: string, payload?: TPayload, config?: AxiosRequestConfig) => Promise<TResponse>;
246
+ put: <TResponse, TPayload = unknown>(url: string, payload?: TPayload, config?: AxiosRequestConfig) => Promise<TResponse>;
247
+ delete: <TResponse>(url: string, config?: AxiosRequestConfig) => Promise<TResponse>;
248
+ };
249
+
250
+ type OcrDocType = "ID" | "LPA";
251
+ type OcrSource = File | string;
252
+ declare const OcrService: {
253
+ scan(docType: OcrDocType, source: OcrSource): Promise<unknown>;
254
+ scanId(source: OcrSource): Promise<IOcrValue>;
255
+ scanLpa(source: OcrSource): Promise<unknown>;
256
+ };
257
+
258
+ declare const GeoApifyService: {
259
+ parseAddress(text: string): Promise<IParsedAddress>;
260
+ };
261
+
262
+ /**
263
+ * PayMongoService
264
+ * ---------------
265
+ * Creates a PayMongo checkout through the C# API (eStoreV2API -> PayMongoAPIController)
266
+ * and returns the payment page link.
267
+ *
268
+ * C# endpoint: POST /CheckOut
269
+ * C# expects: { items: [{ planDesc, productCode, contractPrice, ipInstAmt, planTerm, quantity }] }
270
+ * C# returns: { checkoutUrl: "https://checkout.paymongo.com/..." }
271
+ *
272
+ * Example:
273
+ * const { checkoutUrl } = await PayMongoService.createCheckout([{ planDesc: "ST. ANNE", ipInstAmt: 1500, quantity: 1 }]);
274
+ * window.location.href = checkoutUrl;
275
+ */
276
+ interface ICheckoutItem {
277
+ planDesc: string;
278
+ ipInstAmt: number;
279
+ quantity: number;
280
+ planTerm?: string | number;
281
+ productCode?: string;
282
+ contractPrice?: number;
283
+ }
284
+ interface ICheckoutResult {
285
+ checkoutUrl?: string | undefined;
286
+ }
287
+ interface INewSalesCheckoutItem {
288
+ planDesc: string;
289
+ mode: string;
290
+ ipInstAmt: number;
291
+ quantity: number;
292
+ planTerm?: string | number;
293
+ }
294
+ interface INewSalesCheckoutRequest {
295
+ items: INewSalesCheckoutItem[];
296
+ application: ITransactionData;
297
+ accountNo?: string;
298
+ empCode?: string;
299
+ }
300
+ interface INewSalesCheckoutResult {
301
+ checkoutUrl?: string | undefined;
302
+ requestId?: string | undefined;
303
+ }
304
+ declare const PayMongoService: {
305
+ createCheckout(items: ICheckoutItem[]): Promise<ICheckoutResult>;
306
+ createNewSalesCheckout(request: INewSalesCheckoutRequest): Promise<INewSalesCheckoutResult>;
307
+ };
308
+
232
309
  type QuickAction = {
233
310
  /** React Icons icon component */
234
311
  icon: IconType;
@@ -315,4 +392,4 @@ declare const createEmptyApplicationData: () => IApplicationData;
315
392
  declare const loadApplicationDataFromLocalStorage: (storageKey?: string) => IApplicationData | null;
316
393
  declare const saveApplicationDataToLocalStorage: (data: IApplicationData, storageKey?: string) => void;
317
394
 
318
- export { Beneficiary, type BeneficiaryClass, BottomQuickActions, type CartItem, type DocumentStatus, type DocumentTypeConfig, DocumentUploadCard, GetStarted, type GetStartedNotifyType, type GetStartedProps, HealthDeclaration, type IAddress, type IApplicationData, type IBeneficiary, type IEmployment, type IHealthDeclaration, type IOcrValue, type IParsedAddress, type IPersonalInfo, type ITransactionData, LifePlanApplication1, LifePlanApplication2, LifePlanApplication3, LifePlanApplicationFormWrapper, LifePlanApplicationStepWrapper, type NavOptionDef, type NewSalesCheckoutItem, type NewSalesCheckoutRequest, NotifyInstall, OCR_STORAGE_KEY, type OcrSection, type ProfileUser, type ReusableProfileProps, type ScanIdFn, SharedLifePlanApplication, type SharedLifePlanApplicationProps, ReusableProfile as UserProfile, clearOcrResult, createEmptyApplicationData, loadApplicationDataFromLocalStorage, markOcrApplied, readOcrResult, saveApplicationDataToLocalStorage, saveOcrResult, useOcr };
395
+ export { APIError, Beneficiary, type BeneficiaryClass, BottomQuickActions, type CartItem, type DocumentStatus, type DocumentTypeConfig, DocumentUploadCard, GeoApifyService, GetStarted, type GetStartedNotifyType, type GetStartedProps, HealthDeclaration, type IAddress, type IApplicationData, type IBeneficiary, type ICheckoutItem, type ICheckoutResult, type IEmployment, type IHealthDeclaration, type INewSalesCheckoutItem, type INewSalesCheckoutRequest, type INewSalesCheckoutResult, type IOcrValue, type IParsedAddress, type IPersonalInfo, type ITransactionData, LifePlanApplication1, LifePlanApplication2, LifePlanApplication3, LifePlanApplicationFormWrapper, LifePlanApplicationStepWrapper, type NavOptionDef, type NewSalesCheckoutItem, type NewSalesCheckoutRequest, NotifyInstall, OCR_STORAGE_KEY, type OcrDocType, type OcrSection, OcrService, type OcrSource, PayMongoService, type ProfileUser, type ReusableProfileProps, type ScanIdFn, SharedLifePlanApplication, type SharedLifePlanApplicationProps, ReusableProfile as UserProfile, api, apiClient, clearOcrResult, configureApi, createEmptyApplicationData, loadApplicationDataFromLocalStorage, markOcrApplied, readOcrResult, saveApplicationDataToLocalStorage, saveOcrResult, useOcr };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React$1 from 'react';
3
+ import * as axios from 'axios';
4
+ import { AxiosRequestConfig } from 'axios';
3
5
  import { IconType } from 'react-icons';
4
6
 
5
7
  interface IPersonalInfo {
@@ -154,10 +156,10 @@ type SharedLifePlanApplicationProps = {
154
156
  onPaymentError?: (error: unknown) => void;
155
157
  /**
156
158
  * Called on the payment step with the cart items and application data.
157
- * Must return the checkout URL (e.g. from PayMongoService.createNewSalesCheckout).
159
+ * Must return the checkout URL. Defaults to the built-in PayMongoService (test account).
158
160
  */
159
161
  onCheckout?: (request: NewSalesCheckoutRequest) => Promise<string | undefined>;
160
- /** Optional address parser used to fill the address form from the scanned ID. */
162
+ /** Address parser used to fill the address form from the scanned ID. Defaults to GeoApifyService.parseAddress. */
161
163
  parseAddress?: (addressLine: string) => Promise<IParsedAddress>;
162
164
  };
163
165
  declare const SharedLifePlanApplication: ({ title, description, onPaymentError, onCheckout, parseAddress, }: SharedLifePlanApplicationProps) => react_jsx_runtime.JSX.Element;
@@ -190,8 +192,8 @@ declare function useOcr(scanIdFn: ScanIdFn): {
190
192
 
191
193
  type GetStartedNotifyType = "info" | "error";
192
194
  type GetStartedProps = {
193
- /** Host app's ID scanner, e.g. `OcrService.scanId`. The result is saved for form autofill. */
194
- scanId: ScanIdFn;
195
+ /** ID scanner. Defaults to the built-in `OcrService.scanId`. The result is saved for form autofill. */
196
+ scanId?: ScanIdFn;
195
197
  /** Called on Skip / Continue in the Referral Agent dialog, e.g. `() => router.push("/lifeplan-application")`. */
196
198
  onContinue?: () => void;
197
199
  /** Shows a message to the user, e.g. `(type, msg) => toast[type](msg)`. Defaults to console. */
@@ -229,6 +231,81 @@ declare function DocumentUploadCard({ config, onStatusChange, onProcess, onError
229
231
  onError?: (message: string) => void;
230
232
  }): react_jsx_runtime.JSX.Element;
231
233
 
234
+ declare class APIError extends Error {
235
+ status?: number | undefined;
236
+ constructor(message: string, status?: number);
237
+ }
238
+ declare const apiClient: axios.AxiosInstance;
239
+ /** Sets the API base URL used by the shared services (OCR, address, PayMongo). */
240
+ declare const configureApi: (options: {
241
+ baseUrl: string;
242
+ }) => void;
243
+ declare const api: {
244
+ get: <TResponse>(url: string, params?: Record<string, unknown>, config?: AxiosRequestConfig) => Promise<TResponse>;
245
+ post: <TResponse, TPayload = unknown>(url: string, payload?: TPayload, config?: AxiosRequestConfig) => Promise<TResponse>;
246
+ put: <TResponse, TPayload = unknown>(url: string, payload?: TPayload, config?: AxiosRequestConfig) => Promise<TResponse>;
247
+ delete: <TResponse>(url: string, config?: AxiosRequestConfig) => Promise<TResponse>;
248
+ };
249
+
250
+ type OcrDocType = "ID" | "LPA";
251
+ type OcrSource = File | string;
252
+ declare const OcrService: {
253
+ scan(docType: OcrDocType, source: OcrSource): Promise<unknown>;
254
+ scanId(source: OcrSource): Promise<IOcrValue>;
255
+ scanLpa(source: OcrSource): Promise<unknown>;
256
+ };
257
+
258
+ declare const GeoApifyService: {
259
+ parseAddress(text: string): Promise<IParsedAddress>;
260
+ };
261
+
262
+ /**
263
+ * PayMongoService
264
+ * ---------------
265
+ * Creates a PayMongo checkout through the C# API (eStoreV2API -> PayMongoAPIController)
266
+ * and returns the payment page link.
267
+ *
268
+ * C# endpoint: POST /CheckOut
269
+ * C# expects: { items: [{ planDesc, productCode, contractPrice, ipInstAmt, planTerm, quantity }] }
270
+ * C# returns: { checkoutUrl: "https://checkout.paymongo.com/..." }
271
+ *
272
+ * Example:
273
+ * const { checkoutUrl } = await PayMongoService.createCheckout([{ planDesc: "ST. ANNE", ipInstAmt: 1500, quantity: 1 }]);
274
+ * window.location.href = checkoutUrl;
275
+ */
276
+ interface ICheckoutItem {
277
+ planDesc: string;
278
+ ipInstAmt: number;
279
+ quantity: number;
280
+ planTerm?: string | number;
281
+ productCode?: string;
282
+ contractPrice?: number;
283
+ }
284
+ interface ICheckoutResult {
285
+ checkoutUrl?: string | undefined;
286
+ }
287
+ interface INewSalesCheckoutItem {
288
+ planDesc: string;
289
+ mode: string;
290
+ ipInstAmt: number;
291
+ quantity: number;
292
+ planTerm?: string | number;
293
+ }
294
+ interface INewSalesCheckoutRequest {
295
+ items: INewSalesCheckoutItem[];
296
+ application: ITransactionData;
297
+ accountNo?: string;
298
+ empCode?: string;
299
+ }
300
+ interface INewSalesCheckoutResult {
301
+ checkoutUrl?: string | undefined;
302
+ requestId?: string | undefined;
303
+ }
304
+ declare const PayMongoService: {
305
+ createCheckout(items: ICheckoutItem[]): Promise<ICheckoutResult>;
306
+ createNewSalesCheckout(request: INewSalesCheckoutRequest): Promise<INewSalesCheckoutResult>;
307
+ };
308
+
232
309
  type QuickAction = {
233
310
  /** React Icons icon component */
234
311
  icon: IconType;
@@ -315,4 +392,4 @@ declare const createEmptyApplicationData: () => IApplicationData;
315
392
  declare const loadApplicationDataFromLocalStorage: (storageKey?: string) => IApplicationData | null;
316
393
  declare const saveApplicationDataToLocalStorage: (data: IApplicationData, storageKey?: string) => void;
317
394
 
318
- export { Beneficiary, type BeneficiaryClass, BottomQuickActions, type CartItem, type DocumentStatus, type DocumentTypeConfig, DocumentUploadCard, GetStarted, type GetStartedNotifyType, type GetStartedProps, HealthDeclaration, type IAddress, type IApplicationData, type IBeneficiary, type IEmployment, type IHealthDeclaration, type IOcrValue, type IParsedAddress, type IPersonalInfo, type ITransactionData, LifePlanApplication1, LifePlanApplication2, LifePlanApplication3, LifePlanApplicationFormWrapper, LifePlanApplicationStepWrapper, type NavOptionDef, type NewSalesCheckoutItem, type NewSalesCheckoutRequest, NotifyInstall, OCR_STORAGE_KEY, type OcrSection, type ProfileUser, type ReusableProfileProps, type ScanIdFn, SharedLifePlanApplication, type SharedLifePlanApplicationProps, ReusableProfile as UserProfile, clearOcrResult, createEmptyApplicationData, loadApplicationDataFromLocalStorage, markOcrApplied, readOcrResult, saveApplicationDataToLocalStorage, saveOcrResult, useOcr };
395
+ export { APIError, Beneficiary, type BeneficiaryClass, BottomQuickActions, type CartItem, type DocumentStatus, type DocumentTypeConfig, DocumentUploadCard, GeoApifyService, GetStarted, type GetStartedNotifyType, type GetStartedProps, HealthDeclaration, type IAddress, type IApplicationData, type IBeneficiary, type ICheckoutItem, type ICheckoutResult, type IEmployment, type IHealthDeclaration, type INewSalesCheckoutItem, type INewSalesCheckoutRequest, type INewSalesCheckoutResult, type IOcrValue, type IParsedAddress, type IPersonalInfo, type ITransactionData, LifePlanApplication1, LifePlanApplication2, LifePlanApplication3, LifePlanApplicationFormWrapper, LifePlanApplicationStepWrapper, type NavOptionDef, type NewSalesCheckoutItem, type NewSalesCheckoutRequest, NotifyInstall, OCR_STORAGE_KEY, type OcrDocType, type OcrSection, OcrService, type OcrSource, PayMongoService, type ProfileUser, type ReusableProfileProps, type ScanIdFn, SharedLifePlanApplication, type SharedLifePlanApplicationProps, ReusableProfile as UserProfile, api, apiClient, clearOcrResult, configureApi, createEmptyApplicationData, loadApplicationDataFromLocalStorage, markOcrApplied, readOcrResult, saveApplicationDataToLocalStorage, saveOcrResult, useOcr };
package/dist/index.js CHANGED
@@ -30,9 +30,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ APIError: () => APIError,
33
34
  Beneficiary: () => beneficiary_default,
34
35
  BottomQuickActions: () => BottomQuickActions_default,
35
36
  DocumentUploadCard: () => DocumentUploadCard,
37
+ GeoApifyService: () => GeoApifyService,
36
38
  GetStarted: () => GetStarted_default,
37
39
  HealthDeclaration: () => HealthDeclaration_default,
38
40
  LifePlanApplication1: () => LifePlanApplication1_default,
@@ -42,9 +44,14 @@ __export(index_exports, {
42
44
  LifePlanApplicationStepWrapper: () => LifePlanApplicationStepWrapper_default,
43
45
  NotifyInstall: () => NotifyInstall,
44
46
  OCR_STORAGE_KEY: () => OCR_STORAGE_KEY,
47
+ OcrService: () => OcrService,
48
+ PayMongoService: () => PayMongoService,
45
49
  SharedLifePlanApplication: () => SharedLifePlanApplication_default,
46
50
  UserProfile: () => UserProfile_default,
51
+ api: () => api,
52
+ apiClient: () => apiClient,
47
53
  clearOcrResult: () => clearOcrResult,
54
+ configureApi: () => configureApi,
48
55
  createEmptyApplicationData: () => createEmptyApplicationData,
49
56
  loadApplicationDataFromLocalStorage: () => loadApplicationDataFromLocalStorage,
50
57
  markOcrApplied: () => markOcrApplied,
@@ -3496,8 +3503,131 @@ var HorizontalStepper = ({
3496
3503
  };
3497
3504
  var horizontal_stepper_default = HorizontalStepper;
3498
3505
 
3506
+ // src/services/MainAPIClient.ts
3507
+ var import_axios = __toESM(require("axios"));
3508
+ var APIError = class extends Error {
3509
+ status;
3510
+ constructor(message, status) {
3511
+ super(message);
3512
+ this.name = "APIError";
3513
+ this.status = status;
3514
+ }
3515
+ };
3516
+ var readEnvBaseUrl = () => {
3517
+ try {
3518
+ return process.env.NEXT_PUBLIC_API_URL;
3519
+ } catch {
3520
+ return void 0;
3521
+ }
3522
+ };
3523
+ var apiClient = import_axios.default.create({
3524
+ baseURL: readEnvBaseUrl() ?? "",
3525
+ timeout: 15e3,
3526
+ headers: {
3527
+ "Content-Type": "application/json"
3528
+ }
3529
+ });
3530
+ var configureApi = (options) => {
3531
+ apiClient.defaults.baseURL = options.baseUrl;
3532
+ };
3533
+ apiClient.interceptors.request.use((config) => {
3534
+ if (!config.baseURL) {
3535
+ throw new APIError(
3536
+ "API URL is not set. Add NEXT_PUBLIC_API_URL to .env.local or call configureApi({ baseUrl })."
3537
+ );
3538
+ }
3539
+ return config;
3540
+ });
3541
+ apiClient.interceptors.response.use(
3542
+ (response) => response,
3543
+ (error) => {
3544
+ if (error instanceof APIError) return Promise.reject(error);
3545
+ const status = error.response?.status;
3546
+ const message = error.response?.data?.message || error.message || "Something went wrong";
3547
+ console.error(`[API] ${error.config?.method?.toUpperCase()} ${error.config?.url} failed (${status ?? "no response"}):`, message);
3548
+ return Promise.reject(new APIError(message, status));
3549
+ }
3550
+ );
3551
+ var api = {
3552
+ get: (url, params, config) => apiClient.get(url, { ...config, params }).then((res) => res.data),
3553
+ post: (url, payload, config) => apiClient.post(url, payload, config).then((res) => res.data),
3554
+ put: (url, payload, config) => apiClient.put(url, payload, config).then((res) => res.data),
3555
+ delete: (url, config) => apiClient.delete(url, config).then((res) => res.data)
3556
+ };
3557
+
3558
+ // src/services/GeoApifyService.ts
3559
+ var ENDPOINTS = {
3560
+ parse: "/Address/Parse"
3561
+ };
3562
+ var GeoApifyService = {
3563
+ async parseAddress(text) {
3564
+ return api.get(ENDPOINTS.parse, {
3565
+ text: text.replace(/\s+/g, " ").trim()
3566
+ });
3567
+ }
3568
+ };
3569
+
3570
+ // src/services/PayMongoService.ts
3571
+ var ENDPOINTS2 = {
3572
+ checkout: "/PayMongoAPI/CreateCheckout",
3573
+ newSalesCheckout: "/PayMongoAPI/CreateNewSalesCheckout"
3574
+ };
3575
+ var toWholeNumber = (value) => {
3576
+ const n = Number(value);
3577
+ return value !== void 0 && value !== "" && Number.isFinite(n) ? Math.trunc(n) : void 0;
3578
+ };
3579
+ var toApiItem = (item) => ({
3580
+ planDesc: item.planDesc,
3581
+ ipInstAmt: Number(item.ipInstAmt),
3582
+ quantity: toWholeNumber(item.quantity) ?? 1,
3583
+ planTerm: toWholeNumber(item.planTerm),
3584
+ productCode: item.productCode,
3585
+ contractPrice: item.contractPrice
3586
+ });
3587
+ var PayMongoService = {
3588
+ async createCheckout(items) {
3589
+ const body = { items: items.map(toApiItem) };
3590
+ console.log("PayMongoService: body =", body);
3591
+ console.log("PayMongoService: ENDPOINTS.checkout =", ENDPOINTS2.checkout);
3592
+ const res = await api.post(ENDPOINTS2.checkout, body);
3593
+ return { checkoutUrl: res?.checkoutUrl };
3594
+ },
3595
+ async createNewSalesCheckout(request) {
3596
+ const body = {
3597
+ items: request.items.map((item) => ({
3598
+ planDesc: item.planDesc,
3599
+ mode: item.mode,
3600
+ ipInstAmt: Number(item.ipInstAmt),
3601
+ quantity: toWholeNumber(item.quantity) ?? 1,
3602
+ planTerm: toWholeNumber(item.planTerm)
3603
+ })),
3604
+ application: request.application,
3605
+ accountNo: request.accountNo ?? "",
3606
+ empCode: request.empCode ?? ""
3607
+ };
3608
+ const res = await api.post(
3609
+ ENDPOINTS2.newSalesCheckout,
3610
+ body,
3611
+ { timeout: 6e4 }
3612
+ );
3613
+ return { checkoutUrl: res?.checkoutUrl, requestId: res?.requestId };
3614
+ }
3615
+ };
3616
+
3499
3617
  // src/NewSaleForm/SharedLifePlanApplication.tsx
3500
3618
  var import_jsx_runtime16 = require("react/jsx-runtime");
3619
+ var TEST_ACCOUNT_NO = "SPLPI-22-000021";
3620
+ var defaultCheckout = async ({
3621
+ items,
3622
+ application
3623
+ }) => {
3624
+ const { checkoutUrl } = await PayMongoService.createNewSalesCheckout({
3625
+ items,
3626
+ application,
3627
+ accountNo: TEST_ACCOUNT_NO
3628
+ });
3629
+ return checkoutUrl;
3630
+ };
3501
3631
  var safeParse = (value) => {
3502
3632
  if (!value) return null;
3503
3633
  try {
@@ -3510,8 +3640,8 @@ var SharedLifePlanApplication = ({
3510
3640
  title = "Life Plan Application",
3511
3641
  description = "Please fill out the form below to apply for a life plan.",
3512
3642
  onPaymentError,
3513
- onCheckout,
3514
- parseAddress
3643
+ onCheckout = defaultCheckout,
3644
+ parseAddress = GeoApifyService.parseAddress
3515
3645
  }) => {
3516
3646
  const [currentStep, setCurrentStep] = (0, import_react27.useState)(0);
3517
3647
  const [loading, setLoading] = (0, import_react27.useState)(false);
@@ -3524,7 +3654,7 @@ var SharedLifePlanApplication = ({
3524
3654
  ...applicationSection ? { applicationSection } : {},
3525
3655
  applicationSectionKey,
3526
3656
  onApplicationValidChange: setApplicationValid,
3527
- ...parseAddress ? { parseAddress } : {},
3657
+ parseAddress,
3528
3658
  onEdit: (section) => {
3529
3659
  setApplicationSection(section ?? "personal");
3530
3660
  setApplicationSectionKey((key) => key + 1);
@@ -3536,9 +3666,6 @@ var SharedLifePlanApplication = ({
3536
3666
  if (!allAgreementsAccepted) return;
3537
3667
  setLoading(true);
3538
3668
  try {
3539
- if (!onCheckout) {
3540
- throw new Error("onCheckout prop is not provided");
3541
- }
3542
3669
  const checkoutRaw = sessionStorage.getItem("CheckoutCart");
3543
3670
  const cartRaw = sessionStorage.getItem("Cart");
3544
3671
  const parsed = safeParse(checkoutRaw) ?? safeParse(cartRaw);
@@ -4237,6 +4364,96 @@ function DocumentUploadCard({
4237
4364
  );
4238
4365
  }
4239
4366
 
4367
+ // src/services/OcrService.ts
4368
+ var ENDPOINTS3 = {
4369
+ scan: "/Ocr/Scan"
4370
+ };
4371
+ var isObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
4372
+ var readField = (source, keys) => {
4373
+ if (!source) return "";
4374
+ for (const key of keys) {
4375
+ const match = Object.keys(source).find(
4376
+ (k) => k.toLowerCase() === key.toLowerCase()
4377
+ );
4378
+ const value = match ? source[match] : void 0;
4379
+ if (typeof value === "string" && value.trim()) return value.trim();
4380
+ if (typeof value === "number") return String(value);
4381
+ }
4382
+ return "";
4383
+ };
4384
+ var pad = (value) => String(value).padStart(2, "0");
4385
+ var toIsoDate = (value) => {
4386
+ if (!value) return "";
4387
+ if (/^\d{4}-\d{2}-\d{2}/.test(value)) return value.slice(0, 10);
4388
+ const parts = value.split(/[/-]/).map((part) => part.trim());
4389
+ if (parts.length === 3 && parts.every(Boolean)) {
4390
+ const [first = "", second = "", third = ""] = parts;
4391
+ if (first.length === 4) return `${first}-${pad(second)}-${pad(third)}`;
4392
+ if (third.length === 4) return `${third}-${pad(first)}-${pad(second)}`;
4393
+ }
4394
+ const parsed = new Date(value);
4395
+ if (Number.isNaN(parsed.getTime())) return "";
4396
+ return `${parsed.getFullYear()}-${pad(parsed.getMonth() + 1)}-${pad(parsed.getDate())}`;
4397
+ };
4398
+ var toIdType = (value) => {
4399
+ const text = value.toLowerCase();
4400
+ if (!text) return "";
4401
+ if (text.includes("passport")) return "passport";
4402
+ if (text.includes("driver")) return "driver_license";
4403
+ if (text.includes("national") || text.includes("id")) return "national_id";
4404
+ return "";
4405
+ };
4406
+ var toOcrValue = (body) => {
4407
+ const root = isObject(body) ? body : void 0;
4408
+ const nested = root ? Object.entries(root).find(
4409
+ ([key, value]) => key.toLowerCase() === "response" && isObject(value)
4410
+ )?.[1] : void 0;
4411
+ const source = isObject(nested) ? nested : root;
4412
+ return {
4413
+ firstName: readField(source, ["firstName"]),
4414
+ middleName: readField(source, ["middleName"]),
4415
+ lastName: readField(source, ["lastName"]),
4416
+ birthDate: toIsoDate(readField(source, ["birthDate", "dateOfBirth"])),
4417
+ idType: toIdType(readField(source, ["idType"])),
4418
+ idNumber: readField(source, ["idNumber", "idNo"]),
4419
+ addressLine: readField(source, ["addressLine", "address", "completeAddress"])
4420
+ };
4421
+ };
4422
+ var toFormData = (docType, source) => {
4423
+ const formData = new FormData();
4424
+ formData.append("DocType", docType);
4425
+ if (typeof source === "string") {
4426
+ formData.append("OCRType", "URL");
4427
+ formData.append("ImageUrl", source.trim());
4428
+ } else {
4429
+ formData.append("OCRType", "File");
4430
+ formData.append("File", source);
4431
+ }
4432
+ return formData;
4433
+ };
4434
+ var OcrService = {
4435
+ async scan(docType, source) {
4436
+ return api.post(ENDPOINTS3.scan, toFormData(docType, source), {
4437
+ headers: { "Content-Type": "multipart/form-data" },
4438
+ timeout: 9e4
4439
+ });
4440
+ },
4441
+ async scanId(source) {
4442
+ const body = await OcrService.scan("ID", source);
4443
+ const result = toOcrValue(body);
4444
+ if (!result.firstName && !result.lastName && !result.idNumber) {
4445
+ const description = isObject(body) ? readField(body, ["description", "message"]) : "";
4446
+ throw new APIError(
4447
+ description || "We couldn't read your ID. Please upload a clearer photo."
4448
+ );
4449
+ }
4450
+ return result;
4451
+ },
4452
+ async scanLpa(source) {
4453
+ return OcrService.scan("LPA", source);
4454
+ }
4455
+ };
4456
+
4240
4457
  // src/GetStarted/GetStarted.tsx
4241
4458
  var import_jsx_runtime20 = require("react/jsx-runtime");
4242
4459
  var defaultNotify = (type, message) => {
@@ -4266,7 +4483,7 @@ var SIGNATURE_CONFIG = {
4266
4483
  icon: import_lu7.LuSignature
4267
4484
  };
4268
4485
  var GetStarted = ({
4269
- scanId: scanIdFn,
4486
+ scanId: scanIdFn = OcrService.scanId,
4270
4487
  onContinue,
4271
4488
  notify = defaultNotify
4272
4489
  }) => {
@@ -6379,9 +6596,11 @@ function ReusableProfile({
6379
6596
  var UserProfile_default = ReusableProfile;
6380
6597
  // Annotate the CommonJS export names for ESM import in node:
6381
6598
  0 && (module.exports = {
6599
+ APIError,
6382
6600
  Beneficiary,
6383
6601
  BottomQuickActions,
6384
6602
  DocumentUploadCard,
6603
+ GeoApifyService,
6385
6604
  GetStarted,
6386
6605
  HealthDeclaration,
6387
6606
  LifePlanApplication1,
@@ -6391,9 +6610,14 @@ var UserProfile_default = ReusableProfile;
6391
6610
  LifePlanApplicationStepWrapper,
6392
6611
  NotifyInstall,
6393
6612
  OCR_STORAGE_KEY,
6613
+ OcrService,
6614
+ PayMongoService,
6394
6615
  SharedLifePlanApplication,
6395
6616
  UserProfile,
6617
+ api,
6618
+ apiClient,
6396
6619
  clearOcrResult,
6620
+ configureApi,
6397
6621
  createEmptyApplicationData,
6398
6622
  loadApplicationDataFromLocalStorage,
6399
6623
  markOcrApplied,