@evenicanpm/storefront-core 2.4.1 → 2.5.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/CHANGELOG.md +16 -0
- package/package.json +1 -1
- package/src/api-manager/datasources/d365/d365-cart.datasource.ts +4 -3
- package/src/api-manager/datasources/d365/d365-user.datasource.ts +3 -3
- package/src/api-manager/datasources/d365/utils/get-context-cookie.ts +1 -0
- package/src/api-manager/datasources/e4/address/e4-address.datasource.ts +5 -14
- package/src/api-manager/datasources/e4/address/e4-address.translator.ts +4 -3
- package/src/api-manager/datasources/e4/categories/e4-categories.translator.ts +1 -1
- package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +29 -3
- package/src/api-manager/datasources/e4/product/e4-product.translator.ts +1 -1
- package/src/api-manager/index.ts +1 -1
- package/src/api-manager/lib/get-graphql-client.ts +1 -1
- package/src/api-manager/services/cart/mutations/add-discount-code.ts +0 -11
- package/src/api-manager/services/create-query.ts +13 -7
- package/src/api-manager/services/user/mutations/add-to-wishlist.ts +1 -1
- package/src/api-manager/services/user/mutations/remove-from-wishlist.ts +1 -1
- package/src/auth/AUTH GUIDE.md +880 -0
- package/src/cms/blocks/components/featured-categories.tsx +18 -15
- package/src/cms/blocks/components/featured-products.tsx +3 -2
- package/src/cms/blocks/components/footer/sections/footer-contact.tsx +0 -2
- package/src/cms/blocks/components/footer/sections/footer-logo.tsx +2 -1
- package/src/components/SearchInput.stories.tsx +12 -10
- package/src/components/base-layout.tsx +42 -0
- package/src/components/categories/category-list/category-list.tsx +32 -12
- package/src/components/header/__tests__/header.test.tsx +0 -24
- package/src/components/header/components/mobile-header.tsx +16 -8
- package/src/components/header/header.tsx +6 -3
- package/src/components/mini-cart/components/bottom-actions.tsx +7 -2
- package/src/components/mini-cart/components/cart-item.tsx +16 -13
- package/src/components/mini-cart/components/empty-view.tsx +12 -6
- package/src/components/mini-cart/components/top-header.tsx +9 -8
- package/src/components/mini-cart/mini-cart-trigger.tsx +11 -5
- package/src/components/mini-cart/mini-cart.tsx +30 -15
- package/src/components/mobile-navigation/mobile-navigation-bar.tsx +6 -2
- package/src/components/navbar/categories.tsx +8 -2
- package/src/components/navbar/category-based-menu/category-based-menu.tsx +6 -2
- package/src/components/navbar/mega-menu/mega-menu.tsx +22 -14
- package/src/components/navbar/mobile-menu/mobile-menu.test.tsx +8 -11
- package/src/components/navbar/mobile-menu/mobile-menu.tsx +13 -11
- package/src/components/navbar/nav-list/nav-list.tsx +3 -2
- package/src/components/navbar/navbar.tsx +4 -2
- package/src/components/product-cards/product-card/product-card.tsx +50 -26
- package/src/components/product-cards/product-card-plp/product-card.tsx +37 -16
- package/src/components/product-cards/product-card-plp-list/product-card.tsx +38 -16
- package/src/components/product-cards/product-card-search/product-card.tsx +34 -13
- package/src/components/product-dialog/ProductDialog.stories.tsx +20 -18
- package/src/components/product-dialog/compound/product-dialog.tsx +7 -4
- package/src/components/product-dimensions/compound/dimensions-group.tsx +4 -2
- package/src/components/product-dimensions/compound/dimensions.tsx +15 -6
- package/src/components/product-quantity-buttons/compound/quantity-buttons-root.tsx +21 -13
- package/src/components/products-view/compound/products-grid-view.tsx +11 -4
- package/src/components/products-view/compound/products-list-view.tsx +11 -4
- package/src/components/search-bar/compound/search-bar-root.tsx +6 -4
- package/src/components/search-bar/compound/textfield-adornment-category.tsx +25 -8
- package/src/components/search-bar/hooks/use-click-outside.ts +7 -1
- package/src/components/search-bar/hooks/use-search.ts +3 -3
- package/src/components/user/index.ts +3 -0
- package/src/components/user/use-user-auth.ts +163 -0
- package/src/components/user/user.tsx +215 -0
- package/src/components/wishlist-dialogs/add-to-wishlist/AddToWishlist.stories.tsx +20 -15
- package/src/components/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +11 -8
- package/src/components/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +18 -3
- package/src/components/wishlist-dialogs/add-to-wishlist/index.tsx +0 -1
- package/src/components/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +6 -2
- package/src/hooks/use-overflow-detect.ts +4 -4
- package/src/lib/page-slugs.ts +16 -0
- package/src/pages/account/account-navigation.tsx +7 -14
- package/src/pages/account/account-routes.ts +4 -9
- package/src/pages/account/addresses/address-form.tsx +38 -16
- package/src/pages/account/addresses/address-item.tsx +18 -8
- package/src/pages/account/dashboard-header.tsx +20 -13
- package/src/pages/account/orders/order-history-filters-panel.tsx +21 -20
- package/src/pages/account/orders/order-history-header.tsx +14 -4
- package/src/pages/account/orders/order-history-root.tsx +3 -1
- package/src/pages/account/orders/order-history-row.tsx +12 -4
- package/src/pages/account/orders/order-history-search-and-filter.tsx +88 -59
- package/src/pages/account/orders/order-history-search-dropdown.tsx +26 -9
- package/src/pages/account/orders/order-history-sort.tsx +3 -1
- package/src/pages/account/orders/order-history-table.tsx +27 -5
- package/src/pages/account/orders/order-progress.tsx +12 -6
- package/src/pages/account/orders/order-row.tsx +18 -6
- package/src/pages/account/orders/order-summary.tsx +24 -8
- package/src/pages/account/orders/ordered-products.tsx +15 -5
- package/src/pages/account/profile/user-info.tsx +11 -3
- package/src/pages/account/table-row-skeleton.tsx +1 -1
- package/src/pages/account/wishlist/create-new-list.tsx +33 -9
- package/src/pages/account/wishlist/wishlist-item.tsx +18 -6
- package/src/pages/cart/cart-item.tsx +21 -7
- package/src/pages/cart/checkout-form.tsx +55 -22
- package/src/pages/cart/coupon-entry.tsx +143 -36
- package/src/pages/cart/estimate-shipping.tsx +45 -21
- package/src/pages/checkout/checkout-alt-form/checkout-form.tsx +22 -14
- package/src/pages/checkout/checkout-alt-form/checkout-step.tsx +37 -16
- package/src/pages/checkout/checkout-alt-form/steps/address/address-card.tsx +9 -3
- package/src/pages/checkout/checkout-alt-form/steps/address/delivery-address.tsx +84 -51
- package/src/pages/checkout/checkout-alt-form/steps/address/new-address-form.tsx +41 -19
- package/src/pages/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx +17 -10
- package/src/pages/checkout/checkout-alt-form/steps/payment/payment-details.tsx +15 -6
- package/src/pages/checkout/checkout-alt-form/steps/shipping/delivery-options.tsx +6 -2
- package/src/pages/checkout/checkout-alt-summary/cart-item.tsx +12 -4
- package/src/pages/checkout/checkout-alt-summary/checkout-alt-summary.tsx +12 -5
- package/src/pages/checkout/checkout-alt-summary/list-item.tsx +17 -10
- package/src/pages/confirmation/address.tsx +6 -2
- package/src/pages/confirmation/confirmation-summary.tsx +12 -4
- package/src/pages/confirmation/ordered-products.tsx +12 -4
- package/src/pages/product-details/bopis/store-card/shop-card.tsx +2 -2
- package/src/pages/product-details/bopis/store-card/utils/getDaysResources.ts +1 -1
- package/src/pages/product-details/product-intro/compound/product-info.tsx +41 -18
- package/src/pages/product-details/product-intro/compound/product-intro-images.tsx +18 -12
- package/src/pages/product-details/product-intro/compound/product-intro.tsx +20 -10
- package/src/pages/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +1 -1
- package/src/pages/product-details/product-tabs.tsx +20 -12
- package/src/pages/product-list/product-list-view.tsx +4 -2
- package/src/pages/product-list/search-bar.tsx +7 -7
- package/src/pages/product-list/side-nav.tsx +5 -3
- package/src/pages/quickorder/order-upload.tsx +1 -1
- package/src/pages/quickorder/provider.tsx +26 -14
- package/src/pages/quickorder/quick-order.tsx +49 -22
- package/src/providers/nav-provider/index.tsx +16 -11
- package/tsconfig.json +0 -5
- package/src/components/header/components/user.tsx +0 -322
- /package/src/components/{header → user}/__tests__/user.test.tsx +0 -0
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from "@mui/material";
|
|
21
21
|
import { useTranslations } from "next-intl";
|
|
22
22
|
import type React from "react";
|
|
23
|
-
import { createContext, useContext, useEffect, useState } from "react";
|
|
23
|
+
import { createContext, useContext, useEffect, useMemo, useState } from "react";
|
|
24
24
|
|
|
25
25
|
interface EstimateShippingContextValue {
|
|
26
26
|
selectedCountry: CountryRegionInfo | null;
|
|
@@ -102,23 +102,37 @@ const EstimateShipping = ({
|
|
|
102
102
|
setNoOptionsFound(true);
|
|
103
103
|
}
|
|
104
104
|
};
|
|
105
|
+
const contextValue = useMemo(
|
|
106
|
+
() => ({
|
|
107
|
+
selectedCountry,
|
|
108
|
+
setSelectedCountry,
|
|
109
|
+
selectedState,
|
|
110
|
+
setSelectedState,
|
|
111
|
+
zipCode,
|
|
112
|
+
setZipCode,
|
|
113
|
+
deliveryOptions,
|
|
114
|
+
noOptionsFound,
|
|
115
|
+
doDeliveryMethodLookup,
|
|
116
|
+
countries,
|
|
117
|
+
states,
|
|
118
|
+
}),
|
|
119
|
+
[
|
|
120
|
+
selectedCountry,
|
|
121
|
+
setSelectedCountry,
|
|
122
|
+
selectedState,
|
|
123
|
+
setSelectedState,
|
|
124
|
+
zipCode,
|
|
125
|
+
setZipCode,
|
|
126
|
+
deliveryOptions,
|
|
127
|
+
noOptionsFound,
|
|
128
|
+
doDeliveryMethodLookup,
|
|
129
|
+
countries,
|
|
130
|
+
states,
|
|
131
|
+
],
|
|
132
|
+
);
|
|
105
133
|
|
|
106
134
|
return (
|
|
107
|
-
<EstimateShippingContext.Provider
|
|
108
|
-
value={{
|
|
109
|
-
selectedCountry,
|
|
110
|
-
setSelectedCountry,
|
|
111
|
-
selectedState,
|
|
112
|
-
setSelectedState,
|
|
113
|
-
zipCode,
|
|
114
|
-
setZipCode,
|
|
115
|
-
deliveryOptions,
|
|
116
|
-
noOptionsFound,
|
|
117
|
-
doDeliveryMethodLookup,
|
|
118
|
-
countries,
|
|
119
|
-
states,
|
|
120
|
-
}}
|
|
121
|
-
>
|
|
135
|
+
<EstimateShippingContext.Provider value={contextValue}>
|
|
122
136
|
<Box>
|
|
123
137
|
<Span fontWeight={600} mb={2} display="block">
|
|
124
138
|
{t("estimatesLabel")}
|
|
@@ -130,7 +144,7 @@ const EstimateShipping = ({
|
|
|
130
144
|
};
|
|
131
145
|
|
|
132
146
|
// Subcomponents
|
|
133
|
-
|
|
147
|
+
const EstimateShippingCountry = () => {
|
|
134
148
|
const ctx = useContext(EstimateShippingContext);
|
|
135
149
|
const t = useTranslations("Cart.Sidebar");
|
|
136
150
|
if (!ctx) return null;
|
|
@@ -147,7 +161,9 @@ EstimateShipping.Country = () => {
|
|
|
147
161
|
);
|
|
148
162
|
};
|
|
149
163
|
|
|
150
|
-
EstimateShipping.
|
|
164
|
+
EstimateShipping.Country = EstimateShippingCountry;
|
|
165
|
+
|
|
166
|
+
const EstimateShippingState = () => {
|
|
151
167
|
const ctx = useContext(EstimateShippingContext);
|
|
152
168
|
const t = useTranslations("Cart.Sidebar");
|
|
153
169
|
if (!ctx) return null;
|
|
@@ -172,7 +188,9 @@ EstimateShipping.State = () => {
|
|
|
172
188
|
);
|
|
173
189
|
};
|
|
174
190
|
|
|
175
|
-
EstimateShipping.
|
|
191
|
+
EstimateShipping.State = EstimateShippingState;
|
|
192
|
+
|
|
193
|
+
const EstimateShippingZipCode = () => {
|
|
176
194
|
const ctx = useContext(EstimateShippingContext);
|
|
177
195
|
const t = useTranslations("Cart.Sidebar");
|
|
178
196
|
if (!ctx) return null;
|
|
@@ -189,7 +207,9 @@ EstimateShipping.ZipCode = () => {
|
|
|
189
207
|
);
|
|
190
208
|
};
|
|
191
209
|
|
|
192
|
-
EstimateShipping.
|
|
210
|
+
EstimateShipping.ZipCode = EstimateShippingZipCode;
|
|
211
|
+
|
|
212
|
+
const EstimateShippingSubmit = () => {
|
|
193
213
|
const ctx = useContext(EstimateShippingContext);
|
|
194
214
|
const t = useTranslations("Cart.Sidebar");
|
|
195
215
|
if (!ctx) return null;
|
|
@@ -207,7 +227,9 @@ EstimateShipping.Submit = () => {
|
|
|
207
227
|
);
|
|
208
228
|
};
|
|
209
229
|
|
|
210
|
-
EstimateShipping.
|
|
230
|
+
EstimateShipping.Submit = EstimateShippingSubmit;
|
|
231
|
+
|
|
232
|
+
const EstimateShippingOptions = () => {
|
|
211
233
|
const ctx = useContext(EstimateShippingContext);
|
|
212
234
|
const { formatCurrency } = useCurrencyFormatter();
|
|
213
235
|
const t = useTranslations("Cart.Sidebar");
|
|
@@ -241,4 +263,6 @@ EstimateShipping.Options = () => {
|
|
|
241
263
|
);
|
|
242
264
|
};
|
|
243
265
|
|
|
266
|
+
EstimateShipping.Options = EstimateShippingOptions;
|
|
267
|
+
|
|
244
268
|
export default EstimateShipping;
|
|
@@ -18,6 +18,7 @@ import React, {
|
|
|
18
18
|
type ReactNode,
|
|
19
19
|
useContext,
|
|
20
20
|
useEffect,
|
|
21
|
+
useMemo,
|
|
21
22
|
useRef,
|
|
22
23
|
useState,
|
|
23
24
|
} from "react";
|
|
@@ -51,7 +52,6 @@ interface StepProps<T extends object> {
|
|
|
51
52
|
component: React.FC<CheckoutStepComponentProps & T>;
|
|
52
53
|
componentProps?: T;
|
|
53
54
|
stepNumber?: number;
|
|
54
|
-
isLastStep?: boolean;
|
|
55
55
|
}
|
|
56
56
|
const CheckoutForm = ({ cart, children }: CheckoutFormProps) => {
|
|
57
57
|
const t = useTranslations("Checkout");
|
|
@@ -131,18 +131,20 @@ const CheckoutForm = ({ cart, children }: CheckoutFormProps) => {
|
|
|
131
131
|
setIsSubmitting(false);
|
|
132
132
|
}
|
|
133
133
|
};
|
|
134
|
+
const contextValue = useMemo(
|
|
135
|
+
() => ({
|
|
136
|
+
cart,
|
|
137
|
+
activeStep,
|
|
138
|
+
setActiveStep,
|
|
139
|
+
isSubmitting,
|
|
140
|
+
placeOrder,
|
|
141
|
+
totalSteps,
|
|
142
|
+
}),
|
|
143
|
+
[cart, activeStep, setActiveStep, isSubmitting, placeOrder, totalSteps],
|
|
144
|
+
);
|
|
134
145
|
|
|
135
146
|
return (
|
|
136
|
-
<CheckoutContext.Provider
|
|
137
|
-
value={{
|
|
138
|
-
cart,
|
|
139
|
-
activeStep,
|
|
140
|
-
setActiveStep,
|
|
141
|
-
isSubmitting,
|
|
142
|
-
placeOrder,
|
|
143
|
-
totalSteps,
|
|
144
|
-
}}
|
|
145
|
-
>
|
|
147
|
+
<CheckoutContext.Provider value={contextValue}>
|
|
146
148
|
<Box>
|
|
147
149
|
{React.Children.map(children, (child) =>
|
|
148
150
|
React.isValidElement(child) && child.type === CheckoutForm.Steps
|
|
@@ -159,7 +161,7 @@ const CheckoutForm = ({ cart, children }: CheckoutFormProps) => {
|
|
|
159
161
|
);
|
|
160
162
|
};
|
|
161
163
|
|
|
162
|
-
|
|
164
|
+
const CheckoutFormSteps = ({
|
|
163
165
|
children,
|
|
164
166
|
setTotalSteps,
|
|
165
167
|
}: {
|
|
@@ -185,7 +187,9 @@ CheckoutForm.Steps = ({
|
|
|
185
187
|
);
|
|
186
188
|
};
|
|
187
189
|
|
|
188
|
-
CheckoutForm.
|
|
190
|
+
CheckoutForm.Steps = CheckoutFormSteps;
|
|
191
|
+
|
|
192
|
+
const CheckoutFormStep = <T extends object>({
|
|
189
193
|
title,
|
|
190
194
|
stepNumber,
|
|
191
195
|
component: Component,
|
|
@@ -218,7 +222,9 @@ CheckoutForm.Step = <T extends object>({
|
|
|
218
222
|
);
|
|
219
223
|
};
|
|
220
224
|
|
|
221
|
-
CheckoutForm.
|
|
225
|
+
CheckoutForm.Step = CheckoutFormStep;
|
|
226
|
+
|
|
227
|
+
const CheckoutFormFooter = () => {
|
|
222
228
|
const ctx = useContext(CheckoutContext);
|
|
223
229
|
const t = useTranslations("Checkout");
|
|
224
230
|
if (!ctx) return null;
|
|
@@ -244,4 +250,6 @@ CheckoutForm.Footer = () => {
|
|
|
244
250
|
);
|
|
245
251
|
};
|
|
246
252
|
|
|
253
|
+
CheckoutForm.Footer = CheckoutFormFooter;
|
|
254
|
+
|
|
247
255
|
export default CheckoutForm;
|
|
@@ -6,7 +6,7 @@ import StepHeading from "@evenicanpm/storefront-core/src/pages/checkout/checkout
|
|
|
6
6
|
import { Button, useTheme } from "@mui/material";
|
|
7
7
|
import Grid from "@mui/material/Grid2";
|
|
8
8
|
import { useTranslations } from "next-intl";
|
|
9
|
-
import React, { createContext, useContext } from "react";
|
|
9
|
+
import React, { createContext, useContext, useMemo } from "react";
|
|
10
10
|
|
|
11
11
|
export type StepViewState = "active" | "preview" | "pending";
|
|
12
12
|
export type StepSubmissionState = "idle" | "submitting" | "error";
|
|
@@ -61,18 +61,33 @@ const CheckoutStep = ({
|
|
|
61
61
|
return "pending";
|
|
62
62
|
};
|
|
63
63
|
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
const stepViewState = getStepViewState();
|
|
65
|
+
const ctx: StepContextType = useMemo(
|
|
66
|
+
() => ({
|
|
67
|
+
title,
|
|
68
|
+
stepNumber,
|
|
69
|
+
activeStep,
|
|
70
|
+
setActiveStep,
|
|
71
|
+
cart,
|
|
72
|
+
hasCompleted,
|
|
73
|
+
stepSubmissionState,
|
|
74
|
+
setStepSubmissionState,
|
|
75
|
+
stepViewState,
|
|
76
|
+
handleStepCompletion,
|
|
77
|
+
}),
|
|
78
|
+
[
|
|
79
|
+
title,
|
|
80
|
+
stepNumber,
|
|
81
|
+
activeStep,
|
|
82
|
+
setActiveStep,
|
|
83
|
+
cart,
|
|
84
|
+
hasCompleted,
|
|
85
|
+
stepSubmissionState,
|
|
86
|
+
setStepSubmissionState,
|
|
87
|
+
stepViewState,
|
|
88
|
+
handleStepCompletion,
|
|
89
|
+
],
|
|
90
|
+
);
|
|
76
91
|
|
|
77
92
|
return (
|
|
78
93
|
<StepContext.Provider value={ctx}>
|
|
@@ -90,7 +105,7 @@ const CheckoutStep = ({
|
|
|
90
105
|
);
|
|
91
106
|
};
|
|
92
107
|
|
|
93
|
-
|
|
108
|
+
const CheckoutStepHeader = () => {
|
|
94
109
|
const ctx = useContext(StepContext);
|
|
95
110
|
const t = useTranslations("Checkout.Steps");
|
|
96
111
|
if (!ctx) return null;
|
|
@@ -117,7 +132,9 @@ CheckoutStep.Header = () => {
|
|
|
117
132
|
);
|
|
118
133
|
};
|
|
119
134
|
|
|
120
|
-
CheckoutStep.
|
|
135
|
+
CheckoutStep.Header = CheckoutStepHeader;
|
|
136
|
+
|
|
137
|
+
const CheckoutStepBody = <P extends object = object>({
|
|
121
138
|
component: Component,
|
|
122
139
|
componentProps,
|
|
123
140
|
}: {
|
|
@@ -147,7 +164,9 @@ CheckoutStep.Body = <P extends object = object>({
|
|
|
147
164
|
);
|
|
148
165
|
};
|
|
149
166
|
|
|
150
|
-
CheckoutStep.
|
|
167
|
+
CheckoutStep.Body = CheckoutStepBody;
|
|
168
|
+
|
|
169
|
+
const CheckoutStepActions = () => {
|
|
151
170
|
const ctx = useContext(StepContext);
|
|
152
171
|
const t = useTranslations("Checkout.Steps");
|
|
153
172
|
if (!ctx) return null;
|
|
@@ -168,4 +187,6 @@ CheckoutStep.Actions = () => {
|
|
|
168
187
|
);
|
|
169
188
|
};
|
|
170
189
|
|
|
190
|
+
CheckoutStep.Actions = CheckoutStepActions;
|
|
191
|
+
|
|
171
192
|
export default CheckoutStep;
|
|
@@ -64,7 +64,7 @@ const AddressCard = ({
|
|
|
64
64
|
);
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
const AddressCardControls = () => {
|
|
68
68
|
const ctx = React.useContext(AddressCardContext);
|
|
69
69
|
if (!ctx) return null;
|
|
70
70
|
|
|
@@ -102,7 +102,9 @@ AddressCard.Controls = () => {
|
|
|
102
102
|
);
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
-
AddressCard.
|
|
105
|
+
AddressCard.Controls = AddressCardControls;
|
|
106
|
+
|
|
107
|
+
const AddressCardHeader = () => {
|
|
106
108
|
const ctx = React.useContext(AddressCardContext);
|
|
107
109
|
if (!ctx) return null;
|
|
108
110
|
|
|
@@ -110,7 +112,9 @@ AddressCard.Header = () => {
|
|
|
110
112
|
return <H6 mb={0.5}>{address.Name}</H6>;
|
|
111
113
|
};
|
|
112
114
|
|
|
113
|
-
AddressCard.
|
|
115
|
+
AddressCard.Header = AddressCardHeader;
|
|
116
|
+
|
|
117
|
+
const AddressCardBody = () => {
|
|
114
118
|
const ctx = React.useContext(AddressCardContext);
|
|
115
119
|
if (!ctx) return null;
|
|
116
120
|
|
|
@@ -130,4 +134,6 @@ AddressCard.Body = () => {
|
|
|
130
134
|
);
|
|
131
135
|
};
|
|
132
136
|
|
|
137
|
+
AddressCard.Body = AddressCardBody;
|
|
138
|
+
|
|
133
139
|
export default AddressCard;
|
|
@@ -27,6 +27,7 @@ import React, {
|
|
|
27
27
|
useCallback,
|
|
28
28
|
useContext,
|
|
29
29
|
useEffect,
|
|
30
|
+
useMemo,
|
|
30
31
|
useState,
|
|
31
32
|
} from "react";
|
|
32
33
|
|
|
@@ -246,6 +247,74 @@ const DeliveryAddress: DeliveryAddressCompound = ({
|
|
|
246
247
|
}
|
|
247
248
|
}, [stepSubmissionState, handleStepCompletion, setStepSubmissionState]);
|
|
248
249
|
|
|
250
|
+
// modal helpers (moved before early returns)
|
|
251
|
+
const openNew = () => {
|
|
252
|
+
setEditAddress(undefined);
|
|
253
|
+
setModalOpen(true);
|
|
254
|
+
};
|
|
255
|
+
const openEdit = (addr: Address) => {
|
|
256
|
+
setEditAddress({ ...addr });
|
|
257
|
+
setModalOpen(true);
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const closeModal = () => {
|
|
261
|
+
setModalOpen(false);
|
|
262
|
+
setEditAddress(undefined);
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
// context value (moved before early returns)
|
|
266
|
+
const cartShippingAddressId = cart.ShippingAddress?.Id;
|
|
267
|
+
let visibleAddresses = addressList;
|
|
268
|
+
|
|
269
|
+
if (useDropDown) {
|
|
270
|
+
if (!isGuest) {
|
|
271
|
+
visibleAddresses = addressList.filter(
|
|
272
|
+
(a) => a.RecordId === selectedAddressID,
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const ctx: DeliveryAddressContextValue = useMemo(
|
|
278
|
+
() => ({
|
|
279
|
+
t,
|
|
280
|
+
countries,
|
|
281
|
+
addressList,
|
|
282
|
+
visibleAddresses,
|
|
283
|
+
isGuest,
|
|
284
|
+
cartShippingAddressId,
|
|
285
|
+
showDropDown,
|
|
286
|
+
title,
|
|
287
|
+
selectedAddressID,
|
|
288
|
+
modalOpen,
|
|
289
|
+
editAddress,
|
|
290
|
+
openNew,
|
|
291
|
+
openEdit,
|
|
292
|
+
closeModal,
|
|
293
|
+
pickAddress,
|
|
294
|
+
handleSaveAddress,
|
|
295
|
+
handleDelete,
|
|
296
|
+
}),
|
|
297
|
+
[
|
|
298
|
+
t,
|
|
299
|
+
countries,
|
|
300
|
+
addressList,
|
|
301
|
+
visibleAddresses,
|
|
302
|
+
isGuest,
|
|
303
|
+
cartShippingAddressId,
|
|
304
|
+
showDropDown,
|
|
305
|
+
title,
|
|
306
|
+
selectedAddressID,
|
|
307
|
+
modalOpen,
|
|
308
|
+
editAddress,
|
|
309
|
+
openNew,
|
|
310
|
+
openEdit,
|
|
311
|
+
closeModal,
|
|
312
|
+
pickAddress,
|
|
313
|
+
handleSaveAddress,
|
|
314
|
+
handleDelete,
|
|
315
|
+
],
|
|
316
|
+
);
|
|
317
|
+
|
|
249
318
|
// step state guards
|
|
250
319
|
if (stepViewState === "pending" || !countries) return null;
|
|
251
320
|
|
|
@@ -267,52 +336,6 @@ const DeliveryAddress: DeliveryAddressCompound = ({
|
|
|
267
336
|
);
|
|
268
337
|
}
|
|
269
338
|
|
|
270
|
-
let visibleAddresses = addressList;
|
|
271
|
-
|
|
272
|
-
if (useDropDown) {
|
|
273
|
-
if (!isGuest) {
|
|
274
|
-
visibleAddresses = addressList.filter(
|
|
275
|
-
(a) => a.RecordId === selectedAddressID,
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// modal helpers
|
|
281
|
-
const openNew = () => {
|
|
282
|
-
setEditAddress(undefined);
|
|
283
|
-
setModalOpen(true);
|
|
284
|
-
};
|
|
285
|
-
const openEdit = (addr: Address) => {
|
|
286
|
-
setEditAddress({ ...addr });
|
|
287
|
-
setModalOpen(true);
|
|
288
|
-
};
|
|
289
|
-
|
|
290
|
-
const closeModal = () => {
|
|
291
|
-
setModalOpen(false);
|
|
292
|
-
setEditAddress(undefined);
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
// context value
|
|
296
|
-
const ctx: DeliveryAddressContextValue = {
|
|
297
|
-
t,
|
|
298
|
-
countries,
|
|
299
|
-
addressList,
|
|
300
|
-
visibleAddresses,
|
|
301
|
-
isGuest,
|
|
302
|
-
cartShippingAddressId: cart.ShippingAddress?.Id,
|
|
303
|
-
showDropDown,
|
|
304
|
-
title,
|
|
305
|
-
selectedAddressID,
|
|
306
|
-
modalOpen,
|
|
307
|
-
editAddress,
|
|
308
|
-
openNew,
|
|
309
|
-
openEdit,
|
|
310
|
-
closeModal,
|
|
311
|
-
pickAddress,
|
|
312
|
-
handleSaveAddress,
|
|
313
|
-
handleDelete,
|
|
314
|
-
};
|
|
315
|
-
|
|
316
339
|
// default layout (identical behavior)
|
|
317
340
|
const defaultLayout = (
|
|
318
341
|
<>
|
|
@@ -334,7 +357,7 @@ const DeliveryAddress: DeliveryAddressCompound = ({
|
|
|
334
357
|
|
|
335
358
|
// ---------- Subcomponents ----------
|
|
336
359
|
|
|
337
|
-
|
|
360
|
+
const DeliveryAddressModal = () => {
|
|
338
361
|
const ctx = useContext(DeliveryAddressCtx);
|
|
339
362
|
if (!ctx) return null;
|
|
340
363
|
const {
|
|
@@ -359,8 +382,10 @@ DeliveryAddress.Modal = () => {
|
|
|
359
382
|
);
|
|
360
383
|
};
|
|
361
384
|
|
|
385
|
+
DeliveryAddress.Modal = DeliveryAddressModal;
|
|
386
|
+
|
|
362
387
|
// (configurable via `useDropDown`/`showDropDown`)
|
|
363
|
-
|
|
388
|
+
const DeliveryAddressDropdown = () => {
|
|
364
389
|
const ctx = useContext(DeliveryAddressCtx);
|
|
365
390
|
if (!ctx) return null;
|
|
366
391
|
const { showDropDown, title, addressList, pickAddress, handleSaveAddress } =
|
|
@@ -398,8 +423,10 @@ DeliveryAddress.Dropdown = () => {
|
|
|
398
423
|
);
|
|
399
424
|
};
|
|
400
425
|
|
|
426
|
+
DeliveryAddress.Dropdown = DeliveryAddressDropdown;
|
|
427
|
+
|
|
401
428
|
// List (can accept a renderItem override)
|
|
402
|
-
|
|
429
|
+
const DeliveryAddressList = ({ renderItem }: ListProps) => {
|
|
403
430
|
const ctx = useContext(DeliveryAddressCtx);
|
|
404
431
|
if (!ctx) return null;
|
|
405
432
|
const { visibleAddresses } = ctx;
|
|
@@ -419,8 +446,10 @@ DeliveryAddress.List = ({ renderItem }: ListProps) => {
|
|
|
419
446
|
);
|
|
420
447
|
};
|
|
421
448
|
|
|
449
|
+
DeliveryAddress.List = DeliveryAddressList;
|
|
450
|
+
|
|
422
451
|
// Item → one address card (default uses AddressCard with Controls/Header/Body)
|
|
423
|
-
|
|
452
|
+
const DeliveryAddressCard = ({ address, children }: ItemProps) => {
|
|
424
453
|
const ctx = useContext(DeliveryAddressCtx);
|
|
425
454
|
if (!ctx) return null;
|
|
426
455
|
const { cartShippingAddressId, openEdit, handleSaveAddress, handleDelete } =
|
|
@@ -445,7 +474,9 @@ DeliveryAddress.Card = ({ address, children }: ItemProps) => {
|
|
|
445
474
|
);
|
|
446
475
|
};
|
|
447
476
|
|
|
448
|
-
DeliveryAddress.
|
|
477
|
+
DeliveryAddress.Card = DeliveryAddressCard;
|
|
478
|
+
|
|
479
|
+
const DeliveryAddressNewCard = () => {
|
|
449
480
|
const ctx = useContext(DeliveryAddressCtx);
|
|
450
481
|
if (!ctx) return null;
|
|
451
482
|
const { t, openNew } = ctx;
|
|
@@ -474,4 +505,6 @@ DeliveryAddress.NewCard = () => {
|
|
|
474
505
|
);
|
|
475
506
|
};
|
|
476
507
|
|
|
508
|
+
DeliveryAddress.NewCard = DeliveryAddressNewCard;
|
|
509
|
+
|
|
477
510
|
export default DeliveryAddress;
|
|
@@ -176,21 +176,35 @@ const NewAddressForm = ({
|
|
|
176
176
|
handleClose();
|
|
177
177
|
};
|
|
178
178
|
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
179
|
+
const mappedStates = Array.isArray(states)
|
|
180
|
+
? states.map((s) => ({
|
|
181
|
+
StateName: s.StateName ?? "",
|
|
182
|
+
StateId: s.StateId ?? "",
|
|
183
|
+
}))
|
|
184
|
+
: [];
|
|
185
|
+
|
|
186
|
+
const ctx: NewAddressFormCtx = React.useMemo(
|
|
187
|
+
() => ({
|
|
188
|
+
form,
|
|
189
|
+
countries,
|
|
190
|
+
states: mappedStates,
|
|
191
|
+
selectedCountry,
|
|
192
|
+
setSelectedCountry,
|
|
193
|
+
errors,
|
|
194
|
+
t,
|
|
195
|
+
onCancel: handleClose,
|
|
196
|
+
}),
|
|
197
|
+
[
|
|
198
|
+
form,
|
|
199
|
+
countries,
|
|
200
|
+
mappedStates,
|
|
201
|
+
selectedCountry,
|
|
202
|
+
setSelectedCountry,
|
|
203
|
+
errors,
|
|
204
|
+
t,
|
|
205
|
+
handleClose,
|
|
206
|
+
],
|
|
207
|
+
);
|
|
194
208
|
|
|
195
209
|
const hasCustomChildren = React.Children.count(children) > 0;
|
|
196
210
|
|
|
@@ -231,7 +245,7 @@ const NewAddressForm = ({
|
|
|
231
245
|
};
|
|
232
246
|
|
|
233
247
|
// Generic text field
|
|
234
|
-
|
|
248
|
+
const NewAddressFormField = ({
|
|
235
249
|
name,
|
|
236
250
|
label,
|
|
237
251
|
}: {
|
|
@@ -257,7 +271,9 @@ NewAddressForm.Field = ({
|
|
|
257
271
|
);
|
|
258
272
|
};
|
|
259
273
|
|
|
260
|
-
NewAddressForm.
|
|
274
|
+
NewAddressForm.Field = NewAddressFormField;
|
|
275
|
+
|
|
276
|
+
const NewAddressFormCountrySelect = () => {
|
|
261
277
|
const ctx = React.useContext(FormContext);
|
|
262
278
|
if (!ctx) return null;
|
|
263
279
|
const { countries, form, setSelectedCountry, t, errors } = ctx;
|
|
@@ -297,7 +313,9 @@ NewAddressForm.CountrySelect = () => {
|
|
|
297
313
|
);
|
|
298
314
|
};
|
|
299
315
|
|
|
300
|
-
NewAddressForm.
|
|
316
|
+
NewAddressForm.CountrySelect = NewAddressFormCountrySelect;
|
|
317
|
+
|
|
318
|
+
const NewAddressFormStateSelect = () => {
|
|
301
319
|
const ctx = React.useContext(FormContext);
|
|
302
320
|
if (!ctx) return null;
|
|
303
321
|
const { states, form, t, errors } = ctx;
|
|
@@ -326,7 +344,9 @@ NewAddressForm.StateSelect = () => {
|
|
|
326
344
|
);
|
|
327
345
|
};
|
|
328
346
|
|
|
329
|
-
NewAddressForm.
|
|
347
|
+
NewAddressForm.StateSelect = NewAddressFormStateSelect;
|
|
348
|
+
|
|
349
|
+
const NewAddressFormActions = () => {
|
|
330
350
|
const ctx = React.useContext(FormContext);
|
|
331
351
|
if (!ctx) return null;
|
|
332
352
|
const { t, onCancel } = ctx;
|
|
@@ -343,4 +363,6 @@ NewAddressForm.Actions = () => {
|
|
|
343
363
|
);
|
|
344
364
|
};
|
|
345
365
|
|
|
366
|
+
NewAddressForm.Actions = NewAddressFormActions;
|
|
367
|
+
|
|
346
368
|
export default NewAddressForm;
|
|
@@ -7,7 +7,7 @@ import Box from "@mui/material/Box";
|
|
|
7
7
|
import Grid from "@mui/material/Grid2";
|
|
8
8
|
import TextField from "@mui/material/TextField";
|
|
9
9
|
import { useTranslations } from "next-intl";
|
|
10
|
-
import React, { createContext, useContext } from "react";
|
|
10
|
+
import React, { createContext, useContext, useMemo } from "react";
|
|
11
11
|
import type { SubmitHandler, UseFormReturn } from "react-hook-form";
|
|
12
12
|
import { useForm } from "react-hook-form";
|
|
13
13
|
import * as yup from "yup";
|
|
@@ -97,13 +97,16 @@ const CustomerInformation = (
|
|
|
97
97
|
}
|
|
98
98
|
}, [formState.errors, formState.isSubmitted, setStepSubmissionState]);
|
|
99
99
|
|
|
100
|
-
const ctx: CustomerCtx =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
100
|
+
const ctx: CustomerCtx = useMemo(
|
|
101
|
+
() => ({
|
|
102
|
+
...props,
|
|
103
|
+
email: email ?? null,
|
|
104
|
+
cartId,
|
|
105
|
+
form,
|
|
106
|
+
handleSave,
|
|
107
|
+
}),
|
|
108
|
+
[props, email, cartId, form, handleSave],
|
|
109
|
+
);
|
|
107
110
|
|
|
108
111
|
return (
|
|
109
112
|
<CustomerContext.Provider value={ctx}>
|
|
@@ -117,7 +120,7 @@ const CustomerInformation = (
|
|
|
117
120
|
);
|
|
118
121
|
};
|
|
119
122
|
|
|
120
|
-
|
|
123
|
+
const CustomerInformationPreview = () => {
|
|
121
124
|
const ctx = useContext(CustomerContext);
|
|
122
125
|
const t = useTranslations("Checkout.CustomerInformation");
|
|
123
126
|
if (!ctx) return null;
|
|
@@ -131,7 +134,9 @@ CustomerInformation.Preview = () => {
|
|
|
131
134
|
);
|
|
132
135
|
};
|
|
133
136
|
|
|
134
|
-
CustomerInformation.
|
|
137
|
+
CustomerInformation.Preview = CustomerInformationPreview;
|
|
138
|
+
|
|
139
|
+
const CustomerInformationForm = () => {
|
|
135
140
|
const ctx = useContext(CustomerContext);
|
|
136
141
|
const t = useTranslations("Checkout.CustomerInformation");
|
|
137
142
|
if (!ctx) return null;
|
|
@@ -155,4 +160,6 @@ CustomerInformation.Form = () => {
|
|
|
155
160
|
);
|
|
156
161
|
};
|
|
157
162
|
|
|
163
|
+
CustomerInformation.Form = CustomerInformationForm;
|
|
164
|
+
|
|
158
165
|
export default CustomerInformation;
|