@lookiero/checkout 0.8.16 → 0.8.18

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 (91) hide show
  1. package/dist/domain/checkout/event/createModalNotificationWhenCheckoutSubmitted.d.ts +7 -0
  2. package/dist/domain/checkout/event/createModalNotificationWhenCheckoutSubmitted.js +12 -0
  3. package/dist/domain/checkoutBooking/event/createToastNotificationWhenCheckoutBookingExpired.d.ts +7 -0
  4. package/dist/domain/checkoutBooking/event/createToastNotificationWhenCheckoutBookingExpired.js +13 -0
  5. package/dist/domain/checkoutItem/event/createModalNotificationWhenCheckoutItemReplaced.d.ts +7 -0
  6. package/dist/domain/checkoutItem/event/createModalNotificationWhenCheckoutItemReplaced.js +12 -0
  7. package/dist/domain/checkoutItem/model/checkoutItem.js +1 -0
  8. package/dist/infrastructure/delivery/baseBootstrap.js +8 -2
  9. package/dist/infrastructure/delivery/mock/checkoutDataSource.js +4 -1
  10. package/dist/infrastructure/domain/checkout/react/useSubmitCheckout.js +2 -2
  11. package/dist/infrastructure/domain/checkoutBooking/react/useBlockCheckoutBooking.js +2 -2
  12. package/dist/infrastructure/domain/checkoutBooking/react/useBookCheckoutBookingForCheckoutItem.js +2 -2
  13. package/dist/infrastructure/domain/checkoutFeedback/react/useGiveCheckoutFeedback.js +2 -2
  14. package/dist/infrastructure/domain/checkoutItem/react/useKeepCheckoutItem.js +3 -5
  15. package/dist/infrastructure/domain/checkoutItem/react/useReplaceCheckoutItem.js +3 -6
  16. package/dist/infrastructure/domain/checkoutItem/react/useResetCheckoutItem.js +3 -5
  17. package/dist/infrastructure/domain/checkoutItem/react/useReturnCheckoutItem.js +3 -6
  18. package/dist/infrastructure/projection/bookedProductsVariants/react/useViewBookedProductsVariantsForCheckoutItem.js +4 -1
  19. package/dist/infrastructure/projection/checkout/react/useViewFiveItemsDiscountByCustomerId.js +1 -1
  20. package/dist/infrastructure/projection/checkoutQuestion/react/useListCheckoutQuestionsByCheckoutId.js +1 -1
  21. package/dist/infrastructure/projection/payment/react/useViewPaymentFlowPayloadByCheckoutId.js +6 -1
  22. package/dist/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.js +6 -1
  23. package/dist/infrastructure/projection/returnQuestion/react/useListReturnQuestionsByCheckoutItemId.js +1 -1
  24. package/dist/infrastructure/ui/hooks/usePaymentInstrumentEvents.js +2 -2
  25. package/dist/infrastructure/ui/hooks/useSubmitCheckout.js +2 -2
  26. package/dist/infrastructure/ui/routing/CheckoutMiddleware.js +54 -36
  27. package/dist/infrastructure/ui/routing/Routing.js +1 -7
  28. package/dist/infrastructure/ui/views/App.js +4 -4
  29. package/dist/infrastructure/ui/views/checkout/components/checkoutPaymentModal/CheckoutPaymentModal.js +3 -7
  30. package/dist/infrastructure/ui/views/feedback/Feedback.js +10 -3
  31. package/dist/infrastructure/ui/views/item/Item.js +9 -53
  32. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.d.ts +1 -0
  33. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.js +10 -4
  34. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.d.ts +8 -1
  35. package/dist/infrastructure/ui/views/item/components/banner/CustomerDecissionBanner.style.js +8 -1
  36. package/dist/infrastructure/ui/views/item/components/itemActions/ItemActions.js +2 -1
  37. package/dist/shared/notifications/domain/notification/command/createModalNotification.d.ts +18 -0
  38. package/dist/shared/notifications/domain/notification/command/createModalNotification.js +9 -0
  39. package/dist/shared/notifications/domain/notification/command/createToastNotification.d.ts +18 -0
  40. package/dist/shared/notifications/domain/notification/command/createToastNotification.js +9 -0
  41. package/dist/shared/notifications/domain/notification/model/notification.d.ts +11 -4
  42. package/dist/shared/notifications/domain/notification/model/notification.js +20 -4
  43. package/dist/shared/notifications/index.d.ts +3 -2
  44. package/dist/shared/notifications/index.js +3 -2
  45. package/dist/shared/notifications/infrastructure/delivery/bootstrap.js +7 -4
  46. package/dist/shared/notifications/infrastructure/domain/notification/model/storageNotifications.js +3 -1
  47. package/dist/shared/notifications/infrastructure/domain/notification/model/storageNotificationsCreate.d.ts +1 -1
  48. package/dist/shared/notifications/infrastructure/domain/notification/model/storageNotificationsCreate.js +3 -1
  49. package/dist/shared/notifications/infrastructure/domain/notification/react/useCreateModalNotification.d.ts +20 -0
  50. package/dist/shared/notifications/infrastructure/domain/notification/react/useCreateModalNotification.js +22 -0
  51. package/dist/shared/notifications/infrastructure/domain/notification/react/useCreateToastNotification.d.ts +21 -0
  52. package/dist/shared/notifications/infrastructure/domain/notification/react/{useCreateNotification.js → useCreateToastNotification.js} +4 -4
  53. package/dist/shared/notifications/infrastructure/persistence/notificationDto.d.ts +3 -1
  54. package/dist/shared/notifications/infrastructure/projection/notification/notification.d.ts +2 -2
  55. package/dist/shared/notifications/infrastructure/projection/notification/notification.js +16 -6
  56. package/dist/shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotificationItem.d.ts +10 -0
  57. package/dist/shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotificationItem.js +26 -0
  58. package/dist/{infrastructure/ui/views/checkout/components/checkoutSuccessModal/CheckoutSuccessModal.style.js → shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotificationItem.style.js} +1 -1
  59. package/dist/shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotifications.d.ts +8 -0
  60. package/dist/shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotifications.js +6 -0
  61. package/dist/shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotifications.style.d.ts +25 -0
  62. package/dist/shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotifications.style.js +18 -0
  63. package/dist/shared/notifications/infrastructure/ui/components/toastNotifications/ToastNotificationItem.d.ts +12 -0
  64. package/dist/shared/notifications/infrastructure/ui/components/{NotificationItem.js → toastNotifications/ToastNotificationItem.js} +4 -4
  65. package/dist/shared/notifications/infrastructure/ui/components/toastNotifications/ToastNotifications.d.ts +9 -0
  66. package/dist/shared/notifications/infrastructure/ui/components/toastNotifications/ToastNotifications.js +20 -0
  67. package/dist/shared/notifications/infrastructure/ui/components/{Notifications.style.js → toastNotifications/ToastNotifications.style.js} +1 -1
  68. package/dist/shared/notifications/infrastructure/ui/views/Notifications.js +9 -3
  69. package/dist/shared/notifications/projection/notification/notification.d.ts +18 -2
  70. package/dist/shared/notifications/projection/notification/notification.js +8 -1
  71. package/dist/shared/ui/components/atoms/spinner/Spinner.d.ts +6 -1
  72. package/dist/shared/ui/components/atoms/spinner/Spinner.js +2 -2
  73. package/dist/shared/ui/components/layouts/modal/Modal.d.ts +1 -0
  74. package/dist/shared/ui/components/layouts/modal/Modal.js +2 -2
  75. package/package.json +7 -5
  76. package/dist/domain/checkoutBooking/event/createNotificationWhenCheckoutBookingExpired.d.ts +0 -6
  77. package/dist/domain/checkoutBooking/event/createNotificationWhenCheckoutBookingExpired.js +0 -13
  78. package/dist/infrastructure/ui/views/checkout/components/checkoutSuccessModal/CheckoutSuccessModal.d.ts +0 -7
  79. package/dist/infrastructure/ui/views/checkout/components/checkoutSuccessModal/CheckoutSuccessModal.js +0 -25
  80. package/dist/infrastructure/ui/views/item/components/sizeChangeModal/SizeChangeModal.d.ts +0 -7
  81. package/dist/infrastructure/ui/views/item/components/sizeChangeModal/SizeChangeModal.js +0 -25
  82. package/dist/infrastructure/ui/views/item/components/sizeChangeModal/SizeChangeModal.style.d.ts +0 -16
  83. package/dist/infrastructure/ui/views/item/components/sizeChangeModal/SizeChangeModal.style.js +0 -19
  84. package/dist/shared/notifications/domain/notification/command/createNotification.d.ts +0 -17
  85. package/dist/shared/notifications/domain/notification/command/createNotification.js +0 -7
  86. package/dist/shared/notifications/infrastructure/domain/notification/react/useCreateNotification.d.ts +0 -21
  87. package/dist/shared/notifications/infrastructure/ui/components/NotificationItem.d.ts +0 -12
  88. package/dist/shared/notifications/infrastructure/ui/components/Notifications.d.ts +0 -9
  89. package/dist/shared/notifications/infrastructure/ui/components/Notifications.js +0 -20
  90. /package/dist/{infrastructure/ui/views/checkout/components/checkoutSuccessModal/CheckoutSuccessModal.style.d.ts → shared/notifications/infrastructure/ui/components/modalNotifications/ModalNotificationItem.style.d.ts} +0 -0
  91. /package/dist/shared/notifications/infrastructure/ui/components/{Notifications.style.d.ts → toastNotifications/ToastNotifications.style.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import { CommandStatus, QueryStatus } from "@lookiero/messaging-react";
2
- import React, { useCallback, useEffect } from "react";
2
+ import React, { useCallback, useEffect, useRef } from "react";
3
3
  import { Platform } from "react-native";
4
4
  import { useLogger } from "../../../../shared/logging/useLogger";
5
5
  import { usePageView } from "../../../../shared/tracking/infrastructure/usePageView";
@@ -24,9 +24,11 @@ const Feedback = ({ customerId, country }) => {
24
24
  checkoutId: checkout?.id,
25
25
  logger,
26
26
  });
27
+ const checkoutFeedbackGivenRef = useRef(false);
27
28
  const handleOnSubmit = useCallback(async (feedbacks) => {
28
29
  try {
29
30
  await giveCheckoutFeedback({ feedbacks });
31
+ checkoutFeedbackGivenRef.current = true;
30
32
  }
31
33
  catch (e) { }
32
34
  }, [giveCheckoutFeedback]);
@@ -35,9 +37,14 @@ const Feedback = ({ customerId, country }) => {
35
37
  country,
36
38
  checkoutId: checkout?.id,
37
39
  });
38
- // Give empty feedback when this view is unmounted
40
+ /**
41
+ * Give empty feedback when this view is unmounted
42
+ * (if feedback has not already been given)
43
+ */
39
44
  useEffect(() => () => {
40
- giveCheckoutFeedback({ feedbacks: {} });
45
+ if (!checkoutFeedbackGivenRef.current) {
46
+ giveCheckoutFeedback({ feedbacks: {} });
47
+ }
41
48
  }, [giveCheckoutFeedback]);
42
49
  const dependenciesLoadedStatuses = [QueryStatus.ERROR, QueryStatus.SUCCESS];
43
50
  const dependenciesLoaded = dependenciesLoadedStatuses.includes(checkoutStatus) && dependenciesLoadedStatuses.includes(checkoutQuestionsStatus);
@@ -1,7 +1,7 @@
1
1
  import { CommandStatus, QueryStatus } from "@lookiero/messaging-react";
2
2
  import React, { useCallback, useEffect, useMemo, useState } from "react";
3
3
  import { Platform, View } from "react-native";
4
- import { generatePath, useMatch, useNavigate, useParams } from "react-router-native";
4
+ import { useParams } from "react-router-native";
5
5
  import { CheckoutItemStatus } from "../../../../domain/checkoutItem/model/checkoutItem";
6
6
  import "../../../../projection/checkout/viewFirstAvailableCheckoutByCustomerId";
7
7
  import { useLogger } from "../../../../shared/logging/useLogger";
@@ -19,8 +19,6 @@ import { TrackingPage } from "../../../tracking/tracking";
19
19
  import { Body } from "../../components/layouts/body/Body";
20
20
  import { ReturnQuestionFeedbackProvider } from "../../components/organisms/returnQuestions/behaviors/useReturnQuestionFeedback";
21
21
  import { SafeAreaScrollView } from "../../components/templates/SafeAreaScrollView";
22
- import { Routes } from "../../routing/routes";
23
- import { useBasePath } from "../../routing/useBasePath";
24
22
  import { theme } from "../../theme/theme";
25
23
  import { HEADER_HEIGHT } from "../navigation/components/header/Header.style";
26
24
  import { style } from "./Item.style";
@@ -30,7 +28,6 @@ import { ProductVariantDescription } from "./components/productVariantDescriptio
30
28
  import { ProductVariantSlider } from "./components/productVariantSlider/ProductVariantSlider";
31
29
  import { ReturnQuestionsFeedback } from "./components/returnQuestionsFeedback/ReturnQuestionsFeedback";
32
30
  import { ReturnQuestionsForm } from "./components/returnQuestionsForm/ReturnQuestionsForm";
33
- import { SizeChangeModal } from "./components/sizeChangeModal/SizeChangeModal";
34
31
  import { SizeWithoutStockModal } from "./components/sizeWithoutStockModal/SizeWithoutStockModal";
35
32
  const { spaceXL } = theme();
36
33
  const Item = ({ customerId, country }) => {
@@ -44,35 +41,11 @@ const Item = ({ customerId, country }) => {
44
41
  checkoutId: checkout?.id,
45
42
  checkoutItemId: checkoutItem.id,
46
43
  });
47
- const basePath = useBasePath();
48
- const itemRouteMatch = useMatch(`${basePath}/${Routes.ITEM}`);
49
- const itemDetailRouteMatch = useMatch(`${basePath}/${Routes.ITEM_DETAIL}`);
50
- const navigate = useNavigate();
51
- const navigateToNextView = useCallback(() => {
52
- if (itemRouteMatch) {
53
- const nextItemWithoutCustomerDecision = checkout?.items
54
- .filter((item) => item.id !== id)
55
- .find((item) => item.status === CheckoutItemStatus.INITIAL);
56
- if (nextItemWithoutCustomerDecision) {
57
- navigate(generatePath(`${basePath}/${Routes.ITEM}`, { id: nextItemWithoutCustomerDecision.id }));
58
- }
59
- }
60
- else if (itemDetailRouteMatch) {
61
- navigate(`${basePath}/${Routes.SUMMARY}`);
62
- }
63
- }, [itemRouteMatch, itemDetailRouteMatch, checkout?.items, id, navigate, basePath]);
64
- const [customerDecissionMade, setCustomerDecissionMade] = useState();
65
- useEffect(() => {
66
- setCustomerDecissionMade(checkoutItem.status !== CheckoutItemStatus.INITIAL);
67
- }, [checkoutItem.status, id]);
68
- const [resetCheckoutItem] = useResetCheckoutItem({
44
+ const customerDecissionMade = checkoutItem.status !== CheckoutItemStatus.INITIAL;
45
+ const [resetCheckoutItem, resetCheckoutItemStatus] = useResetCheckoutItem({
69
46
  checkoutItemId: checkoutItem.id,
70
47
  logger,
71
48
  });
72
- const handleOnBannerPress = useCallback(() => {
73
- resetCheckoutItem();
74
- setCustomerDecissionMade(false);
75
- }, [resetCheckoutItem]);
76
49
  const [keepCheckoutItem, keepCheckoutItemStatus] = useKeepCheckoutItem({ checkoutItemId: checkoutItem.id, logger });
77
50
  const [returnCheckoutItem, returnCheckoutItemStatus] = useReturnCheckoutItem({
78
51
  checkoutItemId: checkoutItem.id,
@@ -85,14 +58,6 @@ const Item = ({ customerId, country }) => {
85
58
  const [sizeWithoutStockModalVisible, setSizeWithoutStockModalVisible] = useState(false);
86
59
  const handleOnShowSizeWithoutStockModal = useCallback(() => setSizeWithoutStockModalVisible(true), []);
87
60
  const handleOnHideSizeWithoutStockModal = useCallback(() => setSizeWithoutStockModalVisible(false), []);
88
- const [sizeChangeModalVisible, setSizeChangeModalVisible] = useState(false);
89
- const handleOnShowSizeChangeModal = useCallback(() => setSizeChangeModalVisible(true), []);
90
- const handleOnHideSizeChangeModal = useCallback(() => {
91
- setSizeChangeModalVisible(false);
92
- if (replaceCheckoutItemStatus === CommandStatus.SUCCESS) {
93
- navigateToNextView();
94
- }
95
- }, [navigateToNextView, replaceCheckoutItemStatus]);
96
61
  const [bookedProductsVariants, bookedProductsVariantsStatus] = useViewBookedProductsVariantsForCheckoutItem({
97
62
  checkoutItemId: checkoutItem.id,
98
63
  });
@@ -113,19 +78,11 @@ const Item = ({ customerId, country }) => {
113
78
  const handleOnShowReturnQuestions = useCallback(() => setReturnQuestionsVisible(true), []);
114
79
  const handleOnHideReturnQuestions = useCallback(() => setReturnQuestionsVisible(false), []);
115
80
  const handleOnEditFeedback = useCallback(() => handleOnShowReturnQuestions(), [handleOnShowReturnQuestions]);
116
- const handleOnSubmit = useCallback(async (feedbacks) => {
81
+ const handleOnSubmit = useCallback((feedbacks) => {
117
82
  handleOnHideReturnQuestions();
118
- await returnCheckoutItem({ feedbacks });
119
- navigateToNextView();
120
- }, [handleOnHideReturnQuestions, navigateToNextView, returnCheckoutItem]);
121
- const handleOnKeep = useCallback(async () => {
122
- await keepCheckoutItem();
123
- navigateToNextView();
124
- }, [keepCheckoutItem, navigateToNextView]);
125
- const handleOnReplace = useCallback(async (replacedForId) => {
126
- await replaceCheckoutItem({ replacedForId });
127
- handleOnShowSizeChangeModal();
128
- }, [handleOnShowSizeChangeModal, replaceCheckoutItem]);
83
+ returnCheckoutItem({ feedbacks });
84
+ }, [handleOnHideReturnQuestions, returnCheckoutItem]);
85
+ const handleOnReplace = useCallback((replacedForId) => replaceCheckoutItem({ replacedForId }), [replaceCheckoutItem]);
129
86
  const handleOnReturn = useCallback(() => handleOnShowReturnQuestions(), [handleOnShowReturnQuestions]);
130
87
  const productVariantSelected = useMemo(() => checkoutItem.status === CheckoutItemStatus.REPLACED && checkoutItem.replacedFor
131
88
  ? { id: checkoutItem.replacedFor.id, size: checkoutItem.replacedFor.size }
@@ -142,10 +99,9 @@ const Item = ({ customerId, country }) => {
142
99
  const { media, brand, name, color } = checkoutItem.productVariant;
143
100
  return (React.createElement(ReturnQuestionFeedbackProvider, { feedback: checkoutItem.feedbacks || {} },
144
101
  React.createElement(SizeWithoutStockModal, { visible: sizeWithoutStockModalVisible, onDismiss: handleOnHideSizeWithoutStockModal }),
145
- React.createElement(SizeChangeModal, { visible: sizeChangeModalVisible, onDismiss: handleOnHideSizeChangeModal }),
146
- 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 })) },
102
+ 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: keepCheckoutItem, onLayout: handleOnStickyLayout, onReplace: handleOnReplace, onReturn: handleOnReturn, onSizeSelectorPress: handleOnShowSizeWithoutStockModal })) },
147
103
  React.createElement(Body, null,
148
- customerDecissionMade && (React.createElement(CustomerDecissionBanner, { checkoutItemStatus: checkoutItem.status, onPress: handleOnBannerPress })),
104
+ customerDecissionMade && (React.createElement(CustomerDecissionBanner, { changingDecission: resetCheckoutItemStatus === CommandStatus.LOADING, checkoutItemStatus: checkoutItem.status, onPress: resetCheckoutItem })),
149
105
  React.createElement(View, { style: [style.content, { paddingBottom: Platform.OS === "web" ? spaceXL : stickyHeight }] },
150
106
  React.createElement(View, { style: style.sliderContainer },
151
107
  React.createElement(ProductVariantSlider, { producVariantMedia: media })),
@@ -4,6 +4,7 @@ type CustomerDecissionBannerStatus = Exclude<CheckoutItemStatus, CheckoutItemSta
4
4
  interface CustomerDecissionBannerProps {
5
5
  readonly checkoutItemStatus: CustomerDecissionBannerStatus;
6
6
  readonly onPress: () => void;
7
+ readonly changingDecission: boolean;
7
8
  }
8
9
  declare const CustomerDecissionBanner: FC<CustomerDecissionBannerProps>;
9
10
  export type { CustomerDecissionBannerStatus };
@@ -1,21 +1,27 @@
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 } from "react-native";
4
+ import { Pressable, View } from "react-native";
5
5
  import { CheckoutItemStatus } from "../../../../../../domain/checkoutItem/model/checkoutItem";
6
+ import { Spinner } from "../../../../../../shared/ui/components/atoms/spinner/Spinner";
6
7
  import { Banner } from "../../../../components/layouts/banner/Banner";
7
8
  import { I18nMessages } from "../../../../i18n/i18n";
9
+ import { theme } from "../../../../theme/theme";
8
10
  import { style } from "./CustomerDecissionBanner.style";
11
+ const { colorContent } = theme();
9
12
  const i18nMessageForCheckoutItemStatus = {
10
13
  [CheckoutItemStatus.KEPT]: I18nMessages.ITEM_BANNER_CUSTOMER_KEPT_DECISSION,
11
14
  [CheckoutItemStatus.REPLACED]: I18nMessages.ITEM_BANNER_CUSTOMER_REPLACED_DECISSION,
12
15
  [CheckoutItemStatus.RETURNED]: I18nMessages.ITEM_BANNER_CUSTOMER_RETURNED_DECISSION,
13
16
  };
14
- const CustomerDecissionBanner = ({ checkoutItemStatus, onPress }) => {
17
+ const CustomerDecissionBanner = ({ checkoutItemStatus, onPress, changingDecission, }) => {
15
18
  const decissionText = useI18nMessage({ id: i18nMessageForCheckoutItemStatus[checkoutItemStatus] }) || "";
16
19
  const bannerButtonText = useI18nMessage({ id: I18nMessages.ITEM_BANNER_BUTTON });
17
20
  return (React.createElement(Banner, { text: decissionText },
18
- React.createElement(Pressable, { style: style.button, onPress: onPress },
19
- React.createElement(Text, { level: 2, style: style.buttonText, detail: true }, bannerButtonText))));
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 })))));
20
26
  };
21
27
  export { CustomerDecissionBanner };
@@ -1,9 +1,16 @@
1
1
  declare const style: {
2
- button: {
2
+ actions: {
3
+ flexDirection: "row";
4
+ justifyContent: "space-between";
3
5
  marginTop: number;
6
+ minHeight: number;
7
+ width: string;
4
8
  };
5
9
  buttonText: {
6
10
  textDecorationLine: "underline";
7
11
  };
12
+ placeholder: {
13
+ width: number;
14
+ };
8
15
  };
9
16
  export { style };
@@ -2,11 +2,18 @@ import { StyleSheet } from "react-native";
2
2
  import { theme } from "../../../../theme/theme";
3
3
  const { spaceM } = theme();
4
4
  const style = StyleSheet.create({
5
- button: {
5
+ actions: {
6
+ flexDirection: "row",
7
+ justifyContent: "space-between",
6
8
  marginTop: spaceM,
9
+ minHeight: 20,
10
+ width: "100%",
7
11
  },
8
12
  buttonText: {
9
13
  textDecorationLine: "underline",
10
14
  },
15
+ placeholder: {
16
+ width: 20,
17
+ },
11
18
  });
12
19
  export { style };
@@ -17,7 +17,8 @@ const ItemActions = ({ productVariants, productVariantSelected, keepButtonLoadin
17
17
  label: size({ size: productVariant.size, country }),
18
18
  value: productVariant.id,
19
19
  })), [country, productVariants]);
20
- const disabledSizeSelector = useMemo(() => sizeSelectorOptions.length === 1 && sizeSelectorOptions[0]?.value === productVariantSelected.id, [sizeSelectorOptions, productVariantSelected.id]);
20
+ const disabledSizeSelector = useMemo(() => sizeSelectorOptions.length === 0 ||
21
+ (sizeSelectorOptions.length === 1 && sizeSelectorOptions[0]?.value === productVariantSelected.id), [sizeSelectorOptions, productVariantSelected.id]);
21
22
  return (React.createElement(Sticky, { onLayout: onLayout },
22
23
  React.createElement(Body, { style: { column: style.container } },
23
24
  React.createElement(Button, { busy: keepButtonLoading, onPress: onKeep }, keepButtonText),
@@ -0,0 +1,18 @@
1
+ import { Command } from "@lookiero/messaging";
2
+ import { NotificationType } from "../model/notification";
3
+ declare const CREATE_MODAL_NOTIFICATION = "create_modal_notification";
4
+ interface CreateModalNotificationPayload {
5
+ readonly aggregateId: string;
6
+ readonly bodyI18nKey: string;
7
+ readonly titleI18nKey: string;
8
+ readonly acceptI18nKey: string;
9
+ }
10
+ interface CreateModalNotification extends Command<typeof CREATE_MODAL_NOTIFICATION>, CreateModalNotificationPayload {
11
+ readonly type: NotificationType.MODAL;
12
+ }
13
+ interface CreateModalNotificationFunction {
14
+ (payload: CreateModalNotificationPayload): CreateModalNotification;
15
+ }
16
+ declare const createModalNotification: CreateModalNotificationFunction;
17
+ export type { CreateModalNotification };
18
+ export { CREATE_MODAL_NOTIFICATION, createModalNotification };
@@ -0,0 +1,9 @@
1
+ import { command } from "@lookiero/messaging";
2
+ import { NotificationType } from "../model/notification";
3
+ const CREATE_MODAL_NOTIFICATION = "create_modal_notification";
4
+ const createModalNotification = ({ aggregateId, ...payload }) => ({
5
+ ...command({ aggregateId, name: CREATE_MODAL_NOTIFICATION }),
6
+ ...payload,
7
+ type: NotificationType.MODAL,
8
+ });
9
+ export { CREATE_MODAL_NOTIFICATION, createModalNotification };
@@ -0,0 +1,18 @@
1
+ import { Command } from "@lookiero/messaging";
2
+ import { NotificationLevel, NotificationType } from "../model/notification";
3
+ declare const CREATE_TOAST_NOTIFICATION = "create_toast_notification";
4
+ interface CreateToastNotificationPayload {
5
+ readonly aggregateId: string;
6
+ readonly level: NotificationLevel;
7
+ readonly bodyI18nKey: string;
8
+ readonly titleI18nKey: string | undefined;
9
+ }
10
+ interface CreateToastNotification extends Command<typeof CREATE_TOAST_NOTIFICATION>, CreateToastNotificationPayload {
11
+ readonly type: NotificationType.TOAST;
12
+ }
13
+ interface CreateToastNotificationFunction {
14
+ (payload: CreateToastNotificationPayload): CreateToastNotification;
15
+ }
16
+ declare const createToastNotification: CreateToastNotificationFunction;
17
+ export type { CreateToastNotification };
18
+ export { CREATE_TOAST_NOTIFICATION, createToastNotification };
@@ -0,0 +1,9 @@
1
+ import { command } from "@lookiero/messaging";
2
+ import { NotificationType } from "../model/notification";
3
+ const CREATE_TOAST_NOTIFICATION = "create_toast_notification";
4
+ const createToastNotification = ({ aggregateId, ...payload }) => ({
5
+ ...command({ aggregateId, name: CREATE_TOAST_NOTIFICATION }),
6
+ ...payload,
7
+ type: NotificationType.TOAST,
8
+ });
9
+ export { CREATE_TOAST_NOTIFICATION, createToastNotification };
@@ -1,18 +1,25 @@
1
1
  import { AggregateRoot, CommandHandlerFunction } from "@lookiero/messaging";
2
- import { CreateNotification } from "../command/createNotification";
2
+ import { CreateModalNotification } from "../command/createModalNotification";
3
+ import { CreateToastNotification } from "../command/createToastNotification";
3
4
  import { RemoveNotification } from "../command/removeNotification";
5
+ declare enum NotificationType {
6
+ TOAST = "TOAST",
7
+ MODAL = "MODAL"
8
+ }
4
9
  declare enum NotificationLevel {
5
10
  INFO = "INFO",
6
11
  ERROR = "ERROR",
7
12
  SUCCESS = "SUCCESS"
8
13
  }
9
- export { NotificationLevel };
10
14
  interface Notification extends AggregateRoot {
15
+ readonly type: NotificationType;
11
16
  readonly level: NotificationLevel;
12
17
  readonly bodyI18nKey: string;
13
18
  readonly titleI18nKey: string | undefined;
19
+ readonly acceptI18nKey: string | undefined;
14
20
  }
15
- declare const createNotificationHandler: CommandHandlerFunction<CreateNotification, Notification>;
21
+ declare const createToastNotificationHandler: CommandHandlerFunction<CreateToastNotification, Notification>;
22
+ declare const createModalNotificationHandler: CommandHandlerFunction<CreateModalNotification, Notification>;
16
23
  declare const removeNotificationHandler: CommandHandlerFunction<RemoveNotification, Notification>;
17
24
  export type { Notification };
18
- export { createNotificationHandler, removeNotificationHandler };
25
+ export { NotificationLevel, NotificationType, createToastNotificationHandler, createModalNotificationHandler, removeNotificationHandler, };
@@ -1,22 +1,38 @@
1
1
  import { notificationCreated } from "./notificationCreated";
2
2
  import { notificationRemoved } from "./notificationRemoved";
3
+ var NotificationType;
4
+ (function (NotificationType) {
5
+ NotificationType["TOAST"] = "TOAST";
6
+ NotificationType["MODAL"] = "MODAL";
7
+ })(NotificationType || (NotificationType = {}));
3
8
  var NotificationLevel;
4
9
  (function (NotificationLevel) {
5
10
  NotificationLevel["INFO"] = "INFO";
6
11
  NotificationLevel["ERROR"] = "ERROR";
7
12
  NotificationLevel["SUCCESS"] = "SUCCESS";
8
13
  })(NotificationLevel || (NotificationLevel = {}));
9
- export { NotificationLevel };
10
- const createNotificationHandler = () => async ({ aggregateRoot, command }) => {
11
- const { aggregateId, level, titleI18nKey, bodyI18nKey } = command;
14
+ const createToastNotificationHandler = () => async ({ aggregateRoot, command }) => {
15
+ const { aggregateId, type, level, titleI18nKey, bodyI18nKey } = command;
12
16
  return {
13
17
  ...aggregateRoot,
18
+ type,
14
19
  level,
15
20
  titleI18nKey,
16
21
  bodyI18nKey,
17
22
  domainEvents: [notificationCreated({ aggregateId })],
18
23
  };
19
24
  };
25
+ const createModalNotificationHandler = () => async ({ aggregateRoot, command }) => {
26
+ const { aggregateId, type, titleI18nKey, bodyI18nKey, acceptI18nKey } = command;
27
+ return {
28
+ ...aggregateRoot,
29
+ type,
30
+ titleI18nKey,
31
+ bodyI18nKey,
32
+ acceptI18nKey,
33
+ domainEvents: [notificationCreated({ aggregateId })],
34
+ };
35
+ };
20
36
  const removeNotificationHandler = () => async ({ aggregateRoot, command }) => {
21
37
  const { aggregateId } = command;
22
38
  return {
@@ -24,4 +40,4 @@ const removeNotificationHandler = () => async ({ aggregateRoot, command }) => {
24
40
  domainEvents: [notificationRemoved({ aggregateId })],
25
41
  };
26
42
  };
27
- export { createNotificationHandler, removeNotificationHandler };
43
+ export { NotificationLevel, NotificationType, createToastNotificationHandler, createModalNotificationHandler, removeNotificationHandler, };
@@ -1,8 +1,9 @@
1
- import { useCreateNotification } from "./infrastructure/domain/notification/react/useCreateNotification";
1
+ import { useCreateModalNotification } from "./infrastructure/domain/notification/react/useCreateModalNotification";
2
+ import { useCreateToastNotification } from "./infrastructure/domain/notification/react/useCreateToastNotification";
2
3
  import { useRemoveNotification } from "./infrastructure/domain/notification/react/useRemoveNotification";
3
4
  import { NotificationDto } from "./infrastructure/persistence/notificationDto";
4
5
  import { Storage } from "./infrastructure/persistence/storage";
5
6
  import { notificationsRoot, NotificationsRoot } from "./infrastructure/ui/notificationsRoot";
6
7
  import { useListNotifications } from "./projection/notification/react/useListNotifications";
7
8
  export type { Storage, NotificationDto, NotificationsRoot };
8
- export { useListNotifications, useCreateNotification, useRemoveNotification, notificationsRoot };
9
+ export { useListNotifications, useCreateToastNotification, useCreateModalNotification, useRemoveNotification, notificationsRoot, };
@@ -1,5 +1,6 @@
1
- import { useCreateNotification } from "./infrastructure/domain/notification/react/useCreateNotification";
1
+ import { useCreateModalNotification } from "./infrastructure/domain/notification/react/useCreateModalNotification";
2
+ import { useCreateToastNotification } from "./infrastructure/domain/notification/react/useCreateToastNotification";
2
3
  import { useRemoveNotification } from "./infrastructure/domain/notification/react/useRemoveNotification";
3
4
  import { notificationsRoot } from "./infrastructure/ui/notificationsRoot";
4
5
  import { useListNotifications } from "./projection/notification/react/useListNotifications";
5
- export { useListNotifications, useCreateNotification, useRemoveNotification, notificationsRoot };
6
+ export { useListNotifications, useCreateToastNotification, useCreateModalNotification, useRemoveNotification, notificationsRoot, };
@@ -1,18 +1,21 @@
1
1
  import { bootstrap as messagingReactBootstrap } from "@lookiero/messaging-react";
2
- import { CREATE_NOTIFICATION } from "../../domain/notification/command/createNotification";
2
+ import { CREATE_MODAL_NOTIFICATION } from "../../domain/notification/command/createModalNotification";
3
+ import { CREATE_TOAST_NOTIFICATION } from "../../domain/notification/command/createToastNotification";
3
4
  import { REMOVE_NOTIFICATION } from "../../domain/notification/command/removeNotification";
4
- import { createNotificationHandler, removeNotificationHandler } from "../../domain/notification/model/notification";
5
+ import { createModalNotificationHandler, createToastNotificationHandler, removeNotificationHandler, } from "../../domain/notification/model/notification";
5
6
  import { listNotificationsHandler, LIST_NOTIFICATIONS } from "../../projection/notification/listNotifications";
6
7
  import { getNotification, saveNotification } from "../domain/notification/model/storageNotifications";
7
8
  import { storageListNotificationsView } from "../projection/notification/storageListNotificationsView";
8
9
  const NOTIFICATIONS_MESSAGING_CONTEXT_ID = "notifications";
9
10
  const bootstrap = ({ storage }) => messagingReactBootstrap({ id: NOTIFICATIONS_MESSAGING_CONTEXT_ID })
10
11
  .query(LIST_NOTIFICATIONS, listNotificationsHandler, { view: storageListNotificationsView({ storage }) })
11
- .command(CREATE_NOTIFICATION, createNotificationHandler)(getNotification, saveNotification, { storage })
12
+ .command(CREATE_TOAST_NOTIFICATION, createToastNotificationHandler)(getNotification, saveNotification, { storage })
13
+ .command(CREATE_MODAL_NOTIFICATION, createModalNotificationHandler)(getNotification, saveNotification, { storage })
12
14
  .command(REMOVE_NOTIFICATION, removeNotificationHandler)(getNotification, saveNotification, { storage })
13
15
  .build();
14
16
  const bootstrapWithBuilder = ({ storage, messaging }) => messaging
15
17
  .query(LIST_NOTIFICATIONS, listNotificationsHandler, { view: storageListNotificationsView({ storage }) })
16
- .command(CREATE_NOTIFICATION, createNotificationHandler)(getNotification, saveNotification, { storage })
18
+ .command(CREATE_TOAST_NOTIFICATION, createToastNotificationHandler)(getNotification, saveNotification, { storage })
19
+ .command(CREATE_MODAL_NOTIFICATION, createModalNotificationHandler)(getNotification, saveNotification, { storage })
17
20
  .command(REMOVE_NOTIFICATION, removeNotificationHandler)(getNotification, saveNotification, { storage });
18
21
  export { NOTIFICATIONS_MESSAGING_CONTEXT_ID, bootstrap, bootstrapWithBuilder };
@@ -1,10 +1,12 @@
1
1
  import { storageNotificationsCreate } from "./storageNotificationsCreate";
2
2
  import { storageNotificationsRemove } from "./storageNotificationsRemove";
3
- const toDomain = ({ aggregateId, level, titleI18nKey, bodyI18nKey }) => ({
3
+ const toDomain = ({ aggregateId, type, level, titleI18nKey, bodyI18nKey, acceptI18nKey, }) => ({
4
4
  aggregateId,
5
+ type,
5
6
  level,
6
7
  titleI18nKey,
7
8
  bodyI18nKey,
9
+ acceptI18nKey,
8
10
  domainEvents: [],
9
11
  });
10
12
  const getNotification = ({ storage }) => async (aggregateId) => {
@@ -1,7 +1,7 @@
1
1
  import { Notification } from "../../../../domain/notification/model/notification";
2
2
  import { NotificationDto } from "../../../persistence/notificationDto";
3
3
  import { StorageNotificationsSaveFunction } from "./storageNotifications";
4
- declare const fromDomain: ({ aggregateId, level, titleI18nKey, bodyI18nKey }: Notification) => NotificationDto;
4
+ declare const fromDomain: ({ aggregateId, type, level, titleI18nKey, bodyI18nKey, acceptI18nKey, }: Notification) => NotificationDto;
5
5
  interface StorageNotificationsCreateFunction extends StorageNotificationsSaveFunction {
6
6
  }
7
7
  declare const storageNotificationsCreate: StorageNotificationsCreateFunction;
@@ -1,9 +1,11 @@
1
1
  import { NOTIFICATION_CREATED } from "../../../../domain/notification/model/notificationCreated";
2
- const fromDomain = ({ aggregateId, level, titleI18nKey, bodyI18nKey }) => ({
2
+ const fromDomain = ({ aggregateId, type, level, titleI18nKey, bodyI18nKey, acceptI18nKey, }) => ({
3
3
  aggregateId,
4
+ type,
4
5
  level,
5
6
  titleI18nKey,
6
7
  bodyI18nKey,
8
+ acceptI18nKey,
7
9
  });
8
10
  const isNotificationCreated = (event) => event.name === NOTIFICATION_CREATED;
9
11
  const storageNotificationsCreate = ({ storage }) => async (aggregateRoot) => {
@@ -0,0 +1,20 @@
1
+ import { CommandStatus } from "@lookiero/messaging-react";
2
+ import { Logger } from "../../../../../logging/Logger";
3
+ interface CreateModalNotificationFunctionArgs {
4
+ readonly aggregateId?: string;
5
+ readonly bodyI18nKey: string;
6
+ readonly titleI18nKey: string;
7
+ readonly acceptI18nKey: string;
8
+ }
9
+ interface CreateModalNotificationFunction {
10
+ (args: CreateModalNotificationFunctionArgs): Promise<void>;
11
+ }
12
+ interface UseCreateModalNotificationFunctionArgs {
13
+ readonly contextId: string;
14
+ readonly logger: Logger;
15
+ }
16
+ interface UseCreateModalNotificationFunction {
17
+ (args: UseCreateModalNotificationFunctionArgs): [create: CreateModalNotificationFunction, status: CommandStatus];
18
+ }
19
+ declare const useCreateModalNotification: UseCreateModalNotificationFunction;
20
+ export { useCreateModalNotification };
@@ -0,0 +1,22 @@
1
+ import { useCommand } from "@lookiero/messaging-react";
2
+ import { useCallback } from "react";
3
+ import { v4 as uuid } from "uuid";
4
+ import { createModalNotification } from "../../../../domain/notification/command/createModalNotification";
5
+ const useCreateModalNotification = ({ contextId, logger }) => {
6
+ const [commandBus, status] = useCommand({ contextId });
7
+ const create = useCallback(async ({ aggregateId, titleI18nKey, bodyI18nKey, acceptI18nKey }) => {
8
+ try {
9
+ await commandBus(createModalNotification({
10
+ aggregateId: aggregateId || uuid(),
11
+ titleI18nKey,
12
+ bodyI18nKey,
13
+ acceptI18nKey,
14
+ }));
15
+ }
16
+ catch (error) {
17
+ logger.captureException(error);
18
+ }
19
+ }, [commandBus, logger]);
20
+ return [create, status];
21
+ };
22
+ export { useCreateModalNotification };
@@ -0,0 +1,21 @@
1
+ import { CommandStatus } from "@lookiero/messaging-react";
2
+ import { Logger } from "../../../../../logging/Logger";
3
+ import { NotificationLevel } from "../../../../domain/notification/model/notification";
4
+ interface CreateToastNotificationFunctionArgs {
5
+ readonly aggregateId?: string;
6
+ readonly level: NotificationLevel;
7
+ readonly bodyI18nKey: string;
8
+ readonly titleI18nKey?: string;
9
+ }
10
+ interface CreateToastNotificationFunction {
11
+ (args: CreateToastNotificationFunctionArgs): Promise<void>;
12
+ }
13
+ interface UseCreateToastNotificationFunctionArgs {
14
+ readonly contextId: string;
15
+ readonly logger: Logger;
16
+ }
17
+ interface UseCreateToastNotificationFunction {
18
+ (args: UseCreateToastNotificationFunctionArgs): [create: CreateToastNotificationFunction, status: CommandStatus];
19
+ }
20
+ declare const useCreateToastNotification: UseCreateToastNotificationFunction;
21
+ export { useCreateToastNotification };
@@ -1,12 +1,12 @@
1
1
  import { useCommand } from "@lookiero/messaging-react";
2
2
  import { useCallback } from "react";
3
3
  import { v4 as uuid } from "uuid";
4
- import { createNotification } from "../../../../domain/notification/command/createNotification";
5
- const useCreateNotification = ({ contextId, logger }) => {
4
+ import { createToastNotification } from "../../../../domain/notification/command/createToastNotification";
5
+ const useCreateToastNotification = ({ contextId, logger }) => {
6
6
  const [commandBus, status] = useCommand({ contextId });
7
7
  const create = useCallback(async ({ aggregateId, level, titleI18nKey, bodyI18nKey }) => {
8
8
  try {
9
- await commandBus(createNotification({
9
+ await commandBus(createToastNotification({
10
10
  aggregateId: aggregateId || uuid(),
11
11
  level,
12
12
  titleI18nKey,
@@ -19,4 +19,4 @@ const useCreateNotification = ({ contextId, logger }) => {
19
19
  }, [commandBus, logger]);
20
20
  return [create, status];
21
21
  };
22
- export { useCreateNotification };
22
+ export { useCreateToastNotification };
@@ -1,8 +1,10 @@
1
- import { NotificationLevel } from "../../domain/notification/model/notification";
1
+ import { NotificationLevel, NotificationType } from "../../domain/notification/model/notification";
2
2
  interface NotificationDto {
3
3
  readonly aggregateId: string;
4
+ readonly type: NotificationType;
4
5
  readonly level: NotificationLevel;
5
6
  readonly bodyI18nKey: string;
6
7
  readonly titleI18nKey: string | undefined;
8
+ readonly acceptI18nKey: string | undefined;
7
9
  }
8
10
  export type { NotificationDto };
@@ -1,7 +1,7 @@
1
- import { NotificationProjection } from "../../../projection/notification/notification";
1
+ import { ModalNotificationProjection, ToastNotificationProjection } from "../../../projection/notification/notification";
2
2
  import { NotificationDto } from "../../persistence/notificationDto";
3
3
  interface ToNotificationProjectionFunction {
4
- (notificationDto: NotificationDto): NotificationProjection;
4
+ (notificationDto: NotificationDto): ToastNotificationProjection | ModalNotificationProjection;
5
5
  }
6
6
  declare const toNotificationProjection: ToNotificationProjectionFunction;
7
7
  export { toNotificationProjection };
@@ -1,7 +1,17 @@
1
- const toNotificationProjection = (notificationDto) => ({
2
- id: notificationDto.aggregateId,
3
- level: notificationDto.level,
4
- titleI18nKey: notificationDto.titleI18nKey,
5
- bodyI18nKey: notificationDto.bodyI18nKey,
6
- });
1
+ import { NotificationType } from "../../../domain/notification/model/notification";
2
+ const toNotificationProjection = (notificationDto) => notificationDto.type === NotificationType.TOAST
3
+ ? {
4
+ id: notificationDto.aggregateId,
5
+ type: notificationDto.type,
6
+ level: notificationDto.level,
7
+ titleI18nKey: notificationDto.titleI18nKey,
8
+ bodyI18nKey: notificationDto.bodyI18nKey,
9
+ }
10
+ : {
11
+ id: notificationDto.aggregateId,
12
+ type: notificationDto.type,
13
+ titleI18nKey: notificationDto.titleI18nKey,
14
+ bodyI18nKey: notificationDto.bodyI18nKey,
15
+ acceptI18nKey: notificationDto.acceptI18nKey,
16
+ };
7
17
  export { toNotificationProjection };
@@ -0,0 +1,10 @@
1
+ import { FC } from "react";
2
+ import { ModalNotificationProjection } from "../../../../projection/notification/notification";
3
+ interface ModalNotificationItemProps {
4
+ readonly visible: boolean;
5
+ readonly notification: ModalNotificationProjection;
6
+ readonly onRemove: (notificationId: string) => void;
7
+ readonly testID?: string;
8
+ }
9
+ declare const ModalNotificationItem: FC<ModalNotificationItemProps>;
10
+ export { ModalNotificationItem };