@lookiero/checkout 14.7.0 → 14.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cypress/support/interceptViewPricingByCheckoutId.ts +3 -3
- package/dist/src/ExpoRoot.js +2 -3
- package/dist/src/infrastructure/delivery/bootstrap.mock.js +2 -2
- package/dist/src/infrastructure/projection/pricing/httpPricingByCheckoutIdView.js +2 -3
- package/dist/src/infrastructure/projection/pricing/pricing.mock.d.ts +3 -9
- package/dist/src/infrastructure/projection/pricing/pricing.mock.js +11 -50
- package/dist/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.d.ts +2 -2
- package/dist/src/infrastructure/tracking/useTrackCheckout.d.ts +2 -2
- package/dist/src/infrastructure/tracking/useTrackCheckout.js +3 -3
- package/dist/src/infrastructure/ui/components/atoms/price/Price.d.ts +7 -2
- package/dist/src/infrastructure/ui/components/atoms/price/Price.js +7 -7
- package/dist/src/infrastructure/ui/views/checkout/Checkout.js +2 -2
- package/dist/src/infrastructure/ui/views/item/components/productVariantDescription/ProductVariantDescription.js +1 -1
- package/dist/src/infrastructure/ui/views/item/components/productVariantSlider/ProductVariantSlider.js +2 -1
- package/dist/src/infrastructure/ui/views/item/components/productVariantSlider/components/aspectRatioView/AspectRatioView.d.ts +15 -0
- package/dist/src/infrastructure/ui/views/item/components/productVariantSlider/components/aspectRatioView/AspectRatioView.js +16 -0
- package/dist/src/infrastructure/ui/views/return/components/price/Price.d.ts +7 -2
- package/dist/src/infrastructure/ui/views/return/components/price/Price.js +7 -7
- package/dist/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.js +1 -1
- package/dist/src/infrastructure/ui/views/shared/components/productVariant/ProductVariant.js +1 -1
- package/dist/src/infrastructure/ui/views/summary/Summary.js +3 -3
- package/dist/src/infrastructure/ui/views/summary/components/collapsiblePricing/CollapsiblePricing.d.ts +2 -5
- package/dist/src/infrastructure/ui/views/summary/components/collapsiblePricing/CollapsiblePricing.js +4 -4
- package/dist/src/infrastructure/ui/views/summary/components/pricing/Pricing.d.ts +2 -5
- package/dist/src/infrastructure/ui/views/summary/components/pricing/Pricing.js +16 -18
- package/dist/src/projection/customer/customer.d.ts +0 -1
- package/dist/src/projection/pricing/pricing.d.ts +6 -24
- package/dist/src/projection/pricing/pricing.js +1 -1
- package/dist/src/projection/pricing/viewPricingByCheckoutId.d.ts +2 -2
- package/dist/src/version.d.ts +2 -2
- package/dist/src/version.js +2 -2
- package/package.json +1 -1
- package/src/ExpoRoot.tsx +2 -3
- package/src/infrastructure/delivery/bootstrap.mock.ts +2 -2
- package/src/infrastructure/projection/pricing/httpPricingByCheckoutIdView.test.ts +3 -7
- package/src/infrastructure/projection/pricing/httpPricingByCheckoutIdView.ts +3 -8
- package/src/infrastructure/projection/pricing/pricing.mock.ts +13 -61
- package/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.test.ts +3 -3
- package/src/infrastructure/projection/pricing/react/useViewPricingByCheckoutId.ts +2 -2
- package/src/infrastructure/tracking/useTrackCheckout.test.tsx +9 -9
- package/src/infrastructure/tracking/useTrackCheckout.ts +5 -5
- package/src/infrastructure/ui/components/atoms/price/Price.test.tsx +22 -4
- package/src/infrastructure/ui/components/atoms/price/Price.tsx +14 -9
- package/src/infrastructure/ui/hooks/useCheckoutFlow.test.tsx +2 -2
- package/src/infrastructure/ui/views/checkout/Checkout.test.tsx +4 -10
- package/src/infrastructure/ui/views/checkout/Checkout.tsx +2 -7
- package/src/infrastructure/ui/views/item/components/productVariantDescription/ProductVariantDescription.tsx +1 -1
- package/src/infrastructure/ui/views/item/components/productVariantSlider/ProductVariantSlider.tsx +1 -1
- package/src/infrastructure/ui/views/item/components/productVariantSlider/__snapshots__/ProductVariantSlider.test.tsx.snap +198 -192
- package/src/infrastructure/ui/views/item/components/productVariantSlider/components/aspectRatioView/AspectRatioView.tsx +46 -0
- package/src/infrastructure/ui/views/item/views/productVariant/__snapshots__/ProductVariant.test.tsx.snap +594 -576
- package/src/infrastructure/ui/views/return/components/price/Price.test.tsx +22 -4
- package/src/infrastructure/ui/views/return/components/price/Price.tsx +14 -9
- package/src/infrastructure/ui/views/return/components/productVariantPreview/ProductVariantPreview.tsx +6 -1
- package/src/infrastructure/ui/views/shared/components/productVariant/ProductVariant.tsx +6 -1
- package/src/infrastructure/ui/views/summary/Summary.test.tsx +4 -10
- package/src/infrastructure/ui/views/summary/Summary.tsx +1 -5
- package/src/infrastructure/ui/views/summary/components/collapsiblePricing/CollapsiblePricing.test.tsx +10 -24
- package/src/infrastructure/ui/views/summary/components/collapsiblePricing/CollapsiblePricing.tsx +5 -15
- package/src/infrastructure/ui/views/summary/components/collapsiblePricing/__snapshots__/CollapsiblePricing.test.tsx.snap +2 -2
- package/src/infrastructure/ui/views/summary/components/pricing/Pricing.tsx +42 -38
- package/src/projection/customer/customer.ts +0 -1
- package/src/projection/pricing/pricing.ts +6 -26
- package/src/projection/pricing/viewPricingByCheckoutId.test.ts +4 -5
- package/src/projection/pricing/viewPricingByCheckoutId.ts +2 -2
- package/dist/src/infrastructure/projection/pricing/pricing.d.ts +0 -18
- package/dist/src/infrastructure/projection/pricing/pricing.js +0 -12
- package/src/infrastructure/projection/pricing/pricing.ts +0 -32
|
@@ -20,19 +20,31 @@ const discountedPrice: PriceProjection = {
|
|
|
20
20
|
|
|
21
21
|
describe("Price atom", () => {
|
|
22
22
|
it("matches the snapshot for a non-discounted price", async () => {
|
|
23
|
-
const { toJSON } = render(<Price price={price} />);
|
|
23
|
+
const { toJSON } = render(<Price amount={price.amount} currency={price.currency} />);
|
|
24
24
|
|
|
25
25
|
expect(toJSON()).toMatchSnapshot("non-discounted price");
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
it("matches the snapshot for a discounted price", async () => {
|
|
29
|
-
const { toJSON } = render(
|
|
29
|
+
const { toJSON } = render(
|
|
30
|
+
<Price
|
|
31
|
+
amount={discountedPrice.amount}
|
|
32
|
+
currency={discountedPrice.currency}
|
|
33
|
+
discountedPrice={discountedPrice.discountedPrice}
|
|
34
|
+
/>,
|
|
35
|
+
);
|
|
30
36
|
|
|
31
37
|
expect(toJSON()).toMatchSnapshot("discounted price");
|
|
32
38
|
});
|
|
33
39
|
|
|
34
40
|
it("renders the non-discounted price text", async () => {
|
|
35
|
-
const { findByTestId } = render(
|
|
41
|
+
const { findByTestId } = render(
|
|
42
|
+
<Price
|
|
43
|
+
amount={discountedPrice.amount}
|
|
44
|
+
currency={discountedPrice.currency}
|
|
45
|
+
discountedPrice={discountedPrice.discountedPrice}
|
|
46
|
+
/>,
|
|
47
|
+
);
|
|
36
48
|
|
|
37
49
|
const priceText = await findByTestId("price-text");
|
|
38
50
|
|
|
@@ -40,7 +52,13 @@ describe("Price atom", () => {
|
|
|
40
52
|
});
|
|
41
53
|
|
|
42
54
|
it("renders the discounted price text", async () => {
|
|
43
|
-
const { findByTestId } = render(
|
|
55
|
+
const { findByTestId } = render(
|
|
56
|
+
<Price
|
|
57
|
+
amount={discountedPrice.amount}
|
|
58
|
+
currency={discountedPrice.currency}
|
|
59
|
+
discountedPrice={discountedPrice.discountedPrice}
|
|
60
|
+
/>,
|
|
61
|
+
);
|
|
44
62
|
|
|
45
63
|
const discountedPriceText = await findByTestId("discounted-price-text");
|
|
46
64
|
|
|
@@ -1,28 +1,33 @@
|
|
|
1
1
|
import React, { FC, useMemo } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { useI18nNumber } from "@lookiero/i18n-react";
|
|
4
|
+
import { Currency } from "@lookiero/sty-psp-locale";
|
|
4
5
|
import { Text } from "@lookiero/sty-psp-ui";
|
|
5
|
-
import { PriceProjection } from "../../../../../../projection/price/price";
|
|
6
6
|
import { DOMAIN } from "../../../../i18n/i18n";
|
|
7
7
|
import { style as priceStyle } from "./Price.style";
|
|
8
8
|
|
|
9
9
|
interface PriceProps {
|
|
10
|
-
readonly
|
|
10
|
+
readonly amount: number;
|
|
11
|
+
readonly currency: Currency;
|
|
12
|
+
readonly discountedPrice?: {
|
|
13
|
+
readonly amount: number;
|
|
14
|
+
readonly percentage: number;
|
|
15
|
+
};
|
|
11
16
|
readonly withPercentage?: boolean;
|
|
12
17
|
}
|
|
13
|
-
const Price: FC<PriceProps> = ({
|
|
14
|
-
const isDiscounted =
|
|
18
|
+
const Price: FC<PriceProps> = ({ amount, currency, discountedPrice, withPercentage = false }) => {
|
|
19
|
+
const isDiscounted = discountedPrice && discountedPrice.percentage > 0;
|
|
15
20
|
const productPrice = useI18nNumber({
|
|
16
21
|
domain: DOMAIN,
|
|
17
|
-
value:
|
|
22
|
+
value: amount / 100,
|
|
18
23
|
style: "currency",
|
|
19
|
-
currency
|
|
24
|
+
currency,
|
|
20
25
|
});
|
|
21
26
|
const productDiscountedPrice = useI18nNumber({
|
|
22
27
|
domain: DOMAIN,
|
|
23
|
-
value: (
|
|
28
|
+
value: (discountedPrice?.amount || 0) / 100,
|
|
24
29
|
style: "currency",
|
|
25
|
-
currency
|
|
30
|
+
currency,
|
|
26
31
|
});
|
|
27
32
|
|
|
28
33
|
const priceValue = isDiscounted ? productDiscountedPrice : productPrice;
|
|
@@ -42,7 +47,7 @@ const Price: FC<PriceProps> = ({ price, withPercentage = false }) => {
|
|
|
42
47
|
</Text>
|
|
43
48
|
{isDiscounted && withPercentage ? (
|
|
44
49
|
<Text level={1} style={style.discountedPercentage} testID="discounted-percentage-text" variant="detail">
|
|
45
|
-
{`-${
|
|
50
|
+
{`-${discountedPrice.percentage}%`}
|
|
46
51
|
</Text>
|
|
47
52
|
) : null}
|
|
48
53
|
</View>
|
|
@@ -63,7 +63,12 @@ const ProductVariantPreview: FC<ProductVariantPreviewProps> = ({ item, country }
|
|
|
63
63
|
</View>
|
|
64
64
|
|
|
65
65
|
<View style={style.price}>
|
|
66
|
-
<Price
|
|
66
|
+
<Price
|
|
67
|
+
amount={price.amount}
|
|
68
|
+
currency={price.currency}
|
|
69
|
+
discountedPrice={price.discountedPrice}
|
|
70
|
+
withPercentage
|
|
71
|
+
/>
|
|
67
72
|
</View>
|
|
68
73
|
</Column>
|
|
69
74
|
</Row>
|
|
@@ -88,7 +88,12 @@ const ProductVariant: FC<ProductVariantProps> = ({
|
|
|
88
88
|
)}
|
|
89
89
|
</View>
|
|
90
90
|
|
|
91
|
-
<Price
|
|
91
|
+
<Price
|
|
92
|
+
amount={price.amount}
|
|
93
|
+
currency={price.currency}
|
|
94
|
+
discountedPrice={price.discountedPrice}
|
|
95
|
+
variant="detail"
|
|
96
|
+
/>
|
|
92
97
|
</View>
|
|
93
98
|
</View>
|
|
94
99
|
|
|
@@ -11,7 +11,7 @@ import { Customer } from "../../../../projection/customer/customer";
|
|
|
11
11
|
import { checkout } from "../../../projection/checkout/checkout.mock";
|
|
12
12
|
import { useViewFirstAvailableCheckoutByCustomerId } from "../../../projection/checkout/react/useViewFirstAvailableCheckoutByCustomerId";
|
|
13
13
|
import { useViewFiveItemsDiscountByCustomerId } from "../../../projection/checkout/react/useViewFiveItemsDiscountByCustomerId";
|
|
14
|
-
import {
|
|
14
|
+
import { mockCheckoutPricingProjection } from "../../../projection/pricing/pricing.mock";
|
|
15
15
|
import { useViewPricingByCheckoutId } from "../../../projection/pricing/react/useViewPricingByCheckoutId";
|
|
16
16
|
import { I18nMessages } from "../../i18n/i18n";
|
|
17
17
|
import { render } from "../../test/render";
|
|
@@ -33,7 +33,6 @@ const mockCustomer: Customer = {
|
|
|
33
33
|
customerId,
|
|
34
34
|
country,
|
|
35
35
|
segment,
|
|
36
|
-
migrated: false,
|
|
37
36
|
} as Customer;
|
|
38
37
|
|
|
39
38
|
const mockTradename = Tradename.LOOKIERO;
|
|
@@ -74,7 +73,7 @@ afterAll(() => {
|
|
|
74
73
|
describe("Summary view", () => {
|
|
75
74
|
it("renders correctly", async () => {
|
|
76
75
|
(useViewFirstAvailableCheckoutByCustomerId as jest.Mock).mockReturnValue([checkoutMock, QueryStatus.SUCCESS]);
|
|
77
|
-
(useViewPricingByCheckoutId as jest.Mock).mockReturnValue([
|
|
76
|
+
(useViewPricingByCheckoutId as jest.Mock).mockReturnValue([mockCheckoutPricingProjection, QueryStatus.SUCCESS]);
|
|
78
77
|
(useViewFiveItemsDiscountByCustomerId as jest.Mock).mockReturnValue([fiveItemsDiscountMock, QueryStatus.SUCCESS]);
|
|
79
78
|
|
|
80
79
|
const { findByText, getByText, getByTestId } = render(
|
|
@@ -89,7 +88,7 @@ describe("Summary view", () => {
|
|
|
89
88
|
expect(mockUseNavigate).toHaveBeenCalledWith("tabs/keep", { replace: true });
|
|
90
89
|
|
|
91
90
|
expect(getByText(`${I18nMessages.SUMMARY_TOTAL} ${I18nMessages.SUMMARY_TOTAL_ITEMS_KEPT}`)).toBeTruthy();
|
|
92
|
-
expect(getByText("€
|
|
91
|
+
expect(getByText("€121.27")).toBeTruthy();
|
|
93
92
|
|
|
94
93
|
fireEvent.press(getByTestId("pricing-collapsed"));
|
|
95
94
|
expect(mockTrackPressPricing).toHaveBeenCalledWith({
|
|
@@ -97,16 +96,11 @@ describe("Summary view", () => {
|
|
|
97
96
|
});
|
|
98
97
|
|
|
99
98
|
expect(getByText(`${I18nMessages.SUMMARY_SUBTOTAL} ${I18nMessages.SUMMARY_TOTAL_ITEMS_KEPT}`)).toBeTruthy();
|
|
100
|
-
expect(getByText("€
|
|
99
|
+
expect(getByText("€211.95")).toBeTruthy();
|
|
101
100
|
|
|
102
101
|
expect(getByText(I18nMessages.SUMMARY_DISCOUNT)).toBeTruthy();
|
|
103
|
-
expect(getByText("-€25.00")).toBeTruthy();
|
|
104
|
-
|
|
105
102
|
expect(getByText(I18nMessages.SUMMARY_CREDIT)).toBeTruthy();
|
|
106
|
-
expect(getByText("-€20.00")).toBeTruthy();
|
|
107
|
-
|
|
108
103
|
expect(getByText(I18nMessages.SUMMARY_FEE)).toBeTruthy();
|
|
109
|
-
expect(getByText("-€10.00")).toBeTruthy();
|
|
110
104
|
|
|
111
105
|
fireEvent.press(getByText(I18nMessages.SUMMARY_SUBMIT_BUTTON));
|
|
112
106
|
expect(mockTrackPressContinue).toHaveBeenCalled();
|
|
@@ -28,7 +28,7 @@ interface SummaryProps {
|
|
|
28
28
|
|
|
29
29
|
const Summary: FC<SummaryProps> = ({ layout: Layout, children }) => {
|
|
30
30
|
const {
|
|
31
|
-
customer: { customerId, country, segment
|
|
31
|
+
customer: { customerId, country, segment },
|
|
32
32
|
basePath,
|
|
33
33
|
tradename,
|
|
34
34
|
} = useStaticInfo();
|
|
@@ -152,11 +152,9 @@ const Summary: FC<SummaryProps> = ({ layout: Layout, children }) => {
|
|
|
152
152
|
<CollapsiblePricing
|
|
153
153
|
collapsed={false}
|
|
154
154
|
collapsible={false}
|
|
155
|
-
migrated={migrated}
|
|
156
155
|
pricing={pricing}
|
|
157
156
|
submitButtonText={submitButtonText}
|
|
158
157
|
totalCheckoutItemsKept={totalCheckoutItemsKept}
|
|
159
|
-
tradename={tradename}
|
|
160
158
|
onSubmit={handleOnSubmit}
|
|
161
159
|
/>
|
|
162
160
|
</View>
|
|
@@ -170,11 +168,9 @@ const Summary: FC<SummaryProps> = ({ layout: Layout, children }) => {
|
|
|
170
168
|
<Body>
|
|
171
169
|
<CollapsiblePricing
|
|
172
170
|
collapsed={pricingCollapsed}
|
|
173
|
-
migrated={migrated}
|
|
174
171
|
pricing={pricing}
|
|
175
172
|
submitButtonText={submitButtonText}
|
|
176
173
|
totalCheckoutItemsKept={totalCheckoutItemsKept}
|
|
177
|
-
tradename={tradename}
|
|
178
174
|
onPress={handleOnPressPricing}
|
|
179
175
|
onSubmit={handleOnSubmit}
|
|
180
176
|
/>
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { RenderResult, fireEvent } from "@testing-library/react-native";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { pricing as pricingFunction } from "../../../../../projection/pricing/pricing.mock";
|
|
3
|
+
import { CheckoutPricingProjection } from "../../../../../../projection/pricing/pricing";
|
|
4
|
+
import { mockCheckoutPricingProjection } from "../../../../../projection/pricing/pricing.mock";
|
|
6
5
|
import { I18nMessages } from "../../../../i18n/i18n";
|
|
7
6
|
import { render } from "../../../../test/render";
|
|
8
7
|
import { CollapsiblePricing } from "./CollapsiblePricing";
|
|
@@ -13,7 +12,7 @@ const mockOnSubmit = jest.fn();
|
|
|
13
12
|
interface RenderPricingFunctionArgs {
|
|
14
13
|
readonly collapsed?: boolean;
|
|
15
14
|
readonly collapsible?: boolean;
|
|
16
|
-
readonly pricing?:
|
|
15
|
+
readonly pricing?: CheckoutPricingProjection;
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
interface RenderPricingFunction {
|
|
@@ -23,17 +22,15 @@ interface RenderPricingFunction {
|
|
|
23
22
|
const renderPricing: RenderPricingFunction = ({
|
|
24
23
|
collapsed = true,
|
|
25
24
|
collapsible = true,
|
|
26
|
-
pricing =
|
|
25
|
+
pricing = mockCheckoutPricingProjection,
|
|
27
26
|
} = {}) =>
|
|
28
27
|
render(
|
|
29
28
|
<CollapsiblePricing
|
|
30
29
|
collapsed={collapsed}
|
|
31
30
|
collapsible={collapsible}
|
|
32
|
-
migrated={false}
|
|
33
31
|
pricing={pricing}
|
|
34
32
|
submitButtonText={I18nMessages.SUMMARY_SUBMIT_BUTTON}
|
|
35
33
|
totalCheckoutItemsKept={3}
|
|
36
|
-
tradename={Tradename.LOOKIERO}
|
|
37
34
|
onPress={mockOnPress}
|
|
38
35
|
onSubmit={mockOnSubmit}
|
|
39
36
|
/>,
|
|
@@ -58,7 +55,7 @@ describe("Pricing component", () => {
|
|
|
58
55
|
// expect(getByTestId("arrow-up")).toBeTruthy();
|
|
59
56
|
|
|
60
57
|
expect(getByText(`${I18nMessages.SUMMARY_TOTAL} ${I18nMessages.SUMMARY_TOTAL_ITEMS_KEPT}`)).toBeTruthy();
|
|
61
|
-
expect(getByText("€
|
|
58
|
+
expect(getByText("€121.27")).toBeTruthy();
|
|
62
59
|
|
|
63
60
|
fireEvent.press(getByTestId("pricing-collapsed"));
|
|
64
61
|
expect(mockOnPress).toHaveBeenCalled();
|
|
@@ -73,19 +70,14 @@ describe("Pricing component", () => {
|
|
|
73
70
|
// expect(getByTestId("arrow-down")).toBeTruthy();
|
|
74
71
|
|
|
75
72
|
expect(getByText(`${I18nMessages.SUMMARY_SUBTOTAL} ${I18nMessages.SUMMARY_TOTAL_ITEMS_KEPT}`)).toBeTruthy();
|
|
76
|
-
expect(getByText("€
|
|
73
|
+
expect(getByText("€211.95")).toBeTruthy();
|
|
77
74
|
|
|
78
75
|
expect(getByText(I18nMessages.SUMMARY_DISCOUNT)).toBeTruthy();
|
|
79
|
-
expect(getByText("-€25.00")).toBeTruthy();
|
|
80
|
-
|
|
81
76
|
expect(getByText(I18nMessages.SUMMARY_CREDIT)).toBeTruthy();
|
|
82
|
-
expect(getByText("-€20.00")).toBeTruthy();
|
|
83
|
-
|
|
84
77
|
expect(getByText(I18nMessages.SUMMARY_FEE)).toBeTruthy();
|
|
85
|
-
expect(getByText("-€10.00")).toBeTruthy();
|
|
86
78
|
|
|
87
79
|
expect(getByText(I18nMessages.SUMMARY_TOTAL)).toBeTruthy();
|
|
88
|
-
expect(getByText("€
|
|
80
|
+
expect(getByText("€121.27")).toBeTruthy();
|
|
89
81
|
|
|
90
82
|
fireEvent.press(getByTestId("pricing-collapsed"));
|
|
91
83
|
expect(mockOnPress).toHaveBeenCalled();
|
|
@@ -94,18 +86,12 @@ describe("Pricing component", () => {
|
|
|
94
86
|
expect(mockOnSubmit).toHaveBeenCalled();
|
|
95
87
|
});
|
|
96
88
|
|
|
97
|
-
it("renders correctly
|
|
98
|
-
const { getByText } = renderPricing({ collapsed: false, pricing: pricingFunction({ paidWithPromocode: true }) });
|
|
99
|
-
|
|
100
|
-
expect(getByText(I18nMessages.SUMMARY_FEE)).toBeTruthy();
|
|
101
|
-
expect(getByText(I18nMessages.SUMMARY_FREE)).toBeTruthy();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("renders correctly for a NON paidWithPromocode service", () => {
|
|
89
|
+
it("renders correctly with modifiers", () => {
|
|
105
90
|
const { getByText } = renderPricing({ collapsed: false });
|
|
106
91
|
|
|
92
|
+
expect(getByText(I18nMessages.SUMMARY_DISCOUNT)).toBeTruthy();
|
|
93
|
+
expect(getByText(I18nMessages.SUMMARY_CREDIT)).toBeTruthy();
|
|
107
94
|
expect(getByText(I18nMessages.SUMMARY_FEE)).toBeTruthy();
|
|
108
|
-
expect(getByText("-€10.00")).toBeTruthy();
|
|
109
95
|
});
|
|
110
96
|
|
|
111
97
|
it.skip("renders correctly for non-collapsible pricing", () => {
|
package/src/infrastructure/ui/views/summary/components/collapsiblePricing/CollapsiblePricing.tsx
CHANGED
|
@@ -3,17 +3,14 @@ import { Pressable, View } from "react-native";
|
|
|
3
3
|
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from "react-native-reanimated";
|
|
4
4
|
import { useI18nMessage } from "@lookiero/i18n-react";
|
|
5
5
|
import { Button, Icon, Text } from "@lookiero/sty-psp-ui";
|
|
6
|
-
import {
|
|
7
|
-
import { PricingProjection } from "../../../../../../projection/pricing/pricing";
|
|
6
|
+
import { CheckoutPricingProjection } from "../../../../../../projection/pricing/pricing";
|
|
8
7
|
import { Price } from "../../../../components/atoms/price/Price";
|
|
9
8
|
import { DOMAIN, I18nMessages } from "../../../../i18n/i18n";
|
|
10
9
|
import { Pricing } from "../pricing/Pricing";
|
|
11
10
|
import { style as collapsiblePricingStyle } from "./CollapsiblePricing.style";
|
|
12
11
|
|
|
13
12
|
interface CollapsiblePricingProps {
|
|
14
|
-
readonly
|
|
15
|
-
readonly migrated: boolean;
|
|
16
|
-
readonly pricing: PricingProjection;
|
|
13
|
+
readonly pricing: CheckoutPricingProjection;
|
|
17
14
|
readonly totalCheckoutItemsKept: number;
|
|
18
15
|
readonly collapsible?: boolean;
|
|
19
16
|
readonly collapsed?: boolean;
|
|
@@ -22,8 +19,6 @@ interface CollapsiblePricingProps {
|
|
|
22
19
|
readonly onSubmit: () => void;
|
|
23
20
|
}
|
|
24
21
|
const CollapsiblePricing: FC<CollapsiblePricingProps> = ({
|
|
25
|
-
migrated,
|
|
26
|
-
tradename,
|
|
27
22
|
pricing,
|
|
28
23
|
totalCheckoutItemsKept,
|
|
29
24
|
collapsible = true,
|
|
@@ -32,7 +27,7 @@ const CollapsiblePricing: FC<CollapsiblePricingProps> = ({
|
|
|
32
27
|
onPress = () => void 0,
|
|
33
28
|
onSubmit,
|
|
34
29
|
}) => {
|
|
35
|
-
const {
|
|
30
|
+
const { finalPrice, currency } = pricing;
|
|
36
31
|
|
|
37
32
|
const totalText = useI18nMessage({ domain: DOMAIN, id: I18nMessages.SUMMARY_TOTAL });
|
|
38
33
|
const totalCheckoutItemsKeptText = useI18nMessage({
|
|
@@ -74,7 +69,7 @@ const CollapsiblePricing: FC<CollapsiblePricingProps> = ({
|
|
|
74
69
|
<Text level={1} style={style.totalCollapsed} variant="detail">
|
|
75
70
|
{totalText} {totalCheckoutItemsKeptText}
|
|
76
71
|
</Text>
|
|
77
|
-
<Price
|
|
72
|
+
<Price amount={finalPrice} currency={currency} variant="detail" />
|
|
78
73
|
</View>
|
|
79
74
|
|
|
80
75
|
<View style={style.collapsedContent}>
|
|
@@ -85,12 +80,7 @@ const CollapsiblePricing: FC<CollapsiblePricingProps> = ({
|
|
|
85
80
|
</Animated.View>
|
|
86
81
|
) : (
|
|
87
82
|
<Animated.View key="not-collapsed" style={notCollapsedAnimatedStyle}>
|
|
88
|
-
<Pricing
|
|
89
|
-
migrated={migrated}
|
|
90
|
-
pricing={pricing}
|
|
91
|
-
totalCheckoutItemsKept={totalCheckoutItemsKept}
|
|
92
|
-
tradename={tradename}
|
|
93
|
-
/>
|
|
83
|
+
<Pricing pricing={pricing} totalCheckoutItemsKept={totalCheckoutItemsKept} />
|
|
94
84
|
|
|
95
85
|
<Button testID="submit-checkout-button" onPress={onSubmit}>
|
|
96
86
|
{submitButtonText}
|
|
@@ -172,7 +172,7 @@ exports[`Pricing component matches the snapshot for collaped pricing: collapsed
|
|
|
172
172
|
}
|
|
173
173
|
testID="price-text"
|
|
174
174
|
>
|
|
175
|
-
€
|
|
175
|
+
€121.27
|
|
176
176
|
</Text>
|
|
177
177
|
</View>
|
|
178
178
|
</View>
|
|
@@ -484,7 +484,7 @@ exports[`Pricing component matches the snapshot for non-collaped pricing: non-co
|
|
|
484
484
|
}
|
|
485
485
|
testID="price-text"
|
|
486
486
|
>
|
|
487
|
-
€
|
|
487
|
+
€121.27
|
|
488
488
|
</Text>
|
|
489
489
|
</View>
|
|
490
490
|
</View>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React, { FC, ReactNode, useMemo } from "react";
|
|
2
2
|
import { View } from "react-native";
|
|
3
3
|
import { useI18nMessage } from "@lookiero/i18n-react";
|
|
4
|
+
import { Currency } from "@lookiero/sty-psp-locale";
|
|
4
5
|
import { Text } from "@lookiero/sty-psp-ui";
|
|
5
|
-
import {
|
|
6
|
-
import { PricingProjection } from "../../../../../../projection/pricing/pricing";
|
|
6
|
+
import { CheckoutPricingProjection, CheckoutPricingType } from "../../../../../../projection/pricing/pricing";
|
|
7
7
|
import { Price } from "../../../../components/atoms/price/Price";
|
|
8
8
|
import { DOMAIN, I18nMessages } from "../../../../i18n/i18n";
|
|
9
9
|
import { style as pricingStyle } from "./Pricing.style";
|
|
@@ -26,15 +26,38 @@ const Row: FC<RowProps> = ({ action = false, text, level = 3, children }) => {
|
|
|
26
26
|
</View>
|
|
27
27
|
);
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
interface ModifierRowProps {
|
|
31
|
+
readonly translationKey: string;
|
|
32
|
+
readonly amount: number;
|
|
33
|
+
readonly percentage?: number;
|
|
34
|
+
readonly type: CheckoutPricingType;
|
|
35
|
+
readonly currency: Currency;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const ModifierRow: FC<ModifierRowProps> = ({ translationKey, amount, percentage, currency, type }) => {
|
|
39
|
+
const modifierText = useI18nMessage({
|
|
40
|
+
domain: DOMAIN,
|
|
41
|
+
id: translationKey,
|
|
42
|
+
values: percentage ? { discount: percentage.toString() } : undefined,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const displayAmount = type === CheckoutPricingType.DISCOUNT ? -amount : amount;
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Row text={modifierText}>
|
|
49
|
+
<Price amount={displayAmount} currency={currency} variant="subtotal" />
|
|
50
|
+
</Row>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
29
54
|
interface PricingProps {
|
|
30
|
-
readonly pricing:
|
|
55
|
+
readonly pricing: CheckoutPricingProjection;
|
|
31
56
|
readonly totalCheckoutItemsKept: number;
|
|
32
|
-
readonly tradename: Tradename;
|
|
33
|
-
readonly migrated: boolean;
|
|
34
57
|
}
|
|
35
58
|
|
|
36
|
-
const Pricing: FC<PricingProps> = ({ pricing, totalCheckoutItemsKept
|
|
37
|
-
const {
|
|
59
|
+
const Pricing: FC<PricingProps> = ({ pricing, totalCheckoutItemsKept }) => {
|
|
60
|
+
const { originalPrice, finalPrice, modifiers, currency } = pricing;
|
|
38
61
|
|
|
39
62
|
const style = useMemo(() => pricingStyle(), []);
|
|
40
63
|
|
|
@@ -45,47 +68,28 @@ const Pricing: FC<PricingProps> = ({ pricing, totalCheckoutItemsKept, tradename,
|
|
|
45
68
|
values: { items: totalCheckoutItemsKept.toString() },
|
|
46
69
|
});
|
|
47
70
|
const subtotalText = useI18nMessage({ domain: DOMAIN, id: I18nMessages.SUMMARY_SUBTOTAL });
|
|
48
|
-
const freeText = useI18nMessage({ domain: DOMAIN, id: I18nMessages.SUMMARY_FREE });
|
|
49
|
-
const discountText = useI18nMessage({
|
|
50
|
-
domain: DOMAIN,
|
|
51
|
-
id: I18nMessages.SUMMARY_DISCOUNT,
|
|
52
|
-
values: { discount: discountPercentage?.toString() },
|
|
53
|
-
});
|
|
54
|
-
const creditText = useI18nMessage({ domain: DOMAIN, id: I18nMessages.SUMMARY_CREDIT });
|
|
55
|
-
const feeText = useI18nMessage({ domain: DOMAIN, id: I18nMessages.SUMMARY_FEE });
|
|
56
71
|
|
|
57
72
|
return (
|
|
58
73
|
<View>
|
|
59
74
|
<Row text={`${subtotalText} ${totalCheckoutItemsKeptText}`}>
|
|
60
|
-
<Price
|
|
75
|
+
<Price amount={originalPrice} currency={currency} variant="subtotal" />
|
|
61
76
|
</Row>
|
|
62
77
|
|
|
63
|
-
{
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
)}
|
|
74
|
-
|
|
75
|
-
{(tradename === Tradename.LOOKIERO || (tradename === Tradename.OUTFITTERY && !migrated)) && (
|
|
76
|
-
<Row text={feeText}>
|
|
77
|
-
{service.paidWithPromocode ? (
|
|
78
|
-
<Text level={3}>{freeText}</Text>
|
|
79
|
-
) : (
|
|
80
|
-
<Price price={service.finalPrice} variant="subtotal" />
|
|
81
|
-
)}
|
|
82
|
-
</Row>
|
|
83
|
-
)}
|
|
78
|
+
{modifiers.map((modifier, index) => (
|
|
79
|
+
<ModifierRow
|
|
80
|
+
key={`modifier-${index}`}
|
|
81
|
+
amount={modifier.amount}
|
|
82
|
+
currency={currency}
|
|
83
|
+
percentage={modifier.percentage}
|
|
84
|
+
translationKey={modifier.translationKey}
|
|
85
|
+
type={modifier.type}
|
|
86
|
+
/>
|
|
87
|
+
))}
|
|
84
88
|
|
|
85
89
|
<View style={style.divider} />
|
|
86
90
|
|
|
87
91
|
<Row level={2} text={totalText} action>
|
|
88
|
-
<Price
|
|
92
|
+
<Price amount={finalPrice} currency={currency} variant="total" />
|
|
89
93
|
</Row>
|
|
90
94
|
</View>
|
|
91
95
|
);
|
|
@@ -1,24 +1,4 @@
|
|
|
1
1
|
import { Currency } from "@lookiero/sty-psp-locale";
|
|
2
|
-
import { PriceProjection } from "../price/price";
|
|
3
|
-
|
|
4
|
-
interface ServiceProjection {
|
|
5
|
-
readonly discount: PriceProjection;
|
|
6
|
-
readonly finalPrice: PriceProjection;
|
|
7
|
-
readonly originalPrice: PriceProjection;
|
|
8
|
-
readonly prepaid: boolean;
|
|
9
|
-
readonly reference: string;
|
|
10
|
-
readonly paidWithPromocode?: boolean;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
interface PricingProjection {
|
|
14
|
-
readonly balanceDiscount: PriceProjection;
|
|
15
|
-
readonly discount: PriceProjection;
|
|
16
|
-
readonly discountPercentage: number;
|
|
17
|
-
readonly orderTotal: PriceProjection;
|
|
18
|
-
readonly pendingToPay: PriceProjection;
|
|
19
|
-
readonly service: ServiceProjection;
|
|
20
|
-
readonly subtotal: PriceProjection;
|
|
21
|
-
}
|
|
22
2
|
|
|
23
3
|
enum Type {
|
|
24
4
|
DISCOUNT = "DISCOUNT",
|
|
@@ -31,7 +11,7 @@ enum Context {
|
|
|
31
11
|
BALANCE = "BALANCE",
|
|
32
12
|
}
|
|
33
13
|
|
|
34
|
-
interface
|
|
14
|
+
interface Modifier {
|
|
35
15
|
readonly amount: number;
|
|
36
16
|
readonly percentage?: number;
|
|
37
17
|
readonly type: Type;
|
|
@@ -41,10 +21,10 @@ interface Modify {
|
|
|
41
21
|
|
|
42
22
|
interface CheckoutPricingProjection {
|
|
43
23
|
readonly currency: Currency;
|
|
44
|
-
readonly
|
|
45
|
-
readonly
|
|
46
|
-
readonly modifiers:
|
|
24
|
+
readonly finalPrice: number; // total a pagar
|
|
25
|
+
readonly originalPrice: number; // precio original de la caja
|
|
26
|
+
readonly modifiers: Modifier[];
|
|
47
27
|
}
|
|
48
28
|
|
|
49
|
-
export type {
|
|
50
|
-
export { Type as
|
|
29
|
+
export type { CheckoutPricingProjection };
|
|
30
|
+
export { Type as CheckoutPricingType, Context as CheckoutPricingContext };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mock } from "jest-mock-extended";
|
|
2
2
|
import { QueryBus } from "@lookiero/messaging";
|
|
3
|
-
import {
|
|
3
|
+
import { mockCheckoutPricingProjection } from "../../infrastructure/projection/pricing/pricing.mock";
|
|
4
4
|
import { viewPricingByCheckoutId, viewPricingByCheckoutIdHandler as sut } from "./viewPricingByCheckoutId";
|
|
5
5
|
|
|
6
6
|
const checkoutId = "29790d24-b139-4ab8-b618-d796d101e974";
|
|
@@ -8,10 +8,9 @@ const queryBus = mock<QueryBus>();
|
|
|
8
8
|
const signal = mock<AbortSignal>();
|
|
9
9
|
|
|
10
10
|
describe("viewPricingByCheckoutId", () => {
|
|
11
|
-
it("returns checkout
|
|
12
|
-
const aPricing = pricing();
|
|
11
|
+
it("returns checkout pricing for checkout item", async () => {
|
|
13
12
|
const query = viewPricingByCheckoutId({ checkoutId });
|
|
14
|
-
const view = jest.fn(() => Promise.resolve(
|
|
13
|
+
const view = jest.fn(() => Promise.resolve(mockCheckoutPricingProjection));
|
|
15
14
|
|
|
16
15
|
const pricingProjectionResult = await sut({
|
|
17
16
|
view,
|
|
@@ -19,6 +18,6 @@ describe("viewPricingByCheckoutId", () => {
|
|
|
19
18
|
signal,
|
|
20
19
|
})(query);
|
|
21
20
|
|
|
22
|
-
expect(pricingProjectionResult).toBe(
|
|
21
|
+
expect(pricingProjectionResult).toBe(mockCheckoutPricingProjection);
|
|
23
22
|
});
|
|
24
23
|
});
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
QueryHandlerFunction,
|
|
6
6
|
QueryHandlerFunctionArgs,
|
|
7
7
|
} from "@lookiero/messaging";
|
|
8
|
-
import {
|
|
8
|
+
import { CheckoutPricingProjection } from "./pricing";
|
|
9
9
|
|
|
10
10
|
const VIEW_PRICING_BY_CHECKOUT_ID = "view_pricing_by_checkout_id";
|
|
11
11
|
|
|
@@ -24,7 +24,7 @@ const viewPricingByCheckoutId: ViewPricingByCheckoutIdFunction = (payload) => ({
|
|
|
24
24
|
...payload,
|
|
25
25
|
});
|
|
26
26
|
|
|
27
|
-
type ViewPricingByCheckoutIdResult =
|
|
27
|
+
type ViewPricingByCheckoutIdResult = CheckoutPricingProjection | null;
|
|
28
28
|
|
|
29
29
|
interface PricingByCheckoutIdViewArgs extends CancelableQueryViewArgs {
|
|
30
30
|
readonly checkoutId: string;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { PriceProjection } from "../../../projection/price/price";
|
|
2
|
-
import { PricingProjection, ServiceProjection } from "../../../projection/pricing/pricing";
|
|
3
|
-
interface PricingDto {
|
|
4
|
-
readonly balanceDiscount: PriceProjection;
|
|
5
|
-
readonly discount: PriceProjection;
|
|
6
|
-
readonly discountPercentage: number;
|
|
7
|
-
readonly orderTotal: PriceProjection;
|
|
8
|
-
readonly pendingToPay: PriceProjection;
|
|
9
|
-
readonly service: ServiceProjection;
|
|
10
|
-
readonly subtotal: PriceProjection;
|
|
11
|
-
readonly paidWithPromocode?: boolean;
|
|
12
|
-
}
|
|
13
|
-
interface ToPricingProjectionFunction {
|
|
14
|
-
(pricingDto: PricingDto): PricingProjection;
|
|
15
|
-
}
|
|
16
|
-
declare const toPricingProjection: ToPricingProjectionFunction;
|
|
17
|
-
export type { PricingDto };
|
|
18
|
-
export { toPricingProjection };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const toPricingProjection = (pricingDto) => ({
|
|
2
|
-
...pricingDto,
|
|
3
|
-
discount: {
|
|
4
|
-
...pricingDto.discount,
|
|
5
|
-
amount: -Math.abs(pricingDto.discount.amount),
|
|
6
|
-
},
|
|
7
|
-
balanceDiscount: {
|
|
8
|
-
...pricingDto.balanceDiscount,
|
|
9
|
-
amount: -Math.abs(pricingDto.balanceDiscount.amount),
|
|
10
|
-
},
|
|
11
|
-
});
|
|
12
|
-
export { toPricingProjection };
|