@sonic-equipment/ui 215.0.0 → 217.0.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 (53) hide show
  1. package/dist/buttons/button/button.module.css.js +1 -1
  2. package/dist/buttons/icon-button/icon-button.d.ts +1 -1
  3. package/dist/buttons/icon-button/icon-button.js +5 -3
  4. package/dist/buttons/reorder-button/connected-reorder-button.d.ts +4 -0
  5. package/dist/buttons/reorder-button/connected-reorder-button.js +37 -0
  6. package/dist/buttons/reorder-button/reorder-button.d.ts +9 -0
  7. package/dist/buttons/reorder-button/reorder-button.js +11 -0
  8. package/dist/display/price/price.js +2 -2
  9. package/dist/display/price/price.module.css.js +1 -1
  10. package/dist/exports.d.ts +6 -0
  11. package/dist/header/buttons/account/connected-account-button.d.ts +1 -2
  12. package/dist/header/buttons/account/connected-account-button.js +20 -11
  13. package/dist/header/buttons/account/connected-account-button.module.css.js +3 -0
  14. package/dist/index.js +10 -4
  15. package/dist/intl/translation-id.d.ts +1 -1
  16. package/dist/navigation/mobile-navigation/mobile-navigation.js +2 -2
  17. package/dist/navigation/quick-access-menu/quick-access-menu.d.ts +8 -0
  18. package/dist/navigation/quick-access-menu/quick-access-menu.js +21 -0
  19. package/dist/navigation/quick-access-menu/quick-access-menu.module.css.js +3 -0
  20. package/dist/pages/my-sonic/navigation/connected-my-sonic-navigation.js +3 -16
  21. package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.d.ts +2 -2
  22. package/dist/pages/my-sonic/navigation/my-sonic-desktop-navigation.js +7 -5
  23. package/dist/pages/my-sonic/navigation/my-sonic-mobile-navigation.d.ts +2 -2
  24. package/dist/pages/my-sonic/navigation/my-sonic-mobile-navigation.js +7 -5
  25. package/dist/pages/my-sonic/navigation/my-sonic-navigation-items.d.ts +5 -2
  26. package/dist/pages/my-sonic/navigation/my-sonic-navigation-items.js +16 -5
  27. package/dist/pages/my-sonic/pages/create-ship-to-address-details-page/create-ship-to-address-details-page.js +2 -2
  28. package/dist/pages/my-sonic/pages/edit-bill-to-address-details-page/edit-bill-to-address-details-page.js +2 -2
  29. package/dist/pages/my-sonic/pages/edit-ship-to-address-details-page/edit-ship-to-address-details-page.js +2 -2
  30. package/dist/pages/my-sonic/pages/favorites/favorites-page.js +1 -1
  31. package/dist/pages/my-sonic/pages/my-account/my-account-page.js +2 -2
  32. package/dist/pages/my-sonic/pages/order-details/order-details-content.d.ts +3 -1
  33. package/dist/pages/my-sonic/pages/order-details/order-details-content.js +3 -3
  34. package/dist/pages/my-sonic/pages/order-details/order-details-page.d.ts +4 -1
  35. package/dist/pages/my-sonic/pages/order-details/order-details-page.js +23 -3
  36. package/dist/pages/my-sonic/pages/order-history/order-history-page.js +5 -2
  37. package/dist/shared/api/storefront/hooks/authentication/use-sign-out-mutation.d.ts +5 -0
  38. package/dist/shared/api/storefront/hooks/authentication/use-sign-out-mutation.js +26 -0
  39. package/dist/shared/api/storefront/hooks/authentication/use-sign-out.d.ts +3 -5
  40. package/dist/shared/api/storefront/hooks/authentication/use-sign-out.js +15 -18
  41. package/dist/shared/api/storefront/hooks/cart/use-add-bulk-products-to-current-cart.d.ts +4 -0
  42. package/dist/shared/api/storefront/hooks/cart/use-add-bulk-products-to-current-cart.js +21 -0
  43. package/dist/shared/api/storefront/services/cart-service.d.ts +4 -0
  44. package/dist/shared/api/storefront/services/cart-service.js +13 -1
  45. package/dist/shared/routing/types.d.ts +1 -1
  46. package/dist/shared/utils/greeting.d.ts +1 -0
  47. package/dist/shared/utils/greeting.js +15 -0
  48. package/dist/shared/utils/price.d.ts +1 -0
  49. package/dist/shared/utils/price.js +3 -0
  50. package/dist/shared/utils/types.d.ts +1 -0
  51. package/dist/shared/utils/types.js +4 -1
  52. package/dist/styles.css +117 -12
  53. package/package.json +1 -1
@@ -4,35 +4,46 @@ import { SolidFavoriteIcon } from '../../../icons/solid/solid-favorite-icon.js';
4
4
  import { SolidLoginIcon } from '../../../icons/solid/solid-login-icon.js';
5
5
  import { SolidLogOutIcon } from '../../../icons/solid/solid-logout-icon.js';
6
6
  import { usePaths } from '../../../shared/routing/use-paths.js';
7
+ import { isObject } from '../../../shared/utils/types.js';
7
8
 
9
+ function isMySonicNavigationLink(item) {
10
+ return isObject(item) && 'type' in item && item.type === 'link';
11
+ }
12
+ function isMySonicNavigationAction(item) {
13
+ return isObject(item) && 'type' in item && item.type === 'action';
14
+ }
8
15
  function useMySonicNavigationItems() {
9
16
  const paths = usePaths();
10
17
  return [
11
18
  {
12
19
  Icon: SolidLoginIcon,
20
+ 'data-test-selector': 'accountLink',
13
21
  label: 'Account',
14
- path: paths.ACCOUNT_SETTINGS.toLowerCase(),
22
+ path: paths.ACCOUNT,
15
23
  type: 'link',
16
24
  },
17
25
  {
18
26
  Icon: SolidFavoriteIcon,
27
+ 'data-test-selector': 'favoritesLink',
19
28
  label: 'Favorites',
20
- path: paths.ACCOUNT_MY_LISTS.toLowerCase(),
29
+ path: paths.ACCOUNT_MY_LISTS,
21
30
  type: 'link',
22
31
  },
23
32
  {
24
33
  Icon: SolidCartIcon,
34
+ 'data-test-selector': 'ordersLink',
25
35
  label: 'Orders',
26
- path: paths.ACCOUNT_ORDERS.toLowerCase(),
36
+ path: paths.ACCOUNT_ORDERS,
27
37
  type: 'link',
28
38
  },
29
39
  {
30
40
  Icon: SolidLogOutIcon,
31
- action: 'logout',
41
+ action: 'signout',
42
+ 'data-test-selector': 'logoutButton',
32
43
  label: 'Log out',
33
44
  type: 'action',
34
45
  },
35
46
  ];
36
47
  }
37
48
 
38
- export { useMySonicNavigationItems };
49
+ export { isMySonicNavigationAction, isMySonicNavigationLink, useMySonicNavigationItems };
@@ -17,8 +17,8 @@ function CreateShipToAddressDetailsPageBreadcrumb({ billToId, }) {
17
17
  const paths = usePaths();
18
18
  return (jsx(MySonicLayoutBreadcrumb, { children: jsx(Breadcrumb, { links: [
19
19
  { href: paths.HOME, label: t('Home') },
20
- { href: paths.ACCOUNT, label: t('My Sonic') },
21
- { href: paths.ACCOUNT_SETTINGS, label: t('Account') },
20
+ { href: paths.MY_SONIC, label: t('My Sonic') },
21
+ { href: paths.ACCOUNT, label: t('Account') },
22
22
  {
23
23
  href: `${paths.ACCOUNT_EDIT_BILL_TO_ADDRESS}/${billToId}${paths.ACCOUNT_EDIT_SHIP_TO_ADDRESS}/new`,
24
24
  label: t('Shipping address'),
@@ -17,8 +17,8 @@ function EditBillToAddressDetailsPageBreadcrumb({ billToId, }) {
17
17
  const paths = usePaths();
18
18
  return (jsx(MySonicLayoutBreadcrumb, { children: jsx(Breadcrumb, { links: [
19
19
  { href: paths.HOME, label: t('Home') },
20
- { href: paths.ACCOUNT, label: t('My Sonic') },
21
- { href: paths.ACCOUNT_SETTINGS, label: t('Account') },
20
+ { href: paths.MY_SONIC, label: t('My Sonic') },
21
+ { href: paths.ACCOUNT, label: t('Account') },
22
22
  {
23
23
  href: `${paths.ACCOUNT_EDIT_BILL_TO_ADDRESS}/${billToId}`,
24
24
  label: t('Billing address'),
@@ -17,8 +17,8 @@ function EditShipToAddressDetailsPageBreadcrumb({ billToId, shipToId, }) {
17
17
  const paths = usePaths();
18
18
  return (jsx(MySonicLayoutBreadcrumb, { children: jsx(Breadcrumb, { links: [
19
19
  { href: paths.HOME, label: t('Home') },
20
- { href: paths.ACCOUNT, label: t('My Sonic') },
21
- { href: paths.ACCOUNT_SETTINGS, label: t('Account') },
20
+ { href: paths.MY_SONIC, label: t('My Sonic') },
21
+ { href: paths.ACCOUNT, label: t('Account') },
22
22
  {
23
23
  href: `${paths.ACCOUNT_EDIT_BILL_TO_ADDRESS}/${billToId}${paths.ACCOUNT_EDIT_SHIP_TO_ADDRESS}/${shipToId}`,
24
24
  label: t('Shipping address'),
@@ -15,7 +15,7 @@ function FavoritesPageBreadcrumb() {
15
15
  const paths = usePaths();
16
16
  return (jsx(MySonicLayoutBreadcrumb, { children: jsx(Breadcrumb, { links: [
17
17
  { href: paths.HOME, label: t('Home') },
18
- { href: paths.ACCOUNT, label: t('My Sonic') },
18
+ { href: paths.MY_SONIC, label: t('My Sonic') },
19
19
  { href: paths.ACCOUNT_MY_LISTS, label: t('Favorites') },
20
20
  ] }) }));
21
21
  }
@@ -22,8 +22,8 @@ function MyAccountPageBreadcrumb() {
22
22
  const paths = usePaths();
23
23
  return (jsx(MySonicLayoutBreadcrumb, { children: jsx(Breadcrumb, { links: [
24
24
  { href: paths.HOME, label: t('Home') },
25
- { href: paths.ACCOUNT, label: t('My Sonic') },
26
- { href: paths.ACCOUNT_SETTINGS, label: t('Account') },
25
+ { href: paths.MY_SONIC, label: t('My Sonic') },
26
+ { href: paths.ACCOUNT, label: t('Account') },
27
27
  ] }) }));
28
28
  }
29
29
 
@@ -1,8 +1,10 @@
1
+ import { ReactNode } from 'react';
1
2
  import { OrderModel } from '../../../../shared/api/storefront/model/storefront.model';
2
3
  import { StatusType } from '../../../../text/status-text/status-text';
3
4
  export type OrderDetailsContentProps = {
4
5
  order: OrderModel;
6
+ reorderButton: ReactNode;
5
7
  returnUrl?: string;
6
8
  };
7
9
  export declare const statusMap: Partial<Record<OrderModel['status'], StatusType>>;
8
- export declare function OrderDetailsContent({ order, returnUrl, }: OrderDetailsContentProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function OrderDetailsContent({ order, reorderButton, returnUrl, }: OrderDetailsContentProps): import("react/jsx-runtime").JSX.Element;
@@ -46,10 +46,10 @@ const getOrderShipToAddress = (order) => ({
46
46
  phone: '',
47
47
  postalCode: order.shipToPostalCode,
48
48
  });
49
- function OrderDetailsContent({ order, returnUrl, }) {
49
+ function OrderDetailsContent({ order, reorderButton, returnUrl, }) {
50
50
  const paths = usePaths();
51
51
  const status = statusMap[order.status];
52
- return (jsxs("div", { className: styles['order-details'], children: [jsxs("section", { className: styles['order-header'], children: [jsxs("div", { className: styles['order-header-info'], children: [jsxs(Heading, { size: "xxs", tag: "h2", children: [jsx(FormattedMessage, { id: "Order" }), " #", order.webOrderNumber] }), jsxs("div", { children: [jsx(FormattedMessage, { id: "Status" }), ":", ' ', jsx(StatusText, { "data-test-selector": "order-status", status: status, children: jsx(FormattedMessage, { noTranslationId: true, id: `orderStatus.${order.status}` }) })] })] }), jsx(PrintButton, { size: "sm" }), jsx(Button, { "data-test-selector": "reorder-button", size: "sm", children: jsx(FormattedMessage, { id: "Reorder" }) })] }), jsxs("section", { className: styles['order-additional-info'], children: [jsxs("dl", { children: [jsx("dt", { children: jsx(FormattedMessage, { id: "orderProperty.Date" }) }), jsx("dd", { children: jsx(FormattedDate, { date: order.orderDate }) })] }), jsxs("dl", { children: [jsx("dt", { children: jsx(FormattedMessage, { id: "orderProperty.PO Number" }) }), jsx("dd", { children: order.customerNumber })] })] }), jsx("section", { className: styles['order-billing-and-shipping'], children: jsx(BillingAndInvoiceInformation, { billToAddress: getOrderBillToAddress(order), shipToAddress: getOrderShipToAddress(order) }) }), jsx("section", { className: styles['order-top-button'], children: jsx(Button, { color: "secondary", href: returnUrl || paths.ACCOUNT_ORDERS, size: "sm", variant: "outline", children: jsx(FormattedMessage, { id: "Back" }) }) }), jsxs("section", { className: styles['order-line-list'], children: [jsx(Heading, { size: "xxs", tag: "h3", children: jsx(FormattedMessage, { id: "Products" }) }), jsx(OrderLineList, { children: order.orderLines?.map(line => (jsx(OrderLineCard, { isReadonly: true, href: line.productUri, image: {
52
+ return (jsxs("div", { className: styles['order-details'], children: [jsxs("section", { className: styles['order-header'], children: [jsxs("div", { className: styles['order-header-info'], children: [jsxs(Heading, { size: "xxs", tag: "h2", children: [jsx(FormattedMessage, { id: "Order" }), " #", order.webOrderNumber] }), jsxs("div", { children: [jsx(FormattedMessage, { id: "Status" }), ":", ' ', jsx(StatusText, { "data-test-selector": "order-status", status: status, children: jsx(FormattedMessage, { noTranslationId: true, id: `orderStatus.${order.status}` }) })] })] }), jsx(PrintButton, {}), reorderButton] }), jsxs("section", { className: styles['order-additional-info'], children: [jsxs("dl", { children: [jsx("dt", { children: jsx(FormattedMessage, { id: "orderProperty.Date" }) }), jsx("dd", { children: jsx(FormattedDate, { date: order.orderDate }) })] }), jsxs("dl", { children: [jsx("dt", { children: jsx(FormattedMessage, { id: "orderProperty.PO Number" }) }), jsx("dd", { children: order.customerPO })] })] }), jsx("section", { className: styles['order-billing-and-shipping'], children: jsx(BillingAndInvoiceInformation, { billToAddress: getOrderBillToAddress(order), shipToAddress: getOrderShipToAddress(order) }) }), jsx("section", { className: styles['order-top-button'], children: jsx(Button, { color: "secondary", href: returnUrl || paths.ACCOUNT_ORDERS, variant: "outline", children: jsx(FormattedMessage, { id: "Back" }) }) }), jsxs("section", { className: styles['order-line-list'], children: [jsx(Heading, { size: "xxs", tag: "h3", children: jsx(FormattedMessage, { id: "Products" }) }), jsx(OrderLineList, { children: order.orderLines?.map(line => (jsx(OrderLineCard, { isReadonly: true, href: line.productUri, image: {
53
53
  fit: 'contain',
54
54
  image: {
55
55
  '1': line.mediumImagePath,
@@ -63,7 +63,7 @@ function OrderDetailsContent({ order, returnUrl, }) {
63
63
  originalTotalPrice: ensureNumber(line.lineTotal),
64
64
  pricePerUnit: line.unitPrice,
65
65
  totalPrice: line.lineTotal,
66
- }, productId: line.productId, quantity: line.qtyOrdered, sku: line.customerProductNumber, title: line.shortDescription }, line.id))) })] }), jsx("section", { className: styles['order-cost-overview'], children: jsx(CartTotals, { currencyCode: order.currencyCode, shippingCost: order.shippingAndHandling, subtotal: order.orderSubTotal, tax: order.taxAmount, total: order.orderTotal, vatPercentage: undefined }) }), jsx("section", { className: styles['order-bottom-button'], children: jsx(Button, { color: "secondary", href: returnUrl || paths.ACCOUNT_ORDERS, size: "sm", variant: "outline", children: jsx(FormattedMessage, { id: "Back" }) }) })] }));
66
+ }, productId: line.productId, quantity: line.qtyOrdered, sku: line.customerProductNumber, title: line.shortDescription }, line.id))) })] }), jsx("section", { className: styles['order-cost-overview'], children: jsx(CartTotals, { currencyCode: order.currencyCode, shippingCost: order.shippingAndHandling, subtotal: order.orderSubTotal, tax: order.taxAmount, total: order.orderTotal, vatPercentage: undefined }) }), jsx("section", { className: styles['order-bottom-button'], children: jsx(Button, { color: "secondary", href: returnUrl || paths.ACCOUNT_ORDERS, variant: "outline", children: jsx(FormattedMessage, { id: "Back" }) }) })] }));
67
67
  }
68
68
 
69
69
  export { OrderDetailsContent, statusMap };
@@ -2,4 +2,7 @@ export type OrderDetailsProps = {
2
2
  orderId: string;
3
3
  returnUrl?: string;
4
4
  };
5
- export declare function OrderDetails({ orderId, returnUrl }: OrderDetailsProps): import("react/jsx-runtime").JSX.Element;
5
+ export declare function OrderDetailsPage({ orderId, returnUrl }: OrderDetailsProps): import("react/jsx-runtime").JSX.Element;
6
+ export declare function OrderDetailsPageBreadcrumb({ orderId }: {
7
+ orderId: string;
8
+ }): import("react/jsx-runtime").JSX.Element;
@@ -1,12 +1,19 @@
1
1
  "use client";
2
2
  import { jsx } from 'react/jsx-runtime';
3
+ import { Breadcrumb } from '../../../../breadcrumbs/breadcrumb.js';
4
+ import { ConnectedReorderButton } from '../../../../buttons/reorder-button/connected-reorder-button.js';
5
+ import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
3
6
  import { useFetchOrderById } from '../../../../shared/api/storefront/hooks/orders/use-fetch-order-by-id.js';
7
+ import { usePaths } from '../../../../shared/routing/use-paths.js';
4
8
  import { ErrorPage } from '../../../error-page/error-page.js';
5
9
  import { LoadingPage } from '../../../loading-page/loading-page.js';
10
+ import { MySonicLayoutBreadcrumb } from '../../layouts/my-sonic-layout/my-sonic-layout-breadcrumb.js';
11
+ import { MySonicLayoutPage } from '../../layouts/my-sonic-layout/my-sonic-layout-page.js';
6
12
  import { OrderDetailsContent } from './order-details-content.js';
7
13
 
8
- function OrderDetails({ orderId, returnUrl }) {
14
+ function OrderDetailsPage({ orderId, returnUrl }) {
9
15
  const { data: order, error, isLoading } = useFetchOrderById(orderId);
16
+ const t = useFormattedMessage();
10
17
  if (isLoading) {
11
18
  return jsx(LoadingPage, {});
12
19
  }
@@ -16,7 +23,20 @@ function OrderDetails({ orderId, returnUrl }) {
16
23
  if (!order) {
17
24
  return (jsx(ErrorPage, { error: new Error(`Order with ID ${orderId} not found. Please try again later.`) }));
18
25
  }
19
- return jsx(OrderDetailsContent, { order: order, returnUrl: returnUrl });
26
+ return (jsx(MySonicLayoutPage, { "data-test-selector": "order-history", title: t('Order details'), children: jsx(OrderDetailsContent, { order: order, reorderButton: jsx(ConnectedReorderButton, { orderId: orderId }), returnUrl: returnUrl }) }));
27
+ }
28
+ function OrderDetailsPageBreadcrumb({ orderId }) {
29
+ const t = useFormattedMessage();
30
+ const paths = usePaths();
31
+ return (jsx(MySonicLayoutBreadcrumb, { children: jsx(Breadcrumb, { links: [
32
+ { href: paths.HOME, label: t('Home') },
33
+ { href: paths.MY_SONIC, label: t('My Sonic') },
34
+ { href: paths.ACCOUNT_ORDERS, label: t('Orders') },
35
+ {
36
+ href: `${paths.ACCOUNT_ORDERS}/${orderId}`,
37
+ label: t('Order details'),
38
+ },
39
+ ] }) }));
20
40
  }
21
41
 
22
- export { OrderDetails };
42
+ export { OrderDetailsPage, OrderDetailsPageBreadcrumb };
@@ -9,6 +9,7 @@ import { SearchField } from '../../../../forms/fields/search-field/search-field.
9
9
  import { SelectField } from '../../../../forms/fields/select-field/select-field.js';
10
10
  import { SolidCartIcon } from '../../../../icons/solid/solid-cart-icon.js';
11
11
  import { FormattedDate } from '../../../../intl/formatted-date.js';
12
+ import { FormattedMessage } from '../../../../intl/formatted-message.js';
12
13
  import { useFormattedMessage } from '../../../../intl/use-formatted-message.js';
13
14
  import { useIntl } from '../../../../intl/use-intl.js';
14
15
  import { DynamicLoadingOverlay } from '../../../../loading/dynamic-loading-overlay.js';
@@ -164,7 +165,9 @@ function OrderHistoryPage() {
164
165
  'data-test-selector': 'reorderButton',
165
166
  nowrap: true,
166
167
  },
167
- value: { action: 'reorder' },
168
+ value: {
169
+ render: order => (jsx(Link, { hasUnderline: true, color: "secondary", "data-test-selector": "order-history-order-link", href: `${paths.ACCOUNT_ORDERS}/${order.webOrderNumber}?returnUrl=${encodeURIComponent(`${paths.ACCOUNT_ORDERS}`)}`, children: jsx(FormattedMessage, { id: "Reorder" }) })),
170
+ },
168
171
  },
169
172
  ], data: orders, onSort: (key, direction) => {
170
173
  if (direction === 'NONE')
@@ -182,7 +185,7 @@ function OrderHistoryPageBreadcrumb() {
182
185
  const paths = usePaths();
183
186
  return (jsx(MySonicLayoutBreadcrumb, { children: jsx(Breadcrumb, { links: [
184
187
  { href: paths.HOME, label: t('Home') },
185
- { href: paths.ACCOUNT, label: t('My Sonic') },
188
+ { href: paths.MY_SONIC, label: t('My Sonic') },
186
189
  { href: paths.ACCOUNT_ORDERS, label: t('Orders') },
187
190
  ] }) }));
188
191
  }
@@ -0,0 +1,5 @@
1
+ export interface UseSignOutArgs {
2
+ onError?: (error: Error) => void;
3
+ onSuccess?: VoidFunction;
4
+ }
5
+ export declare function useSignOutMutation(options?: UseSignOutArgs): import("@tanstack/react-query").UseMutationResult<void, Error, void, unknown>;
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { useQueryClient, useMutation } from '@tanstack/react-query';
3
+ import { UnauthorizedRequestError } from '../../../../fetch/request.js';
4
+ import { signOut } from '../../services/authentication-service.js';
5
+
6
+ function useSignOutMutation(options = {}) {
7
+ const queryClient = useQueryClient();
8
+ return useMutation({
9
+ ...options,
10
+ mutationFn: async () => {
11
+ try {
12
+ await signOut();
13
+ }
14
+ catch (error) {
15
+ if (error instanceof UnauthorizedRequestError)
16
+ return;
17
+ throw error;
18
+ }
19
+ finally {
20
+ queryClient.resetQueries();
21
+ }
22
+ },
23
+ });
24
+ }
25
+
26
+ export { useSignOutMutation };
@@ -1,5 +1,3 @@
1
- export interface UseSignOutArgs {
2
- onError?: (error: Error) => void;
3
- onSuccess?: VoidFunction;
4
- }
5
- export declare function useSignOut(options?: UseSignOutArgs): import("@tanstack/react-query").UseMutationResult<void, Error, void, unknown>;
1
+ export declare function useSignOut(options?: {
2
+ onSignOut?: VoidFunction;
3
+ }): import("@tanstack/react-query").UseMutateFunction<void, Error, void, unknown>;
@@ -1,26 +1,23 @@
1
1
  "use client";
2
- import { useQueryClient, useMutation } from '@tanstack/react-query';
3
- import { UnauthorizedRequestError } from '../../../../fetch/request.js';
4
- import { signOut } from '../../services/authentication-service.js';
2
+ import Cookies from 'js-cookie';
3
+ import { logger } from '../../../../../logging/logger.js';
4
+ import { useNavigate } from '../../../../routing/use-navigate.js';
5
+ import { usePaths } from '../../../../routing/use-paths.js';
6
+ import { useSignOutMutation } from './use-sign-out-mutation.js';
5
7
 
6
8
  function useSignOut(options = {}) {
7
- const queryClient = useQueryClient();
8
- return useMutation({
9
- ...options,
10
- mutationFn: async () => {
11
- try {
12
- await signOut();
13
- }
14
- catch (error) {
15
- if (error instanceof UnauthorizedRequestError)
16
- return;
17
- throw error;
18
- }
19
- finally {
20
- queryClient.resetQueries();
21
- }
9
+ const { navigate } = useNavigate();
10
+ const paths = usePaths();
11
+ const { mutate } = useSignOutMutation({
12
+ onError: logger.error,
13
+ onSuccess: () => {
14
+ // TODO: Remove when Spire is deprecated
15
+ Cookies.remove('NavigationMode');
16
+ navigate(paths.HOME, { reload: true });
17
+ options.onSignOut?.();
22
18
  },
23
19
  });
20
+ return mutate;
24
21
  }
25
22
 
26
23
  export { useSignOut };
@@ -0,0 +1,4 @@
1
+ import { useMutation } from '@tanstack/react-query';
2
+ import { CartLineModel } from '../../model/storefront.model';
3
+ import { AddBulkProductsToCurrentCartParams } from '../../services/cart-service';
4
+ export declare function useAddBulkProductsToCurrentCart(options?: Parameters<typeof useMutation<CartLineModel[], Error, AddBulkProductsToCurrentCartParams>>[0]): import("@tanstack/react-query").UseMutationResult<CartLineModel[], Error, AddBulkProductsToCurrentCartParams, unknown>;
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { useQueryClient, useMutation } from '@tanstack/react-query';
3
+ import { addBulkProductsToCurrentCart } from '../../services/cart-service.js';
4
+
5
+ function useAddBulkProductsToCurrentCart(options) {
6
+ const queryClient = useQueryClient();
7
+ return useMutation({
8
+ mutationFn: async (params) => {
9
+ const result = await addBulkProductsToCurrentCart(params);
10
+ queryClient.invalidateQueries({ queryKey: ['carts', 'current'] });
11
+ return result;
12
+ },
13
+ onError: (error, variables, context) => {
14
+ queryClient.invalidateQueries({ queryKey: ['carts', 'current'] });
15
+ options?.onError?.(error, variables, context);
16
+ },
17
+ ...options,
18
+ });
19
+ }
20
+
21
+ export { useAddBulkProductsToCurrentCart };
@@ -21,7 +21,11 @@ export interface AddProductToCurrentCartParams {
21
21
  qtyOrdered: number;
22
22
  unitOfMeasure: string;
23
23
  }
24
+ export interface AddBulkProductsToCurrentCartParams {
25
+ cartLines: AddProductToCurrentCartParams[];
26
+ }
24
27
  export declare function addProductToCurrentCart(productOrderData: AddProductToCurrentCartParams): Promise<ShopCartLineModel>;
28
+ export declare function addBulkProductsToCurrentCart(params: AddBulkProductsToCurrentCartParams): Promise<ShopCartLineModel[]>;
25
29
  export declare function fetchCurrentCartProductAtp(): Promise<ProductAtp[]>;
26
30
  export declare function fetchCurrentCheckoutAtp(): Promise<CheckoutAtpEntry[]>;
27
31
  export declare function postAdyenPayment({ currencyCode, data, orderAmount, returnUrl, webOrderNumber, }: {
@@ -67,6 +67,18 @@ async function addProductToCurrentCart(productOrderData) {
67
67
  });
68
68
  return body;
69
69
  }
70
+ async function addBulkProductsToCurrentCart(params) {
71
+ const { body } = await request({
72
+ body: JSON.stringify(params),
73
+ credentials: 'include',
74
+ headers: {
75
+ 'Content-Type': 'application/json',
76
+ },
77
+ method: 'POST',
78
+ url: `${config.SHOP_API_URL}/api/v1/carts/current/cartlines/batch`,
79
+ });
80
+ return body;
81
+ }
70
82
  async function fetchCurrentCartProductAtp() {
71
83
  const { body } = await request({
72
84
  credentials: 'include',
@@ -152,4 +164,4 @@ function convertToMinorUnits(value, currencyCode) {
152
164
  return Math.round(valueInMinorUnits);
153
165
  }
154
166
 
155
- export { addProductToCurrentCart, convertToMinorUnits, deleteCartLineById, deleteCurrentCart, fetchCart, fetchCurrentCart, fetchCurrentCartLines, fetchCurrentCartProductAtp, fetchCurrentCartPromotions, fetchCurrentCheckoutAtp, getAdyenPaymentDetails, patchCartLineById, postAdyenPayment };
167
+ export { addBulkProductsToCurrentCart, addProductToCurrentCart, convertToMinorUnits, deleteCartLineById, deleteCurrentCart, fetchCart, fetchCurrentCart, fetchCurrentCartLines, fetchCurrentCartProductAtp, fetchCurrentCartPromotions, fetchCurrentCheckoutAtp, getAdyenPaymentDetails, patchCartLineById, postAdyenPayment };
@@ -8,12 +8,12 @@ export interface Paths {
8
8
  ACCOUNT_INVOICES: string;
9
9
  ACCOUNT_MY_LISTS: string;
10
10
  ACCOUNT_ORDERS: string;
11
- ACCOUNT_SETTINGS: string;
12
11
  CART: string;
13
12
  CHECKOUT_SHIPPING: string;
14
13
  CHECKOUT_SHIPPING_VIA_SIGNIN: string;
15
14
  FAVORITES: string;
16
15
  HOME: string;
16
+ MY_SONIC: string;
17
17
  ORDER_CONFIRMATION: string;
18
18
  REVIEW_AND_SUBMIT: string;
19
19
  SIGN_IN: string;
@@ -0,0 +1 @@
1
+ export declare function useGreeting(): string;
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { useFormattedMessage } from '../../intl/use-formatted-message.js';
3
+
4
+ const greetings = [
5
+ 'Goodnight',
6
+ 'Good morning',
7
+ 'Good afternoon',
8
+ 'Good evening',
9
+ ];
10
+ function useGreeting() {
11
+ const t = useFormattedMessage();
12
+ return t(greetings[Math.trunc(new Date().getHours() / 6)] || 'Good day');
13
+ }
14
+
15
+ export { useGreeting };
@@ -3,6 +3,7 @@ type NumberFormatPartTypes = ReturnType<Intl.NumberFormat['formatToParts']>[0]['
3
3
  interface ParcedCurrencyResult extends Partial<Record<NumberFormatPartTypes, string>> {
4
4
  integers?: string[];
5
5
  parts: Intl.NumberFormatPart[];
6
+ symbolPosition: 'before' | 'after';
6
7
  }
7
8
  export declare function parseCurrency({ currencyCode, locale, price, }: {
8
9
  currencyCode: string;
@@ -18,6 +18,9 @@ function parseCurrency({ currencyCode, locale, price, }) {
18
18
  ...namedParts,
19
19
  integer: namedParts.integers?.join(namedParts.group),
20
20
  parts,
21
+ symbolPosition: parts.findIndex(part => part.type === 'currency') === parts.length - 1
22
+ ? 'after'
23
+ : 'before',
21
24
  };
22
25
  }
23
26
  function formatCurrency({ currencyCode, locale, price, replaceNonBreakingSpace = false, }) {
@@ -1,3 +1,4 @@
1
1
  export type NoValue = null | undefined | '';
2
2
  export declare function has<T>(obj: T | undefined): obj is Exclude<T, NoValue>;
3
3
  export declare function hasNo<T>(obj: T | NoValue): obj is NoValue;
4
+ export declare function isObject(item: unknown): item is object;
@@ -4,5 +4,8 @@ function has(obj) {
4
4
  function hasNo(obj) {
5
5
  return obj === undefined || obj === null || obj === '';
6
6
  }
7
+ function isObject(item) {
8
+ return Boolean(item) && typeof item === 'object';
9
+ }
7
10
 
8
- export { has, hasNo };
11
+ export { has, hasNo, isObject };