@lookiero/checkout 6.5.1 → 6.6.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 (51) hide show
  1. package/dist/src/ExpoRoot.js +1 -8
  2. package/dist/src/infrastructure/ab-testing/kameleoonEnvironment.d.ts +2 -6
  3. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.js +1 -10
  4. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.style.d.ts +1 -7
  5. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.style.js +1 -7
  6. package/dist/src/infrastructure/ui/components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem.js +2 -7
  7. package/dist/src/infrastructure/ui/routing/Routing.js +2 -4
  8. package/dist/src/infrastructure/ui/views/checkout/Checkout.js +4 -4
  9. package/dist/src/infrastructure/ui/views/feedback/Feedback.d.ts +2 -2
  10. package/dist/src/infrastructure/ui/views/item/Item.js +4 -33
  11. package/dist/src/infrastructure/ui/views/return/Return.js +8 -127
  12. package/dist/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.js +5 -7
  13. package/dist/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.d.ts +15 -0
  14. package/dist/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.js +112 -0
  15. package/dist/src/infrastructure/ui/views/summary/Summary.js +4 -4
  16. package/dist/src/version.d.ts +1 -1
  17. package/dist/src/version.js +1 -1
  18. package/package.json +1 -1
  19. package/src/ExpoRoot.tsx +1 -8
  20. package/src/infrastructure/ab-testing/kameleoonEnvironment.ts +3 -7
  21. package/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.style.ts +1 -7
  22. package/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.test.tsx +0 -5
  23. package/src/infrastructure/ui/components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem.tsx +2 -17
  24. package/src/infrastructure/ui/components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem.test.tsx +0 -5
  25. package/src/infrastructure/ui/components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem.tsx +11 -20
  26. package/src/infrastructure/ui/routing/Routing.tsx +3 -6
  27. package/src/infrastructure/ui/views/checkout/Checkout.tsx +6 -6
  28. package/src/infrastructure/ui/views/feedback/Feedback.tsx +2 -2
  29. package/src/infrastructure/ui/views/item/Item.test.tsx +6 -62
  30. package/src/infrastructure/ui/views/item/Item.tsx +5 -48
  31. package/src/infrastructure/ui/views/return/Return.test.tsx +54 -0
  32. package/src/infrastructure/ui/views/return/Return.tsx +12 -200
  33. package/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.test.tsx +32 -0
  34. package/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.tsx +12 -7
  35. package/src/infrastructure/ui/views/return/components/productVariantPreview/__snapshots__/ProductVariantPreview.test.tsx.snap +221 -0
  36. package/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.test.tsx +95 -0
  37. package/src/infrastructure/ui/views/return/components/returnQuestionsForm/ReturnQuestionsForm.tsx +184 -0
  38. package/src/infrastructure/ui/views/summary/Summary.tsx +6 -6
  39. package/dist/src/infrastructure/ui/hooks/useNewFeedbackExperiment.d.ts +0 -11
  40. package/dist/src/infrastructure/ui/hooks/useNewFeedbackExperiment.js +0 -49
  41. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.d.ts +0 -11
  42. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.js +0 -40
  43. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.style.d.ts +0 -12
  44. package/dist/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.style.js +0 -15
  45. package/src/infrastructure/ui/hooks/useNewFeedbackExperiment.test.tsx +0 -84
  46. package/src/infrastructure/ui/hooks/useNewFeedbackExperiment.tsx +0 -82
  47. package/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.style.ts +0 -18
  48. package/src/infrastructure/ui/views/item/components/returnQuestionsForm/ReturnQuestionsForm.tsx +0 -79
  49. /package/dist/src/infrastructure/ui/views/return/{Return.style.d.ts → components/returnQuestionsForm/ReturnQuestionsForm.style.d.ts} +0 -0
  50. /package/dist/src/infrastructure/ui/views/return/{Return.style.js → components/returnQuestionsForm/ReturnQuestionsForm.style.js} +0 -0
  51. /package/src/infrastructure/ui/views/return/{Return.style.ts → components/returnQuestionsForm/ReturnQuestionsForm.style.ts} +0 -0
@@ -0,0 +1,184 @@
1
+ import { PortalHost } from "@gorhom/portal";
2
+ import React, { FC, useCallback, useMemo } from "react";
3
+ import { ScrollView } from "react-native";
4
+ import { generatePath, useNavigate } from "react-router-native";
5
+ import { Box, Button, Layout as AuroraLayout, Spinner, Text, View, useDevice } from "@lookiero/aurora";
6
+ import { useI18nMessage } from "@lookiero/i18n-react";
7
+ import { CommandStatus } from "@lookiero/messaging-react";
8
+ import { useLogger } from "@lookiero/sty-psp-logging";
9
+ import { Segment } from "@lookiero/sty-psp-segment";
10
+ import { Layout as UiLayout } from "@lookiero/sty-psp-ui";
11
+ import { CheckoutProjection } from "../../../../../../projection/checkout/checkout";
12
+ import { CheckoutItemProjection } from "../../../../../../projection/checkoutItem/checkoutItem";
13
+ import { ReturnQuestionType } from "../../../../../../projection/returnQuestion/returnQuestion";
14
+ import { Country } from "../../../../../../projection/shared/country";
15
+ import { useReturnCheckoutItem } from "../../../../../domain/checkoutItem/react/useReturnCheckoutItem";
16
+ import { useListReturnQuestionsByCheckoutItemId } from "../../../../../projection/returnQuestion/react/useListReturnQuestionsByCheckoutItemId";
17
+ import { TrackingPage } from "../../../../../tracking/tracking";
18
+ import { useTrackPageView } from "../../../../../tracking/useTrackPageView";
19
+ import { useTrackPressBack } from "../../../../../tracking/useTrackPressBack";
20
+ import { useTrackPressNext } from "../../../../../tracking/useTrackPressNext";
21
+ import { useTrackReturnItem } from "../../../../../tracking/useTrackReturnItem";
22
+ import { ReturnQuestions } from "../../../../components/organisms/returnQuestions/ReturnQuestions";
23
+ import { useReturnQuestionFeedback } from "../../../../components/organisms/returnQuestions/behaviors/useReturnQuestionFeedback";
24
+ import {
25
+ ReturnQuestionItemProvider,
26
+ ReturnQuestionItems,
27
+ } from "../../../../components/organisms/returnQuestions/behaviors/useReturnQuestionItem";
28
+ import { HostDefaultReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem";
29
+ import { HostRadioGroupReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostRadioGroupReturnQuestionItem/HostRadioGroupReturnQuestionItem";
30
+ import { HostStackReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostStackReturnQuestionItem/form/HostStackReturnQuestionItem";
31
+ import { RadioReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/radioReturnQuestionItem/RadioReturnQuestionItem";
32
+ import { TextareaReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem";
33
+ import { ItemDetailHeader } from "../../../../components/templates/header/itemDetailHeader/ItemDetailHeader";
34
+ import { I18nMessages } from "../../../../i18n/i18n";
35
+ import { Routes } from "../../../../routing/routes";
36
+ import { useBasePath } from "../../../../routing/useBasePath";
37
+ import { ProductVariantPreview } from "../productVariantPreview/ProductVariantPreview";
38
+ import { style } from "./ReturnQuestionsForm.style";
39
+
40
+ const RETURN_QUESTION_FORM_PORTAL_HOST_NAME = "return-question-form-portal";
41
+
42
+ const returnQuestionItems: ReturnQuestionItems = {
43
+ [ReturnQuestionType.HOST_DEFAULT]: HostDefaultReturnQuestionItem,
44
+ [ReturnQuestionType.HOST_TEXTAREA]: HostDefaultReturnQuestionItem,
45
+ [ReturnQuestionType.HOST_SELECT]: HostRadioGroupReturnQuestionItem,
46
+ [ReturnQuestionType.HOST_STACK]: HostStackReturnQuestionItem,
47
+ [ReturnQuestionType.TEXTAREA]: TextareaReturnQuestionItem,
48
+ [ReturnQuestionType.OPTION]: RadioReturnQuestionItem,
49
+ };
50
+
51
+ interface ReturnQuestionsFormProps {
52
+ readonly checkout: CheckoutProjection;
53
+ readonly checkoutItem: CheckoutItemProjection;
54
+ readonly country: Country;
55
+ readonly layout: UiLayout;
56
+ readonly segment: Segment;
57
+ }
58
+
59
+ const ReturnQuestionsForm: FC<ReturnQuestionsFormProps> = ({
60
+ checkout,
61
+ checkoutItem,
62
+ country,
63
+ layout: Layout,
64
+ segment,
65
+ }) => {
66
+ const navigate = useNavigate();
67
+ const basePath = useBasePath();
68
+ const logger = useLogger();
69
+
70
+ const { screen } = useDevice();
71
+
72
+ const titleText = useI18nMessage({ id: I18nMessages.RETURN_QUESTIONS_TITLE });
73
+ const descriptionText = useI18nMessage({ id: I18nMessages.RETURN_QUESTIONS_DESCRIPTION });
74
+ const submitButtonText = useI18nMessage({ id: I18nMessages.RETURN_QUESTIONS_SUBMIT_BUTTON });
75
+
76
+ const feedback = useReturnQuestionFeedback();
77
+ const [returnQuestions] = useListReturnQuestionsByCheckoutItemId({
78
+ checkoutItemId: checkoutItem.id,
79
+ });
80
+
81
+ const [returnCheckoutItem, returnCheckoutItemStatus] = useReturnCheckoutItem({
82
+ checkoutItemId: checkoutItem.id,
83
+ logger,
84
+ });
85
+ const trackReturnItem = useTrackReturnItem({
86
+ page: TrackingPage.RETURN,
87
+ country,
88
+ segment,
89
+ checkoutId: checkout.id,
90
+ checkoutItemId: checkoutItem.id,
91
+ });
92
+
93
+ useTrackPageView({ checkoutId: checkout.id, country, segment, page: TrackingPage.RETURN });
94
+
95
+ const trackPressBack = useTrackPressBack({
96
+ page: TrackingPage.ITEM,
97
+ country,
98
+ segment,
99
+ checkoutId: checkout?.id,
100
+ });
101
+ const handleOnBack = useCallback(() => {
102
+ trackPressBack();
103
+ navigate(-1);
104
+ }, [navigate, trackPressBack]);
105
+
106
+ const trackPressNext = useTrackPressNext({
107
+ page: TrackingPage.ITEM,
108
+ country,
109
+ segment,
110
+ checkoutId: checkout.id,
111
+ });
112
+
113
+ const handleOnSubmit = useCallback(async () => {
114
+ returnCheckoutItem({ feedbacks: feedback });
115
+ trackReturnItem();
116
+
117
+ const itemIndex = checkout.items.indexOf(checkoutItem);
118
+ const nextItemIndex = itemIndex === checkout.items.length - 1 ? 0 : itemIndex + 1;
119
+ const nextItem = checkout.items[nextItemIndex] as CheckoutItemProjection;
120
+
121
+ trackPressNext({ from: checkoutItem.id, to: nextItem.id });
122
+ navigate(generatePath(`${basePath}/${Routes.ITEM}`, { id: nextItem.id }));
123
+ }, [basePath, checkout.items, checkoutItem, feedback, navigate, returnCheckoutItem, trackPressNext, trackReturnItem]);
124
+
125
+ const header = useMemo(
126
+ () => (
127
+ <Box style={style.headerWrapper}>
128
+ <ItemDetailHeader onBack={handleOnBack} />
129
+ </Box>
130
+ ),
131
+ [handleOnBack],
132
+ );
133
+
134
+ const dependenciesLoaded = checkoutItem && returnQuestions && returnCheckoutItemStatus !== CommandStatus.LOADING;
135
+
136
+ if (!dependenciesLoaded) {
137
+ return <Spinner />;
138
+ }
139
+
140
+ return (
141
+ <ReturnQuestionItemProvider returnQuestionItems={returnQuestionItems}>
142
+ <PortalHost name={RETURN_QUESTION_FORM_PORTAL_HOST_NAME} />
143
+
144
+ <Layout
145
+ header={header}
146
+ scrollEnabled={false}
147
+ style={{
148
+ safeAreaView: style.safeAreaView,
149
+ scrollView: style.scrollView,
150
+ }}
151
+ >
152
+ <ProductVariantPreview country={country} item={checkoutItem} />
153
+
154
+ <ScrollView showsVerticalScrollIndicator={false} testID="return-questions-form">
155
+ <AuroraLayout fullWidth={!screen.L} style={[style.layout, screen.L ? style.desktopLayoutSpacing : undefined]}>
156
+ <Box size={{ L: "2/3" }}>
157
+ <View style={[style.info, !screen.S && style.desktopInfo]}>
158
+ <Text level={3} heading>
159
+ {titleText}
160
+ </Text>
161
+ <Text level={1} style={style.description} detail>
162
+ {descriptionText}
163
+ </Text>
164
+ </View>
165
+
166
+ <ReturnQuestions
167
+ portalHostName={RETURN_QUESTION_FORM_PORTAL_HOST_NAME}
168
+ returnQuestions={returnQuestions}
169
+ />
170
+
171
+ <View style={style.submit}>
172
+ <Button testID="return-questions-button" onPress={handleOnSubmit}>
173
+ {submitButtonText}
174
+ </Button>
175
+ </View>
176
+ </Box>
177
+ </AuroraLayout>
178
+ </ScrollView>
179
+ </Layout>
180
+ </ReturnQuestionItemProvider>
181
+ );
182
+ };
183
+
184
+ export { ReturnQuestionsForm };
@@ -1,7 +1,7 @@
1
1
  import React, { FC, ReactNode, useCallback, useEffect, useMemo, useState } from "react";
2
2
  import { LayoutRectangle, Platform, ScrollView, View } from "react-native";
3
3
  import { generatePath, useMatch, useNavigate } from "react-router-native";
4
- import { Box, Text, Layout, useDevice, Spinner } from "@lookiero/aurora";
4
+ import { Box, Text, Layout as AuroraLayout, useDevice, Spinner } from "@lookiero/aurora";
5
5
  import { useI18nMessage } from "@lookiero/i18n-react";
6
6
  import { QueryStatus } from "@lookiero/messaging-react";
7
7
  import { Layout as UiLayout, Sticky } from "@lookiero/sty-psp-ui";
@@ -27,7 +27,7 @@ interface SummaryProps {
27
27
  readonly children: ReactNode;
28
28
  }
29
29
 
30
- const Summary: FC<SummaryProps> = ({ layout: UiLayout, children }) => {
30
+ const Summary: FC<SummaryProps> = ({ layout: Layout, children }) => {
31
31
  const {
32
32
  customer: { customerId, country, segment },
33
33
  } = useStaticInfo();
@@ -110,7 +110,7 @@ const Summary: FC<SummaryProps> = ({ layout: UiLayout, children }) => {
110
110
  }
111
111
 
112
112
  return (
113
- <UiLayout
113
+ <Layout
114
114
  scrollEnabled={false}
115
115
  style={{
116
116
  header: style.header,
@@ -120,7 +120,7 @@ const Summary: FC<SummaryProps> = ({ layout: UiLayout, children }) => {
120
120
  <ScrollView showsVerticalScrollIndicator={false}>
121
121
  {fiveItemsDiscount !== 0 && <FiveItemsDiscountBanner fiveItemsDiscount={fiveItemsDiscount} />}
122
122
 
123
- <Layout
123
+ <AuroraLayout
124
124
  fullWidth={!screen.L}
125
125
  style={[screen.L && style.desktopLayoutSpacing, !screen.L && { paddingBottom: pricingHeight }]}
126
126
  >
@@ -153,7 +153,7 @@ const Summary: FC<SummaryProps> = ({ layout: UiLayout, children }) => {
153
153
  </View>
154
154
  </Box>
155
155
  ) : null}
156
- </Layout>
156
+ </AuroraLayout>
157
157
  </ScrollView>
158
158
 
159
159
  {pricing && !screen.L ? (
@@ -170,7 +170,7 @@ const Summary: FC<SummaryProps> = ({ layout: UiLayout, children }) => {
170
170
  </Body>
171
171
  </Sticky>
172
172
  ) : null}
173
- </UiLayout>
173
+ </Layout>
174
174
  );
175
175
  };
176
176
 
@@ -1,11 +0,0 @@
1
- import { FC, ReactNode } from "react";
2
- declare enum NewFeedbackExperimentVariation {
3
- CONTROL = "control",
4
- RETURN_PAGE = "return_page"
5
- }
6
- interface NewFeedbackExperimentProviderProps {
7
- readonly children: ReactNode;
8
- }
9
- declare const NewFeedbackExperimentProvider: FC<NewFeedbackExperimentProviderProps>;
10
- declare const useNewFeedbackExperiment: () => NewFeedbackExperimentVariation;
11
- export { useNewFeedbackExperiment, NewFeedbackExperimentProvider, NewFeedbackExperimentVariation };
@@ -1,49 +0,0 @@
1
- import React, { createContext, useContext, useEffect, useMemo, useRef } from "react";
2
- import invariant from "tiny-invariant";
3
- import { Spinner } from "@lookiero/aurora";
4
- import { useAssignedVariationByExperimentId } from "@lookiero/sty-psp-ab-testing";
5
- import { useViewFirstAvailableCheckoutByCustomerId } from "../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
6
- import { useTrackAssignedVariationByExperiment } from "../../tracking/useTrackAssignedVariationByExperiment";
7
- import { useStaticInfo } from "./useStaticInfo";
8
- var NewFeedbackExperimentVariation;
9
- (function (NewFeedbackExperimentVariation) {
10
- NewFeedbackExperimentVariation["CONTROL"] = "control";
11
- NewFeedbackExperimentVariation["RETURN_PAGE"] = "return_page";
12
- })(NewFeedbackExperimentVariation || (NewFeedbackExperimentVariation = {}));
13
- const NewFeedbackExperimentContext = createContext(null);
14
- const NewFeedbackExperimentProvider = ({ children }) => {
15
- const { kameleoon: { experiments: { newFeedback: { id: newFeedbackId, variations }, }, }, customer: { customerId, country, segment }, } = useStaticInfo();
16
- const [checkout] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
17
- const { assignedVariation: newFeedbackVariation } = useAssignedVariationByExperimentId({
18
- experimentId: newFeedbackId,
19
- });
20
- const trackAssignedVariation = useTrackAssignedVariationByExperiment({
21
- checkoutId: checkout?.id,
22
- country,
23
- segment,
24
- experimentId: newFeedbackId,
25
- });
26
- const value = useMemo(() => ({
27
- variation: newFeedbackVariation?.id === Number(variations.v1)
28
- ? NewFeedbackExperimentVariation.RETURN_PAGE
29
- : NewFeedbackExperimentVariation.CONTROL,
30
- }), [newFeedbackVariation?.id, variations.v1]);
31
- const assignedVariantTracked = useRef(false);
32
- useEffect(() => {
33
- if (assignedVariantTracked.current || !newFeedbackVariation || !checkout?.id) {
34
- return;
35
- }
36
- trackAssignedVariation({ assignedVariation: newFeedbackVariation });
37
- assignedVariantTracked.current = true;
38
- }, [checkout?.id, newFeedbackVariation, trackAssignedVariation]);
39
- if (!checkout) {
40
- return React.createElement(Spinner, null);
41
- }
42
- return React.createElement(NewFeedbackExperimentContext.Provider, { value: value }, children);
43
- };
44
- const useNewFeedbackExperiment = () => {
45
- const newFeedbackExperiment = useContext(NewFeedbackExperimentContext);
46
- invariant(newFeedbackExperiment, "Your are trying to use the useNewFeedbackExperiment hook without wrapping your app with the <NewFeedbackExperimentProvider>.");
47
- return newFeedbackExperiment.variation;
48
- };
49
- export { useNewFeedbackExperiment, NewFeedbackExperimentProvider, NewFeedbackExperimentVariation };
@@ -1,11 +0,0 @@
1
- import { FC } from "react";
2
- import { FeedbackProjection } from "../../../../../../projection/feedback/feedback";
3
- import { ReturnQuestionProjection } from "../../../../../../projection/returnQuestion/returnQuestion";
4
- interface ReturnQuestionsFormProps {
5
- readonly visible: boolean;
6
- readonly returnQuestions: ReturnQuestionProjection[];
7
- readonly onSubmit: (feedback: FeedbackProjection) => void;
8
- readonly onClose: () => void;
9
- }
10
- declare const ReturnQuestionsForm: FC<ReturnQuestionsFormProps>;
11
- export { ReturnQuestionsForm };
@@ -1,40 +0,0 @@
1
- import { PortalHost } from "@gorhom/portal";
2
- import React, { useCallback } from "react";
3
- import { View } from "react-native";
4
- import { Button, Text } from "@lookiero/aurora";
5
- import { useI18nMessage } from "@lookiero/i18n-react";
6
- import { Modal } from "@lookiero/sty-psp-ui";
7
- import { ReturnQuestionType, } from "../../../../../../projection/returnQuestion/returnQuestion";
8
- import { ReturnQuestions } from "../../../../components/organisms/returnQuestions/ReturnQuestions";
9
- import { useReturnQuestionFeedback } from "../../../../components/organisms/returnQuestions/behaviors/useReturnQuestionFeedback";
10
- import { ReturnQuestionItemProvider, } from "../../../../components/organisms/returnQuestions/behaviors/useReturnQuestionItem";
11
- import { HostDefaultReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem";
12
- import { HostSelectReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostSelectReturnQuestionItem/HostSelectReturnQuestionItem";
13
- import { HostStackReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostStackReturnQuestionItem/modal/HostStackReturnQuestionItem";
14
- import { OptionReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/optionReturnQuestionItem/OptionReturnQuestionItem";
15
- import { TextareaReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem";
16
- import { I18nMessages } from "../../../../i18n/i18n";
17
- import { style } from "./ReturnQuestionsForm.style";
18
- const RETURN_QUESTION_FORM_PORTAL_HOST_NAME = "return-question-form-portal";
19
- const returnQuestionItems = {
20
- [ReturnQuestionType.HOST_DEFAULT]: HostDefaultReturnQuestionItem,
21
- [ReturnQuestionType.HOST_TEXTAREA]: HostDefaultReturnQuestionItem,
22
- [ReturnQuestionType.HOST_SELECT]: HostSelectReturnQuestionItem,
23
- [ReturnQuestionType.HOST_STACK]: HostStackReturnQuestionItem,
24
- [ReturnQuestionType.TEXTAREA]: TextareaReturnQuestionItem,
25
- [ReturnQuestionType.OPTION]: OptionReturnQuestionItem,
26
- };
27
- const ReturnQuestionsForm = ({ returnQuestions, visible, onSubmit, onClose }) => {
28
- const titleText = useI18nMessage({ id: I18nMessages.RETURN_QUESTIONS_TITLE });
29
- const submitButtonText = useI18nMessage({ id: I18nMessages.RETURN_QUESTIONS_SUBMIT_BUTTON });
30
- const feedback = useReturnQuestionFeedback();
31
- const handleOnSubmit = useCallback(() => onSubmit(feedback), [feedback, onSubmit]);
32
- return (React.createElement(ReturnQuestionItemProvider, { returnQuestionItems: returnQuestionItems },
33
- React.createElement(PortalHost, { name: RETURN_QUESTION_FORM_PORTAL_HOST_NAME }),
34
- React.createElement(Modal, { portalHostName: RETURN_QUESTION_FORM_PORTAL_HOST_NAME, testID: "return-questions-form-modal", visible: visible, scroll: true, showCloseButton: true, onClose: onClose },
35
- React.createElement(View, { style: style.modalContent },
36
- React.createElement(Text, { level: 3, style: style.title, heading: true }, titleText),
37
- React.createElement(ReturnQuestions, { portalHostName: RETURN_QUESTION_FORM_PORTAL_HOST_NAME, returnQuestions: returnQuestions }),
38
- React.createElement(Button, { style: style.submit, testID: "return-questions-button", onPress: handleOnSubmit }, submitButtonText)))));
39
- };
40
- export { ReturnQuestionsForm };
@@ -1,12 +0,0 @@
1
- declare const style: {
2
- modalContent: {
3
- paddingHorizontal: number;
4
- };
5
- submit: {
6
- marginTop: number;
7
- };
8
- title: {
9
- marginBottom: number;
10
- };
11
- };
12
- export { style };
@@ -1,15 +0,0 @@
1
- import { StyleSheet } from "react-native";
2
- import { theme } from "@lookiero/sty-psp-ui";
3
- const { space6, space8 } = theme();
4
- const style = StyleSheet.create({
5
- modalContent: {
6
- paddingHorizontal: space6,
7
- },
8
- submit: {
9
- marginTop: space8,
10
- },
11
- title: {
12
- marginBottom: space6,
13
- },
14
- });
15
- export { style };
@@ -1,84 +0,0 @@
1
- import { renderHook, waitFor } from "@testing-library/react-native";
2
- import React, { FC } from "react";
3
- import { Variation, useAssignedVariationByExperimentId } from "@lookiero/sty-psp-ab-testing";
4
- import { Segment } from "@lookiero/sty-psp-segment";
5
- import { CheckoutProjection } from "../../../projection/checkout/checkout";
6
- import { Country } from "../../../projection/shared/country";
7
- import { KameleoonEnvironment } from "../../ab-testing/kameleoonEnvironment";
8
- import {
9
- NewFeedbackExperimentProvider,
10
- NewFeedbackExperimentVariation,
11
- useNewFeedbackExperiment as sut,
12
- } from "./useNewFeedbackExperiment";
13
-
14
- const mockKameleoon: KameleoonEnvironment = {
15
- siteCode: "aplm4v3ckn",
16
- experiments: {
17
- newFeedback: {
18
- id: "245000",
19
- variations: {
20
- v1: "964072",
21
- },
22
- },
23
- },
24
- };
25
-
26
- const country = Country.ES;
27
- const segment = Segment.WOMEN;
28
- const customerId = "1f410890-b3e1-49d2-9950-2ff89182cb79";
29
- const mockTrackAssignedVariation = jest.fn();
30
- // useStaticInfo
31
-
32
- jest.mock("../../tracking/useTrackAssignedVariationByExperiment", () => ({
33
- useTrackAssignedVariationByExperiment: () => mockTrackAssignedVariation,
34
- }));
35
-
36
- jest.mock("@lookiero/sty-psp-ab-testing");
37
-
38
- jest.mock("./useStaticInfo", () => ({
39
- useStaticInfo: () => ({ kameleoon: mockKameleoon, customer: { customerId, country, segment } }),
40
- }));
41
-
42
- jest.mock("../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId", () => ({
43
- useViewFirstAvailableCheckoutByCustomerId: () => [
44
- { id: "3db6984e-c8d2-4242-a795-ab5babb25e8c" } as CheckoutProjection,
45
- ],
46
- }));
47
-
48
- interface WrapperProps {
49
- readonly children: JSX.Element;
50
- }
51
-
52
- const Wrapper: FC<WrapperProps> = ({ children }) => (
53
- <NewFeedbackExperimentProvider>{children}</NewFeedbackExperimentProvider>
54
- );
55
-
56
- beforeEach(() => {
57
- mockTrackAssignedVariation.mockClear();
58
- });
59
-
60
- describe("useNewFeedbackExperiment hook", () => {
61
- it("returns 'control' as variation", async () => {
62
- const assignedVariation: Variation = { id: 0, name: "Control" };
63
- (useAssignedVariationByExperimentId as jest.Mock).mockReturnValue({ assignedVariation });
64
-
65
- const { result } = renderHook(() => sut(), { wrapper: Wrapper });
66
-
67
- await waitFor(() => expect(result.current).toBe(NewFeedbackExperimentVariation.CONTROL));
68
- await waitFor(() => {
69
- expect(mockTrackAssignedVariation).toHaveBeenCalledWith({ assignedVariation });
70
- });
71
- });
72
-
73
- it("returns 'return_page' as variation", async () => {
74
- const assignedVariation: Variation = { id: 964072, name: "Variation 1" };
75
- (useAssignedVariationByExperimentId as jest.Mock).mockReturnValue({ assignedVariation });
76
-
77
- const { result } = renderHook(() => sut(), { wrapper: Wrapper });
78
-
79
- await waitFor(() => expect(result.current).toBe(NewFeedbackExperimentVariation.RETURN_PAGE));
80
- await waitFor(() => {
81
- expect(mockTrackAssignedVariation).toHaveBeenCalledWith({ assignedVariation });
82
- });
83
- });
84
- });
@@ -1,82 +0,0 @@
1
- import React, { createContext, FC, ReactNode, useContext, useEffect, useMemo, useRef } from "react";
2
- import invariant from "tiny-invariant";
3
- import { Spinner } from "@lookiero/aurora";
4
- import { useAssignedVariationByExperimentId } from "@lookiero/sty-psp-ab-testing";
5
- import { useViewFirstAvailableCheckoutByCustomerId } from "../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
6
- import { useTrackAssignedVariationByExperiment } from "../../tracking/useTrackAssignedVariationByExperiment";
7
- import { useStaticInfo } from "./useStaticInfo";
8
-
9
- enum NewFeedbackExperimentVariation {
10
- CONTROL = "control",
11
- RETURN_PAGE = "return_page",
12
- }
13
-
14
- interface NewFeedbackExperiment {
15
- readonly variation: NewFeedbackExperimentVariation;
16
- }
17
-
18
- const NewFeedbackExperimentContext = createContext<NewFeedbackExperiment>(null as unknown as NewFeedbackExperiment);
19
-
20
- interface NewFeedbackExperimentProviderProps {
21
- readonly children: ReactNode;
22
- }
23
-
24
- const NewFeedbackExperimentProvider: FC<NewFeedbackExperimentProviderProps> = ({ children }) => {
25
- const {
26
- kameleoon: {
27
- experiments: {
28
- newFeedback: { id: newFeedbackId, variations },
29
- },
30
- },
31
- customer: { customerId, country, segment },
32
- } = useStaticInfo();
33
- const [checkout] = useViewFirstAvailableCheckoutByCustomerId({ customerId });
34
- const { assignedVariation: newFeedbackVariation } = useAssignedVariationByExperimentId({
35
- experimentId: newFeedbackId,
36
- });
37
- const trackAssignedVariation = useTrackAssignedVariationByExperiment({
38
- checkoutId: checkout?.id,
39
- country,
40
- segment,
41
- experimentId: newFeedbackId,
42
- });
43
-
44
- const value = useMemo(
45
- () => ({
46
- variation:
47
- newFeedbackVariation?.id === Number(variations.v1)
48
- ? NewFeedbackExperimentVariation.RETURN_PAGE
49
- : NewFeedbackExperimentVariation.CONTROL,
50
- }),
51
- [newFeedbackVariation?.id, variations.v1],
52
- );
53
-
54
- const assignedVariantTracked = useRef(false);
55
- useEffect(() => {
56
- if (assignedVariantTracked.current || !newFeedbackVariation || !checkout?.id) {
57
- return;
58
- }
59
-
60
- trackAssignedVariation({ assignedVariation: newFeedbackVariation });
61
- assignedVariantTracked.current = true;
62
- }, [checkout?.id, newFeedbackVariation, trackAssignedVariation]);
63
-
64
- if (!checkout) {
65
- return <Spinner />;
66
- }
67
-
68
- return <NewFeedbackExperimentContext.Provider value={value}>{children}</NewFeedbackExperimentContext.Provider>;
69
- };
70
-
71
- const useNewFeedbackExperiment = () => {
72
- const newFeedbackExperiment = useContext(NewFeedbackExperimentContext);
73
-
74
- invariant(
75
- newFeedbackExperiment,
76
- "Your are trying to use the useNewFeedbackExperiment hook without wrapping your app with the <NewFeedbackExperimentProvider>.",
77
- );
78
-
79
- return newFeedbackExperiment.variation;
80
- };
81
-
82
- export { useNewFeedbackExperiment, NewFeedbackExperimentProvider, NewFeedbackExperimentVariation };
@@ -1,18 +0,0 @@
1
- import { StyleSheet } from "react-native";
2
- import { theme } from "@lookiero/sty-psp-ui";
3
-
4
- const { space6, space8 } = theme();
5
-
6
- const style = StyleSheet.create({
7
- modalContent: {
8
- paddingHorizontal: space6,
9
- },
10
- submit: {
11
- marginTop: space8,
12
- },
13
- title: {
14
- marginBottom: space6,
15
- },
16
- });
17
-
18
- export { style };
@@ -1,79 +0,0 @@
1
- import { PortalHost } from "@gorhom/portal";
2
- import React, { FC, useCallback } from "react";
3
- import { View } from "react-native";
4
- import { Button, Text } from "@lookiero/aurora";
5
- import { useI18nMessage } from "@lookiero/i18n-react";
6
- import { Modal } from "@lookiero/sty-psp-ui";
7
- import { FeedbackProjection } from "../../../../../../projection/feedback/feedback";
8
- import {
9
- ReturnQuestionProjection,
10
- ReturnQuestionType,
11
- } from "../../../../../../projection/returnQuestion/returnQuestion";
12
- import { ReturnQuestions } from "../../../../components/organisms/returnQuestions/ReturnQuestions";
13
- import { useReturnQuestionFeedback } from "../../../../components/organisms/returnQuestions/behaviors/useReturnQuestionFeedback";
14
- import {
15
- ReturnQuestionItemProvider,
16
- ReturnQuestionItems,
17
- } from "../../../../components/organisms/returnQuestions/behaviors/useReturnQuestionItem";
18
- import { HostDefaultReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostDefaultReturnQuestionItem/HostDefaultReturnQuestionItem";
19
- import { HostSelectReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostSelectReturnQuestionItem/HostSelectReturnQuestionItem";
20
- import { HostStackReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/hostStackReturnQuestionItem/modal/HostStackReturnQuestionItem";
21
- import { OptionReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/optionReturnQuestionItem/OptionReturnQuestionItem";
22
- import { TextareaReturnQuestionItem } from "../../../../components/organisms/returnQuestions/components/textareaReturnQuestionItem/TextareaReturnQuestionItem";
23
- import { I18nMessages } from "../../../../i18n/i18n";
24
- import { style } from "./ReturnQuestionsForm.style";
25
-
26
- const RETURN_QUESTION_FORM_PORTAL_HOST_NAME = "return-question-form-portal";
27
-
28
- const returnQuestionItems: ReturnQuestionItems = {
29
- [ReturnQuestionType.HOST_DEFAULT]: HostDefaultReturnQuestionItem,
30
- [ReturnQuestionType.HOST_TEXTAREA]: HostDefaultReturnQuestionItem,
31
- [ReturnQuestionType.HOST_SELECT]: HostSelectReturnQuestionItem,
32
- [ReturnQuestionType.HOST_STACK]: HostStackReturnQuestionItem,
33
- [ReturnQuestionType.TEXTAREA]: TextareaReturnQuestionItem,
34
- [ReturnQuestionType.OPTION]: OptionReturnQuestionItem,
35
- };
36
-
37
- interface ReturnQuestionsFormProps {
38
- readonly visible: boolean;
39
- readonly returnQuestions: ReturnQuestionProjection[];
40
- readonly onSubmit: (feedback: FeedbackProjection) => void;
41
- readonly onClose: () => void;
42
- }
43
-
44
- const ReturnQuestionsForm: FC<ReturnQuestionsFormProps> = ({ returnQuestions, visible, onSubmit, onClose }) => {
45
- const titleText = useI18nMessage({ id: I18nMessages.RETURN_QUESTIONS_TITLE });
46
- const submitButtonText = useI18nMessage({ id: I18nMessages.RETURN_QUESTIONS_SUBMIT_BUTTON });
47
-
48
- const feedback = useReturnQuestionFeedback();
49
-
50
- const handleOnSubmit = useCallback(() => onSubmit(feedback), [feedback, onSubmit]);
51
-
52
- return (
53
- <ReturnQuestionItemProvider returnQuestionItems={returnQuestionItems}>
54
- <PortalHost name={RETURN_QUESTION_FORM_PORTAL_HOST_NAME} />
55
- <Modal
56
- portalHostName={RETURN_QUESTION_FORM_PORTAL_HOST_NAME}
57
- testID="return-questions-form-modal"
58
- visible={visible}
59
- scroll
60
- showCloseButton
61
- onClose={onClose}
62
- >
63
- <View style={style.modalContent}>
64
- <Text level={3} style={style.title} heading>
65
- {titleText}
66
- </Text>
67
-
68
- <ReturnQuestions portalHostName={RETURN_QUESTION_FORM_PORTAL_HOST_NAME} returnQuestions={returnQuestions} />
69
-
70
- <Button style={style.submit} testID="return-questions-button" onPress={handleOnSubmit}>
71
- {submitButtonText}
72
- </Button>
73
- </View>
74
- </Modal>
75
- </ReturnQuestionItemProvider>
76
- );
77
- };
78
-
79
- export { ReturnQuestionsForm };