@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.
Files changed (25) hide show
  1. package/dist/infrastructure/ui/routing/Routing.js +1 -1
  2. package/dist/infrastructure/ui/views/App.d.ts +2 -0
  3. package/dist/infrastructure/ui/views/App.js +2 -2
  4. package/dist/infrastructure/ui/views/item/Item.js +3 -2
  5. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.d.ts +0 -1
  6. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.js +4 -10
  7. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.d.ts +2 -8
  8. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.js +2 -8
  9. package/dist/infrastructure/ui/views/navigation/Navigation.d.ts +2 -0
  10. package/dist/infrastructure/ui/views/navigation/Navigation.js +47 -4
  11. package/dist/infrastructure/ui/views/navigation/components/header/Header.d.ts +47 -2
  12. package/dist/infrastructure/ui/views/navigation/components/header/Header.js +52 -18
  13. package/dist/shared/tracking/infrastructure/useTrackPressBack.d.ts +15 -0
  14. package/dist/shared/tracking/infrastructure/useTrackPressBack.js +22 -0
  15. package/dist/shared/tracking/infrastructure/useTrackPressMenu.d.ts +16 -0
  16. package/dist/shared/tracking/infrastructure/useTrackPressMenu.js +23 -0
  17. package/dist/shared/tracking/infrastructure/useTrackPressNext.d.ts +17 -0
  18. package/dist/shared/tracking/infrastructure/useTrackPressNext.js +24 -0
  19. package/dist/shared/tracking/infrastructure/useTrackPressPrevious.d.ts +17 -0
  20. package/dist/shared/tracking/infrastructure/useTrackPressPrevious.js +24 -0
  21. package/dist/shared/tracking/tracking.d.ts +18 -2
  22. package/dist/shared/tracking/tracking.js +4 -0
  23. package/dist/shared/ui/components/atoms/spinner/Spinner.d.ts +1 -6
  24. package/dist/shared/ui/components/atoms/spinner/Spinner.js +4 -5
  25. 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, { changingDecission: resetCheckoutItemStatus === CommandStatus.LOADING, checkoutItemStatus: checkoutItem.status, onPress: handleOnPressCustomerDecissionBanner })),
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, View } from "react-native";
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, changingDecission, }) => {
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(View, { style: style.actions },
22
- React.createElement(View, { style: style.placeholder }),
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 };
@@ -1,16 +1,10 @@
1
1
  declare const style: {
2
- actions: {
3
- flexDirection: "row";
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 };
@@ -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
- actions: {
6
- flexDirection: "row",
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 handleOnOpenMenu = useCallback(() => setMenuVisible(true), []);
9
- const handleOnCloseMenu = useCallback(() => setMenuVisible(false), []);
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: () => void;
9
- readonly onCloseMenu: () => void;
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(() => navigate(-1), [navigate]);
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(() => navigate(`${basePath}/${Routes.SUMMARY}`), [basePath, navigate]);
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, null);
110
+ header = React.createElement(ItemDetailHeader, { onBack: handleOnBack });
77
111
  }
78
112
  }
79
113
  else if (checkoutRouteMatch || checkoutPaymentRouteMatch) {
80
- header = React.createElement(CheckoutHeader, null);
114
+ header = React.createElement(CheckoutHeader, { onBack: handleOnBack });
81
115
  }
82
116
  else {
83
- header = React.createElement(DefaultHeader, { onOpenMenu: 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: onCloseMenu })));
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
- export type { BaseTrackingEvent, ChangeFeedbackTrackingEvent, ImageViewTrackingEvent, ItemPageViewTrackingEvent, KeepItemTrackingEvent, PageViewTrackingEvent, PressContinueTrackingEvent, PressItemTrackingEvent, PressPricingTrackingEvent, ReplaceItemTrackingEvent, ResetItemTrackingEvent, ReturnItemTrackingEvent, TabViewTrackingEvent, };
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
- import { ColorValue } from "react-native";
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 { ActivityIndicator, View } from "react-native";
3
- import { theme } from "../../../../../infrastructure/ui/theme/theme";
3
+ import { View } from "react-native";
4
4
  import { style } from "./Spinner.style";
5
- const { colorPrimary } = theme();
6
- const Spinner = ({ color = colorPrimary, size = "large" }) => (React.createElement(View, { style: style.container },
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.8.27",
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.185",
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.185",
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",