@lookiero/checkout 12.1.2 → 12.2.0-beta.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/dist/public/public/assets/adaptive-icon.png +0 -0
- package/dist/public/public/assets/favicon.png +0 -0
- package/dist/public/public/assets/icon.png +0 -0
- package/dist/public/public/assets/splash.png +0 -0
- package/dist/public/public/images/not-found.png +0 -0
- package/dist/src/infrastructure/integration/useRedirect.d.ts +7 -0
- package/dist/src/infrastructure/integration/useRedirect.js +1 -0
- package/dist/src/infrastructure/ui/Root.d.ts +2 -1
- package/dist/src/infrastructure/ui/hooks/useCheckoutFlow.d.ts +2 -0
- package/dist/src/infrastructure/ui/hooks/useCheckoutFlow.js +5 -5
- package/dist/src/infrastructure/ui/hooks/useSubmitCheckout.d.ts +27 -0
- package/dist/src/infrastructure/ui/hooks/useSubmitCheckout.js +97 -0
- package/dist/src/infrastructure/ui/routing/Routing.d.ts +2 -1
- package/dist/src/infrastructure/ui/routing/useBasePath.d.ts +8 -0
- package/dist/src/infrastructure/ui/routing/useBasePath.js +9 -0
- package/dist/src/infrastructure/ui/views/checkout/Checkout.d.ts +2 -1
- package/dist/src/infrastructure/ui/views/checkout/Checkout.js +1 -0
- package/dist/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.d.ts +12 -0
- package/dist/src/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.js +90 -0
- package/dist/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.d.ts +2 -1
- package/dist/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.js +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
- package/src/ExpoRoot.tsx +2 -1
- package/src/infrastructure/integration/useRedirect.ts +9 -0
- package/src/infrastructure/ui/Root.tsx +2 -1
- package/src/infrastructure/ui/hooks/useCheckoutFlow.test.tsx +12 -7
- package/src/infrastructure/ui/hooks/useCheckoutFlow.tsx +6 -4
- package/src/infrastructure/ui/routing/Routing.tsx +2 -1
- package/src/infrastructure/ui/views/checkout/Checkout.tsx +3 -1
- package/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.tsx +3 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -11,6 +11,7 @@ import { Customer } from "../../projection/customer/customer";
|
|
|
11
11
|
import { OrderProjection } from "../../projection/order/order";
|
|
12
12
|
import { SubscriptionProjection } from "../../projection/subscription/subscription";
|
|
13
13
|
import { KameleoonEnvironment } from "../ab-testing/kameleoonEnvironment";
|
|
14
|
+
import { UseRedirectFunction } from "../integration/useRedirect";
|
|
14
15
|
interface RootFunctionArgs {
|
|
15
16
|
readonly Messaging: MessagingRoot;
|
|
16
17
|
readonly I18n: I18n;
|
|
@@ -33,7 +34,7 @@ interface RootProps {
|
|
|
33
34
|
readonly tradename: Tradename;
|
|
34
35
|
readonly onNotAccessible: () => void;
|
|
35
36
|
readonly onCheckoutFlowSuccess: () => void;
|
|
36
|
-
readonly useRedirect:
|
|
37
|
+
readonly useRedirect: UseRedirectFunction;
|
|
37
38
|
readonly useRoutes?: typeof reactRouterUseRoutes;
|
|
38
39
|
}
|
|
39
40
|
declare const root: RootFunction;
|
|
@@ -2,6 +2,7 @@ import { ReactNode } from "react";
|
|
|
2
2
|
import { CheckoutProjection } from "../../../projection/checkout/checkout";
|
|
3
3
|
import { OrderProjection } from "../../../projection/order/order";
|
|
4
4
|
import { SubscriptionProjection } from "../../../projection/subscription/subscription";
|
|
5
|
+
import { UseRedirectFunction } from "../../integration/useRedirect";
|
|
5
6
|
type CheckoutFlowStatus = "idle" | "loading" | "success" | "error";
|
|
6
7
|
interface CheckoutFlowFunction {
|
|
7
8
|
(): Promise<void>;
|
|
@@ -17,6 +18,7 @@ interface UseCheckoutFlowArgs {
|
|
|
17
18
|
readonly subscription: SubscriptionProjection;
|
|
18
19
|
readonly getAuthToken: () => Promise<string>;
|
|
19
20
|
readonly onSuccess: () => void;
|
|
21
|
+
readonly useRedirect: UseRedirectFunction;
|
|
20
22
|
}
|
|
21
23
|
interface UseCheckoutFlowFunction {
|
|
22
24
|
(args: UseCheckoutFlowArgs): CheckoutFlowReturn;
|
|
@@ -12,14 +12,14 @@ import { useViewPaymentFlowPayloadByCheckoutId } from "../../projection/payment/
|
|
|
12
12
|
import { useViewPricingByCheckoutId } from "../../projection/pricing/react/useViewPricingByCheckoutId";
|
|
13
13
|
import { useTrackCheckout } from "../../tracking/useTrackCheckout";
|
|
14
14
|
import { I18nMessages } from "../i18n/i18n";
|
|
15
|
-
import { Routes } from "../routing/routes";
|
|
16
15
|
import { usePaymentInstrumentEvents } from "./usePaymentInstrumentEvents";
|
|
17
16
|
import { useQueryBus } from "./useQueryBus";
|
|
18
17
|
import { useStaticInfo } from "./useStaticInfo";
|
|
19
|
-
const useCheckoutFlow = ({ checkout: checkoutProjection, order: orderProjection, subscription: subscriptionProjection, getAuthToken, onSuccess, }) => {
|
|
18
|
+
const useCheckoutFlow = ({ checkout: checkoutProjection, order: orderProjection, subscription: subscriptionProjection, getAuthToken, onSuccess, useRedirect, }) => {
|
|
20
19
|
const logger = useLogger();
|
|
21
20
|
const queryBus = useQueryBus();
|
|
22
|
-
const { customer: { customerId, country, segment, name, email },
|
|
21
|
+
const { customer: { customerId, country, segment, name, email }, tradename, } = useStaticInfo();
|
|
22
|
+
const { returnUrl } = useRedirect();
|
|
23
23
|
const paymentFlowRef = useRef(null);
|
|
24
24
|
const [paymentFlowPayload] = useViewPaymentFlowPayloadByCheckoutId({
|
|
25
25
|
checkoutId: checkoutProjection?.id,
|
|
@@ -73,14 +73,14 @@ const useCheckoutFlow = ({ checkout: checkoutProjection, order: orderProjection,
|
|
|
73
73
|
paymentFlowRef.current?.startLegacyBoxCheckout({
|
|
74
74
|
...paymentFlowPayload,
|
|
75
75
|
userInformation: { email, name },
|
|
76
|
-
returnUrl
|
|
76
|
+
returnUrl,
|
|
77
77
|
});
|
|
78
78
|
}, [
|
|
79
79
|
checkoutProjection?.checkoutBookingId,
|
|
80
80
|
paymentFlowPayload,
|
|
81
81
|
email,
|
|
82
82
|
name,
|
|
83
|
-
|
|
83
|
+
returnUrl,
|
|
84
84
|
sizeChangeEnabled,
|
|
85
85
|
blockCheckoutBooking,
|
|
86
86
|
queryBus,
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RefObject } from "react";
|
|
2
|
+
import { PaymentFlowRef } from "@lookiero/payments-front";
|
|
3
|
+
import { Logger } from "@lookiero/sty-psp-logging";
|
|
4
|
+
import { PaymentFlowPayloadProjection } from "../../../projection/payment/paymentFlowPayload";
|
|
5
|
+
type Status = "idle" | "loading" | "success" | "error";
|
|
6
|
+
interface SubmitCheckoutFunctionArgs {
|
|
7
|
+
readonly paymentFlowPayload: PaymentFlowPayloadProjection;
|
|
8
|
+
readonly sizeChangeEnabled: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface SubmitCheckoutFunction {
|
|
11
|
+
(args: SubmitCheckoutFunctionArgs): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
type UseSubmitCheckoutResult = [submitCheckout: SubmitCheckoutFunction, status: Status];
|
|
14
|
+
interface UseSubmitCheckoutFunctionArgs {
|
|
15
|
+
readonly checkoutId: string;
|
|
16
|
+
readonly checkoutBookingId: string;
|
|
17
|
+
readonly paymentFlowRef: RefObject<PaymentFlowRef>;
|
|
18
|
+
readonly onError: () => void;
|
|
19
|
+
readonly onSuccess?: () => void;
|
|
20
|
+
readonly logger: Logger;
|
|
21
|
+
}
|
|
22
|
+
interface UseSubmitCheckoutFunction {
|
|
23
|
+
(args: UseSubmitCheckoutFunctionArgs): UseSubmitCheckoutResult;
|
|
24
|
+
}
|
|
25
|
+
declare const useSubmitCheckout: UseSubmitCheckoutFunction;
|
|
26
|
+
export type { Status, SubmitCheckoutFunction };
|
|
27
|
+
export { useSubmitCheckout };
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from "react";
|
|
2
|
+
import { CommandStatus } from "@lookiero/messaging-react";
|
|
3
|
+
import { NotificationLevel, useCreateToastNotification } from "@lookiero/sty-psp-notifications";
|
|
4
|
+
import { viewCheckoutBookingById, } from "../../../projection/checkoutBooking/viewCheckoutBookingById";
|
|
5
|
+
import { MESSAGING_CONTEXT_ID } from "../../delivery/baseBootstrap";
|
|
6
|
+
import { useSubmitCheckout as useSubmitCheckoutCommand } from "../../domain/checkout/react/useSubmitCheckout";
|
|
7
|
+
import { useBlockCheckoutBooking } from "../../domain/checkoutBooking/react/useBlockCheckoutBooking";
|
|
8
|
+
import { I18nMessages } from "../i18n/i18n";
|
|
9
|
+
import { useQueryBus } from "./useQueryBus";
|
|
10
|
+
var ChargeStatus;
|
|
11
|
+
(function (ChargeStatus) {
|
|
12
|
+
ChargeStatus["EXECUTED"] = "EXECUTED";
|
|
13
|
+
ChargeStatus["REQUIRES_ACTION"] = "REQUIRES_ACTION";
|
|
14
|
+
ChargeStatus["REQUIRED_ACTION_CANCELLED"] = "REQUIRED_ACTION_CANCELLED";
|
|
15
|
+
ChargeStatus["REJECTED"] = "REJECTED";
|
|
16
|
+
ChargeStatus["CANCELLED"] = "CANCELLED";
|
|
17
|
+
ChargeStatus["TO_CONFIRM"] = "TO_CONFIRM";
|
|
18
|
+
ChargeStatus["ERROR"] = "ERROR";
|
|
19
|
+
ChargeStatus["UNKNOWN"] = "UNKNOWN";
|
|
20
|
+
})(ChargeStatus || (ChargeStatus = {}));
|
|
21
|
+
const useSubmitCheckout = ({ checkoutId, checkoutBookingId, paymentFlowRef, onError, onSuccess, logger, }) => {
|
|
22
|
+
const queryBus = useQueryBus();
|
|
23
|
+
const [submitCheckoutCommand, submitCheckoutCommandStatus] = useSubmitCheckoutCommand({ checkoutId, logger });
|
|
24
|
+
const [blockCheckoutBooking, blockCheckoutBookingStatus] = useBlockCheckoutBooking({ checkoutBookingId, logger });
|
|
25
|
+
const [createNotification] = useCreateToastNotification({ contextId: MESSAGING_CONTEXT_ID, logger });
|
|
26
|
+
const [checkoutBookingExpired, setCheckoutBookingExpired] = useState(false);
|
|
27
|
+
const [startLegacyBoxCheckoutStatus, setStartLegacyBoxCheckoutStatus] = useState("idle");
|
|
28
|
+
const submitCheckout = useCallback(async ({ paymentFlowPayload, sizeChangeEnabled }) => {
|
|
29
|
+
try {
|
|
30
|
+
sizeChangeEnabled && (await blockCheckoutBooking());
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const checkoutBooking = await queryBus(viewCheckoutBookingById({ checkoutBookingId }));
|
|
36
|
+
if (checkoutBooking?.isExpired) {
|
|
37
|
+
setCheckoutBookingExpired(true);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
paymentFlowRef.current?.startLegacyBoxCheckout(
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
paymentFlowPayload, async ({ status, toaster, final }) => {
|
|
44
|
+
setStartLegacyBoxCheckoutStatus("loading");
|
|
45
|
+
if (final) {
|
|
46
|
+
if (status === ChargeStatus.EXECUTED) {
|
|
47
|
+
setStartLegacyBoxCheckoutStatus("success");
|
|
48
|
+
await submitCheckoutCommand();
|
|
49
|
+
onSuccess?.();
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
createNotification({
|
|
53
|
+
level: NotificationLevel.ERROR,
|
|
54
|
+
bodyI18nKey: toaster?.id || I18nMessages.CHECKOUT_TOAST_PAYMENT_ERROR,
|
|
55
|
+
});
|
|
56
|
+
setStartLegacyBoxCheckoutStatus("error");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}, [
|
|
61
|
+
queryBus,
|
|
62
|
+
checkoutBookingId,
|
|
63
|
+
paymentFlowRef,
|
|
64
|
+
blockCheckoutBooking,
|
|
65
|
+
submitCheckoutCommand,
|
|
66
|
+
onSuccess,
|
|
67
|
+
createNotification,
|
|
68
|
+
]);
|
|
69
|
+
const status = useMemo(() => {
|
|
70
|
+
if (blockCheckoutBookingStatus === CommandStatus.LOADING ||
|
|
71
|
+
startLegacyBoxCheckoutStatus === "loading" ||
|
|
72
|
+
submitCheckoutCommandStatus === CommandStatus.LOADING) {
|
|
73
|
+
return "loading";
|
|
74
|
+
}
|
|
75
|
+
if (blockCheckoutBookingStatus === CommandStatus.SUCCESS &&
|
|
76
|
+
startLegacyBoxCheckoutStatus === "success" &&
|
|
77
|
+
submitCheckoutCommandStatus === CommandStatus.SUCCESS) {
|
|
78
|
+
return "success";
|
|
79
|
+
}
|
|
80
|
+
if (blockCheckoutBookingStatus === CommandStatus.ERROR ||
|
|
81
|
+
startLegacyBoxCheckoutStatus === "error" ||
|
|
82
|
+
submitCheckoutCommandStatus === CommandStatus.ERROR ||
|
|
83
|
+
checkoutBookingExpired) {
|
|
84
|
+
onError();
|
|
85
|
+
return "error";
|
|
86
|
+
}
|
|
87
|
+
return "idle";
|
|
88
|
+
}, [
|
|
89
|
+
blockCheckoutBookingStatus,
|
|
90
|
+
startLegacyBoxCheckoutStatus,
|
|
91
|
+
submitCheckoutCommandStatus,
|
|
92
|
+
checkoutBookingExpired,
|
|
93
|
+
onError,
|
|
94
|
+
]);
|
|
95
|
+
return [submitCheckout, status];
|
|
96
|
+
};
|
|
97
|
+
export { useSubmitCheckout };
|
|
@@ -8,6 +8,7 @@ import { Customer } from "../../../projection/customer/customer";
|
|
|
8
8
|
import { OrderProjection } from "../../../projection/order/order";
|
|
9
9
|
import { SubscriptionProjection } from "../../../projection/subscription/subscription";
|
|
10
10
|
import { KameleoonEnvironment } from "../../ab-testing/kameleoonEnvironment";
|
|
11
|
+
import { UseRedirectFunction } from "../../integration/useRedirect";
|
|
11
12
|
interface RoutingProps {
|
|
12
13
|
readonly basePath?: string;
|
|
13
14
|
readonly customer: Customer;
|
|
@@ -22,7 +23,7 @@ interface RoutingProps {
|
|
|
22
23
|
readonly onNotAccessible: () => void;
|
|
23
24
|
readonly onCheckoutFlowSuccess: () => void;
|
|
24
25
|
readonly onI18nError?: (err: Error) => void;
|
|
25
|
-
readonly useRedirect:
|
|
26
|
+
readonly useRedirect: UseRedirectFunction;
|
|
26
27
|
readonly useRoutes: typeof reactRouterUseRoutes;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React, { createContext, useContext } from "react";
|
|
2
|
+
import invariant from "tiny-invariant";
|
|
3
|
+
const BasePathContext = createContext(null);
|
|
4
|
+
export const BasePathProvider = ({ basePath, children }) => (React.createElement(BasePathContext.Provider, { value: basePath }, children));
|
|
5
|
+
export const useBasePath = () => {
|
|
6
|
+
const basePath = useContext(BasePathContext);
|
|
7
|
+
invariant(basePath !== null, "Your are trying to use the useBasePath hook without wrapping your app with the <BasePathProvider>.");
|
|
8
|
+
return basePath;
|
|
9
|
+
};
|
|
@@ -2,13 +2,14 @@ import { FC } from "react";
|
|
|
2
2
|
import { Layout as UiLayout } from "@lookiero/sty-psp-ui";
|
|
3
3
|
import { OrderProjection } from "../../../../projection/order/order";
|
|
4
4
|
import { SubscriptionProjection } from "../../../../projection/subscription/subscription";
|
|
5
|
+
import { UseRedirectFunction } from "../../../integration/useRedirect";
|
|
5
6
|
interface CheckoutProps {
|
|
6
7
|
readonly layout: UiLayout;
|
|
7
8
|
readonly order: OrderProjection;
|
|
8
9
|
readonly subscription: SubscriptionProjection;
|
|
9
10
|
readonly getAuthToken: () => Promise<string>;
|
|
10
11
|
readonly onCheckoutFlowSuccess: () => void;
|
|
11
|
-
readonly useRedirect:
|
|
12
|
+
readonly useRedirect: UseRedirectFunction;
|
|
12
13
|
}
|
|
13
14
|
declare const Checkout: FC<CheckoutProps>;
|
|
14
15
|
export { Checkout };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
import { Subscription } from "../../../../../../projection/subscription/subscription";
|
|
3
|
+
interface CheckoutPaymentModalProps {
|
|
4
|
+
readonly coupon: string | null;
|
|
5
|
+
readonly orderNumber: number;
|
|
6
|
+
readonly isFirstOrder: boolean;
|
|
7
|
+
readonly subscription: Subscription;
|
|
8
|
+
readonly getAuthToken: () => Promise<string>;
|
|
9
|
+
readonly onCheckoutSubmitted?: () => void;
|
|
10
|
+
}
|
|
11
|
+
declare const CheckoutPaymentModal: FC<CheckoutPaymentModalProps>;
|
|
12
|
+
export { CheckoutPaymentModal };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
+
import { useNavigate } from "react-router-native";
|
|
3
|
+
import { QueryStatus } from "@lookiero/messaging-react";
|
|
4
|
+
import { PaymentFlow } from "@lookiero/payments-front";
|
|
5
|
+
import { useLogger } from "@lookiero/sty-psp-logging";
|
|
6
|
+
import { CheckoutItemStatus } from "../../../../../../domain/checkoutItem/model/checkoutItem";
|
|
7
|
+
import { useViewFirstAvailableCheckoutByCustomerId } from "../../../../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
|
|
8
|
+
import { useViewIsSizeChangeEnabledByCheckoutId } from "../../../../../projection/checkout/react/useViewIsSizeChangeEnabledByCheckoutId";
|
|
9
|
+
import { useViewPaymentFlowPayloadByCheckoutId } from "../../../../../projection/payment/react/useViewPaymentFlowPayloadByCheckoutId";
|
|
10
|
+
import { useViewPricingByCheckoutId } from "../../../../../projection/pricing/react/useViewPricingByCheckoutId";
|
|
11
|
+
import { TrackingPage } from "../../../../../tracking/tracking";
|
|
12
|
+
import { useTrackCheckout } from "../../../../../tracking/useTrackCheckout";
|
|
13
|
+
import { useStaticInfo } from "../../../../hooks/useStaticInfo";
|
|
14
|
+
import { useSubmitCheckout } from "../../../../hooks/useSubmitCheckout";
|
|
15
|
+
import { Routes } from "../../../../routing/routes";
|
|
16
|
+
import { useBasePath } from "../../../../routing/useBasePath";
|
|
17
|
+
const CheckoutPaymentModal = ({ coupon, isFirstOrder, subscription, orderNumber, getAuthToken, onCheckoutSubmitted, }) => {
|
|
18
|
+
const paymentFlowRef = useRef(null);
|
|
19
|
+
const logger = useLogger();
|
|
20
|
+
const { customer: { customerId, country, segment }, } = useStaticInfo();
|
|
21
|
+
const [checkout, checkoutStatus] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
|
|
22
|
+
const [paymentFlowPayload] = useViewPaymentFlowPayloadByCheckoutId({
|
|
23
|
+
checkoutId: checkout?.id,
|
|
24
|
+
});
|
|
25
|
+
const [sizeChangeEnabled] = useViewIsSizeChangeEnabledByCheckoutId({ checkoutId: checkout?.id });
|
|
26
|
+
const [pricing] = useViewPricingByCheckoutId({
|
|
27
|
+
checkoutId: checkout?.id,
|
|
28
|
+
queryOptions: { refetchOnMount: true },
|
|
29
|
+
});
|
|
30
|
+
const [authToken, setAuthToken] = useState();
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const loadAuthToken = async () => setAuthToken(await getAuthToken());
|
|
33
|
+
loadAuthToken();
|
|
34
|
+
}, [getAuthToken]);
|
|
35
|
+
const basePath = useBasePath();
|
|
36
|
+
const navigate = useNavigate();
|
|
37
|
+
const trackCheckout = useTrackCheckout({
|
|
38
|
+
page: TrackingPage.CHECKOUT,
|
|
39
|
+
checkoutId: checkout?.id,
|
|
40
|
+
country,
|
|
41
|
+
segment,
|
|
42
|
+
});
|
|
43
|
+
const handleOnSubmitCheckoutError = useCallback(() => navigate(`${basePath}/${Routes.CHECKOUT}`, { replace: true }), [basePath, navigate]);
|
|
44
|
+
const handleOnSubmitCheckoutSuccess = useCallback(() => {
|
|
45
|
+
const checkoutItemsKept = checkout?.items.filter((checkoutItem) => checkoutItem.status === CheckoutItemStatus.KEPT || checkoutItem.status === CheckoutItemStatus.REPLACED);
|
|
46
|
+
const totalReplacedFor = checkoutItemsKept?.filter(({ replacedFor }) => Boolean(replacedFor)).length || 0;
|
|
47
|
+
trackCheckout({
|
|
48
|
+
totalCheckoutItemsKept: checkoutItemsKept?.length || 0,
|
|
49
|
+
pendingToPay: pricing?.pendingToPay.amount / 100,
|
|
50
|
+
coupon,
|
|
51
|
+
currencyCode: pricing?.pendingToPay.currency,
|
|
52
|
+
isFirstOrder,
|
|
53
|
+
orderNumber,
|
|
54
|
+
totalReplacedFor,
|
|
55
|
+
subscription,
|
|
56
|
+
userId: customerId,
|
|
57
|
+
});
|
|
58
|
+
onCheckoutSubmitted?.();
|
|
59
|
+
}, [
|
|
60
|
+
checkout?.items,
|
|
61
|
+
coupon,
|
|
62
|
+
customerId,
|
|
63
|
+
isFirstOrder,
|
|
64
|
+
onCheckoutSubmitted,
|
|
65
|
+
orderNumber,
|
|
66
|
+
pricing?.pendingToPay.amount,
|
|
67
|
+
pricing?.pendingToPay.currency,
|
|
68
|
+
subscription,
|
|
69
|
+
trackCheckout,
|
|
70
|
+
]);
|
|
71
|
+
const [submitCheckout] = useSubmitCheckout({
|
|
72
|
+
checkoutId: checkout?.id,
|
|
73
|
+
checkoutBookingId: checkout?.checkoutBookingId,
|
|
74
|
+
paymentFlowRef,
|
|
75
|
+
onError: handleOnSubmitCheckoutError,
|
|
76
|
+
onSuccess: handleOnSubmitCheckoutSuccess,
|
|
77
|
+
logger,
|
|
78
|
+
});
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (paymentFlowPayload && sizeChangeEnabled !== undefined && pricing !== undefined) {
|
|
81
|
+
submitCheckout({ paymentFlowPayload, sizeChangeEnabled });
|
|
82
|
+
}
|
|
83
|
+
}, [paymentFlowPayload, pricing, sizeChangeEnabled, submitCheckout]);
|
|
84
|
+
const dependenciesLoadedStatuses = [QueryStatus.ERROR, QueryStatus.SUCCESS];
|
|
85
|
+
const dependenciesLoaded = (dependenciesLoadedStatuses.includes(checkoutStatus) || checkout) && authToken;
|
|
86
|
+
if (!dependenciesLoaded)
|
|
87
|
+
return null;
|
|
88
|
+
return React.createElement(PaymentFlow, { ref: paymentFlowRef, token: authToken });
|
|
89
|
+
};
|
|
90
|
+
export { CheckoutPaymentModal };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
|
+
import { UseRedirectFunction } from "../../../../../integration/useRedirect";
|
|
2
3
|
interface PaymentInstrumentProps {
|
|
3
|
-
readonly useRedirect:
|
|
4
|
+
readonly useRedirect: UseRedirectFunction;
|
|
4
5
|
}
|
|
5
6
|
declare const PaymentInstrument: FC<PaymentInstrumentProps>;
|
|
6
7
|
export { PaymentInstrument };
|
package/dist/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.js
CHANGED
|
@@ -4,7 +4,7 @@ import { useStaticInfo } from "../../../../hooks/useStaticInfo";
|
|
|
4
4
|
const PaymentInstrument = ({ useRedirect }) => {
|
|
5
5
|
const { returnUrl } = useRedirect();
|
|
6
6
|
const { customer } = useStaticInfo();
|
|
7
|
-
return (React.createElement(PaymentInstrumentSelect, { beforeRedirect:
|
|
7
|
+
return (React.createElement(PaymentInstrumentSelect, { beforeRedirect: () => Promise.resolve(returnUrl), hasError: false, section: Section.BOX_CHECKOUT, userInformation: {
|
|
8
8
|
email: customer.email,
|
|
9
9
|
name: customer.name,
|
|
10
10
|
}, showSingleUsePaymentMethods: true }));
|
package/dist/src/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "12.
|
|
1
|
+
export declare const VERSION = "12.2.0-beta.0";
|
package/dist/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "12.
|
|
1
|
+
export const VERSION = "12.2.0-beta.0";
|
package/package.json
CHANGED
package/src/ExpoRoot.tsx
CHANGED
|
@@ -17,6 +17,7 @@ import { Tradename } from "@lookiero/sty-sp-tradename";
|
|
|
17
17
|
import { KameleoonEnvironment } from "./infrastructure/ab-testing/kameleoonEnvironment";
|
|
18
18
|
import { bootstrap as checkoutBootstrap } from "./infrastructure/delivery/bootstrap";
|
|
19
19
|
import { bootstrap as checkoutMockBootstrap } from "./infrastructure/delivery/bootstrap.mock";
|
|
20
|
+
import { UseRedirectFunction } from "./infrastructure/integration/useRedirect";
|
|
20
21
|
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";
|
|
@@ -79,7 +80,7 @@ const translations: EndpointFunction[] = [
|
|
|
79
80
|
})(locale),
|
|
80
81
|
];
|
|
81
82
|
|
|
82
|
-
const useRedirect:
|
|
83
|
+
const useRedirect: UseRedirectFunction = () => ({
|
|
83
84
|
returnUrl: "https://web2.dev.aws.lookiero.es/user/",
|
|
84
85
|
});
|
|
85
86
|
|
|
@@ -13,6 +13,7 @@ import { Customer } from "../../projection/customer/customer";
|
|
|
13
13
|
import { OrderProjection } from "../../projection/order/order";
|
|
14
14
|
import { SubscriptionProjection } from "../../projection/subscription/subscription";
|
|
15
15
|
import { KameleoonEnvironment } from "../ab-testing/kameleoonEnvironment";
|
|
16
|
+
import { UseRedirectFunction } from "../integration/useRedirect";
|
|
16
17
|
import { QueryBusProvider } from "./hooks/useQueryBus";
|
|
17
18
|
import { Routing } from "./routing/Routing";
|
|
18
19
|
|
|
@@ -40,7 +41,7 @@ interface RootProps {
|
|
|
40
41
|
readonly tradename: Tradename;
|
|
41
42
|
readonly onNotAccessible: () => void;
|
|
42
43
|
readonly onCheckoutFlowSuccess: () => void;
|
|
43
|
-
readonly useRedirect:
|
|
44
|
+
readonly useRedirect: UseRedirectFunction;
|
|
44
45
|
readonly useRoutes?: typeof reactRouterUseRoutes;
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -11,6 +11,7 @@ import { OrderProjection } from "../../../projection/order/order";
|
|
|
11
11
|
import { SubscriptionProjection } from "../../../projection/subscription/subscription";
|
|
12
12
|
import { useSubmitCheckout } from "../../domain/checkout/react/useSubmitCheckout";
|
|
13
13
|
import { useBlockCheckoutBooking } from "../../domain/checkoutBooking/react/useBlockCheckoutBooking";
|
|
14
|
+
import { UseRedirectFunction } from "../../integration/useRedirect";
|
|
14
15
|
import { checkout } from "../../projection/checkout/checkout.mock";
|
|
15
16
|
import { useViewIsSizeChangeEnabledByCheckoutId } from "../../projection/checkout/react/useViewIsSizeChangeEnabledByCheckoutId";
|
|
16
17
|
import { paymentFlowPayload as mockPaymentFlowPayload } from "../../projection/payment/paymentFlowPayload.mock";
|
|
@@ -18,11 +19,15 @@ import { useViewPaymentFlowPayloadByCheckoutId } from "../../projection/payment/
|
|
|
18
19
|
import { pricing } from "../../projection/pricing/pricing.mock";
|
|
19
20
|
import { useViewPricingByCheckoutId } from "../../projection/pricing/react/useViewPricingByCheckoutId";
|
|
20
21
|
import { I18nMessages } from "../i18n/i18n";
|
|
21
|
-
import { Routes } from "../routing/routes";
|
|
22
22
|
import { useCheckoutFlow as sut } from "./useCheckoutFlow";
|
|
23
23
|
import { usePaymentInstrumentEvents } from "./usePaymentInstrumentEvents";
|
|
24
24
|
import { useQueryBus } from "./useQueryBus";
|
|
25
25
|
|
|
26
|
+
const returnUrl = "/checkout";
|
|
27
|
+
const useRedirect: UseRedirectFunction = () => ({
|
|
28
|
+
returnUrl,
|
|
29
|
+
});
|
|
30
|
+
|
|
26
31
|
const getAuthToken = () => Promise.resolve("token");
|
|
27
32
|
const mockCheckout = checkout({
|
|
28
33
|
items: [
|
|
@@ -119,7 +124,7 @@ describe("useCheckoutFlow custom hook", () => {
|
|
|
119
124
|
});
|
|
120
125
|
|
|
121
126
|
const { result } = renderHook(() =>
|
|
122
|
-
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess }),
|
|
127
|
+
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess, useRedirect }),
|
|
123
128
|
);
|
|
124
129
|
|
|
125
130
|
let checkoutFlow: () => void, status, paymentFlowComponent;
|
|
@@ -145,7 +150,7 @@ describe("useCheckoutFlow custom hook", () => {
|
|
|
145
150
|
expect.objectContaining({
|
|
146
151
|
...mockPaymentFlowPayload,
|
|
147
152
|
userInformation: { email, name },
|
|
148
|
-
returnUrl
|
|
153
|
+
returnUrl,
|
|
149
154
|
}),
|
|
150
155
|
);
|
|
151
156
|
expect(mockSubmitCheckout).toHaveBeenCalled();
|
|
@@ -175,7 +180,7 @@ describe("useCheckoutFlow custom hook", () => {
|
|
|
175
180
|
});
|
|
176
181
|
|
|
177
182
|
const { result } = renderHook(() =>
|
|
178
|
-
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess }),
|
|
183
|
+
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess, useRedirect }),
|
|
179
184
|
);
|
|
180
185
|
|
|
181
186
|
let checkoutFlow: () => void, status, paymentFlowComponent;
|
|
@@ -201,7 +206,7 @@ describe("useCheckoutFlow custom hook", () => {
|
|
|
201
206
|
expect.objectContaining({
|
|
202
207
|
...mockPaymentFlowPayload,
|
|
203
208
|
userInformation: { email, name },
|
|
204
|
-
returnUrl
|
|
209
|
+
returnUrl,
|
|
205
210
|
}),
|
|
206
211
|
);
|
|
207
212
|
expect(mockSubmitCheckout).toHaveBeenCalled();
|
|
@@ -231,7 +236,7 @@ describe("useCheckoutFlow custom hook", () => {
|
|
|
231
236
|
});
|
|
232
237
|
|
|
233
238
|
const { result } = renderHook(() =>
|
|
234
|
-
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess }),
|
|
239
|
+
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess, useRedirect }),
|
|
235
240
|
);
|
|
236
241
|
|
|
237
242
|
let checkoutFlow: () => void, status, paymentFlowComponent;
|
|
@@ -278,7 +283,7 @@ describe("useCheckoutFlow custom hook", () => {
|
|
|
278
283
|
});
|
|
279
284
|
|
|
280
285
|
const { result } = renderHook(() =>
|
|
281
|
-
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess }),
|
|
286
|
+
sut({ checkout: mockCheckout, order, subscription, getAuthToken, onSuccess: mockOnSuccess, useRedirect }),
|
|
282
287
|
);
|
|
283
288
|
|
|
284
289
|
let checkoutFlow: () => void, status, paymentFlowComponent;
|
|
@@ -15,12 +15,12 @@ import { SubscriptionProjection } from "../../../projection/subscription/subscri
|
|
|
15
15
|
import { MESSAGING_CONTEXT_ID } from "../../delivery/baseBootstrap";
|
|
16
16
|
import { useSubmitCheckout } from "../../domain/checkout/react/useSubmitCheckout";
|
|
17
17
|
import { useBlockCheckoutBooking } from "../../domain/checkoutBooking/react/useBlockCheckoutBooking";
|
|
18
|
+
import { UseRedirectFunction } from "../../integration/useRedirect";
|
|
18
19
|
import { useViewIsSizeChangeEnabledByCheckoutId } from "../../projection/checkout/react/useViewIsSizeChangeEnabledByCheckoutId";
|
|
19
20
|
import { useViewPaymentFlowPayloadByCheckoutId } from "../../projection/payment/react/useViewPaymentFlowPayloadByCheckoutId";
|
|
20
21
|
import { useViewPricingByCheckoutId } from "../../projection/pricing/react/useViewPricingByCheckoutId";
|
|
21
22
|
import { useTrackCheckout } from "../../tracking/useTrackCheckout";
|
|
22
23
|
import { I18nMessages } from "../i18n/i18n";
|
|
23
|
-
import { Routes } from "../routing/routes";
|
|
24
24
|
import { usePaymentInstrumentEvents } from "./usePaymentInstrumentEvents";
|
|
25
25
|
import { useQueryBus } from "./useQueryBus";
|
|
26
26
|
import { useStaticInfo } from "./useStaticInfo";
|
|
@@ -43,6 +43,7 @@ interface UseCheckoutFlowArgs {
|
|
|
43
43
|
readonly subscription: SubscriptionProjection;
|
|
44
44
|
readonly getAuthToken: () => Promise<string>;
|
|
45
45
|
readonly onSuccess: () => void;
|
|
46
|
+
readonly useRedirect: UseRedirectFunction;
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
interface UseCheckoutFlowFunction {
|
|
@@ -55,14 +56,15 @@ const useCheckoutFlow: UseCheckoutFlowFunction = ({
|
|
|
55
56
|
subscription: subscriptionProjection,
|
|
56
57
|
getAuthToken,
|
|
57
58
|
onSuccess,
|
|
59
|
+
useRedirect,
|
|
58
60
|
}) => {
|
|
59
61
|
const logger = useLogger();
|
|
60
62
|
const queryBus = useQueryBus();
|
|
61
63
|
const {
|
|
62
64
|
customer: { customerId, country, segment, name, email },
|
|
63
|
-
basePath,
|
|
64
65
|
tradename,
|
|
65
66
|
} = useStaticInfo();
|
|
67
|
+
const { returnUrl } = useRedirect();
|
|
66
68
|
const paymentFlowRef = useRef<PaymentFlowRef>(null);
|
|
67
69
|
const [paymentFlowPayload] = useViewPaymentFlowPayloadByCheckoutId({
|
|
68
70
|
checkoutId: checkoutProjection?.id as string,
|
|
@@ -122,14 +124,14 @@ const useCheckoutFlow: UseCheckoutFlowFunction = ({
|
|
|
122
124
|
paymentFlowRef.current?.startLegacyBoxCheckout({
|
|
123
125
|
...paymentFlowPayload,
|
|
124
126
|
userInformation: { email, name },
|
|
125
|
-
returnUrl
|
|
127
|
+
returnUrl,
|
|
126
128
|
} as unknown as LegacyBoxCheckoutStrategyPayload);
|
|
127
129
|
}, [
|
|
128
130
|
checkoutProjection?.checkoutBookingId,
|
|
129
131
|
paymentFlowPayload,
|
|
130
132
|
email,
|
|
131
133
|
name,
|
|
132
|
-
|
|
134
|
+
returnUrl,
|
|
133
135
|
sizeChangeEnabled,
|
|
134
136
|
blockCheckoutBooking,
|
|
135
137
|
queryBus,
|
|
@@ -10,6 +10,7 @@ import { Customer } from "../../../projection/customer/customer";
|
|
|
10
10
|
import { OrderProjection } from "../../../projection/order/order";
|
|
11
11
|
import { SubscriptionProjection } from "../../../projection/subscription/subscription";
|
|
12
12
|
import { KameleoonEnvironment } from "../../ab-testing/kameleoonEnvironment";
|
|
13
|
+
import { UseRedirectFunction } from "../../integration/useRedirect";
|
|
13
14
|
import { StaticInfoProvider } from "../hooks/useStaticInfo";
|
|
14
15
|
import { App } from "../views/App";
|
|
15
16
|
import { Checkout } from "../views/checkout/Checkout";
|
|
@@ -35,7 +36,7 @@ interface RoutingProps {
|
|
|
35
36
|
readonly onNotAccessible: () => void;
|
|
36
37
|
readonly onCheckoutFlowSuccess: () => void;
|
|
37
38
|
readonly onI18nError?: (err: Error) => void;
|
|
38
|
-
readonly useRedirect:
|
|
39
|
+
readonly useRedirect: UseRedirectFunction;
|
|
39
40
|
readonly useRoutes: typeof reactRouterUseRoutes;
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -9,6 +9,7 @@ import { Layout as UiLayout, Sticky, useScreenSize } from "@lookiero/sty-psp-ui"
|
|
|
9
9
|
import { CheckoutItemStatus } from "../../../../domain/checkoutItem/model/checkoutItem";
|
|
10
10
|
import { OrderProjection } from "../../../../projection/order/order";
|
|
11
11
|
import { SubscriptionProjection } from "../../../../projection/subscription/subscription";
|
|
12
|
+
import { UseRedirectFunction } from "../../../integration/useRedirect";
|
|
12
13
|
import { useViewFirstAvailableCheckoutByCustomerId } from "../../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
|
|
13
14
|
import { useViewPricingByCheckoutId } from "../../../projection/pricing/react/useViewPricingByCheckoutId";
|
|
14
15
|
import { TrackingPage } from "../../../tracking/tracking";
|
|
@@ -33,7 +34,7 @@ interface CheckoutProps {
|
|
|
33
34
|
readonly subscription: SubscriptionProjection;
|
|
34
35
|
readonly getAuthToken: () => Promise<string>;
|
|
35
36
|
readonly onCheckoutFlowSuccess: () => void;
|
|
36
|
-
readonly useRedirect:
|
|
37
|
+
readonly useRedirect: UseRedirectFunction;
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
const Checkout: FC<CheckoutProps> = ({
|
|
@@ -68,6 +69,7 @@ const Checkout: FC<CheckoutProps> = ({
|
|
|
68
69
|
subscription,
|
|
69
70
|
getAuthToken,
|
|
70
71
|
onSuccess: onCheckoutFlowSuccess,
|
|
72
|
+
useRedirect,
|
|
71
73
|
});
|
|
72
74
|
|
|
73
75
|
useTrackPageView({
|
package/src/infrastructure/ui/views/checkout/components/paymentInstrument/PaymentInstrument.tsx
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import React, { FC } from "react";
|
|
2
2
|
import { PaymentInstrumentSelect, Section } from "@lookiero/payments-front";
|
|
3
|
+
import { UseRedirectFunction } from "../../../../../integration/useRedirect";
|
|
3
4
|
import { useStaticInfo } from "../../../../hooks/useStaticInfo";
|
|
4
5
|
|
|
5
6
|
interface PaymentInstrumentProps {
|
|
6
|
-
readonly useRedirect:
|
|
7
|
+
readonly useRedirect: UseRedirectFunction;
|
|
7
8
|
}
|
|
8
9
|
const PaymentInstrument: FC<PaymentInstrumentProps> = ({ useRedirect }) => {
|
|
9
10
|
const { returnUrl } = useRedirect();
|
|
@@ -11,7 +12,7 @@ const PaymentInstrument: FC<PaymentInstrumentProps> = ({ useRedirect }) => {
|
|
|
11
12
|
|
|
12
13
|
return (
|
|
13
14
|
<PaymentInstrumentSelect
|
|
14
|
-
beforeRedirect={
|
|
15
|
+
beforeRedirect={() => Promise.resolve(returnUrl)}
|
|
15
16
|
hasError={false}
|
|
16
17
|
section={Section.BOX_CHECKOUT}
|
|
17
18
|
userInformation={{
|