@lookiero/checkout 0.8.26 → 0.8.28

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 (23) hide show
  1. package/dist/infrastructure/ui/components/organisms/checkoutQuestions/behaviors/useCheckoutQuestionFeedback.d.ts +2 -0
  2. package/dist/infrastructure/ui/components/organisms/checkoutQuestions/behaviors/useCheckoutQuestionFeedback.js +11 -4
  3. package/dist/infrastructure/ui/routing/Routing.js +1 -1
  4. package/dist/infrastructure/ui/views/App.d.ts +2 -0
  5. package/dist/infrastructure/ui/views/App.js +2 -2
  6. package/dist/infrastructure/ui/views/feedback/Feedback.js +32 -7
  7. package/dist/infrastructure/ui/views/navigation/Navigation.d.ts +2 -0
  8. package/dist/infrastructure/ui/views/navigation/Navigation.js +47 -4
  9. package/dist/infrastructure/ui/views/navigation/components/header/Header.d.ts +47 -2
  10. package/dist/infrastructure/ui/views/navigation/components/header/Header.js +52 -18
  11. package/dist/shared/tracking/infrastructure/useTrackChangeFeedback.d.ts +20 -0
  12. package/dist/shared/tracking/infrastructure/useTrackChangeFeedback.js +25 -0
  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 +24 -2
  22. package/dist/shared/tracking/tracking.js +5 -0
  23. package/package.json +1 -1
@@ -3,12 +3,14 @@ import { CheckoutFeedbackProjection } from "../../../../../../projection/checkou
3
3
  interface OnChangeCheckoutQuestionFeedbackFunctionArgs {
4
4
  readonly checkoutQuestionId: string;
5
5
  readonly checkoutQuestionFeedback: string | undefined;
6
+ readonly hasFeedback?: boolean;
6
7
  }
7
8
  interface OnChangeCheckoutQuestionFeedbackFunction {
8
9
  (args: OnChangeCheckoutQuestionFeedbackFunctionArgs): void;
9
10
  }
10
11
  interface CheckoutQuestionFeedbackContextProviderProps {
11
12
  readonly feedback: CheckoutFeedbackProjection | undefined;
13
+ readonly onChanged?: OnChangeCheckoutQuestionFeedbackFunction;
12
14
  readonly children: ReactNode;
13
15
  }
14
16
  declare const CheckoutQuestionFeedbackProvider: FC<CheckoutQuestionFeedbackContextProviderProps>;
@@ -1,11 +1,18 @@
1
1
  import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from "react";
2
2
  import invariant from "tiny-invariant";
3
3
  const CheckoutQuestionFeedbackContext = createContext(null);
4
- const CheckoutQuestionFeedbackProvider = ({ feedback = {}, children, }) => {
4
+ const CheckoutQuestionFeedbackProvider = ({ feedback = {}, onChanged, children, }) => {
5
5
  const [contextFeedback, setContextFeedback] = useState(feedback);
6
- const onChange = useCallback(({ checkoutQuestionId, checkoutQuestionFeedback }) => setContextFeedback((feedback) => checkoutQuestionFeedback
7
- ? { ...feedback, [checkoutQuestionId]: checkoutQuestionFeedback }
8
- : Object.entries(feedback).reduce((acc, [id, feedback]) => (id !== checkoutQuestionId ? { ...acc, [id]: feedback } : acc), {})), []);
6
+ const onChange = useCallback(({ checkoutQuestionId, checkoutQuestionFeedback }) => {
7
+ setContextFeedback((feedback) => checkoutQuestionFeedback
8
+ ? { ...feedback, [checkoutQuestionId]: checkoutQuestionFeedback }
9
+ : Object.entries(feedback).reduce((acc, [id, feedback]) => (id !== checkoutQuestionId ? { ...acc, [id]: feedback } : acc), {}));
10
+ onChanged?.({
11
+ checkoutQuestionId,
12
+ checkoutQuestionFeedback,
13
+ hasFeedback: Boolean(contextFeedback[checkoutQuestionId]),
14
+ });
15
+ }, [contextFeedback, onChanged]);
9
16
  useEffect(() => setContextFeedback(feedback), [feedback]);
10
17
  const value = useMemo(() => ({
11
18
  feedback: contextFeedback,
@@ -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 };
@@ -1,8 +1,11 @@
1
1
  import { CommandStatus, QueryStatus } from "@lookiero/messaging-react";
2
2
  import React, { useCallback, useEffect, useRef } from "react";
3
3
  import { Platform } from "react-native";
4
+ import { CheckoutQuestionType } from "../../../../projection/checkoutQuestion/checkoutQuestion";
4
5
  import { useLogger } from "../../../../shared/logging/useLogger";
6
+ import { useTrackChangeFeedback } from "../../../../shared/tracking/infrastructure/useTrackChangeFeedback";
5
7
  import { useTrackPageView } from "../../../../shared/tracking/infrastructure/useTrackPageView";
8
+ import { useTrackPressContinue } from "../../../../shared/tracking/infrastructure/useTrackPressContinue";
6
9
  import { Spinner } from "../../../../shared/ui/components/atoms/spinner/Spinner";
7
10
  import { useGiveCheckoutFeedback } from "../../../domain/checkoutFeedback/react/useGiveCheckoutFeedback";
8
11
  import { useViewFirstAvailableCheckoutByCustomerId } from "../../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
@@ -20,23 +23,45 @@ const Feedback = ({ customerId, country }) => {
20
23
  const [checkoutQuestions, checkoutQuestionsStatus] = useListCheckoutQuestionsByCheckoutId({
21
24
  checkoutId: checkout?.id,
22
25
  });
26
+ useTrackPageView({
27
+ page: TrackingPage.FEEDBACK,
28
+ country,
29
+ checkoutId: checkout?.id,
30
+ });
31
+ const trackChangeFeedback = useTrackChangeFeedback({
32
+ page: TrackingPage.FEEDBACK,
33
+ country,
34
+ checkoutId: checkout?.id,
35
+ });
36
+ const handleOnChangedFeedback = useCallback(({ checkoutQuestionId, checkoutQuestionFeedback, hasFeedback }) => {
37
+ const question = checkoutQuestions?.find((question) => question.id === checkoutQuestionId);
38
+ if (question?.type === CheckoutQuestionType.HOST_TEXTAREA && hasFeedback) {
39
+ return;
40
+ }
41
+ trackChangeFeedback({
42
+ questionId: checkoutQuestionId,
43
+ questionName: question?.name,
44
+ feedback: checkoutQuestionFeedback,
45
+ });
46
+ }, [checkoutQuestions, trackChangeFeedback]);
23
47
  const [giveCheckoutFeedback, giveCheckoutFeedbackStatus] = useGiveCheckoutFeedback({
24
48
  checkoutId: checkout?.id,
25
49
  logger,
26
50
  });
27
51
  const checkoutFeedbackGivenRef = useRef(false);
52
+ const trackPressContinue = useTrackPressContinue({
53
+ page: TrackingPage.FEEDBACK,
54
+ country,
55
+ checkoutId: checkout?.id,
56
+ });
28
57
  const handleOnSubmit = useCallback(async (feedbacks) => {
29
58
  try {
59
+ trackPressContinue();
30
60
  await giveCheckoutFeedback({ feedbacks });
31
61
  checkoutFeedbackGivenRef.current = true;
32
62
  }
33
63
  catch (e) { }
34
- }, [giveCheckoutFeedback]);
35
- useTrackPageView({
36
- page: TrackingPage.FEEDBACK,
37
- country,
38
- checkoutId: checkout?.id,
39
- });
64
+ }, [giveCheckoutFeedback, trackPressContinue]);
40
65
  /**
41
66
  * Give empty feedback when this view is unmounted
42
67
  * (if feedback has not already been given)
@@ -50,7 +75,7 @@ const Feedback = ({ customerId, country }) => {
50
75
  const dependenciesLoaded = dependenciesLoadedStatuses.includes(checkoutStatus) && dependenciesLoadedStatuses.includes(checkoutQuestionsStatus);
51
76
  if (!dependenciesLoaded)
52
77
  return React.createElement(Spinner, null);
53
- return (React.createElement(CheckoutQuestionFeedbackProvider, { feedback: {} },
78
+ return (React.createElement(CheckoutQuestionFeedbackProvider, { feedback: {}, onChanged: handleOnChangedFeedback },
54
79
  React.createElement(SafeAreaScrollView, { scrollerPaddingTop: Platform.OS === "web" || Platform.OS === "android" ? HEADER_HEIGHT : 0 },
55
80
  React.createElement(Body, { style: { column: style.bodyColumn } },
56
81
  React.createElement(CheckoutQuestionsForm, { checkoutQuestions: checkoutQuestions || [], submitButtonDisabled: giveCheckoutFeedbackStatus === CommandStatus.LOADING, onSubmit: handleOnSubmit })))));
@@ -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,20 @@
1
+ import { TrackingPage } from "../../../infrastructure/tracking/tracking";
2
+ import { Country } from "../../../projection/shared/country";
3
+ interface ChangeFeedbackFunctionArgs {
4
+ readonly questionId: string;
5
+ readonly questionName: string;
6
+ readonly feedback: string | undefined;
7
+ }
8
+ interface ChangeFeedbackFunction {
9
+ (args: ChangeFeedbackFunctionArgs): void;
10
+ }
11
+ interface UseTrackChangeFeedbackArgs {
12
+ readonly page: TrackingPage;
13
+ readonly country: Country;
14
+ readonly checkoutId?: string;
15
+ }
16
+ interface UseTrackChangeFeedback {
17
+ (agrs: UseTrackChangeFeedbackArgs): ChangeFeedbackFunction;
18
+ }
19
+ declare const useTrackChangeFeedback: UseTrackChangeFeedback;
20
+ export { useTrackChangeFeedback };
@@ -0,0 +1,25 @@
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 useTrackChangeFeedback = ({ page, country, checkoutId }) => {
6
+ const emitUserEvent = useEmitUserEvent();
7
+ const changeFeedback = useCallback(({ questionId, questionName, feedback }) => {
8
+ if (!checkoutId) {
9
+ return;
10
+ }
11
+ const changeFeedbackTrackingEvent = {
12
+ event: TrackingEvent.CHANGE_FEEDBACK,
13
+ eventCategory: TrackingEventCategory.NAVIGATION,
14
+ section: `${PROJECT}_${page}`,
15
+ store: country,
16
+ checkoutId,
17
+ questionId,
18
+ questionName,
19
+ feedback,
20
+ };
21
+ emitUserEvent(changeFeedbackTrackingEvent);
22
+ }, [checkoutId, country, emitUserEvent, page]);
23
+ return changeFeedback;
24
+ };
25
+ export { useTrackChangeFeedback };
@@ -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 };
@@ -10,7 +10,12 @@ declare enum TrackingEvent {
10
10
  PRESS_PRICING = "press-pricing",
11
11
  PRESS_ITEM = "press-item",
12
12
  PRESS_CONTINUE = "press-continue",
13
- TAB_VIEW = "tab-view"
13
+ TAB_VIEW = "tab-view",
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"
14
19
  }
15
20
  declare enum TrackingEventCategory {
16
21
  NAVIGATION = "navigation"
@@ -58,5 +63,22 @@ type PressContinueTrackingEvent = BaseTrackingEvent;
58
63
  interface TabViewTrackingEvent<T> extends BaseTrackingEvent {
59
64
  readonly tab: T;
60
65
  }
61
- export type { BaseTrackingEvent, ImageViewTrackingEvent, ItemPageViewTrackingEvent, KeepItemTrackingEvent, PageViewTrackingEvent, PressContinueTrackingEvent, PressItemTrackingEvent, PressPricingTrackingEvent, ReplaceItemTrackingEvent, ResetItemTrackingEvent, ReturnItemTrackingEvent, TabViewTrackingEvent, };
66
+ interface ChangeFeedbackTrackingEvent extends BaseTrackingEvent {
67
+ readonly questionId: string;
68
+ readonly questionName: string;
69
+ readonly feedback: string | undefined;
70
+ }
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, };
62
84
  export { TrackingEvent, TrackingEventCategory };
@@ -10,6 +10,11 @@ var TrackingEvent;
10
10
  TrackingEvent["PRESS_ITEM"] = "press-item";
11
11
  TrackingEvent["PRESS_CONTINUE"] = "press-continue";
12
12
  TrackingEvent["TAB_VIEW"] = "tab-view";
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";
13
18
  })(TrackingEvent || (TrackingEvent = {}));
14
19
  var TrackingEventCategory;
15
20
  (function (TrackingEventCategory) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lookiero/checkout",
3
- "version": "0.8.26",
3
+ "version": "0.8.28",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [