@sonic-equipment/ui 259.0.3 → 259.0.5

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.
@@ -73,7 +73,7 @@ function Header({ className, headerNavigationSection, sticky, }) {
73
73
  const mainNavigationSection = headerNavigationSection?.items
74
74
  .filter(isNavigationSection)
75
75
  .find(item => item.key === 'main-navigation');
76
- return (jsxs(Fragment, { children: [jsx("header", { ref: headerRef, className: clsx(styles['header'], sticky && styles['sticky'], className), "data-test-selector": "pageHeader", children: jsx(HeaderLayout, { hamburgerButton: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", "data-test-selector": "pageHeaderHamburgerButton", isActive: mobileNavigationOpen, onActiveChange: toggleMobileNavigation }), hasDrawersOpen: hasDrawersOpen, logo: jsx(SonicLogo, { "data-test-selector": "pageHeaderLogo", href: homeLink?.href || undefined, title: t('Home') }), mainNavigation: jsx(NavigationLinkList, { activeLink: activeLinkGroup, "data-test-selector": "pageHeaderMainNavigation", navigationSection: mainNavigationSection, onSubmenuToggle: toggleActiveSubmenu }), navigationActions: jsxs(Fragment, { children: [jsx(ConnectedAccountButton, { "data-test-selector": "pageHeaderAccountButton" }), jsx(ConnectedFavoritesButton, { "data-test-selector": "pageHeaderFavoritesButton", href: "abc" }), jsx(ConnectedCartButton, { "data-test-selector": "pageHeaderCartButton", href: paths.CART })] }), search: jsx(SearchButton, { "aria-controls": "global-search", "data-test-selector": "pageHeaderSearchButton", isActive: searchOpen, onActiveChange: toggleSearch }) }) }), jsx(SearchDrawer, { groupId: searchGroupId, instanceId: searchInstanceId }), !isXl && (jsx(MobileNavigationDrawer, { groupId: mobileNavigationDrawer.groupId, instanceId: mobileNavigationDrawer.instanceId, linkItems: mainNavigationSection?.items.filter(isNavigationLinkItem) })), isXl && (jsx(DesktopNavigationDrawer, { groupId: desktopNavigationDrawer.groupId, instanceId: desktopNavigationDrawer.instanceId, linkGroup: activeLinkGroup, onClosed: () => setActiveLinkGroup(undefined) }))] }));
76
+ return (jsxs(Fragment, { children: [jsx("header", { ref: headerRef, className: clsx(styles['header'], sticky && styles['sticky'], className), "data-test-selector": "pageHeader", children: jsx(HeaderLayout, { hamburgerButton: jsx(HamburgerButton, { "aria-controls": "mobile-navigation", "data-test-selector": "pageHeaderHamburgerButton", isActive: mobileNavigationOpen, onActiveChange: toggleMobileNavigation }), hasDrawersOpen: hasDrawersOpen, logo: jsx(SonicLogo, { "data-test-selector": "pageHeaderLogo", href: homeLink?.href || undefined, title: t('Home') }), mainNavigation: jsx(NavigationLinkList, { activeLink: activeLinkGroup, "data-test-selector": "pageHeaderMainNavigation", navigationSection: mainNavigationSection, onSubmenuToggle: toggleActiveSubmenu }), navigationActions: jsxs(Fragment, { children: [jsx(ConnectedAccountButton, { "data-test-selector": "pageHeaderAccountButton" }), jsx(ConnectedFavoritesButton, { "data-test-selector": "pageHeaderFavoritesButton", href: paths.FAVORITES }), jsx(ConnectedCartButton, { "data-test-selector": "pageHeaderCartButton", href: paths.CART })] }), search: jsx(SearchButton, { "aria-controls": "global-search", "data-test-selector": "pageHeaderSearchButton", isActive: searchOpen, onActiveChange: toggleSearch }) }) }), jsx(SearchDrawer, { groupId: searchGroupId, instanceId: searchInstanceId }), !isXl && (jsx(MobileNavigationDrawer, { groupId: mobileNavigationDrawer.groupId, instanceId: mobileNavigationDrawer.instanceId, linkItems: mainNavigationSection?.items.filter(isNavigationLinkItem) })), isXl && (jsx(DesktopNavigationDrawer, { groupId: desktopNavigationDrawer.groupId, instanceId: desktopNavigationDrawer.instanceId, linkGroup: activeLinkGroup, onClosed: () => setActiveLinkGroup(undefined) }))] }));
77
77
  }
78
78
 
79
79
  export { Header };
@@ -82,7 +82,7 @@ function ShippingPage() {
82
82
  }, [cart, createEcommerceEvent, dataLayer]);
83
83
  if (errorFetchCart)
84
84
  return jsx(ErrorPage, { error: errorFetchCart });
85
- if (isLoading || isNavigating || isError || isSuccess)
85
+ if (isLoading || isNavigating || isSuccess)
86
86
  return jsx(LoadingPage, {});
87
87
  if (hasNoBillToAddress && !countries)
88
88
  throw new Error('Countries are missing');
@@ -97,29 +97,35 @@ function ShippingPage() {
97
97
  async function handleSubmit({ address, cart, notes, }) {
98
98
  if (!cart.billTo)
99
99
  throw new Error('No billTo address found');
100
- await patchShippingDetails({
101
- billTo: {
102
- ...cart.billTo,
103
- address1: address.address1,
104
- address2: address.address2,
105
- address3: address.address3,
106
- attention: address.attention,
107
- city: address.city,
108
- companyName: address.companyName,
109
- country: { id: address.country.id },
110
- email: address.email,
111
- firstName: address.firstName,
112
- lastName: address.lastName,
113
- phone: address.phone,
114
- postalCode: address.postalCode,
115
- },
116
- cart,
117
- notes,
118
- });
119
- dataLayer.push(createEcommerceEvent({
120
- cart,
121
- event: { event: 'add_shipping_info' },
122
- }));
100
+ try {
101
+ await patchShippingDetails({
102
+ billTo: {
103
+ ...cart.billTo,
104
+ address1: address.address1,
105
+ address2: address.address2,
106
+ address3: address.address3,
107
+ attention: address.attention,
108
+ city: address.city,
109
+ companyName: address.companyName,
110
+ country: { id: address.country.id },
111
+ email: address.email,
112
+ firstName: address.firstName,
113
+ lastName: address.lastName,
114
+ phone: address.phone,
115
+ postalCode: address.postalCode,
116
+ },
117
+ cart,
118
+ notes,
119
+ });
120
+ dataLayer.push(createEcommerceEvent({
121
+ cart,
122
+ event: { event: 'add_shipping_info' },
123
+ }));
124
+ }
125
+ catch {
126
+ // Error is tracked by usePatchShippingDetails via isError/error state,
127
+ // surfaced to the UI via errorPatchBillingAddress
128
+ }
123
129
  }
124
130
  return (jsx(ShippingPageContent, { cart: cart,
125
131
  // TODO: Combine editAddress and readOnlyAddress into one section in order
@@ -157,28 +163,34 @@ function ShippingPage() {
157
163
  }, readOnlyAddress: jsx(ReadOnlyAddresses, { billTo: cart.billTo, cartId: cart.id, countries: countries || [], currentCountry: currentCountry, isLoading: isPatching, isPickup: isPickup, notes: cart.notes, onSubmit: async ({ cart: updatedCart, notes, shipTo }) => {
158
164
  if (!cart.billTo)
159
165
  return;
160
- if (notes ||
161
- cart.shipTo === null ||
162
- (shipTo && shipTo.id !== cart.shipTo?.id) ||
163
- (updatedCart &&
164
- (updatedCart.shipTo?.id !== cart.shipTo?.id ||
165
- updatedCart.shipTo === null))) {
166
- await patchShippingDetails({
167
- cart: {
168
- ...cart,
169
- ...updatedCart,
170
- },
171
- notes,
172
- shipTo,
173
- });
166
+ try {
167
+ if (notes ||
168
+ cart.shipTo === null ||
169
+ (shipTo && shipTo.id !== cart.shipTo?.id) ||
170
+ (updatedCart &&
171
+ (updatedCart.shipTo?.id !== cart.shipTo?.id ||
172
+ updatedCart.shipTo === null))) {
173
+ await patchShippingDetails({
174
+ cart: {
175
+ ...cart,
176
+ ...updatedCart,
177
+ },
178
+ notes,
179
+ shipTo,
180
+ });
181
+ }
182
+ else {
183
+ navigate(paths.REVIEW_AND_SUBMIT);
184
+ }
185
+ dataLayer.push(createEcommerceEvent({
186
+ cart,
187
+ event: { event: 'add_shipping_info' },
188
+ }));
174
189
  }
175
- else {
176
- navigate(paths.REVIEW_AND_SUBMIT);
190
+ catch {
191
+ // Error is tracked by usePatchShippingDetails via isError/error state,
192
+ // surfaced to the UI via errorPatchBillingAddress
177
193
  }
178
- dataLayer.push(createEcommerceEvent({
179
- cart,
180
- event: { event: 'add_shipping_info' },
181
- }));
182
194
  }, shipTo: cart.shipTo }) }));
183
195
  }
184
196
 
@@ -6,12 +6,15 @@ import { Details } from '../../display/details/details.js';
6
6
  import { StrokeRecentIcon } from '../../icons/stroke/stroke-recent-icon.js';
7
7
  import { useFormattedMessage } from '../../intl/use-formatted-message.js';
8
8
  import { Heading } from '../../typography/heading/heading.js';
9
+ import { isRequestError } from '../fetch/request.js';
9
10
  import { isProductionEnvironment } from '../utils/environment.js';
10
11
  import styles from './default-error-view.module.css.js';
11
12
 
12
13
  function DefaultErrorView({ className, error, errorInfo, resetError, resetLabel, showErrorDetails = !isProductionEnvironment, showReset, title, }) {
13
14
  const t = useFormattedMessage();
14
- return (jsxs("section", { className: clsx(styles['default-error-view'], className), children: [title && (jsx(Heading, { className: styles['title'], size: "s", tag: "h1", children: title || t('Something went wrong') })), jsx("p", { children: error.message || t('An unexpected error occured. Please try again.') }), showErrorDetails && (jsxs(Details, { className: styles['error-details'], lang: "en", summary: "Technical Details (only visible in development mode)", children: [jsx("output", { className: styles['error-kind'], children: error.toString() }), error.stack && (jsxs("div", { className: styles['error-info'], children: [jsx(Heading, { className: styles['error-info-title'], size: "xs", tag: "h2", children: "Stack:" }), jsx("pre", { className: styles['error-info-data'], children: error.stack })] })), errorInfo?.componentStack && (jsxs("div", { className: styles['component-info'], children: [jsx(Heading, { className: styles['error-info-title'], size: "xs", tag: "h2", children: "Component stack:" }), jsx("pre", { className: styles['error-info-data'], children: errorInfo.componentStack })] }))] })), showReset && resetError && (jsx(Button, { light: true, className: styles['reset-button'], color: "secondary", icon: jsx(StrokeRecentIcon, {}), onClick: resetError, size: "sm", type: "button", variant: "outline", children: resetLabel || t('Reset') }))] }));
15
+ return (jsxs("section", { className: clsx(styles['default-error-view'], className), children: [title && (jsx(Heading, { className: styles['title'], size: "s", tag: "h1", children: title || t('Something went wrong') })), jsx("p", { children: !isRequestError(error) && error.message
16
+ ? error.message
17
+ : t('An unexpected error occured. Please try again.') }), showErrorDetails && (jsxs(Details, { className: styles['error-details'], lang: "en", summary: "Technical Details (only visible in development mode)", children: [jsx("output", { className: styles['error-kind'], children: error.toString() }), error.stack && (jsxs("div", { className: styles['error-info'], children: [jsx(Heading, { className: styles['error-info-title'], size: "xs", tag: "h2", children: "Stack:" }), jsx("pre", { className: styles['error-info-data'], children: error.stack })] })), errorInfo?.componentStack && (jsxs("div", { className: styles['component-info'], children: [jsx(Heading, { className: styles['error-info-title'], size: "xs", tag: "h2", children: "Component stack:" }), jsx("pre", { className: styles['error-info-data'], children: errorInfo.componentStack })] }))] })), showReset && resetError && (jsx(Button, { light: true, className: styles['reset-button'], color: "secondary", icon: jsx(StrokeRecentIcon, {}), onClick: resetError, size: "sm", type: "button", variant: "outline", children: resetLabel || t('Reset') }))] }));
15
18
  }
16
19
 
17
20
  export { DefaultErrorView };
@@ -68,6 +68,19 @@ class RequestError extends Error {
68
68
  this.options = options?.options;
69
69
  // eslint-disable-next-line unicorn/custom-error-definition
70
70
  this.name = this.name || this.constructor.name || 'RequestError';
71
+ // Replace the non-serializable Response cause with a plain object so error
72
+ // reporting tools (e.g. Sentry) can capture full request/response context.
73
+ this.cause = {
74
+ request: {
75
+ method: this.options?.method ?? 'GET',
76
+ url: this.options?.url,
77
+ },
78
+ response: {
79
+ body: this.body,
80
+ status: this.status,
81
+ statusText: this.statusText,
82
+ },
83
+ };
71
84
  }
72
85
  toJSON() {
73
86
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sonic-equipment/ui",
3
- "version": "259.0.3",
3
+ "version": "259.0.5",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "engines": {