@lookiero/checkout 0.8.27 → 1.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.
- package/dist/infrastructure/ui/routing/Routing.js +1 -1
- package/dist/infrastructure/ui/views/App.d.ts +2 -0
- package/dist/infrastructure/ui/views/App.js +2 -2
- package/dist/infrastructure/ui/views/item/Item.js +3 -2
- package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.d.ts +0 -1
- package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.js +4 -10
- package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.d.ts +2 -8
- package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.js +2 -8
- package/dist/infrastructure/ui/views/navigation/Navigation.d.ts +2 -0
- package/dist/infrastructure/ui/views/navigation/Navigation.js +47 -4
- package/dist/infrastructure/ui/views/navigation/components/header/Header.d.ts +47 -2
- package/dist/infrastructure/ui/views/navigation/components/header/Header.js +52 -18
- package/dist/shared/tracking/infrastructure/useTrackPressBack.d.ts +15 -0
- package/dist/shared/tracking/infrastructure/useTrackPressBack.js +22 -0
- package/dist/shared/tracking/infrastructure/useTrackPressMenu.d.ts +16 -0
- package/dist/shared/tracking/infrastructure/useTrackPressMenu.js +23 -0
- package/dist/shared/tracking/infrastructure/useTrackPressNext.d.ts +17 -0
- package/dist/shared/tracking/infrastructure/useTrackPressNext.js +24 -0
- package/dist/shared/tracking/infrastructure/useTrackPressPrevious.d.ts +17 -0
- package/dist/shared/tracking/infrastructure/useTrackPressPrevious.js +24 -0
- package/dist/shared/tracking/tracking.d.ts +18 -2
- package/dist/shared/tracking/tracking.js +4 -0
- package/dist/shared/ui/components/atoms/spinner/Spinner.d.ts +1 -6
- package/dist/shared/ui/components/atoms/spinner/Spinner.js +4 -5
- package/package.json +3 -3
|
@@ -19,7 +19,7 @@ const Routing = ({ basePath = "", customer, locale, I18n, menu, tabBar, getAuthT
|
|
|
19
19
|
React.createElement(CheckoutAccessibilityMiddleware, { customerId: customer?.customerId, onNotAccessible: onNotAccessible },
|
|
20
20
|
React.createElement(I18n, { loader: React.createElement(Spinner, null), locale: locale, onError: onI18nError },
|
|
21
21
|
React.createElement(CheckoutMiddleware, { customerId: customer?.customerId },
|
|
22
|
-
React.createElement(App, { customerId: customer?.customerId, menu: menu, tabBar: tabBar },
|
|
22
|
+
React.createElement(App, { country: customer?.country, customerId: customer?.customerId, menu: menu, tabBar: tabBar },
|
|
23
23
|
React.createElement(Outlet, null))))))),
|
|
24
24
|
children: [
|
|
25
25
|
{
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
|
+
import { Country } from "../../../projection/shared/country";
|
|
2
3
|
import { Menu, TabBar } from "./navigation/Navigation";
|
|
3
4
|
interface AppProps {
|
|
4
5
|
readonly customerId: string;
|
|
6
|
+
readonly country: Country;
|
|
5
7
|
readonly menu: Menu;
|
|
6
8
|
readonly tabBar: TabBar;
|
|
7
9
|
readonly children: JSX.Element;
|
|
@@ -7,9 +7,9 @@ import { MESSAGING_CONTEXT_ID } from "../../delivery/baseBootstrap";
|
|
|
7
7
|
import { theme } from "../theme/theme";
|
|
8
8
|
import { Navigation } from "./navigation/Navigation";
|
|
9
9
|
const { colorBase } = theme();
|
|
10
|
-
const App = ({ customerId, menu, tabBar, children }) => (React.createElement(SafeAreaProvider, null,
|
|
10
|
+
const App = ({ customerId, country, menu, tabBar, children }) => (React.createElement(SafeAreaProvider, null,
|
|
11
11
|
React.createElement(PortalProvider, null,
|
|
12
12
|
React.createElement(StatusBar, { backgroundColor: colorBase, barStyle: "dark-content", translucent: true }),
|
|
13
13
|
React.createElement(Notifications, { contextId: MESSAGING_CONTEXT_ID }),
|
|
14
|
-
React.createElement(Navigation, { customerId: customerId, menu: menu, tabBar: tabBar }, children))));
|
|
14
|
+
React.createElement(Navigation, { country: country, customerId: customerId, menu: menu, tabBar: tabBar }, children))));
|
|
15
15
|
export { App };
|
|
@@ -160,7 +160,8 @@ const Item = ({ customerId, country }) => {
|
|
|
160
160
|
dependenciesLoadedStatuses.includes(sizeChangeEnabledStatus) &&
|
|
161
161
|
// This will ensure that the view is not shown until bookCheckoutBooking use-case is dispatched (if required)
|
|
162
162
|
(isBookingRequired ? checkout?.checkoutBookingId && bookedProductsVariants : true) &&
|
|
163
|
-
(dependenciesLoadedStatuses.includes(checkoutStatus) || checkout)
|
|
163
|
+
(dependenciesLoadedStatuses.includes(checkoutStatus) || checkout) &&
|
|
164
|
+
resetCheckoutItemStatus !== CommandStatus.LOADING;
|
|
164
165
|
if (!dependenciesLoaded)
|
|
165
166
|
return React.createElement(Spinner, null);
|
|
166
167
|
const { price } = checkoutItem;
|
|
@@ -169,7 +170,7 @@ const Item = ({ customerId, country }) => {
|
|
|
169
170
|
React.createElement(SizeWithoutStockModal, { visible: sizeWithoutStockModalVisible, onDismiss: handleOnHideSizeWithoutStockModal }),
|
|
170
171
|
React.createElement(SafeAreaScrollView, { scrollerPaddingTop: Platform.OS === "web" || Platform.OS === "android" ? HEADER_HEIGHT : 0, footer: !customerDecissionMade && (React.createElement(ItemActions, { country: country, keepButtonLoading: keepCheckoutItemStatus === CommandStatus.LOADING, productVariantSelected: productVariantSelected, productVariants: bookedProductsVariants?.productVariants, returnButtonLoading: returnCheckoutItemStatus === CommandStatus.LOADING, sizeSelectorDisabled: replaceCheckoutItemStatus === CommandStatus.LOADING, onKeep: handleOnKeep, onLayout: handleOnStickyLayout, onReplace: handleOnReplace, onReturn: handleOnReturn, onSizeSelectorPress: handleOnShowSizeWithoutStockModal })) },
|
|
171
172
|
React.createElement(Body, null,
|
|
172
|
-
customerDecissionMade && (React.createElement(CustomerDecissionBanner, {
|
|
173
|
+
customerDecissionMade && (React.createElement(CustomerDecissionBanner, { checkoutItemStatus: checkoutItem.status, onPress: handleOnPressCustomerDecissionBanner })),
|
|
173
174
|
React.createElement(View, { style: [style.content, { paddingBottom: Platform.OS === "web" ? spaceXL : stickyHeight }] },
|
|
174
175
|
React.createElement(View, { style: style.sliderContainer },
|
|
175
176
|
React.createElement(ProductVariantSlider, { producVariantMedia: media, onChanged: handleOnChangedProductVariantSlider })),
|
|
@@ -4,7 +4,6 @@ type CustomerDecissionBannerStatus = Exclude<CheckoutItemStatus, CheckoutItemSta
|
|
|
4
4
|
interface CustomerDecissionBannerProps {
|
|
5
5
|
readonly checkoutItemStatus: CustomerDecissionBannerStatus;
|
|
6
6
|
readonly onPress: () => void;
|
|
7
|
-
readonly changingDecission: boolean;
|
|
8
7
|
}
|
|
9
8
|
declare const CustomerDecissionBanner: FC<CustomerDecissionBannerProps>;
|
|
10
9
|
export type { CustomerDecissionBannerStatus };
|
|
@@ -1,27 +1,21 @@
|
|
|
1
1
|
import { Text } from "@lookiero/aurora-next/build/components/primitives/Text/Text";
|
|
2
2
|
import { useI18nMessage } from "@lookiero/i18n-react";
|
|
3
3
|
import React from "react";
|
|
4
|
-
import { Pressable
|
|
4
|
+
import { Pressable } from "react-native";
|
|
5
5
|
import { CheckoutItemStatus } from "../../../../../../domain/checkoutItem/model/checkoutItem";
|
|
6
|
-
import { Spinner } from "../../../../../../shared/ui/components/atoms/spinner/Spinner";
|
|
7
6
|
import { Banner } from "../../../../components/layouts/banner/Banner";
|
|
8
7
|
import { I18nMessages } from "../../../../i18n/i18n";
|
|
9
|
-
import { theme } from "../../../../theme/theme";
|
|
10
8
|
import { style } from "./CustomerDecissionBanner.style";
|
|
11
|
-
const { colorContent } = theme();
|
|
12
9
|
const i18nMessageForCheckoutItemStatus = {
|
|
13
10
|
[CheckoutItemStatus.KEPT]: I18nMessages.ITEM_BANNER_CUSTOMER_KEPT_DECISSION,
|
|
14
11
|
[CheckoutItemStatus.REPLACED]: I18nMessages.ITEM_BANNER_CUSTOMER_REPLACED_DECISSION,
|
|
15
12
|
[CheckoutItemStatus.RETURNED]: I18nMessages.ITEM_BANNER_CUSTOMER_RETURNED_DECISSION,
|
|
16
13
|
};
|
|
17
|
-
const CustomerDecissionBanner = ({ checkoutItemStatus, onPress
|
|
14
|
+
const CustomerDecissionBanner = ({ checkoutItemStatus, onPress }) => {
|
|
18
15
|
const decissionText = useI18nMessage({ id: i18nMessageForCheckoutItemStatus[checkoutItemStatus] }) || "";
|
|
19
16
|
const bannerButtonText = useI18nMessage({ id: I18nMessages.ITEM_BANNER_BUTTON });
|
|
20
17
|
return (React.createElement(Banner, { text: decissionText },
|
|
21
|
-
React.createElement(
|
|
22
|
-
React.createElement(
|
|
23
|
-
React.createElement(Pressable, { onPress: changingDecission ? undefined : onPress },
|
|
24
|
-
React.createElement(Text, { level: 2, style: style.buttonText, detail: true }, bannerButtonText)),
|
|
25
|
-
React.createElement(View, { style: style.placeholder }, changingDecission && React.createElement(Spinner, { color: colorContent, size: 20 })))));
|
|
18
|
+
React.createElement(Pressable, { style: style.button, onPress: onPress },
|
|
19
|
+
React.createElement(Text, { level: 2, style: style.buttonText, detail: true }, bannerButtonText))));
|
|
26
20
|
};
|
|
27
21
|
export { CustomerDecissionBanner };
|
package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.d.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
declare const style: {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
justifyContent: "space-between";
|
|
2
|
+
button: {
|
|
3
|
+
alignItems: "center";
|
|
5
4
|
marginTop: number;
|
|
6
|
-
minHeight: number;
|
|
7
|
-
width: string;
|
|
8
5
|
};
|
|
9
6
|
buttonText: {
|
|
10
7
|
textDecorationLine: "underline";
|
|
11
8
|
};
|
|
12
|
-
placeholder: {
|
|
13
|
-
width: number;
|
|
14
|
-
};
|
|
15
9
|
};
|
|
16
10
|
export { style };
|
package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.js
CHANGED
|
@@ -2,18 +2,12 @@ import { StyleSheet } from "react-native";
|
|
|
2
2
|
import { theme } from "../../../../theme/theme";
|
|
3
3
|
const { spaceM } = theme();
|
|
4
4
|
const style = StyleSheet.create({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
justifyContent: "space-between",
|
|
5
|
+
button: {
|
|
6
|
+
alignItems: "center",
|
|
8
7
|
marginTop: spaceM,
|
|
9
|
-
minHeight: 20,
|
|
10
|
-
width: "100%",
|
|
11
8
|
},
|
|
12
9
|
buttonText: {
|
|
13
10
|
textDecorationLine: "underline",
|
|
14
11
|
},
|
|
15
|
-
placeholder: {
|
|
16
|
-
width: 20,
|
|
17
|
-
},
|
|
18
12
|
});
|
|
19
13
|
export { style };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { FC, ReactNode } from "react";
|
|
2
|
+
import { Country } from "../../../../projection/shared/country";
|
|
2
3
|
interface MenuProps {
|
|
3
4
|
readonly isVisible: boolean;
|
|
4
5
|
readonly onClose: () => void;
|
|
@@ -11,6 +12,7 @@ interface TabBarProps {
|
|
|
11
12
|
type TabBar = FC<TabBarProps>;
|
|
12
13
|
interface NavigationProps {
|
|
13
14
|
readonly customerId: string;
|
|
15
|
+
readonly country: Country;
|
|
14
16
|
readonly menu: Menu;
|
|
15
17
|
readonly tabBar: TabBar;
|
|
16
18
|
readonly children: ReactNode;
|
|
@@ -1,15 +1,58 @@
|
|
|
1
1
|
import { usePortal } from "@lookiero/aurora-next/build/contexts/Portal/Portal";
|
|
2
2
|
import React, { useCallback, useState } from "react";
|
|
3
3
|
import { Platform } from "react-native";
|
|
4
|
+
import { useTrackPressBack } from "../../../../shared/tracking/infrastructure/useTrackPressBack";
|
|
5
|
+
import { useTrackPressMenu } from "../../../../shared/tracking/infrastructure/useTrackPressMenu";
|
|
6
|
+
import { useTrackPressNext } from "../../../../shared/tracking/infrastructure/useTrackPressNext";
|
|
7
|
+
import { useTrackPressPrevious } from "../../../../shared/tracking/infrastructure/useTrackPressPrevious";
|
|
4
8
|
import { style } from "./Navigation.style";
|
|
5
9
|
import { Header } from "./components/header/Header";
|
|
6
|
-
const Navigation = ({ customerId, menu, tabBar: TabBar, children }) => {
|
|
10
|
+
const Navigation = ({ customerId, country, menu, tabBar: TabBar, children }) => {
|
|
7
11
|
const [menuVisible, setMenuVisible] = useState(false);
|
|
8
|
-
const
|
|
9
|
-
const
|
|
12
|
+
const trackPressMenu = useTrackPressMenu();
|
|
13
|
+
const handleOnOpenMenu = useCallback(({ page, checkoutId, open }) => {
|
|
14
|
+
setMenuVisible(true);
|
|
15
|
+
trackPressMenu({
|
|
16
|
+
page,
|
|
17
|
+
country,
|
|
18
|
+
checkoutId,
|
|
19
|
+
open,
|
|
20
|
+
});
|
|
21
|
+
}, [country, trackPressMenu]);
|
|
22
|
+
const handleOnCloseMenu = useCallback(({ page, checkoutId, open }) => {
|
|
23
|
+
setMenuVisible(false);
|
|
24
|
+
trackPressMenu({
|
|
25
|
+
page,
|
|
26
|
+
country,
|
|
27
|
+
checkoutId,
|
|
28
|
+
open,
|
|
29
|
+
});
|
|
30
|
+
}, [country, trackPressMenu]);
|
|
31
|
+
const trackPressBack = useTrackPressBack();
|
|
32
|
+
const handleOnBack = useCallback(({ page, checkoutId }) => trackPressBack({
|
|
33
|
+
page,
|
|
34
|
+
country,
|
|
35
|
+
checkoutId,
|
|
36
|
+
}), [country, trackPressBack]);
|
|
37
|
+
const trackPressNext = useTrackPressNext();
|
|
38
|
+
const handleOnNext = useCallback(({ page, checkoutId, from, to }) => trackPressNext({
|
|
39
|
+
page,
|
|
40
|
+
country,
|
|
41
|
+
checkoutId,
|
|
42
|
+
from,
|
|
43
|
+
to,
|
|
44
|
+
}), [country, trackPressNext]);
|
|
45
|
+
const trackPressPrevious = useTrackPressPrevious();
|
|
46
|
+
const handleOnPrevious = useCallback(({ page, checkoutId, from, to }) => trackPressPrevious({
|
|
47
|
+
page,
|
|
48
|
+
country,
|
|
49
|
+
checkoutId,
|
|
50
|
+
from,
|
|
51
|
+
to,
|
|
52
|
+
}), [country, trackPressPrevious]);
|
|
10
53
|
const { busy } = usePortal();
|
|
11
54
|
return (React.createElement(React.Fragment, null,
|
|
12
|
-
React.createElement(Header, { customerId: customerId, menu: menu, menuVisible: menuVisible, style: style.header, onCloseMenu: handleOnCloseMenu, onOpenMenu: handleOnOpenMenu }),
|
|
55
|
+
React.createElement(Header, { customerId: customerId, menu: menu, menuVisible: menuVisible, style: style.header, onBack: handleOnBack, onCloseMenu: handleOnCloseMenu, onNext: handleOnNext, onOpenMenu: handleOnOpenMenu, onPrevious: handleOnPrevious }),
|
|
13
56
|
children,
|
|
14
57
|
Platform.OS !== "web" && React.createElement(TabBar, { isPortalBusy: busy, panel: menuVisible })));
|
|
15
58
|
};
|
|
@@ -1,12 +1,57 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
2
|
import { StyleProp, ViewStyle } from "react-native";
|
|
3
|
+
import { TrackingPage } from "../../../../../tracking/tracking";
|
|
3
4
|
import { Menu } from "../../Navigation";
|
|
5
|
+
interface OnOpenMenuFunctionArgs {
|
|
6
|
+
readonly page: TrackingPage;
|
|
7
|
+
readonly checkoutId: string | undefined;
|
|
8
|
+
readonly open: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface OnOpenMenuFunction {
|
|
11
|
+
(args: OnOpenMenuFunctionArgs): void;
|
|
12
|
+
}
|
|
13
|
+
interface OnCloseMenuFunctionArgs {
|
|
14
|
+
readonly page: TrackingPage;
|
|
15
|
+
readonly checkoutId: string | undefined;
|
|
16
|
+
readonly open: boolean;
|
|
17
|
+
}
|
|
18
|
+
interface OnCloseMenuFunction {
|
|
19
|
+
(args: OnCloseMenuFunctionArgs): void;
|
|
20
|
+
}
|
|
21
|
+
interface OnBackFunctionArgs {
|
|
22
|
+
readonly page: TrackingPage;
|
|
23
|
+
readonly checkoutId: string | undefined;
|
|
24
|
+
}
|
|
25
|
+
interface OnBackFunction {
|
|
26
|
+
(args: OnBackFunctionArgs): void;
|
|
27
|
+
}
|
|
28
|
+
interface OnNextFunctionArgs {
|
|
29
|
+
readonly page: TrackingPage;
|
|
30
|
+
readonly checkoutId: string | undefined;
|
|
31
|
+
readonly from: string;
|
|
32
|
+
readonly to: string;
|
|
33
|
+
}
|
|
34
|
+
interface OnNextFunction {
|
|
35
|
+
(args: OnNextFunctionArgs): void;
|
|
36
|
+
}
|
|
37
|
+
interface OnPreviousFunctionArgs {
|
|
38
|
+
readonly page: TrackingPage;
|
|
39
|
+
readonly checkoutId: string | undefined;
|
|
40
|
+
readonly from: string;
|
|
41
|
+
readonly to: string;
|
|
42
|
+
}
|
|
43
|
+
interface OnPreviousFunction {
|
|
44
|
+
(args: OnPreviousFunctionArgs): void;
|
|
45
|
+
}
|
|
4
46
|
interface HeaderProps {
|
|
5
47
|
readonly customerId: string;
|
|
6
48
|
readonly menu: Menu;
|
|
7
49
|
readonly menuVisible: boolean;
|
|
8
|
-
readonly onOpenMenu:
|
|
9
|
-
readonly onCloseMenu:
|
|
50
|
+
readonly onOpenMenu: OnOpenMenuFunction;
|
|
51
|
+
readonly onCloseMenu: OnCloseMenuFunction;
|
|
52
|
+
readonly onBack?: OnBackFunction;
|
|
53
|
+
readonly onNext?: OnNextFunction;
|
|
54
|
+
readonly onPrevious?: OnPreviousFunction;
|
|
10
55
|
readonly style?: StyleProp<ViewStyle>;
|
|
11
56
|
}
|
|
12
57
|
declare const Header: FC<HeaderProps>;
|
|
@@ -6,6 +6,7 @@ import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context"
|
|
|
6
6
|
import { generatePath, useMatch, useNavigate, useParams } from "react-router-native";
|
|
7
7
|
import { ButtonIcon } from "../../../../../../shared/ui/components/molecules/buttonIcon/ButtonIcon";
|
|
8
8
|
import { useViewFirstAvailableCheckoutByCustomerId } from "../../../../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
|
|
9
|
+
import { TrackingPage } from "../../../../../tracking/tracking";
|
|
9
10
|
import { I18nMessages } from "../../../../i18n/i18n";
|
|
10
11
|
import { Routes } from "../../../../routing/routes";
|
|
11
12
|
import { useBasePath } from "../../../../routing/useBasePath";
|
|
@@ -15,8 +16,8 @@ const ButtonIconPlaceholder = () => React.createElement(View, { style: style.but
|
|
|
15
16
|
const DefaultHeader = ({ onOpenMenu }) => (React.createElement(View, { style: style.header, testID: "default-header" },
|
|
16
17
|
React.createElement(Logo, { style: style.logo }),
|
|
17
18
|
React.createElement(ButtonIconPlaceholder, null),
|
|
18
|
-
React.createElement(ButtonIcon, { name: "menu", onPress: onOpenMenu })));
|
|
19
|
-
const ItemHeader = ({ items, item }) => {
|
|
19
|
+
React.createElement(ButtonIcon, { name: "menu", testID: "menu-button-icon", onPress: onOpenMenu })));
|
|
20
|
+
const ItemHeader = ({ items, item, onNext, onPrevious }) => {
|
|
20
21
|
const title = useI18nMessage({ id: I18nMessages.HEADER_CHECKOUT_TITLE });
|
|
21
22
|
const itemIndex = items.indexOf(item);
|
|
22
23
|
const isFirstItem = itemIndex === 0;
|
|
@@ -26,64 +27,97 @@ const ItemHeader = ({ items, item }) => {
|
|
|
26
27
|
const navigateToPreviousItem = useCallback(() => {
|
|
27
28
|
const previousItemIndex = itemIndex === 0 ? items.length - 1 : itemIndex - 1;
|
|
28
29
|
const previousItem = items[previousItemIndex];
|
|
30
|
+
onPrevious?.({ from: item.id, to: previousItem.id });
|
|
29
31
|
navigate(generatePath(`${basePath}/${Routes.ITEM}`, { id: previousItem.id }));
|
|
30
|
-
}, [basePath, itemIndex, items, navigate]);
|
|
32
|
+
}, [basePath, item.id, itemIndex, items, navigate, onPrevious]);
|
|
31
33
|
const navigateToNextItem = useCallback(() => {
|
|
32
34
|
const nextItemIndex = itemIndex === items.length - 1 ? 0 : itemIndex + 1;
|
|
33
35
|
const nextItem = items[nextItemIndex];
|
|
36
|
+
onNext?.({ from: item.id, to: nextItem.id });
|
|
34
37
|
navigate(generatePath(`${basePath}/${Routes.ITEM}`, { id: nextItem.id }));
|
|
35
|
-
}, [basePath, itemIndex, items, navigate]);
|
|
38
|
+
}, [basePath, item.id, itemIndex, items, navigate, onNext]);
|
|
36
39
|
return (React.createElement(View, { style: style.header, testID: "item-header" },
|
|
37
|
-
!isFirstItem ? React.createElement(ButtonIcon, { name: "arrow-left", onPress: navigateToPreviousItem }) : React.createElement(ButtonIconPlaceholder, null),
|
|
40
|
+
!isFirstItem ? (React.createElement(ButtonIcon, { name: "arrow-left", testID: "arrow-left-button-icon", onPress: navigateToPreviousItem })) : (React.createElement(ButtonIconPlaceholder, null)),
|
|
38
41
|
React.createElement(Text, { level: 3, style: style.title, detail: true }, title),
|
|
39
|
-
!isLastItem ? React.createElement(ButtonIcon, { name: "arrow-right", onPress: navigateToNextItem }) : React.createElement(ButtonIconPlaceholder, null)));
|
|
42
|
+
!isLastItem ? (React.createElement(ButtonIcon, { name: "arrow-right", testID: "arrow-right-button-icon", onPress: navigateToNextItem })) : (React.createElement(ButtonIconPlaceholder, null))));
|
|
40
43
|
};
|
|
41
|
-
const ItemDetailHeader = () => {
|
|
44
|
+
const ItemDetailHeader = ({ onBack }) => {
|
|
42
45
|
const title = useI18nMessage({ id: I18nMessages.HEADER_CHECKOUT_TITLE });
|
|
43
46
|
const navigate = useNavigate();
|
|
44
|
-
const handleOnBack = useCallback(() =>
|
|
47
|
+
const handleOnBack = useCallback(() => {
|
|
48
|
+
onBack?.();
|
|
49
|
+
navigate(-1);
|
|
50
|
+
}, [navigate, onBack]);
|
|
45
51
|
return (React.createElement(View, { style: style.header, testID: "item-detail-header" },
|
|
46
52
|
React.createElement(ButtonIconPlaceholder, null),
|
|
47
53
|
React.createElement(Text, { level: 3, style: style.title, detail: true }, title),
|
|
48
|
-
React.createElement(ButtonIcon, { name: "close", onPress: handleOnBack })));
|
|
54
|
+
React.createElement(ButtonIcon, { name: "close", testID: "close-button-icon", onPress: handleOnBack })));
|
|
49
55
|
};
|
|
50
|
-
const CheckoutHeader = () => {
|
|
56
|
+
const CheckoutHeader = ({ onBack }) => {
|
|
51
57
|
const title = useI18nMessage({ id: I18nMessages.HEADER_COMPLETE_CHECKOUT_TITLE });
|
|
52
58
|
const basePath = useBasePath();
|
|
53
59
|
const navigate = useNavigate();
|
|
54
|
-
const handleOnBack = useCallback(() =>
|
|
60
|
+
const handleOnBack = useCallback(() => {
|
|
61
|
+
onBack?.();
|
|
62
|
+
navigate(`${basePath}/${Routes.SUMMARY}`);
|
|
63
|
+
}, [basePath, navigate, onBack]);
|
|
55
64
|
return (React.createElement(View, { style: style.header, testID: "checkout-header" },
|
|
56
|
-
React.createElement(ButtonIcon, { name: "arrow-left", onPress: handleOnBack }),
|
|
65
|
+
React.createElement(ButtonIcon, { name: "arrow-left", testID: "arrow-left-button-icon", onPress: handleOnBack }),
|
|
57
66
|
React.createElement(Text, { level: 3, style: style.title, detail: true }, title),
|
|
58
67
|
React.createElement(ButtonIconPlaceholder, null)));
|
|
59
68
|
};
|
|
60
|
-
const Header = ({ customerId, menu: Menu, menuVisible, onOpenMenu, onCloseMenu, style: customStyle, }) => {
|
|
69
|
+
const Header = ({ customerId, menu: Menu, menuVisible, onOpenMenu, onCloseMenu, onBack, onNext, onPrevious, style: customStyle, }) => {
|
|
61
70
|
const { id: itemId } = useParams();
|
|
62
71
|
const [checkout] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
|
|
63
72
|
const currentItem = checkout?.items.find((item) => item.id === itemId);
|
|
64
73
|
const basePath = useBasePath();
|
|
65
74
|
const itemRouteMatch = useMatch(`${basePath}/${Routes.ITEM}`);
|
|
66
75
|
const itemDetailRouteMatch = useMatch(`${basePath}/${Routes.ITEM_DETAIL}`);
|
|
76
|
+
const summaryRouteMatch = useMatch(`${basePath}/${Routes.SUMMARY}`);
|
|
67
77
|
const checkoutRouteMatch = useMatch(`${basePath}/${Routes.CHECKOUT}`);
|
|
68
78
|
const checkoutPaymentRouteMatch = useMatch(`${basePath}/${Routes.CHECKOUT}/${Routes.CHECKOUT_PAYMENT}`);
|
|
79
|
+
const feedbackRouteMatch = useMatch(`${basePath}/${Routes.FEEDBACK}`);
|
|
80
|
+
const trackingPage = useCallback(() => {
|
|
81
|
+
if (itemRouteMatch || itemDetailRouteMatch)
|
|
82
|
+
return TrackingPage.ITEM;
|
|
83
|
+
if (checkoutRouteMatch || checkoutPaymentRouteMatch)
|
|
84
|
+
return TrackingPage.CHECKOUT;
|
|
85
|
+
if (summaryRouteMatch)
|
|
86
|
+
return TrackingPage.SUMMARY;
|
|
87
|
+
if (feedbackRouteMatch)
|
|
88
|
+
return TrackingPage.FEEDBACK;
|
|
89
|
+
return TrackingPage.NOT_FOUND;
|
|
90
|
+
}, [
|
|
91
|
+
checkoutPaymentRouteMatch,
|
|
92
|
+
checkoutRouteMatch,
|
|
93
|
+
feedbackRouteMatch,
|
|
94
|
+
itemDetailRouteMatch,
|
|
95
|
+
itemRouteMatch,
|
|
96
|
+
summaryRouteMatch,
|
|
97
|
+
]);
|
|
69
98
|
const { top: safeAreaInsetTop } = useSafeAreaInsets();
|
|
99
|
+
const handleOnOpenMenu = useCallback(() => onOpenMenu({ page: trackingPage(), checkoutId: checkout?.id, open: true }), [checkout?.id, onOpenMenu, trackingPage]);
|
|
100
|
+
const handleOnCloseMenu = useCallback(() => onCloseMenu({ page: trackingPage(), checkoutId: checkout?.id, open: false }), [checkout?.id, onCloseMenu, trackingPage]);
|
|
101
|
+
const handleOnBack = useCallback(() => onBack?.({ page: trackingPage(), checkoutId: checkout?.id }), [checkout?.id, onBack, trackingPage]);
|
|
102
|
+
const handleOnNext = useCallback(({ from, to }) => onNext?.({ page: trackingPage(), checkoutId: checkout?.id, from, to }), [checkout?.id, onNext, trackingPage]);
|
|
103
|
+
const handleOnPrevious = useCallback(({ from, to }) => onPrevious?.({ page: trackingPage(), checkoutId: checkout?.id, from, to }), [checkout?.id, onPrevious, trackingPage]);
|
|
70
104
|
let header;
|
|
71
105
|
if (checkout?.items && currentItem) {
|
|
72
106
|
if (itemRouteMatch) {
|
|
73
|
-
header = React.createElement(ItemHeader, { item: currentItem, items: checkout.items });
|
|
107
|
+
header = (React.createElement(ItemHeader, { item: currentItem, items: checkout.items, onNext: handleOnNext, onPrevious: handleOnPrevious }));
|
|
74
108
|
}
|
|
75
109
|
else if (itemDetailRouteMatch) {
|
|
76
|
-
header = React.createElement(ItemDetailHeader,
|
|
110
|
+
header = React.createElement(ItemDetailHeader, { onBack: handleOnBack });
|
|
77
111
|
}
|
|
78
112
|
}
|
|
79
113
|
else if (checkoutRouteMatch || checkoutPaymentRouteMatch) {
|
|
80
|
-
header = React.createElement(CheckoutHeader,
|
|
114
|
+
header = React.createElement(CheckoutHeader, { onBack: handleOnBack });
|
|
81
115
|
}
|
|
82
116
|
else {
|
|
83
|
-
header = React.createElement(DefaultHeader, { onOpenMenu:
|
|
117
|
+
header = React.createElement(DefaultHeader, { onOpenMenu: handleOnOpenMenu });
|
|
84
118
|
}
|
|
85
119
|
return (React.createElement(React.Fragment, null,
|
|
86
120
|
React.createElement(SafeAreaView, { edges: ["top"], style: [style.container, { height: HEADER_HEIGHT + safeAreaInsetTop }, customStyle] }, header),
|
|
87
|
-
React.createElement(Menu, { isVisible: menuVisible, onClose:
|
|
121
|
+
React.createElement(Menu, { isVisible: menuVisible, onClose: handleOnCloseMenu })));
|
|
88
122
|
};
|
|
89
123
|
export { Header };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TrackingPage } from "../../../infrastructure/tracking/tracking";
|
|
2
|
+
import { Country } from "../../../projection/shared/country";
|
|
3
|
+
interface PressBackFunctionArgs {
|
|
4
|
+
readonly page: TrackingPage;
|
|
5
|
+
readonly country: Country;
|
|
6
|
+
readonly checkoutId: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
interface PressBackFunction {
|
|
9
|
+
(args: PressBackFunctionArgs): void;
|
|
10
|
+
}
|
|
11
|
+
interface UseTrackPressBackFunction {
|
|
12
|
+
(): PressBackFunction;
|
|
13
|
+
}
|
|
14
|
+
declare const useTrackPressBack: UseTrackPressBackFunction;
|
|
15
|
+
export { useTrackPressBack };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { PROJECT } from "../../../infrastructure/tracking/tracking";
|
|
3
|
+
import { TrackingEvent, TrackingEventCategory } from "../tracking";
|
|
4
|
+
import { useEmitUserEvent } from "./useEmitUserEvent";
|
|
5
|
+
const useTrackPressBack = () => {
|
|
6
|
+
const emitUserEvent = useEmitUserEvent();
|
|
7
|
+
const pressBack = useCallback(({ page, country, checkoutId }) => {
|
|
8
|
+
if (!checkoutId) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const pressBackTrackingEvent = {
|
|
12
|
+
event: TrackingEvent.PRESS_BACK,
|
|
13
|
+
eventCategory: TrackingEventCategory.NAVIGATION,
|
|
14
|
+
section: `${PROJECT}_${page}`,
|
|
15
|
+
store: country,
|
|
16
|
+
checkoutId,
|
|
17
|
+
};
|
|
18
|
+
emitUserEvent(pressBackTrackingEvent);
|
|
19
|
+
}, [emitUserEvent]);
|
|
20
|
+
return pressBack;
|
|
21
|
+
};
|
|
22
|
+
export { useTrackPressBack };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TrackingPage } from "../../../infrastructure/tracking/tracking";
|
|
2
|
+
import { Country } from "../../../projection/shared/country";
|
|
3
|
+
interface PressMenuFunctionArgs {
|
|
4
|
+
readonly page: TrackingPage;
|
|
5
|
+
readonly country: Country;
|
|
6
|
+
readonly checkoutId: string | undefined;
|
|
7
|
+
readonly open: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface PressMenuFunction {
|
|
10
|
+
(args: PressMenuFunctionArgs): void;
|
|
11
|
+
}
|
|
12
|
+
interface UseTrackPressMenuFunction {
|
|
13
|
+
(): PressMenuFunction;
|
|
14
|
+
}
|
|
15
|
+
declare const useTrackPressMenu: UseTrackPressMenuFunction;
|
|
16
|
+
export { useTrackPressMenu };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { PROJECT } from "../../../infrastructure/tracking/tracking";
|
|
3
|
+
import { TrackingEvent, TrackingEventCategory } from "../tracking";
|
|
4
|
+
import { useEmitUserEvent } from "./useEmitUserEvent";
|
|
5
|
+
const useTrackPressMenu = () => {
|
|
6
|
+
const emitUserEvent = useEmitUserEvent();
|
|
7
|
+
const pressMenu = useCallback(({ page, country, checkoutId, open }) => {
|
|
8
|
+
if (!checkoutId) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const pressMenuTrackingEvent = {
|
|
12
|
+
event: TrackingEvent.PRESS_MENU,
|
|
13
|
+
eventCategory: TrackingEventCategory.NAVIGATION,
|
|
14
|
+
section: `${PROJECT}_${page}`,
|
|
15
|
+
store: country,
|
|
16
|
+
checkoutId,
|
|
17
|
+
open,
|
|
18
|
+
};
|
|
19
|
+
emitUserEvent(pressMenuTrackingEvent);
|
|
20
|
+
}, [emitUserEvent]);
|
|
21
|
+
return pressMenu;
|
|
22
|
+
};
|
|
23
|
+
export { useTrackPressMenu };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TrackingPage } from "../../../infrastructure/tracking/tracking";
|
|
2
|
+
import { Country } from "../../../projection/shared/country";
|
|
3
|
+
interface PressNextFunctionArgs {
|
|
4
|
+
readonly page: TrackingPage;
|
|
5
|
+
readonly country: Country;
|
|
6
|
+
readonly checkoutId: string | undefined;
|
|
7
|
+
readonly from: string;
|
|
8
|
+
readonly to: string;
|
|
9
|
+
}
|
|
10
|
+
interface PressNextFunction {
|
|
11
|
+
(args: PressNextFunctionArgs): void;
|
|
12
|
+
}
|
|
13
|
+
interface UseTrackPressNextFunction {
|
|
14
|
+
(): PressNextFunction;
|
|
15
|
+
}
|
|
16
|
+
declare const useTrackPressNext: UseTrackPressNextFunction;
|
|
17
|
+
export { useTrackPressNext };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { PROJECT } from "../../../infrastructure/tracking/tracking";
|
|
3
|
+
import { TrackingEvent, TrackingEventCategory } from "../tracking";
|
|
4
|
+
import { useEmitUserEvent } from "./useEmitUserEvent";
|
|
5
|
+
const useTrackPressNext = () => {
|
|
6
|
+
const emitUserEvent = useEmitUserEvent();
|
|
7
|
+
const pressNext = useCallback(({ page, country, checkoutId, from, to }) => {
|
|
8
|
+
if (!checkoutId) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const pressNextTrackingEvent = {
|
|
12
|
+
event: TrackingEvent.PRESS_NEXT,
|
|
13
|
+
eventCategory: TrackingEventCategory.NAVIGATION,
|
|
14
|
+
section: `${PROJECT}_${page}`,
|
|
15
|
+
store: country,
|
|
16
|
+
checkoutId,
|
|
17
|
+
from,
|
|
18
|
+
to,
|
|
19
|
+
};
|
|
20
|
+
emitUserEvent(pressNextTrackingEvent);
|
|
21
|
+
}, [emitUserEvent]);
|
|
22
|
+
return pressNext;
|
|
23
|
+
};
|
|
24
|
+
export { useTrackPressNext };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { TrackingPage } from "../../../infrastructure/tracking/tracking";
|
|
2
|
+
import { Country } from "../../../projection/shared/country";
|
|
3
|
+
interface PressPreviousFunctionArgs {
|
|
4
|
+
readonly page: TrackingPage;
|
|
5
|
+
readonly country: Country;
|
|
6
|
+
readonly checkoutId: string | undefined;
|
|
7
|
+
readonly from: string;
|
|
8
|
+
readonly to: string;
|
|
9
|
+
}
|
|
10
|
+
interface PressPreviousFunction {
|
|
11
|
+
(args: PressPreviousFunctionArgs): void;
|
|
12
|
+
}
|
|
13
|
+
interface UseTrackPressPreviousFunction {
|
|
14
|
+
(): PressPreviousFunction;
|
|
15
|
+
}
|
|
16
|
+
declare const useTrackPressPrevious: UseTrackPressPreviousFunction;
|
|
17
|
+
export { useTrackPressPrevious };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { PROJECT } from "../../../infrastructure/tracking/tracking";
|
|
3
|
+
import { TrackingEvent, TrackingEventCategory } from "../tracking";
|
|
4
|
+
import { useEmitUserEvent } from "./useEmitUserEvent";
|
|
5
|
+
const useTrackPressPrevious = () => {
|
|
6
|
+
const emitUserEvent = useEmitUserEvent();
|
|
7
|
+
const pressPrevious = useCallback(({ page, country, checkoutId, from, to }) => {
|
|
8
|
+
if (!checkoutId) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const pressPreviousTrackingEvent = {
|
|
12
|
+
event: TrackingEvent.PRESS_PREVIOUS,
|
|
13
|
+
eventCategory: TrackingEventCategory.NAVIGATION,
|
|
14
|
+
section: `${PROJECT}_${page}`,
|
|
15
|
+
store: country,
|
|
16
|
+
checkoutId,
|
|
17
|
+
from,
|
|
18
|
+
to,
|
|
19
|
+
};
|
|
20
|
+
emitUserEvent(pressPreviousTrackingEvent);
|
|
21
|
+
}, [emitUserEvent]);
|
|
22
|
+
return pressPrevious;
|
|
23
|
+
};
|
|
24
|
+
export { useTrackPressPrevious };
|
|
@@ -11,7 +11,11 @@ declare enum TrackingEvent {
|
|
|
11
11
|
PRESS_ITEM = "press-item",
|
|
12
12
|
PRESS_CONTINUE = "press-continue",
|
|
13
13
|
TAB_VIEW = "tab-view",
|
|
14
|
-
CHANGE_FEEDBACK = "change-feedback"
|
|
14
|
+
CHANGE_FEEDBACK = "change-feedback",
|
|
15
|
+
PRESS_MENU = "press-menu",
|
|
16
|
+
PRESS_BACK = "press-back",
|
|
17
|
+
PRESS_NEXT = "press-next",
|
|
18
|
+
PRESS_PREVIOUS = "press-previous"
|
|
15
19
|
}
|
|
16
20
|
declare enum TrackingEventCategory {
|
|
17
21
|
NAVIGATION = "navigation"
|
|
@@ -64,5 +68,17 @@ interface ChangeFeedbackTrackingEvent extends BaseTrackingEvent {
|
|
|
64
68
|
readonly questionName: string;
|
|
65
69
|
readonly feedback: string | undefined;
|
|
66
70
|
}
|
|
67
|
-
|
|
71
|
+
interface PressMenuTrackingEvent extends BaseTrackingEvent {
|
|
72
|
+
readonly open: boolean;
|
|
73
|
+
}
|
|
74
|
+
type PressBackTrackingEvent = BaseTrackingEvent;
|
|
75
|
+
interface PressNextTrackingEvent extends BaseTrackingEvent {
|
|
76
|
+
readonly from: string;
|
|
77
|
+
readonly to: string;
|
|
78
|
+
}
|
|
79
|
+
interface PressPreviousTrackingEvent extends BaseTrackingEvent {
|
|
80
|
+
readonly from: string;
|
|
81
|
+
readonly to: string;
|
|
82
|
+
}
|
|
83
|
+
export type { BaseTrackingEvent, ChangeFeedbackTrackingEvent, ImageViewTrackingEvent, ItemPageViewTrackingEvent, KeepItemTrackingEvent, PageViewTrackingEvent, PressContinueTrackingEvent, PressItemTrackingEvent, PressPricingTrackingEvent, ReplaceItemTrackingEvent, ResetItemTrackingEvent, ReturnItemTrackingEvent, TabViewTrackingEvent, PressMenuTrackingEvent, PressBackTrackingEvent, PressNextTrackingEvent, PressPreviousTrackingEvent, };
|
|
68
84
|
export { TrackingEvent, TrackingEventCategory };
|
|
@@ -11,6 +11,10 @@ var TrackingEvent;
|
|
|
11
11
|
TrackingEvent["PRESS_CONTINUE"] = "press-continue";
|
|
12
12
|
TrackingEvent["TAB_VIEW"] = "tab-view";
|
|
13
13
|
TrackingEvent["CHANGE_FEEDBACK"] = "change-feedback";
|
|
14
|
+
TrackingEvent["PRESS_MENU"] = "press-menu";
|
|
15
|
+
TrackingEvent["PRESS_BACK"] = "press-back";
|
|
16
|
+
TrackingEvent["PRESS_NEXT"] = "press-next";
|
|
17
|
+
TrackingEvent["PRESS_PREVIOUS"] = "press-previous";
|
|
14
18
|
})(TrackingEvent || (TrackingEvent = {}));
|
|
15
19
|
var TrackingEventCategory;
|
|
16
20
|
(function (TrackingEventCategory) {
|
|
@@ -1,8 +1,3 @@
|
|
|
1
1
|
import { FC } from "react";
|
|
2
|
-
|
|
3
|
-
interface SpinnerProps {
|
|
4
|
-
readonly color?: ColorValue;
|
|
5
|
-
readonly size?: number | "large" | "small";
|
|
6
|
-
}
|
|
7
|
-
declare const Spinner: FC<SpinnerProps>;
|
|
2
|
+
declare const Spinner: FC;
|
|
8
3
|
export { Spinner };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
+
import { Spinner as AuroraSpinner } from "@lookiero/aurora-next/build/components/atoms/Spinner/Spinner";
|
|
1
2
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { theme } from "../../../../../infrastructure/ui/theme/theme";
|
|
3
|
+
import { View } from "react-native";
|
|
4
4
|
import { style } from "./Spinner.style";
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
React.createElement(ActivityIndicator, { color: color, size: size })));
|
|
5
|
+
const Spinner = () => (React.createElement(View, { style: style.container },
|
|
6
|
+
React.createElement(AuroraSpinner, null)));
|
|
8
7
|
export { Spinner };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lookiero/checkout",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@lookiero/aurora-fonts": "^1.0.6",
|
|
47
47
|
"@lookiero/aurora-iconfont": "^2.0.37",
|
|
48
|
-
"@lookiero/aurora-next": "^3.0.
|
|
48
|
+
"@lookiero/aurora-next": "^3.0.191",
|
|
49
49
|
"@lookiero/data-sources": "^0.3",
|
|
50
50
|
"@lookiero/event": "^0.3",
|
|
51
51
|
"@lookiero/locale": "^0.3",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@expo/webpack-config": "^0.17.2",
|
|
68
68
|
"@lookiero/aurora-fonts": "^1.0.6",
|
|
69
69
|
"@lookiero/aurora-iconfont": "^2.0.37",
|
|
70
|
-
"@lookiero/aurora-next": "^3.0.
|
|
70
|
+
"@lookiero/aurora-next": "^3.0.191",
|
|
71
71
|
"@lookiero/data-sources": "^0.3",
|
|
72
72
|
"@lookiero/event": "^0.3",
|
|
73
73
|
"@lookiero/locale": "^0.3",
|