@lookiero/checkout 10.0.0-beta.4 → 10.0.0

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.
Files changed (82) hide show
  1. package/dist/fake-dependencies/@lookiero/payments-front/index.d.ts +6 -8
  2. package/dist/fake-dependencies/@lookiero/payments-front/index.js +4 -7
  3. package/dist/index.d.ts +4 -3
  4. package/dist/src/ExpoRoot.js +13 -17
  5. package/dist/src/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.d.ts +1 -1
  6. package/dist/src/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.js +0 -2
  7. package/dist/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.d.ts +1 -1
  8. package/dist/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.js +1 -2
  9. package/dist/src/infrastructure/tracking/tracking.d.ts +2 -2
  10. package/dist/src/infrastructure/tracking/useTrackCheckout.d.ts +17 -10
  11. package/dist/src/infrastructure/tracking/useTrackCheckout.js +12 -27
  12. package/dist/src/infrastructure/ui/Root.d.ts +9 -7
  13. package/dist/src/infrastructure/ui/Root.js +3 -2
  14. package/dist/src/infrastructure/ui/hooks/usePaymentInstrumentEvents.d.ts +2 -3
  15. package/dist/src/infrastructure/ui/hooks/usePaymentInstrumentEvents.js +26 -17
  16. package/dist/src/infrastructure/ui/hooks/useStaticInfo.d.ts +3 -0
  17. package/dist/src/infrastructure/ui/hooks/useStaticInfo.js +7 -2
  18. package/dist/src/infrastructure/ui/i18n/i18n.d.ts +0 -1
  19. package/dist/src/infrastructure/ui/i18n/i18n.js +0 -1
  20. package/dist/src/infrastructure/ui/routing/CheckoutMiddleware.js +12 -1
  21. package/dist/src/infrastructure/ui/routing/Routing.d.ts +7 -5
  22. package/dist/src/infrastructure/ui/routing/Routing.js +11 -3
  23. package/dist/src/infrastructure/ui/routing/routes.d.ts +1 -0
  24. package/dist/src/infrastructure/ui/routing/routes.js +1 -0
  25. package/dist/src/infrastructure/ui/views/App.js +6 -5
  26. package/dist/src/infrastructure/ui/views/checkout/Checkout.d.ts +2 -7
  27. package/dist/src/infrastructure/ui/views/checkout/Checkout.js +9 -20
  28. package/dist/src/infrastructure/ui/views/checkout/Checkout.style.d.ts +0 -3
  29. package/dist/src/infrastructure/ui/views/checkout/Checkout.style.js +0 -3
  30. package/dist/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.js +1 -3
  31. package/dist/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.js +7 -7
  32. package/dist/src/infrastructure/ui/views/summary/Summary.js +1 -2
  33. package/dist/src/projection/customer/customer.d.ts +0 -2
  34. package/dist/src/projection/order/order.d.ts +1 -1
  35. package/dist/src/projection/subscription/subscription.d.ts +1 -1
  36. package/dist/src/version.d.ts +1 -1
  37. package/dist/src/version.js +1 -1
  38. package/fake-dependencies/@lookiero/payments-front/index.tsx +9 -32
  39. package/index.ts +4 -10
  40. package/package.json +4 -3
  41. package/src/ExpoRoot.tsx +37 -42
  42. package/src/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.ts +1 -4
  43. package/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.ts +2 -3
  44. package/src/infrastructure/tracking/tracking.ts +2 -2
  45. package/src/infrastructure/tracking/useTrackCheckout.ts +56 -66
  46. package/src/infrastructure/ui/Root.tsx +14 -10
  47. package/src/infrastructure/ui/components/templates/header/itemHeader/ItemHeader.test.tsx +6 -0
  48. package/src/infrastructure/ui/components/templates/header/itemHeader/ItemHeader.tsx +0 -1
  49. package/src/infrastructure/ui/hooks/usePaymentInstrumentEvents.ts +60 -18
  50. package/src/infrastructure/ui/hooks/useStaticInfo.test.tsx +6 -1
  51. package/src/infrastructure/ui/hooks/useStaticInfo.tsx +13 -2
  52. package/src/infrastructure/ui/hooks/useSubmitCheckout.test.ts +297 -0
  53. package/src/infrastructure/ui/hooks/useSubmitCheckout.ts +169 -0
  54. package/src/infrastructure/ui/i18n/i18n.ts +0 -1
  55. package/src/infrastructure/ui/routing/CheckoutMiddleware.test.tsx +9 -1
  56. package/src/infrastructure/ui/routing/CheckoutMiddleware.tsx +15 -1
  57. package/src/infrastructure/ui/routing/Routing.tsx +29 -15
  58. package/src/infrastructure/ui/routing/routes.ts +1 -0
  59. package/src/infrastructure/ui/views/App.tsx +13 -5
  60. package/src/infrastructure/ui/views/checkout/Checkout.style.ts +0 -3
  61. package/src/infrastructure/ui/views/checkout/Checkout.test.tsx +43 -51
  62. package/src/infrastructure/ui/views/checkout/Checkout.tsx +13 -51
  63. package/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.test.tsx +134 -0
  64. package/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.tsx +124 -0
  65. package/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.tsx +8 -8
  66. package/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.test.tsx +6 -0
  67. package/src/infrastructure/ui/views/summary/Summary.tsx +1 -1
  68. package/src/infrastructure/ui/views/summaryTabs/SummaryTabs.test.tsx +4 -1
  69. package/src/projection/customer/customer.ts +0 -2
  70. package/src/projection/order/order.ts +1 -1
  71. package/src/projection/subscription/subscription.ts +1 -1
  72. package/dist/public/public/assets/adaptive-icon.png +0 -0
  73. package/dist/public/public/assets/favicon.png +0 -0
  74. package/dist/public/public/assets/icon.png +0 -0
  75. package/dist/public/public/assets/splash.png +0 -0
  76. package/dist/public/public/images/not-found.png +0 -0
  77. package/dist/src/infrastructure/ui/hooks/useCheckoutFlow.d.ts +0 -26
  78. package/dist/src/infrastructure/ui/hooks/useCheckoutFlow.js +0 -127
  79. package/dist/src/infrastructure/ui/routing/useBasePath.d.ts +0 -8
  80. package/dist/src/infrastructure/ui/routing/useBasePath.js +0 -9
  81. package/src/infrastructure/ui/hooks/useCheckoutFlow.test.tsx +0 -302
  82. package/src/infrastructure/ui/hooks/useCheckoutFlow.tsx +0 -203
@@ -1,23 +1,21 @@
1
1
  import { FC, ForwardRefExoticComponent, PropsWithChildren, RefAttributes } from "react";
2
- import { PaymentPayload } from "@lookiero/payments-front";
3
2
  declare const setPaymentsBridge: () => undefined;
4
3
  declare const PaymentsQueryProvider: FC<PropsWithChildren>;
5
4
  declare const PaymentInstrumentSelect: FC;
5
+ interface StartLegacyBoxCheckoutCallbackArgs {
6
+ readonly status: string;
7
+ readonly final: boolean;
8
+ }
6
9
  interface StartLegacyBoxCheckoutFunction {
7
- (paymentFlowPayload: unknown): void;
10
+ (paymentFlowPayload: unknown, callback: (params: StartLegacyBoxCheckoutCallbackArgs) => Promise<void>): void;
8
11
  }
9
12
  interface PaymentFlowRef {
10
13
  readonly startLegacyBoxCheckout: StartLegacyBoxCheckoutFunction;
11
14
  }
12
15
  declare const paymentFlowRef: PaymentFlowRef;
13
16
  declare const PaymentFlow: ForwardRefExoticComponent<RefAttributes<PaymentFlowRef>>;
14
- interface UsePaymentStatusManagerResult {
15
- isLoading: boolean;
16
- consumePayload: (callback: (payload: PaymentPayload) => void) => void;
17
- }
18
- declare const usePaymentStatusManager: (section: Section) => UsePaymentStatusManagerResult;
19
17
  declare enum Section {
20
18
  BOX_CHECKOUT = "box-checkout"
21
19
  }
22
20
  export type { PaymentFlowRef };
23
- export { PaymentsQueryProvider, PaymentInstrumentSelect, PaymentFlow, Section, setPaymentsBridge, paymentFlowRef, usePaymentStatusManager, };
21
+ export { PaymentsQueryProvider, PaymentInstrumentSelect, PaymentFlow, Section, setPaymentsBridge, paymentFlowRef };
@@ -4,20 +4,17 @@ const setPaymentsBridge = () => void 0;
4
4
  const PaymentsQueryProvider = ({ children }) => children;
5
5
  const PaymentInstrumentSelect = () => null;
6
6
  const paymentFlowRef = {
7
- startLegacyBoxCheckout: async () => { },
7
+ startLegacyBoxCheckout: async (_paymentFlowPayload, callback) => {
8
+ await callback({ status: "EXECUTED", final: true });
9
+ },
8
10
  };
9
11
  const PaymentFlow = forwardRef((_props, ref) => {
10
12
  useImperativeHandle(ref, () => paymentFlowRef, []);
11
13
  return null;
12
14
  });
13
15
  PaymentFlow.displayName = "PaymentFlow";
14
- const paymentStatusManagerResult = {
15
- isLoading: false,
16
- consumePayload: (callback) => callback({ success: true }),
17
- };
18
- const usePaymentStatusManager = () => paymentStatusManagerResult;
19
16
  var Section;
20
17
  (function (Section) {
21
18
  Section["BOX_CHECKOUT"] = "box-checkout";
22
19
  })(Section || (Section = {}));
23
- export { PaymentsQueryProvider, PaymentInstrumentSelect, PaymentFlow, Section, setPaymentsBridge, paymentFlowRef, usePaymentStatusManager, };
20
+ export { PaymentsQueryProvider, PaymentInstrumentSelect, PaymentFlow, Section, setPaymentsBridge, paymentFlowRef };
package/dist/index.d.ts CHANGED
@@ -4,13 +4,14 @@ import { translationEndpoint, translationExternalEndpoint } from "@lookiero/sty-
4
4
  import { Country, Locale } from "@lookiero/sty-psp-locale";
5
5
  import { SentryEnvironment, SentryLoggerFunctionArgs } from "@lookiero/sty-psp-logging";
6
6
  import { Segment } from "@lookiero/sty-psp-segment";
7
+ import { Tradename } from "@lookiero/sty-sp-tradename";
7
8
  import { CheckoutStatus } from "./src/domain/checkout/model/checkout";
8
9
  import { KameleoonEnvironment } from "./src/infrastructure/ab-testing/kameleoonEnvironment";
9
10
  import { RootProps } from "./src/infrastructure/ui/Root";
10
11
  import { CheckoutProjection } from "./src/projection/checkout/checkout";
11
12
  import { Customer } from "./src/projection/customer/customer";
12
- import { OrderProjection } from "./src/projection/order/order";
13
- import { SubscriptionProjection } from "./src/projection/subscription/subscription";
13
+ import { Order } from "./src/projection/order/order";
14
+ import { Subscription } from "./src/projection/subscription/subscription";
14
15
  interface FirstAvailableCheckoutByCustomerIdFunctionArgs {
15
16
  readonly customerId: string | undefined;
16
17
  }
@@ -33,4 +34,4 @@ interface BootstrapFunction {
33
34
  }
34
35
  declare const bootstrap: BootstrapFunction;
35
36
  export { bootstrap, translationEndpoint, translationExternalEndpoint, Country, Segment, CheckoutStatus };
36
- export type { SentryEnvironment, KameleoonEnvironment, Customer, SubscriptionProjection as Subscription, OrderProjection as Order, Locale, };
37
+ export type { SentryEnvironment, KameleoonEnvironment, Customer, Subscription, Order, Locale, Tradename };
@@ -1,4 +1,3 @@
1
- import { PortalProvider } from "@gorhom/portal";
2
1
  import { useFonts } from "expo-font";
3
2
  import "expo/build/Expo.fx";
4
3
  import React, { useCallback, useState } from "react";
@@ -12,13 +11,14 @@ import { fetchTranslations, translationExternalEndpoint } from "@lookiero/sty-ps
12
11
  import { Country, Locale } from "@lookiero/sty-psp-locale";
13
12
  import { Segment } from "@lookiero/sty-psp-segment";
14
13
  import { DummyLayout } from "@lookiero/sty-psp-ui";
14
+ import { Tradename } from "@lookiero/sty-sp-tradename";
15
15
  import { bootstrap as checkoutBootstrap } from "./infrastructure/delivery/bootstrap";
16
16
  import { bootstrap as checkoutMockBootstrap } from "./infrastructure/delivery/bootstrap.mock";
17
17
  import { root } from "./infrastructure/ui/Root";
18
18
  import { DOMAIN } from "./infrastructure/ui/i18n/i18n";
19
19
  import { Router } from "./infrastructure/ui/routing/router/Router";
20
20
  import { VERSION } from "./version";
21
- const locale = Locale.es_ES;
21
+ const locale = Locale.en_GB;
22
22
  const subscription = "b";
23
23
  const order = {
24
24
  isFirstOrder: false,
@@ -26,11 +26,9 @@ const order = {
26
26
  coupon: "MYLOOKIERO",
27
27
  };
28
28
  const customer = {
29
- customerId: "9cfb056e-6008-44b1-9075-320479bf92ac",
30
- country: Country.NL,
29
+ customerId: "a4355713-469b-4684-bf90-3215702dfb1c",
30
+ country: Country.ES,
31
31
  segment: Segment.WOMEN,
32
- email: "email@example.com",
33
- name: "Adèle Léonce Émilie",
34
32
  };
35
33
  const sentryConfig = {
36
34
  publicKey: "66cadf9444db4ea5945670f12ec08ae7",
@@ -43,7 +41,7 @@ const apiUrl = Platform.OS !== "web"
43
41
  : __DEV__
44
42
  ? "/local-to-dev"
45
43
  : "/checkout/api";
46
- const authToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjU2NDk0NjYsImV4cCI6MTc0MjQ3MDI5OSwiZGlzcGxheU5hbWUiOiJNaWtlbCIsImNvdW50cnlfY29kZSI6IkVTIiwiYWNjZXNzVmlhIjoiZW1haWwiLCJzdWJzY3JpcHRpb25TdGFydGluZ0RhdGUiOiIyMDI0LTExLTExIiwiaW1wZXJzb25hdGVkIjpmYWxzZSwidXVpZCI6ImQzYzIzNTRiLTk4MTEtNDZkNC1iMmJhLTVmYmEwMTJlZDk0ZCIsImlhdCI6MTc0MDA1MTA5OX0.AkuUZTsn9mgplQwatg0dPKyv1Hsc6r267UMahxMH19g";
44
+ const authToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjU2ODkxMDAsImV4cCI6MTc0NjI3ODQwMiwiZGlzcGxheU5hbWUiOiJUZXN0aW5nIiwiY291bnRyeV9jb2RlIjoiRVMiLCJhY2Nlc3NWaWEiOiJlbWFpbCIsInN1YnNjcmlwdGlvblN0YXJ0aW5nRGF0ZSI6IjIwMjUtMDQtMDMiLCJpbXBlcnNvbmF0ZWQiOmZhbHNlLCJ1dWlkIjoiYTQzNTU3MTMtNDY5Yi00Njg0LWJmOTAtMzIxNTcwMmRmYjFjIiwiaWF0IjoxNzQzNjg2NDAyfQ.pmqFo-4s0USFpzCnijRt78bWuBdu2Q7f4L9UtOkfAwo";
47
45
  const getAuthToken = () => Promise.resolve(authToken);
48
46
  const externalTranslationsUrl = Platform.OS !== "web"
49
47
  ? "https://backend-for-user.dev.envs.lookiero.tech/api/v2/translations"
@@ -78,7 +76,6 @@ setPaymentsBridge({
78
76
  useFeatureFlags: () => ({}),
79
77
  locale: () => Promise.resolve("es-ES"),
80
78
  scrollView: ScrollView,
81
- hostUrl: "",
82
79
  });
83
80
  const kameleoonConfig = {
84
81
  siteCode: "aplm4v3ckn",
@@ -109,14 +106,13 @@ const ExpoRoot = () => {
109
106
  });
110
107
  const [isAccessible, setIsAccessible] = useState();
111
108
  const onNotAccessible = useCallback(() => setIsAccessible(false), []);
112
- return fontsLoaded ? (React.createElement(PortalProvider, null,
113
- React.createElement(PaymentsQueryProvider, null,
114
- React.createElement(EventProvider, null,
115
- React.createElement(Aurora, null,
116
- isAccessible === false && React.createElement(Text, { heading: true }, "Checkout is not accessible!"),
117
- React.createElement(Router, null,
118
- React.createElement(Routes, null,
119
- React.createElement(Route, { path: "/checkout/*", element: React.createElement(Root, { basePath: "/checkout", customer: customer, layout: DummyLayout, locale: locale, order: order, subscription: subscription, useRedirect: useRedirect, onCheckoutFlowSuccess: () => console.log("Checkout flow success!"), onNotAccessible: onNotAccessible }) }),
120
- React.createElement(Route, { element: React.createElement(Navigate, { to: "/checkout", replace: true }), path: "*" })))))))) : null;
109
+ return fontsLoaded ? (React.createElement(PaymentsQueryProvider, null,
110
+ React.createElement(EventProvider, null,
111
+ React.createElement(Aurora, null,
112
+ isAccessible === false && React.createElement(Text, { heading: true }, "Checkout is not accessible!"),
113
+ React.createElement(Router, null,
114
+ React.createElement(Routes, null,
115
+ React.createElement(Route, { path: "/checkout/*", element: React.createElement(Root, { basePath: "/checkout", customer: customer, layout: DummyLayout, locale: locale, order: order, subscription: subscription, tradename: Tradename.LOOKIERO, useRedirect: useRedirect, onNotAccessible: onNotAccessible }) }),
116
+ React.createElement(Route, { element: React.createElement(Navigate, { to: "/checkout", replace: true }), path: "*" }))))))) : null;
121
117
  };
122
118
  export { ExpoRoot };
@@ -5,7 +5,7 @@ interface BlockCheckoutBookingFunction {
5
5
  }
6
6
  type UseBlockCheckoutBooking = [blockCheckoutBooking: BlockCheckoutBookingFunction, status: CommandStatus];
7
7
  interface UseBlockCheckoutBookingFunctionArgs {
8
- readonly checkoutBookingId: string | undefined;
8
+ readonly checkoutBookingId: string;
9
9
  readonly logger: Logger;
10
10
  }
11
11
  interface UseBlockCheckoutBookingFunction {
@@ -1,5 +1,4 @@
1
1
  import { useCallback } from "react";
2
- import invariant from "tiny-invariant";
3
2
  import { useCommand } from "@lookiero/messaging-react";
4
3
  import { NotificationLevel, useCreateToastNotification } from "@lookiero/sty-psp-notifications";
5
4
  import { blockCheckoutBooking as blockCheckoutBookingCommand } from "../../../../domain/checkoutBooking/command/blockCheckoutBooking";
@@ -9,7 +8,6 @@ const useBlockCheckoutBooking = ({ checkoutBookingId, logger }) => {
9
8
  const [commandBus, status] = useCommand({ contextId: MESSAGING_CONTEXT_ID });
10
9
  const [createNotification] = useCreateToastNotification({ contextId: MESSAGING_CONTEXT_ID, logger });
11
10
  const blockCheckoutBooking = useCallback(async () => {
12
- invariant(checkoutBookingId, "checkoutBookingId is required");
13
11
  try {
14
12
  await commandBus(blockCheckoutBookingCommand({
15
13
  aggregateId: checkoutBookingId,
@@ -4,7 +4,7 @@ interface QueryOptions {
4
4
  readonly refetchOnMount?: boolean | "always";
5
5
  }
6
6
  interface UseViewPricingByCheckoutIdFunctionArgs {
7
- readonly checkoutId: string | undefined;
7
+ readonly checkoutId: string;
8
8
  readonly queryOptions?: QueryOptions;
9
9
  }
10
10
  interface UseViewPricingByCheckoutIdFunction {
@@ -13,7 +13,7 @@ const DEFAULT_QUERY_OPTIONS = {
13
13
  refetchOnMount: "always",
14
14
  };
15
15
  const useViewPricingByCheckoutId = ({ checkoutId, queryOptions = DEFAULT_QUERY_OPTIONS, }) => useQuery({
16
- query: viewPricingByCheckoutId({ checkoutId: checkoutId }),
16
+ query: viewPricingByCheckoutId({ checkoutId }),
17
17
  contextId: MESSAGING_CONTEXT_ID,
18
18
  invalidation: shouldInvalidate,
19
19
  options: {
@@ -21,7 +21,6 @@ const useViewPricingByCheckoutId = ({ checkoutId, queryOptions = DEFAULT_QUERY_O
21
21
  staleTime: Infinity,
22
22
  retry: false,
23
23
  refetchOnWindowFocus: false,
24
- enabled: Boolean(checkoutId),
25
24
  },
26
25
  });
27
26
  export { useViewPricingByCheckoutId };
@@ -2,7 +2,7 @@ import { BaseTrackingEvent, TrackingEventCategory } from "@lookiero/sty-psp-trac
2
2
  import { CheckoutItemStatus } from "../../domain/checkoutItem/model/checkoutItem";
3
3
  import { Currency } from "../../domain/checkoutItem/model/currency";
4
4
  import { MediaPerspective } from "../../projection/checkoutItem/checkoutItem";
5
- import { SubscriptionProjection } from "../../projection/subscription/subscription";
5
+ import { Subscription } from "../../projection/subscription/subscription";
6
6
  declare const PROJECT = "checkout";
7
7
  declare enum TrackingPage {
8
8
  ITEM = "item",
@@ -96,7 +96,7 @@ interface CheckoutTrackingEvent extends CheckoutBaseTrackingEvent<TrackingEventN
96
96
  readonly actionField: {
97
97
  readonly items: number;
98
98
  readonly currencyCode: Currency;
99
- readonly subscription: SubscriptionProjection;
99
+ readonly subscription: Subscription;
100
100
  readonly coupon: string | null;
101
101
  readonly orderId: number;
102
102
  readonly value: number;
@@ -1,19 +1,26 @@
1
1
  import { Country } from "@lookiero/sty-psp-locale";
2
2
  import { Segment } from "@lookiero/sty-psp-segment";
3
- import { CheckoutProjection } from "../../projection/checkout/checkout";
4
- import { OrderProjection } from "../../projection/order/order";
5
- import { PricingProjection } from "../../projection/pricing/pricing";
6
- import { SubscriptionProjection } from "../../projection/subscription/subscription";
3
+ import { Currency } from "../../domain/checkoutItem/model/currency";
4
+ import { Subscription } from "../../projection/subscription/subscription";
5
+ import { TrackingPage } from "./tracking";
6
+ interface TrackCheckoutFunctionArgs {
7
+ readonly userId: string;
8
+ readonly totalReplacedFor: number;
9
+ readonly isFirstOrder: boolean;
10
+ readonly totalCheckoutItemsKept: number;
11
+ readonly currencyCode: Currency;
12
+ readonly subscription: Subscription;
13
+ readonly coupon: string | null;
14
+ readonly orderNumber: number;
15
+ readonly pendingToPay: number;
16
+ }
7
17
  interface TrackCheckoutFunction {
8
- (): void;
18
+ (args: TrackCheckoutFunctionArgs): void;
9
19
  }
10
20
  interface UseTrackCheckoutFunctionArgs {
11
- readonly order: OrderProjection;
12
- readonly checkout: CheckoutProjection | undefined;
13
- readonly pricing: PricingProjection | undefined;
14
- readonly subscription: SubscriptionProjection;
15
- readonly userId: string;
21
+ readonly page: TrackingPage;
16
22
  readonly country: Country;
23
+ readonly checkoutId: string | undefined;
17
24
  readonly segment: Segment;
18
25
  }
19
26
  interface UseTrackCheckoutFunction {
@@ -1,53 +1,38 @@
1
1
  import { useCallback } from "react";
2
- import invariant from "tiny-invariant";
3
2
  import { useEmitUserEvent } from "@lookiero/sty-psp-tracking";
4
- import { CheckoutItemStatus } from "../../domain/checkoutItem/model/checkoutItem";
5
- import { PROJECT, TrackingPage } from "./tracking";
3
+ import { PROJECT } from "./tracking";
6
4
  import { TrackingEventName, TrackingEventCategory } from "./tracking";
7
- const useTrackCheckout = ({ order, checkout, pricing, subscription, segment, country, userId, }) => {
5
+ const useTrackCheckout = ({ page, country, checkoutId, segment }) => {
8
6
  const emitUserEvent = useEmitUserEvent();
9
- const { coupon, isFirstOrder, orderNumber } = order;
10
- const trackCheckout = useCallback(() => {
11
- invariant(checkout, "Checkout must be defined to track checkout");
12
- const checkoutItemsKept = checkout.items.filter((checkoutItem) => checkoutItem.status === CheckoutItemStatus.KEPT || checkoutItem.status === CheckoutItemStatus.REPLACED);
13
- const totalReplacedFor = checkoutItemsKept?.filter(({ replacedFor }) => Boolean(replacedFor)).length || 0;
7
+ const trackCheckout = useCallback(({ coupon, currencyCode, isFirstOrder, orderNumber, pendingToPay, subscription, totalCheckoutItemsKept, totalReplacedFor, userId, }) => {
8
+ if (!checkoutId) {
9
+ return;
10
+ }
14
11
  const checkoutTrackingEvent = {
15
12
  event: TrackingEventName.CHECKOUT,
16
13
  eventCategory: TrackingEventCategory.ECOMMERCE,
17
- section: `${PROJECT}_${TrackingPage.CHECKOUT}`,
14
+ section: `${PROJECT}_${page}`,
18
15
  store: country,
19
16
  segment,
20
- checkoutId: checkout.id,
17
+ checkoutId,
21
18
  userId,
22
19
  sizeChanges: totalReplacedFor,
23
20
  isFirstOrder,
24
21
  ecommerce: {
25
22
  checkout: {
26
23
  actionField: {
27
- items: checkoutItemsKept.length || 0,
28
- currencyCode: pricing?.pendingToPay.currency,
24
+ items: totalCheckoutItemsKept,
25
+ currencyCode,
29
26
  subscription,
30
27
  coupon,
31
28
  orderId: orderNumber,
32
- value: pricing?.pendingToPay.amount / 100,
29
+ value: pendingToPay,
33
30
  },
34
31
  },
35
32
  },
36
33
  };
37
34
  emitUserEvent(checkoutTrackingEvent);
38
- }, [
39
- checkout,
40
- country,
41
- coupon,
42
- emitUserEvent,
43
- isFirstOrder,
44
- orderNumber,
45
- pricing?.pendingToPay.amount,
46
- pricing?.pendingToPay.currency,
47
- segment,
48
- subscription,
49
- userId,
50
- ]);
35
+ }, [checkoutId, country, emitUserEvent, page, segment]);
51
36
  return trackCheckout;
52
37
  };
53
38
  export { useTrackCheckout };
@@ -6,15 +6,16 @@ import { MessagingRoot } from "@lookiero/messaging-react/bootstrap";
6
6
  import { Locale } from "@lookiero/sty-psp-locale";
7
7
  import { SentryEnvironment, SentryLoggerFunctionArgs } from "@lookiero/sty-psp-logging";
8
8
  import { Layout } from "@lookiero/sty-psp-ui";
9
+ import { Tradename } from "@lookiero/sty-sp-tradename";
9
10
  import { Customer } from "../../projection/customer/customer";
10
- import { OrderProjection } from "../../projection/order/order";
11
- import { SubscriptionProjection } from "../../projection/subscription/subscription";
11
+ import { Order } from "../../projection/order/order";
12
+ import { Subscription } from "../../projection/subscription/subscription";
12
13
  import { KameleoonEnvironment } from "../ab-testing/kameleoonEnvironment";
13
14
  interface RootFunctionArgs {
14
15
  readonly Messaging: MessagingRoot;
15
16
  readonly I18n: I18n;
16
- readonly queryBus: QueryBus;
17
17
  readonly development?: boolean;
18
+ readonly queryBus: QueryBus;
18
19
  readonly sentry: () => SentryEnvironment;
19
20
  readonly getAuthToken: () => Promise<string>;
20
21
  readonly kameleoon: () => KameleoonEnvironment;
@@ -24,13 +25,14 @@ interface RootFunction {
24
25
  }
25
26
  interface RootProps {
26
27
  readonly basePath: string;
27
- readonly locale: Locale;
28
+ readonly locale?: Locale;
28
29
  readonly customer: Customer;
29
- readonly order: OrderProjection;
30
- readonly subscription: SubscriptionProjection;
30
+ readonly order: Order | undefined;
31
+ readonly subscription: Subscription | undefined;
31
32
  readonly layout: Layout;
33
+ readonly tradename: Tradename;
32
34
  readonly onNotAccessible: () => void;
33
- readonly onCheckoutFlowSuccess: () => void;
35
+ readonly onCheckoutSubmitted?: () => void;
34
36
  readonly useRedirect: () => Record<string, string>;
35
37
  readonly useRoutes?: typeof reactRouterUseRoutes;
36
38
  }
@@ -2,6 +2,7 @@
2
2
  import React, { useCallback } from "react";
3
3
  import { Platform } from "react-native";
4
4
  import { useRoutes as reactRouterUseRoutes } from "react-router-native";
5
+ import { Locale } from "@lookiero/sty-psp-locale";
5
6
  import { sentryLogger, sentryLoggerHOC } from "@lookiero/sty-psp-logging";
6
7
  import { QueryBusProvider } from "./hooks/useQueryBus";
7
8
  import { Routing } from "./routing/Routing";
@@ -9,11 +10,11 @@ const root = ({ Messaging, I18n, queryBus, getAuthToken, development, sentry, ka
9
10
  const logger = sentryLogger(sentry);
10
11
  const kameleoon = kameleoonConfig();
11
12
  // eslint-disable-next-line react/display-name, react/prop-types
12
- const Root = ({ basePath, locale, customer, order, subscription, layout, onNotAccessible, onCheckoutFlowSuccess, useRedirect, useRoutes = reactRouterUseRoutes, }) => {
13
+ const Root = ({ basePath, locale = Locale.en_GB, customer, order, subscription, layout, tradename, onNotAccessible, onCheckoutSubmitted, useRedirect, useRoutes = reactRouterUseRoutes, }) => {
13
14
  const handleOnI18nError = useCallback((error) => logger.captureException(error), []);
14
15
  return (React.createElement(Messaging, { includeReactQueryDevTools: Platform.OS === "web" },
15
16
  React.createElement(QueryBusProvider, { queryBus: queryBus },
16
- React.createElement(Routing, { I18n: I18n, basePath: basePath, customer: customer, getAuthToken: getAuthToken, kameleoon: kameleoon, layout: layout, locale: locale, order: order, subscription: subscription, useRedirect: useRedirect, useRoutes: useRoutes, onCheckoutFlowSuccess: onCheckoutFlowSuccess, onI18nError: development ? undefined : handleOnI18nError, onNotAccessible: onNotAccessible }))));
17
+ React.createElement(Routing, { I18n: I18n, basePath: basePath, customer: customer, getAuthToken: getAuthToken, kameleoon: kameleoon, layout: layout, locale: locale, order: order, subscription: subscription, tradename: tradename, useRedirect: useRedirect, useRoutes: useRoutes, onCheckoutSubmitted: onCheckoutSubmitted, onI18nError: development ? undefined : handleOnI18nError, onNotAccessible: onNotAccessible }))));
17
18
  };
18
19
  const hoc = sentryLoggerHOC({ logger });
19
20
  /**
@@ -1,7 +1,6 @@
1
- import { PaymentPayload } from "@lookiero/payments-front";
1
+ import { Logger } from "@lookiero/sty-psp-logging";
2
2
  interface UsePaymentInstrumentEventsFunctionArgs {
3
- readonly onSuccess: (payload: PaymentPayload) => void;
4
- readonly onError: (payload: PaymentPayload) => void;
3
+ readonly logger: Logger;
5
4
  }
6
5
  interface UsePaymentInstrumentEventsFunction {
7
6
  (args: UsePaymentInstrumentEventsFunctionArgs): void;
@@ -1,20 +1,29 @@
1
- import { useEffect } from "react";
2
- import { Section, usePaymentStatusManager } from "@lookiero/payments-front";
3
- const usePaymentInstrumentEvents = ({ onSuccess, onError }) => {
4
- const refreshStatus = usePaymentStatusManager(Section.BOX_CHECKOUT);
5
- useEffect(() => {
6
- const { isLoading, consumePayload } = refreshStatus;
7
- if (isLoading) {
8
- return;
1
+ import { useCallback, useEffect } from "react";
2
+ import { useEvent } from "@lookiero/event";
3
+ import { NotificationLevel, useCreateToastNotification } from "@lookiero/sty-psp-notifications";
4
+ import { MESSAGING_CONTEXT_ID } from "../../delivery/baseBootstrap";
5
+ import { I18nMessages } from "../i18n/i18n";
6
+ const PAYMENT_ERROR = "ERROR";
7
+ const PAYMENT_SUCCESS = "PAYMENT_INSTRUMENT_UPDATED";
8
+ const usePaymentInstrumentEvents = ({ logger }) => {
9
+ const { subscribe, unsubscribe } = useEvent();
10
+ const [createNotification] = useCreateToastNotification({ contextId: MESSAGING_CONTEXT_ID, logger });
11
+ const onSuccess = useCallback(({ message }) => createNotification({ bodyI18nKey: message.id, level: NotificationLevel.SUCCESS }), [createNotification]);
12
+ const onError = useCallback(({ error }) => {
13
+ if (error.toaster) {
14
+ createNotification({
15
+ bodyI18nKey: error.toaster.id || I18nMessages.CHECKOUT_TOAST_PAYMENT_ERROR,
16
+ level: NotificationLevel.ERROR,
17
+ });
9
18
  }
10
- consumePayload((payload) => {
11
- if (payload.success) {
12
- onSuccess(payload);
13
- }
14
- else {
15
- onError(payload);
16
- }
17
- });
18
- }, [onError, onSuccess, refreshStatus]);
19
+ }, [createNotification]);
20
+ useEffect(() => {
21
+ subscribe({ event: PAYMENT_ERROR }, onError);
22
+ subscribe({ event: PAYMENT_SUCCESS }, onSuccess);
23
+ return () => {
24
+ unsubscribe({ event: PAYMENT_ERROR }, onError);
25
+ unsubscribe({ event: PAYMENT_SUCCESS }, onSuccess);
26
+ };
27
+ }, [subscribe, unsubscribe, createNotification, onError, onSuccess]);
19
28
  };
20
29
  export { usePaymentInstrumentEvents };
@@ -1,15 +1,18 @@
1
1
  import { FC, ReactNode } from "react";
2
+ import { Tradename } from "@lookiero/sty-sp-tradename";
2
3
  import { Customer } from "../../../projection/customer/customer";
3
4
  import { KameleoonEnvironment } from "../../ab-testing/kameleoonEnvironment";
4
5
  interface StaticInfo {
5
6
  readonly kameleoon: KameleoonEnvironment;
6
7
  readonly customer: Customer;
8
+ readonly tradename: Tradename;
7
9
  readonly basePath: string;
8
10
  }
9
11
  interface StaticInfoProviderProps {
10
12
  readonly children: ReactNode;
11
13
  readonly kameleoon: KameleoonEnvironment;
12
14
  readonly customer: Customer;
15
+ readonly tradename: Tradename;
13
16
  readonly basePath: string;
14
17
  }
15
18
  declare const StaticInfoProvider: FC<StaticInfoProviderProps>;
@@ -1,8 +1,13 @@
1
1
  import React, { createContext, useContext, useMemo } from "react";
2
2
  import invariant from "tiny-invariant";
3
3
  const StaticInfoContext = createContext(null);
4
- const StaticInfoProvider = ({ children, kameleoon, customer, basePath }) => {
5
- const value = useMemo(() => ({ kameleoon, customer, basePath }), [customer, kameleoon, basePath]);
4
+ const StaticInfoProvider = ({ children, kameleoon, customer, tradename, basePath }) => {
5
+ const value = useMemo(() => ({
6
+ kameleoon,
7
+ customer,
8
+ tradename,
9
+ basePath,
10
+ }), [basePath, customer, kameleoon, tradename]);
6
11
  return React.createElement(StaticInfoContext.Provider, { value: value }, children);
7
12
  };
8
13
  const useStaticInfo = () => {
@@ -47,7 +47,6 @@ declare enum I18nMessages {
47
47
  CHECKOUT_TITLE = "checkout.title",
48
48
  CHECKOUT_PAY_BUTTON = "checkout.pay_button",
49
49
  CHECKOUT_TOAST_PAYMENT_ERROR = "checkout.toast_payment_error",
50
- CHECKOUT_TOAST_PAYMENT_SUCCESS = "checkout.toast_payment_success",
51
50
  CHECKOUT_SUCCESS_MODAL_TITLE = "checkout.success_modal_title",
52
51
  CHECKOUT_SUCCESS_MODAL_DESCRIPTION = "checkout.success_modal_description",
53
52
  CHECKOUT_SUCCESS_MODAL_BUTTON = "checkout.success_modal_button",
@@ -49,7 +49,6 @@ var I18nMessages;
49
49
  I18nMessages["CHECKOUT_TITLE"] = "checkout.title";
50
50
  I18nMessages["CHECKOUT_PAY_BUTTON"] = "checkout.pay_button";
51
51
  I18nMessages["CHECKOUT_TOAST_PAYMENT_ERROR"] = "checkout.toast_payment_error";
52
- I18nMessages["CHECKOUT_TOAST_PAYMENT_SUCCESS"] = "checkout.toast_payment_success";
53
52
  I18nMessages["CHECKOUT_SUCCESS_MODAL_TITLE"] = "checkout.success_modal_title";
54
53
  I18nMessages["CHECKOUT_SUCCESS_MODAL_DESCRIPTION"] = "checkout.success_modal_description";
55
54
  I18nMessages["CHECKOUT_SUCCESS_MODAL_BUTTON"] = "checkout.success_modal_button";
@@ -33,6 +33,11 @@ const CheckoutMiddleware = ({ customerId, onNotAccessible, loader = React.create
33
33
  const feedbackRouteMatch = useMatch(`${basePath}/${Routes.FEEDBACK}`);
34
34
  const feedbackRouteMatchRef = useRef(feedbackRouteMatch);
35
35
  feedbackRouteMatchRef.current = feedbackRouteMatch;
36
+ const checkoutPaymentRouteMatch = useMatch(`${basePath}/${Routes.CHECKOUT}/${Routes.CHECKOUT_PAYMENT}`);
37
+ const checkoutPaymentRouteMatchRef = useRef(checkoutPaymentRouteMatch);
38
+ checkoutPaymentRouteMatchRef.current = checkoutPaymentRouteMatch;
39
+ const checkoutShown = useRef(false);
40
+ checkoutShown.current = checkoutShown.current || (Boolean(checkoutRouteMatch) && !Boolean(checkoutPaymentRouteMatch));
36
41
  const [checkout] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
37
42
  const checkoutItemsRef = useRef();
38
43
  /* This hook is mounted at this level, although not being used directly, for optimization (regarding cache) */
@@ -61,7 +66,8 @@ const CheckoutMiddleware = ({ customerId, onNotAccessible, loader = React.create
61
66
  !(summaryRouteMatchRef.current ||
62
67
  summaryTabsRouteMatchRef.current ||
63
68
  itemDetailRouteMatchRef.current ||
64
- checkoutRouteMatchRef.current)) {
69
+ checkoutRouteMatchRef.current ||
70
+ checkoutPaymentRouteMatchRef.current)) {
65
71
  navigateRef.current(`${basePath}/${Routes.SUMMARY}`, { replace: true });
66
72
  }
67
73
  if (itemWithoutCustomerDecision &&
@@ -79,6 +85,11 @@ const CheckoutMiddleware = ({ customerId, onNotAccessible, loader = React.create
79
85
  onNotAccessible();
80
86
  return null;
81
87
  }
88
+ /* Prevent direct payment access */
89
+ if (checkoutPaymentRouteMatch && !checkoutShown.current) {
90
+ onNotAccessible();
91
+ return null;
92
+ }
82
93
  return children;
83
94
  };
84
95
  export { CheckoutMiddleware };
@@ -3,22 +3,24 @@ import { useRoutes as reactRouterUseRoutes } from "react-router-native";
3
3
  import { I18n } from "@lookiero/i18n-react";
4
4
  import { Locale } from "@lookiero/sty-psp-locale";
5
5
  import { Layout } from "@lookiero/sty-psp-ui";
6
+ import { Tradename } from "@lookiero/sty-sp-tradename";
6
7
  import { Customer } from "../../../projection/customer/customer";
7
- import { OrderProjection } from "../../../projection/order/order";
8
- import { SubscriptionProjection } from "../../../projection/subscription/subscription";
8
+ import { Order } from "../../../projection/order/order";
9
+ import { Subscription } from "../../../projection/subscription/subscription";
9
10
  import { KameleoonEnvironment } from "../../ab-testing/kameleoonEnvironment";
10
11
  interface RoutingProps {
11
12
  readonly basePath?: string;
12
13
  readonly customer: Customer;
13
- readonly order: OrderProjection;
14
- readonly subscription: SubscriptionProjection;
14
+ readonly order: Order | undefined;
15
+ readonly subscription: Subscription | undefined;
15
16
  readonly locale: Locale;
16
17
  readonly I18n: I18n;
17
18
  readonly kameleoon: KameleoonEnvironment;
18
19
  readonly layout: Layout;
20
+ readonly tradename: Tradename;
19
21
  readonly getAuthToken: () => Promise<string>;
20
22
  readonly onNotAccessible: () => void;
21
- readonly onCheckoutFlowSuccess: () => void;
23
+ readonly onCheckoutSubmitted?: () => void;
22
24
  readonly onI18nError?: (err: Error) => void;
23
25
  readonly useRedirect: () => Record<string, string>;
24
26
  readonly useRoutes: typeof reactRouterUseRoutes;
@@ -5,6 +5,7 @@ import { Kameleoon } from "@lookiero/sty-psp-ab-testing";
5
5
  import { StaticInfoProvider } from "../hooks/useStaticInfo";
6
6
  import { App } from "../views/App";
7
7
  import { Checkout } from "../views/checkout/Checkout";
8
+ import { CheckoutPaymentModal } from "../views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal";
8
9
  import { Feedback } from "../views/feedback/Feedback";
9
10
  import { Item } from "../views/item/Item";
10
11
  import { Return } from "../views/return/Return";
@@ -12,11 +13,11 @@ import { Summary } from "../views/summary/Summary";
12
13
  import { SummaryTabs } from "../views/summaryTabs/SummaryTabs";
13
14
  import { CheckoutMiddleware } from "./CheckoutMiddleware";
14
15
  import { Routes } from "./routes";
15
- const Routing = ({ basePath = "", customer, order, subscription, locale, I18n, kameleoon, layout, getAuthToken, onI18nError, onNotAccessible, onCheckoutFlowSuccess, useRedirect, useRoutes = reactRouterUseRoutes, }) => {
16
+ const Routing = ({ basePath = "", customer, order, subscription, locale, I18n, kameleoon, layout, tradename, getAuthToken, onI18nError, onNotAccessible, onCheckoutSubmitted, useRedirect, useRoutes = reactRouterUseRoutes, }) => {
16
17
  return useRoutes([
17
18
  {
18
19
  path: "",
19
- element: (React.createElement(StaticInfoProvider, { basePath: basePath, customer: customer, kameleoon: kameleoon },
20
+ element: (React.createElement(StaticInfoProvider, { basePath: basePath, customer: customer, kameleoon: kameleoon, tradename: tradename },
20
21
  React.createElement(I18n, { loader: React.createElement(Spinner, null), locale: locale, onError: onI18nError },
21
22
  React.createElement(Kameleoon, { loader: React.createElement(Spinner, null), siteCode: kameleoon.siteCode },
22
23
  React.createElement(CheckoutMiddleware, { customerId: customer?.customerId, onNotAccessible: onNotAccessible },
@@ -49,7 +50,14 @@ const Routing = ({ basePath = "", customer, order, subscription, locale, I18n, k
49
50
  {
50
51
  path: Routes.CHECKOUT,
51
52
  element: (React.createElement(Suspense, { fallback: React.createElement(Spinner, null) },
52
- React.createElement(Checkout, { getAuthToken: getAuthToken, layout: layout, order: order, subscription: subscription, useRedirect: useRedirect, onCheckoutFlowSuccess: onCheckoutFlowSuccess }))),
53
+ React.createElement(Checkout, { layout: layout, useRedirect: useRedirect },
54
+ React.createElement(Outlet, null)))),
55
+ children: [
56
+ {
57
+ path: Routes.CHECKOUT_PAYMENT,
58
+ element: (React.createElement(CheckoutPaymentModal, { coupon: order?.coupon || null, getAuthToken: getAuthToken, isFirstOrder: order?.isFirstOrder, orderNumber: order?.orderNumber, subscription: subscription, onCheckoutSubmitted: onCheckoutSubmitted })),
59
+ },
60
+ ],
53
61
  },
54
62
  {
55
63
  path: Routes.FEEDBACK,
@@ -5,6 +5,7 @@ export declare enum Routes {
5
5
  SUMMARY = "summary",
6
6
  SUMMARY_TABS = "tabs/:tab",
7
7
  CHECKOUT = "checkout",
8
+ CHECKOUT_PAYMENT = "payment",
8
9
  FEEDBACK = "feedback",
9
10
  RETURN = "return/:id"
10
11
  }
@@ -6,6 +6,7 @@ export var Routes;
6
6
  Routes["SUMMARY"] = "summary";
7
7
  Routes["SUMMARY_TABS"] = "tabs/:tab";
8
8
  Routes["CHECKOUT"] = "checkout";
9
+ Routes["CHECKOUT_PAYMENT"] = "payment";
9
10
  Routes["FEEDBACK"] = "feedback";
10
11
  Routes["RETURN"] = "return/:id";
11
12
  })(Routes || (Routes = {}));