@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.mjs CHANGED
@@ -3503,8 +3503,131 @@ var HorizontalStepper = ({
3503
3503
  };
3504
3504
  var horizontal_stepper_default = HorizontalStepper;
3505
3505
 
3506
+ // src/services/MainAPIClient.ts
3507
+ import axios from "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 = axios.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
+
3506
3617
  // src/NewSaleForm/SharedLifePlanApplication.tsx
3507
3618
  import { jsx as jsx16 } from "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
+ };
3508
3631
  var safeParse = (value) => {
3509
3632
  if (!value) return null;
3510
3633
  try {
@@ -3517,8 +3640,8 @@ var SharedLifePlanApplication = ({
3517
3640
  title = "Life Plan Application",
3518
3641
  description = "Please fill out the form below to apply for a life plan.",
3519
3642
  onPaymentError,
3520
- onCheckout,
3521
- parseAddress
3643
+ onCheckout = defaultCheckout,
3644
+ parseAddress = GeoApifyService.parseAddress
3522
3645
  }) => {
3523
3646
  const [currentStep, setCurrentStep] = useState11(0);
3524
3647
  const [loading, setLoading] = useState11(false);
@@ -3531,7 +3654,7 @@ var SharedLifePlanApplication = ({
3531
3654
  ...applicationSection ? { applicationSection } : {},
3532
3655
  applicationSectionKey,
3533
3656
  onApplicationValidChange: setApplicationValid,
3534
- ...parseAddress ? { parseAddress } : {},
3657
+ parseAddress,
3535
3658
  onEdit: (section) => {
3536
3659
  setApplicationSection(section ?? "personal");
3537
3660
  setApplicationSectionKey((key) => key + 1);
@@ -3543,9 +3666,6 @@ var SharedLifePlanApplication = ({
3543
3666
  if (!allAgreementsAccepted) return;
3544
3667
  setLoading(true);
3545
3668
  try {
3546
- if (!onCheckout) {
3547
- throw new Error("onCheckout prop is not provided");
3548
- }
3549
3669
  const checkoutRaw = sessionStorage.getItem("CheckoutCart");
3550
3670
  const cartRaw = sessionStorage.getItem("Cart");
3551
3671
  const parsed = safeParse(checkoutRaw) ?? safeParse(cartRaw);
@@ -4270,6 +4390,96 @@ function DocumentUploadCard({
4270
4390
  );
4271
4391
  }
4272
4392
 
4393
+ // src/services/OcrService.ts
4394
+ var ENDPOINTS3 = {
4395
+ scan: "/Ocr/Scan"
4396
+ };
4397
+ var isObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
4398
+ var readField = (source, keys) => {
4399
+ if (!source) return "";
4400
+ for (const key of keys) {
4401
+ const match = Object.keys(source).find(
4402
+ (k) => k.toLowerCase() === key.toLowerCase()
4403
+ );
4404
+ const value = match ? source[match] : void 0;
4405
+ if (typeof value === "string" && value.trim()) return value.trim();
4406
+ if (typeof value === "number") return String(value);
4407
+ }
4408
+ return "";
4409
+ };
4410
+ var pad = (value) => String(value).padStart(2, "0");
4411
+ var toIsoDate = (value) => {
4412
+ if (!value) return "";
4413
+ if (/^\d{4}-\d{2}-\d{2}/.test(value)) return value.slice(0, 10);
4414
+ const parts = value.split(/[/-]/).map((part) => part.trim());
4415
+ if (parts.length === 3 && parts.every(Boolean)) {
4416
+ const [first = "", second = "", third = ""] = parts;
4417
+ if (first.length === 4) return `${first}-${pad(second)}-${pad(third)}`;
4418
+ if (third.length === 4) return `${third}-${pad(first)}-${pad(second)}`;
4419
+ }
4420
+ const parsed = new Date(value);
4421
+ if (Number.isNaN(parsed.getTime())) return "";
4422
+ return `${parsed.getFullYear()}-${pad(parsed.getMonth() + 1)}-${pad(parsed.getDate())}`;
4423
+ };
4424
+ var toIdType = (value) => {
4425
+ const text = value.toLowerCase();
4426
+ if (!text) return "";
4427
+ if (text.includes("passport")) return "passport";
4428
+ if (text.includes("driver")) return "driver_license";
4429
+ if (text.includes("national") || text.includes("id")) return "national_id";
4430
+ return "";
4431
+ };
4432
+ var toOcrValue = (body) => {
4433
+ const root = isObject(body) ? body : void 0;
4434
+ const nested = root ? Object.entries(root).find(
4435
+ ([key, value]) => key.toLowerCase() === "response" && isObject(value)
4436
+ )?.[1] : void 0;
4437
+ const source = isObject(nested) ? nested : root;
4438
+ return {
4439
+ firstName: readField(source, ["firstName"]),
4440
+ middleName: readField(source, ["middleName"]),
4441
+ lastName: readField(source, ["lastName"]),
4442
+ birthDate: toIsoDate(readField(source, ["birthDate", "dateOfBirth"])),
4443
+ idType: toIdType(readField(source, ["idType"])),
4444
+ idNumber: readField(source, ["idNumber", "idNo"]),
4445
+ addressLine: readField(source, ["addressLine", "address", "completeAddress"])
4446
+ };
4447
+ };
4448
+ var toFormData = (docType, source) => {
4449
+ const formData = new FormData();
4450
+ formData.append("DocType", docType);
4451
+ if (typeof source === "string") {
4452
+ formData.append("OCRType", "URL");
4453
+ formData.append("ImageUrl", source.trim());
4454
+ } else {
4455
+ formData.append("OCRType", "File");
4456
+ formData.append("File", source);
4457
+ }
4458
+ return formData;
4459
+ };
4460
+ var OcrService = {
4461
+ async scan(docType, source) {
4462
+ return api.post(ENDPOINTS3.scan, toFormData(docType, source), {
4463
+ headers: { "Content-Type": "multipart/form-data" },
4464
+ timeout: 9e4
4465
+ });
4466
+ },
4467
+ async scanId(source) {
4468
+ const body = await OcrService.scan("ID", source);
4469
+ const result = toOcrValue(body);
4470
+ if (!result.firstName && !result.lastName && !result.idNumber) {
4471
+ const description = isObject(body) ? readField(body, ["description", "message"]) : "";
4472
+ throw new APIError(
4473
+ description || "We couldn't read your ID. Please upload a clearer photo."
4474
+ );
4475
+ }
4476
+ return result;
4477
+ },
4478
+ async scanLpa(source) {
4479
+ return OcrService.scan("LPA", source);
4480
+ }
4481
+ };
4482
+
4273
4483
  // src/GetStarted/GetStarted.tsx
4274
4484
  import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
4275
4485
  var defaultNotify = (type, message) => {
@@ -4299,7 +4509,7 @@ var SIGNATURE_CONFIG = {
4299
4509
  icon: LuSignature
4300
4510
  };
4301
4511
  var GetStarted = ({
4302
- scanId: scanIdFn,
4512
+ scanId: scanIdFn = OcrService.scanId,
4303
4513
  onContinue,
4304
4514
  notify = defaultNotify
4305
4515
  }) => {
@@ -6469,9 +6679,11 @@ function ReusableProfile({
6469
6679
  }
6470
6680
  var UserProfile_default = ReusableProfile;
6471
6681
  export {
6682
+ APIError,
6472
6683
  beneficiary_default as Beneficiary,
6473
6684
  BottomQuickActions_default as BottomQuickActions,
6474
6685
  DocumentUploadCard,
6686
+ GeoApifyService,
6475
6687
  GetStarted_default as GetStarted,
6476
6688
  HealthDeclaration_default as HealthDeclaration,
6477
6689
  LifePlanApplication1_default as LifePlanApplication1,
@@ -6481,9 +6693,14 @@ export {
6481
6693
  LifePlanApplicationStepWrapper_default as LifePlanApplicationStepWrapper,
6482
6694
  NotifyInstall,
6483
6695
  OCR_STORAGE_KEY,
6696
+ OcrService,
6697
+ PayMongoService,
6484
6698
  SharedLifePlanApplication_default as SharedLifePlanApplication,
6485
6699
  UserProfile_default as UserProfile,
6700
+ api,
6701
+ apiClient,
6486
6702
  clearOcrResult,
6703
+ configureApi,
6487
6704
  createEmptyApplicationData,
6488
6705
  loadApplicationDataFromLocalStorage,
6489
6706
  markOcrApplied,