@lookiero/checkout 10.1.0 → 11.1.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.
- package/cypress/integration/checkout.spec.ts +0 -3
- package/dist/fake-dependencies/@lookiero/payments-front/index.d.ts +8 -7
- package/dist/fake-dependencies/@lookiero/payments-front/index.js +11 -3
- package/dist/index.d.ts +3 -3
- package/dist/src/Expo.js +8 -2
- package/dist/src/ExpoRoot.d.ts +5 -1
- package/dist/src/ExpoRoot.js +26 -17
- package/dist/src/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.d.ts +1 -1
- package/dist/src/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.js +2 -0
- package/dist/src/infrastructure/projection/checkout/checkout.mock.d.ts +1 -0
- package/dist/src/infrastructure/projection/checkout/checkout.mock.js +3 -3
- package/dist/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.d.ts +1 -1
- package/dist/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.js +2 -1
- package/dist/src/infrastructure/tracking/tracking.d.ts +2 -2
- package/dist/src/infrastructure/tracking/useTrackCheckout.d.ts +10 -17
- package/dist/src/infrastructure/tracking/useTrackCheckout.js +27 -12
- package/dist/src/infrastructure/ui/Root.d.ts +6 -6
- package/dist/src/infrastructure/ui/Root.js +2 -3
- package/dist/src/infrastructure/ui/hooks/useCheckoutFlow.d.ts +26 -0
- package/dist/src/infrastructure/ui/hooks/useCheckoutFlow.js +127 -0
- package/dist/src/infrastructure/ui/hooks/usePaymentInstrumentEvents.d.ts +3 -2
- package/dist/src/infrastructure/ui/hooks/usePaymentInstrumentEvents.js +17 -26
- package/dist/src/infrastructure/ui/i18n/i18n.d.ts +1 -0
- package/dist/src/infrastructure/ui/i18n/i18n.js +1 -0
- package/dist/src/infrastructure/ui/routing/CheckoutMiddleware.js +1 -12
- package/dist/src/infrastructure/ui/routing/Routing.d.ts +5 -5
- package/dist/src/infrastructure/ui/routing/Routing.js +2 -10
- package/dist/src/infrastructure/ui/routing/routes.d.ts +0 -1
- package/dist/src/infrastructure/ui/routing/routes.js +0 -1
- package/dist/src/infrastructure/ui/views/App.js +5 -6
- package/dist/src/infrastructure/ui/views/checkout/Checkout.d.ts +7 -2
- package/dist/src/infrastructure/ui/views/checkout/Checkout.js +20 -9
- package/dist/src/infrastructure/ui/views/checkout/Checkout.style.d.ts +3 -0
- package/dist/src/infrastructure/ui/views/checkout/Checkout.style.js +3 -0
- package/dist/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.js +7 -7
- package/dist/src/projection/customer/customer.d.ts +2 -0
- package/dist/src/projection/order/order.d.ts +1 -1
- package/dist/src/projection/subscription/subscription.d.ts +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/fake-dependencies/@lookiero/payments-front/index.tsx +36 -8
- package/index.ts +10 -3
- package/package.json +3 -4
- package/src/Expo.tsx +10 -2
- package/src/ExpoRoot.tsx +58 -43
- package/src/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.ts +4 -1
- package/src/infrastructure/projection/checkout/checkout.mock.ts +8 -3
- package/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.ts +3 -2
- package/src/infrastructure/tracking/tracking.ts +2 -2
- package/src/infrastructure/tracking/useTrackCheckout.test.tsx +51 -24
- package/src/infrastructure/tracking/useTrackCheckout.ts +66 -56
- package/src/infrastructure/ui/Root.tsx +9 -9
- package/src/infrastructure/ui/components/templates/header/itemHeader/ItemHeader.tsx +1 -0
- package/src/infrastructure/ui/hooks/useCheckoutFlow.test.tsx +302 -0
- package/src/infrastructure/ui/hooks/useCheckoutFlow.tsx +203 -0
- package/src/infrastructure/ui/hooks/usePaymentInstrumentEvents.ts +18 -60
- package/src/infrastructure/ui/i18n/i18n.ts +1 -0
- package/src/infrastructure/ui/routing/CheckoutMiddleware.test.tsx +0 -11
- package/src/infrastructure/ui/routing/CheckoutMiddleware.tsx +1 -15
- package/src/infrastructure/ui/routing/Routing.tsx +14 -25
- package/src/infrastructure/ui/routing/routes.ts +0 -1
- package/src/infrastructure/ui/views/App.tsx +5 -13
- package/src/infrastructure/ui/views/checkout/Checkout.style.ts +3 -0
- package/src/infrastructure/ui/views/checkout/Checkout.test.tsx +51 -43
- package/src/infrastructure/ui/views/checkout/Checkout.tsx +51 -13
- package/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.tsx +8 -8
- package/src/infrastructure/ui/views/item/components/itemActions/__snapshots__/ItemActions.test.tsx.snap +8 -0
- package/src/infrastructure/ui/views/item/components/selectModal/__snapshots__/SelecModal.test.tsx.snap +8 -0
- package/src/infrastructure/ui/views/item/components/sizeWithoutStockModal/__snapshots__/SizeWithoutStockModal.test.tsx.snap +8 -0
- package/src/projection/customer/customer.ts +2 -0
- package/src/projection/order/order.ts +1 -1
- package/src/projection/subscription/subscription.ts +1 -1
- package/dist/src/infrastructure/ui/hooks/useSubmitCheckout.d.ts +0 -27
- package/dist/src/infrastructure/ui/hooks/useSubmitCheckout.js +0 -97
- package/dist/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.d.ts +0 -12
- package/dist/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.js +0 -88
- package/src/infrastructure/ui/hooks/useSubmitCheckout.test.ts +0 -297
- package/src/infrastructure/ui/hooks/useSubmitCheckout.ts +0 -169
- package/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.test.tsx +0 -134
- package/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.tsx +0 -124
package/src/ExpoRoot.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PortalProvider } from "@gorhom/portal";
|
|
1
2
|
import { useFonts } from "expo-font";
|
|
2
3
|
import "expo/build/Expo.fx";
|
|
3
4
|
import React, { FC, useCallback, useState } from "react";
|
|
@@ -12,7 +13,7 @@ import { fetchTranslations, translationExternalEndpoint } from "@lookiero/sty-ps
|
|
|
12
13
|
import { Country, Locale } from "@lookiero/sty-psp-locale";
|
|
13
14
|
import { SentryEnvironment } from "@lookiero/sty-psp-logging";
|
|
14
15
|
import { Segment } from "@lookiero/sty-psp-segment";
|
|
15
|
-
import { DummyLayout } from "@lookiero/sty-psp-ui";
|
|
16
|
+
import { DummyLayout, themeByTradename } from "@lookiero/sty-psp-ui";
|
|
16
17
|
import { Tradename } from "@lookiero/sty-sp-tradename";
|
|
17
18
|
import { KameleoonEnvironment } from "./infrastructure/ab-testing/kameleoonEnvironment";
|
|
18
19
|
import { bootstrap as checkoutBootstrap } from "./infrastructure/delivery/bootstrap";
|
|
@@ -21,22 +22,24 @@ import { root } from "./infrastructure/ui/Root";
|
|
|
21
22
|
import { DOMAIN } from "./infrastructure/ui/i18n/i18n";
|
|
22
23
|
import { Router } from "./infrastructure/ui/routing/router/Router";
|
|
23
24
|
import { Customer } from "./projection/customer/customer";
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
25
|
+
import { OrderProjection } from "./projection/order/order";
|
|
26
|
+
import { SubscriptionProjection } from "./projection/subscription/subscription";
|
|
26
27
|
import { VERSION } from "./version";
|
|
27
28
|
|
|
28
|
-
const locale: Locale = Locale.
|
|
29
|
-
const subscription:
|
|
30
|
-
const order:
|
|
29
|
+
const locale: Locale = Locale.es_ES;
|
|
30
|
+
const subscription: SubscriptionProjection = "b";
|
|
31
|
+
const order: OrderProjection = {
|
|
31
32
|
isFirstOrder: false,
|
|
32
33
|
orderNumber: 3687582,
|
|
33
34
|
coupon: "MYLOOKIERO",
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
const customer: Customer = {
|
|
37
|
-
customerId: "
|
|
38
|
-
country: Country.
|
|
38
|
+
customerId: "9cfb056e-6008-44b1-9075-320479bf92ac",
|
|
39
|
+
country: Country.NL,
|
|
39
40
|
segment: Segment.WOMEN,
|
|
41
|
+
email: "email@example.com",
|
|
42
|
+
name: "Adèle Léonce Émilie",
|
|
40
43
|
};
|
|
41
44
|
|
|
42
45
|
const sentryConfig: SentryEnvironment = {
|
|
@@ -53,7 +56,7 @@ const apiUrl =
|
|
|
53
56
|
? "/local-to-dev"
|
|
54
57
|
: "/checkout/api";
|
|
55
58
|
const authToken =
|
|
56
|
-
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
|
|
59
|
+
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjU2NDk0NjYsImV4cCI6MTc0MjQ3MDI5OSwiZGlzcGxheU5hbWUiOiJNaWtlbCIsImNvdW50cnlfY29kZSI6IkVTIiwiYWNjZXNzVmlhIjoiZW1haWwiLCJzdWJzY3JpcHRpb25TdGFydGluZ0RhdGUiOiIyMDI0LTExLTExIiwiaW1wZXJzb25hdGVkIjpmYWxzZSwidXVpZCI6ImQzYzIzNTRiLTk4MTEtNDZkNC1iMmJhLTVmYmEwMTJlZDk0ZCIsImlhdCI6MTc0MDA1MTA5OX0.AkuUZTsn9mgplQwatg0dPKyv1Hsc6r267UMahxMH19g";
|
|
57
60
|
const getAuthToken = () => Promise.resolve(authToken);
|
|
58
61
|
|
|
59
62
|
const externalTranslationsUrl =
|
|
@@ -94,6 +97,7 @@ setPaymentsBridge({
|
|
|
94
97
|
useFeatureFlags: () => ({}),
|
|
95
98
|
locale: () => Promise.resolve("es-ES"),
|
|
96
99
|
scrollView: ScrollView,
|
|
100
|
+
hostUrl: "",
|
|
97
101
|
});
|
|
98
102
|
|
|
99
103
|
const kameleoonConfig: KameleoonEnvironment = {
|
|
@@ -119,48 +123,59 @@ const Root = root({
|
|
|
119
123
|
kameleoon: () => kameleoonConfig,
|
|
120
124
|
})({ customerId: customer.customerId });
|
|
121
125
|
|
|
122
|
-
|
|
126
|
+
interface ExpoRootProps {
|
|
127
|
+
readonly tradename: Tradename;
|
|
128
|
+
}
|
|
129
|
+
const ExpoRoot: FC<ExpoRootProps> = ({ tradename }) => {
|
|
123
130
|
const [fontsLoaded] = useFonts({
|
|
124
|
-
["AreaInktrap-Semibold"]: require("@lookiero/aurora
|
|
125
|
-
["AreaNormal-Semibold"]: require("@lookiero/aurora
|
|
126
|
-
["AreaNormal-Extrabold"]: require("@lookiero/aurora
|
|
131
|
+
["AreaInktrap-Semibold"]: require("@lookiero/aurora/build/assets/fonts/AreaInktrap-Semibold.otf"),
|
|
132
|
+
["AreaNormal-Semibold"]: require("@lookiero/aurora/build/assets/fonts/AreaNormal-Semibold.otf"),
|
|
133
|
+
["AreaNormal-Extrabold"]: require("@lookiero/aurora/build/assets/fonts/AreaNormal-Extrabold.otf"),
|
|
134
|
+
["OpenSans-Regular"]: require("@lookiero/aurora/build/assets/fonts/OpenSans-Regular.ttf"),
|
|
135
|
+
["OpenSans-Bold"]: require("@lookiero/aurora/build/assets/fonts/OpenSans-Bold.ttf"),
|
|
136
|
+
["DalaFloda-Bold"]: require("@lookiero/aurora/build/assets/fonts/DalaFloda-Bold.otf"),
|
|
127
137
|
auroraicons: require("@lookiero/aurora-iconfont/dist/auroraicons.ttf"),
|
|
128
138
|
});
|
|
129
139
|
|
|
130
140
|
const [isAccessible, setIsAccessible] = useState<boolean>();
|
|
131
141
|
const onNotAccessible = useCallback(() => setIsAccessible(false), []);
|
|
132
142
|
|
|
143
|
+
const theme = themeByTradename({ tradename });
|
|
144
|
+
|
|
133
145
|
return fontsLoaded ? (
|
|
134
|
-
<
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
<
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
146
|
+
<PortalProvider>
|
|
147
|
+
<PaymentsQueryProvider>
|
|
148
|
+
<EventProvider>
|
|
149
|
+
<Aurora theme={theme}>
|
|
150
|
+
{isAccessible === false && <Text heading={true}>Checkout is not accessible!</Text>}
|
|
151
|
+
|
|
152
|
+
<Router>
|
|
153
|
+
<Routes>
|
|
154
|
+
<Route
|
|
155
|
+
path="/checkout/*"
|
|
156
|
+
element={
|
|
157
|
+
<Root
|
|
158
|
+
basePath="/checkout"
|
|
159
|
+
customer={customer}
|
|
160
|
+
layout={DummyLayout}
|
|
161
|
+
locale={locale}
|
|
162
|
+
order={order}
|
|
163
|
+
subscription={subscription}
|
|
164
|
+
tradename={Tradename.LOOKIERO}
|
|
165
|
+
useRedirect={useRedirect}
|
|
166
|
+
onCheckoutFlowSuccess={() => console.log("Checkout flow success!")}
|
|
167
|
+
onNotAccessible={onNotAccessible}
|
|
168
|
+
/>
|
|
169
|
+
}
|
|
170
|
+
/>
|
|
171
|
+
|
|
172
|
+
<Route element={<Navigate to="/checkout" replace />} path="*" />
|
|
173
|
+
</Routes>
|
|
174
|
+
</Router>
|
|
175
|
+
</Aurora>
|
|
176
|
+
</EventProvider>
|
|
177
|
+
</PaymentsQueryProvider>
|
|
178
|
+
</PortalProvider>
|
|
164
179
|
) : null;
|
|
165
180
|
};
|
|
166
181
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
|
+
import invariant from "tiny-invariant";
|
|
2
3
|
import { CommandStatus, useCommand } from "@lookiero/messaging-react";
|
|
3
4
|
import { Logger } from "@lookiero/sty-psp-logging";
|
|
4
5
|
import { NotificationLevel, useCreateToastNotification } from "@lookiero/sty-psp-notifications";
|
|
@@ -13,7 +14,7 @@ interface BlockCheckoutBookingFunction {
|
|
|
13
14
|
type UseBlockCheckoutBooking = [blockCheckoutBooking: BlockCheckoutBookingFunction, status: CommandStatus];
|
|
14
15
|
|
|
15
16
|
interface UseBlockCheckoutBookingFunctionArgs {
|
|
16
|
-
readonly checkoutBookingId: string;
|
|
17
|
+
readonly checkoutBookingId: string | undefined;
|
|
17
18
|
readonly logger: Logger;
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -26,6 +27,8 @@ const useBlockCheckoutBooking: UseBlockCheckoutBookingFunction = ({ checkoutBook
|
|
|
26
27
|
const [createNotification] = useCreateToastNotification({ contextId: MESSAGING_CONTEXT_ID, logger });
|
|
27
28
|
|
|
28
29
|
const blockCheckoutBooking = useCallback(async () => {
|
|
30
|
+
invariant(checkoutBookingId, "checkoutBookingId is required");
|
|
31
|
+
|
|
29
32
|
try {
|
|
30
33
|
await commandBus(
|
|
31
34
|
blockCheckoutBookingCommand({
|
|
@@ -11,6 +11,7 @@ const itemIds = [
|
|
|
11
11
|
"8890e00b-d4ed-4220-ae13-52cd88ae8ed5",
|
|
12
12
|
];
|
|
13
13
|
interface CheckoutDtoFunctionArgs {
|
|
14
|
+
readonly id?: string;
|
|
14
15
|
readonly status?: CheckoutStatus;
|
|
15
16
|
readonly items: CheckoutItemFunctionArgs[];
|
|
16
17
|
}
|
|
@@ -19,8 +20,12 @@ interface CheckoutDtoFunction {
|
|
|
19
20
|
(args: CheckoutDtoFunctionArgs): CheckoutDto;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
const checkoutDto: CheckoutDtoFunction = ({
|
|
23
|
-
id
|
|
23
|
+
const checkoutDto: CheckoutDtoFunction = ({
|
|
24
|
+
id = "9c450400-0cd7-44a4-b0e3-e0002a9bf8df",
|
|
25
|
+
status = CheckoutStatus.STARTED,
|
|
26
|
+
items,
|
|
27
|
+
}) => ({
|
|
28
|
+
id,
|
|
24
29
|
status,
|
|
25
30
|
customerId: "0df61ca7-7e4d-462b-a422-a57de0d116b4",
|
|
26
31
|
boxId: "9c406e57-100a-4aa6-83c5-016e7c2970e7",
|
|
@@ -37,6 +42,6 @@ interface CheckoutFunction {
|
|
|
37
42
|
(args: CheckoutFunctionArgs): CheckoutProjection;
|
|
38
43
|
}
|
|
39
44
|
|
|
40
|
-
const checkout: CheckoutFunction = ({ status, items }) => toCheckoutProjection(checkoutDto({ status, items }));
|
|
45
|
+
const checkout: CheckoutFunction = ({ id, status, items }) => toCheckoutProjection(checkoutDto({ id, status, items }));
|
|
41
46
|
|
|
42
47
|
export { checkout, checkoutDto };
|
|
@@ -23,7 +23,7 @@ const DEFAULT_QUERY_OPTIONS: QueryOptions = {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
interface UseViewPricingByCheckoutIdFunctionArgs {
|
|
26
|
-
readonly checkoutId: string;
|
|
26
|
+
readonly checkoutId: string | undefined;
|
|
27
27
|
readonly queryOptions?: QueryOptions;
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -36,7 +36,7 @@ const useViewPricingByCheckoutId: UseViewPricingByCheckoutIdFunction = ({
|
|
|
36
36
|
queryOptions = DEFAULT_QUERY_OPTIONS,
|
|
37
37
|
}) =>
|
|
38
38
|
useQuery({
|
|
39
|
-
query: viewPricingByCheckoutId({ checkoutId }),
|
|
39
|
+
query: viewPricingByCheckoutId({ checkoutId: checkoutId as string }),
|
|
40
40
|
contextId: MESSAGING_CONTEXT_ID,
|
|
41
41
|
invalidation: shouldInvalidate,
|
|
42
42
|
options: {
|
|
@@ -44,6 +44,7 @@ const useViewPricingByCheckoutId: UseViewPricingByCheckoutIdFunction = ({
|
|
|
44
44
|
staleTime: Infinity,
|
|
45
45
|
retry: false,
|
|
46
46
|
refetchOnWindowFocus: false,
|
|
47
|
+
enabled: Boolean(checkoutId),
|
|
47
48
|
},
|
|
48
49
|
});
|
|
49
50
|
|
|
@@ -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 {
|
|
5
|
+
import { SubscriptionProjection } from "../../projection/subscription/subscription";
|
|
6
6
|
|
|
7
7
|
const PROJECT = "checkout";
|
|
8
8
|
|
|
@@ -121,7 +121,7 @@ interface CheckoutTrackingEvent
|
|
|
121
121
|
readonly actionField: {
|
|
122
122
|
readonly items: number;
|
|
123
123
|
readonly currencyCode: Currency;
|
|
124
|
-
readonly subscription:
|
|
124
|
+
readonly subscription: SubscriptionProjection;
|
|
125
125
|
readonly coupon: string | null;
|
|
126
126
|
readonly orderId: number;
|
|
127
127
|
readonly value: number;
|
|
@@ -2,9 +2,15 @@ import { renderHook } from "@testing-library/react-native";
|
|
|
2
2
|
import { Country } from "@lookiero/sty-psp-locale";
|
|
3
3
|
import { Segment } from "@lookiero/sty-psp-segment";
|
|
4
4
|
import { useEmitUserEvent } from "@lookiero/sty-psp-tracking";
|
|
5
|
+
import { CheckoutStatus } from "../../domain/checkout/model/checkout";
|
|
6
|
+
import { CheckoutItemStatus } from "../../domain/checkoutItem/model/checkoutItem";
|
|
5
7
|
import { Currency } from "../../domain/checkoutItem/model/currency";
|
|
8
|
+
import { CheckoutProjection } from "../../projection/checkout/checkout";
|
|
9
|
+
import { OrderProjection } from "../../projection/order/order";
|
|
10
|
+
import { PricingProjection } from "../../projection/pricing/pricing";
|
|
11
|
+
import { SubscriptionProjection } from "../../projection/subscription/subscription";
|
|
12
|
+
import { checkout as checkoutMock } from "../projection/checkout/checkout.mock";
|
|
6
13
|
import { CheckoutTrackingEvent, TrackingEventName, TrackingEventCategory } from "./tracking";
|
|
7
|
-
import { TrackingPage } from "./tracking";
|
|
8
14
|
import { useTrackCheckout as sut } from "./useTrackCheckout";
|
|
9
15
|
|
|
10
16
|
const mockEmitUserEvent = jest.fn();
|
|
@@ -12,6 +18,34 @@ jest.mock("@lookiero/sty-psp-tracking");
|
|
|
12
18
|
|
|
13
19
|
const country = Country.ES;
|
|
14
20
|
const segment = Segment.WOMEN;
|
|
21
|
+
const userId = "80c38da1-7091-483d-a2ad-8f1642211e80";
|
|
22
|
+
const order: OrderProjection = {
|
|
23
|
+
coupon: null,
|
|
24
|
+
isFirstOrder: false,
|
|
25
|
+
orderNumber: 3691625,
|
|
26
|
+
};
|
|
27
|
+
const checkoutItemsReturned = 1;
|
|
28
|
+
const checkoutItemsKept = 2;
|
|
29
|
+
const checkoutItemsReplaced = 2;
|
|
30
|
+
const checkout: CheckoutProjection = checkoutMock({
|
|
31
|
+
id: "c513ebc8-df68-4f47-b899-8ec0ced84ca8",
|
|
32
|
+
status: CheckoutStatus.STARTED,
|
|
33
|
+
items: [
|
|
34
|
+
...new Array(checkoutItemsReturned).fill(1).map(() => ({ status: CheckoutItemStatus.RETURNED })),
|
|
35
|
+
...new Array(checkoutItemsKept).fill(1).map(() => ({ status: CheckoutItemStatus.KEPT })),
|
|
36
|
+
...new Array(checkoutItemsReplaced).fill(1).map(() => ({
|
|
37
|
+
status: CheckoutItemStatus.REPLACED,
|
|
38
|
+
replacedFor: { id: "26184353-c4bd-467a-bfd5-c9f688956058" },
|
|
39
|
+
})),
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
const pricing: PricingProjection = {
|
|
43
|
+
pendingToPay: {
|
|
44
|
+
amount: 16691,
|
|
45
|
+
currency: Currency.EUR,
|
|
46
|
+
},
|
|
47
|
+
} as PricingProjection;
|
|
48
|
+
const subscription: SubscriptionProjection = "b";
|
|
15
49
|
|
|
16
50
|
const event: CheckoutTrackingEvent = {
|
|
17
51
|
event: TrackingEventName.CHECKOUT,
|
|
@@ -19,19 +53,19 @@ const event: CheckoutTrackingEvent = {
|
|
|
19
53
|
section: "checkout_checkout",
|
|
20
54
|
store: country,
|
|
21
55
|
segment,
|
|
22
|
-
checkoutId:
|
|
23
|
-
userId
|
|
24
|
-
sizeChanges:
|
|
25
|
-
isFirstOrder:
|
|
56
|
+
checkoutId: checkout.id,
|
|
57
|
+
userId,
|
|
58
|
+
sizeChanges: checkoutItemsReplaced,
|
|
59
|
+
isFirstOrder: order.isFirstOrder,
|
|
26
60
|
ecommerce: {
|
|
27
61
|
checkout: {
|
|
28
62
|
actionField: {
|
|
29
|
-
items:
|
|
30
|
-
currencyCode:
|
|
31
|
-
subscription
|
|
32
|
-
coupon:
|
|
33
|
-
orderId:
|
|
34
|
-
value:
|
|
63
|
+
items: checkoutItemsKept + checkoutItemsReplaced,
|
|
64
|
+
currencyCode: pricing.pendingToPay.currency,
|
|
65
|
+
subscription,
|
|
66
|
+
coupon: order.coupon,
|
|
67
|
+
orderId: order.orderNumber,
|
|
68
|
+
value: pricing.pendingToPay.amount / 100,
|
|
35
69
|
},
|
|
36
70
|
},
|
|
37
71
|
},
|
|
@@ -43,24 +77,17 @@ describe("useTrackCheckout custom hook", () => {
|
|
|
43
77
|
|
|
44
78
|
const { result } = renderHook(() =>
|
|
45
79
|
sut({
|
|
46
|
-
|
|
80
|
+
order,
|
|
81
|
+
checkout,
|
|
82
|
+
pricing,
|
|
83
|
+
subscription,
|
|
84
|
+
userId,
|
|
47
85
|
country,
|
|
48
86
|
segment,
|
|
49
|
-
checkoutId: "c513ebc8-df68-4f47-b899-8ec0ced84ca8",
|
|
50
87
|
}),
|
|
51
88
|
);
|
|
52
89
|
|
|
53
|
-
result.current(
|
|
54
|
-
totalCheckoutItemsKept: 5,
|
|
55
|
-
pendingToPay: 166.91,
|
|
56
|
-
coupon: null,
|
|
57
|
-
currencyCode: Currency.EUR,
|
|
58
|
-
isFirstOrder: false,
|
|
59
|
-
orderNumber: 3691625,
|
|
60
|
-
totalReplacedFor: 0,
|
|
61
|
-
subscription: "b",
|
|
62
|
-
userId: "80c38da1-7091-483d-a2ad-8f1642211e80",
|
|
63
|
-
});
|
|
90
|
+
result.current();
|
|
64
91
|
|
|
65
92
|
expect(mockEmitUserEvent).toHaveBeenCalledWith(event);
|
|
66
93
|
});
|
|
@@ -1,84 +1,94 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
|
+
import invariant from "tiny-invariant";
|
|
2
3
|
import { Country } from "@lookiero/sty-psp-locale";
|
|
3
4
|
import { Segment } from "@lookiero/sty-psp-segment";
|
|
4
5
|
import { useEmitUserEvent } from "@lookiero/sty-psp-tracking";
|
|
6
|
+
import { CheckoutItemStatus } from "../../domain/checkoutItem/model/checkoutItem";
|
|
5
7
|
import { Currency } from "../../domain/checkoutItem/model/currency";
|
|
6
|
-
import {
|
|
8
|
+
import { CheckoutProjection } from "../../projection/checkout/checkout";
|
|
9
|
+
import { OrderProjection } from "../../projection/order/order";
|
|
10
|
+
import { PricingProjection } from "../../projection/pricing/pricing";
|
|
11
|
+
import { SubscriptionProjection } from "../../projection/subscription/subscription";
|
|
7
12
|
import { PROJECT, TrackingPage } from "./tracking";
|
|
8
13
|
import { CheckoutTrackingEvent, TrackingEventName, TrackingEventCategory } from "./tracking";
|
|
9
14
|
|
|
10
|
-
interface TrackCheckoutFunctionArgs {
|
|
11
|
-
readonly userId: string;
|
|
12
|
-
readonly totalReplacedFor: number;
|
|
13
|
-
readonly isFirstOrder: boolean;
|
|
14
|
-
readonly totalCheckoutItemsKept: number;
|
|
15
|
-
readonly currencyCode: Currency;
|
|
16
|
-
readonly subscription: Subscription;
|
|
17
|
-
readonly coupon: string | null;
|
|
18
|
-
readonly orderNumber: number;
|
|
19
|
-
readonly pendingToPay: number;
|
|
20
|
-
}
|
|
21
15
|
interface TrackCheckoutFunction {
|
|
22
|
-
(
|
|
16
|
+
(): void;
|
|
23
17
|
}
|
|
24
18
|
|
|
25
19
|
interface UseTrackCheckoutFunctionArgs {
|
|
26
|
-
readonly
|
|
20
|
+
readonly order: OrderProjection;
|
|
21
|
+
readonly checkout: CheckoutProjection | undefined;
|
|
22
|
+
readonly pricing: PricingProjection | undefined;
|
|
23
|
+
readonly subscription: SubscriptionProjection;
|
|
24
|
+
readonly userId: string;
|
|
27
25
|
readonly country: Country;
|
|
28
|
-
readonly checkoutId: string | undefined;
|
|
29
26
|
readonly segment: Segment;
|
|
30
27
|
}
|
|
28
|
+
|
|
31
29
|
interface UseTrackCheckoutFunction {
|
|
32
30
|
(args: UseTrackCheckoutFunctionArgs): TrackCheckoutFunction;
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
const useTrackCheckout: UseTrackCheckoutFunction = ({
|
|
33
|
+
const useTrackCheckout: UseTrackCheckoutFunction = ({
|
|
34
|
+
order,
|
|
35
|
+
checkout,
|
|
36
|
+
pricing,
|
|
37
|
+
subscription,
|
|
38
|
+
segment,
|
|
39
|
+
country,
|
|
40
|
+
userId,
|
|
41
|
+
}) => {
|
|
36
42
|
const emitUserEvent = useEmitUserEvent<CheckoutTrackingEvent>();
|
|
43
|
+
const { coupon, isFirstOrder, orderNumber } = order;
|
|
37
44
|
|
|
38
|
-
const trackCheckout: TrackCheckoutFunction = useCallback(
|
|
39
|
-
(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
totalCheckoutItemsKept,
|
|
47
|
-
totalReplacedFor,
|
|
48
|
-
userId,
|
|
49
|
-
}) => {
|
|
50
|
-
if (!checkoutId) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
45
|
+
const trackCheckout: TrackCheckoutFunction = useCallback(() => {
|
|
46
|
+
invariant(checkout, "Checkout must be defined to track checkout");
|
|
47
|
+
|
|
48
|
+
const checkoutItemsKept = checkout.items.filter(
|
|
49
|
+
(checkoutItem) =>
|
|
50
|
+
checkoutItem.status === CheckoutItemStatus.KEPT || checkoutItem.status === CheckoutItemStatus.REPLACED,
|
|
51
|
+
);
|
|
52
|
+
const totalReplacedFor = checkoutItemsKept?.filter(({ replacedFor }) => Boolean(replacedFor)).length || 0;
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
54
|
+
const checkoutTrackingEvent: CheckoutTrackingEvent = {
|
|
55
|
+
event: TrackingEventName.CHECKOUT,
|
|
56
|
+
eventCategory: TrackingEventCategory.ECOMMERCE,
|
|
57
|
+
section: `${PROJECT}_${TrackingPage.CHECKOUT}`,
|
|
58
|
+
store: country,
|
|
59
|
+
segment,
|
|
60
|
+
checkoutId: checkout.id,
|
|
61
|
+
userId,
|
|
62
|
+
sizeChanges: totalReplacedFor,
|
|
63
|
+
isFirstOrder,
|
|
64
|
+
ecommerce: {
|
|
65
|
+
checkout: {
|
|
66
|
+
actionField: {
|
|
67
|
+
items: checkoutItemsKept.length || 0,
|
|
68
|
+
currencyCode: pricing?.pendingToPay.currency as Currency,
|
|
69
|
+
subscription,
|
|
70
|
+
coupon,
|
|
71
|
+
orderId: orderNumber,
|
|
72
|
+
value: (pricing?.pendingToPay.amount as number) / 100,
|
|
74
73
|
},
|
|
75
74
|
},
|
|
76
|
-
}
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
emitUserEvent(checkoutTrackingEvent);
|
|
79
|
+
}, [
|
|
80
|
+
checkout,
|
|
81
|
+
country,
|
|
82
|
+
coupon,
|
|
83
|
+
emitUserEvent,
|
|
84
|
+
isFirstOrder,
|
|
85
|
+
orderNumber,
|
|
86
|
+
pricing?.pendingToPay.amount,
|
|
87
|
+
pricing?.pendingToPay.currency,
|
|
88
|
+
segment,
|
|
89
|
+
subscription,
|
|
90
|
+
userId,
|
|
91
|
+
]);
|
|
82
92
|
|
|
83
93
|
return trackCheckout;
|
|
84
94
|
};
|
|
@@ -10,8 +10,8 @@ import { SentryEnvironment, SentryLoggerFunctionArgs, sentryLogger, sentryLogger
|
|
|
10
10
|
import { Layout } from "@lookiero/sty-psp-ui";
|
|
11
11
|
import { Tradename } from "@lookiero/sty-sp-tradename";
|
|
12
12
|
import { Customer } from "../../projection/customer/customer";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
13
|
+
import { OrderProjection } from "../../projection/order/order";
|
|
14
|
+
import { SubscriptionProjection } from "../../projection/subscription/subscription";
|
|
15
15
|
import { KameleoonEnvironment } from "../ab-testing/kameleoonEnvironment";
|
|
16
16
|
import { QueryBusProvider } from "./hooks/useQueryBus";
|
|
17
17
|
import { Routing } from "./routing/Routing";
|
|
@@ -32,14 +32,14 @@ interface RootFunction {
|
|
|
32
32
|
|
|
33
33
|
interface RootProps {
|
|
34
34
|
readonly basePath: string;
|
|
35
|
-
readonly locale
|
|
35
|
+
readonly locale: Locale;
|
|
36
36
|
readonly customer: Customer;
|
|
37
|
-
readonly order:
|
|
38
|
-
readonly subscription:
|
|
37
|
+
readonly order: OrderProjection;
|
|
38
|
+
readonly subscription: SubscriptionProjection;
|
|
39
39
|
readonly layout: Layout;
|
|
40
40
|
readonly tradename: Tradename;
|
|
41
41
|
readonly onNotAccessible: () => void;
|
|
42
|
-
readonly
|
|
42
|
+
readonly onCheckoutFlowSuccess: () => void;
|
|
43
43
|
readonly useRedirect: () => Record<string, string>;
|
|
44
44
|
readonly useRoutes?: typeof reactRouterUseRoutes;
|
|
45
45
|
}
|
|
@@ -59,14 +59,14 @@ const root: RootFunction = ({
|
|
|
59
59
|
// eslint-disable-next-line react/display-name, react/prop-types
|
|
60
60
|
const Root = ({
|
|
61
61
|
basePath,
|
|
62
|
-
locale
|
|
62
|
+
locale,
|
|
63
63
|
customer,
|
|
64
64
|
order,
|
|
65
65
|
subscription,
|
|
66
66
|
layout,
|
|
67
67
|
tradename,
|
|
68
68
|
onNotAccessible,
|
|
69
|
-
|
|
69
|
+
onCheckoutFlowSuccess,
|
|
70
70
|
useRedirect,
|
|
71
71
|
useRoutes = reactRouterUseRoutes,
|
|
72
72
|
}: RootProps) => {
|
|
@@ -88,7 +88,7 @@ const root: RootFunction = ({
|
|
|
88
88
|
tradename={tradename}
|
|
89
89
|
useRedirect={useRedirect}
|
|
90
90
|
useRoutes={useRoutes}
|
|
91
|
-
|
|
91
|
+
onCheckoutFlowSuccess={onCheckoutFlowSuccess}
|
|
92
92
|
onI18nError={development ? undefined : handleOnI18nError}
|
|
93
93
|
onNotAccessible={onNotAccessible}
|
|
94
94
|
/>
|
|
@@ -33,6 +33,7 @@ interface ItemHeaderProps {
|
|
|
33
33
|
readonly onNext?: OnNextItemFunction;
|
|
34
34
|
readonly onPrevious?: OnPreviousItemFunction;
|
|
35
35
|
}
|
|
36
|
+
|
|
36
37
|
const ItemHeader: FC<ItemHeaderProps> = ({ items, item, onNext, onPrevious }) => {
|
|
37
38
|
const title = useI18nMessage({ domain: DOMAIN, id: I18nMessages.HEADER_CHECKOUT_TITLE });
|
|
38
39
|
const itemIndex = items.indexOf(item);
|