@evenicanpm/storefront-core 2.4.2 → 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.
Files changed (142) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/package.json +90 -90
  3. package/src/api-manager/datasources/d365/d365-cart.datasource.ts +4 -3
  4. package/src/api-manager/datasources/d365/d365-user.datasource.ts +3 -3
  5. package/src/api-manager/datasources/d365/utils/get-context-cookie.ts +1 -0
  6. package/src/api-manager/datasources/e4/address/e4-address.datasource.ts +5 -14
  7. package/src/api-manager/datasources/e4/address/e4-address.translator.ts +4 -3
  8. package/src/api-manager/datasources/e4/categories/e4-categories.translator.ts +1 -1
  9. package/src/api-manager/datasources/e4/graphqlRequestSdk.ts +29 -3
  10. package/src/api-manager/datasources/e4/product/e4-product.translator.ts +1 -1
  11. package/src/api-manager/index.ts +1 -1
  12. package/src/api-manager/lib/get-graphql-client.ts +1 -1
  13. package/src/api-manager/services/cart/mutations/add-discount-code.ts +0 -11
  14. package/src/api-manager/services/create-query.ts +13 -7
  15. package/src/api-manager/services/user/mutations/add-to-wishlist.ts +1 -1
  16. package/src/api-manager/services/user/mutations/remove-from-wishlist.ts +1 -1
  17. package/src/auth/AUTH GUIDE.md +880 -0
  18. package/src/cms/blocks/components/featured-categories.tsx +18 -15
  19. package/src/cms/blocks/components/featured-products.tsx +3 -2
  20. package/src/cms/blocks/components/footer/data/index.ts +0 -0
  21. package/src/cms/blocks/components/footer/index.tsx +0 -0
  22. package/src/cms/blocks/components/footer/sections/footer-app-store.tsx +0 -0
  23. package/src/cms/blocks/components/footer/sections/footer-contact.tsx +0 -2
  24. package/src/cms/blocks/components/footer/sections/footer-links.tsx +0 -0
  25. package/src/cms/blocks/components/footer/sections/footer-logo.tsx +2 -1
  26. package/src/cms/blocks/components/footer/sections/footer-social-links.tsx +0 -0
  27. package/src/cms/blocks/components/footer/styles/index.ts +0 -0
  28. package/src/cms/blocks/components/hero-carousel/index.tsx +0 -0
  29. package/src/cms/blocks/components/product-carousel/index.tsx +0 -0
  30. package/src/cms/blocks/components/shared/featured-product-card.tsx +0 -0
  31. package/src/cms/blocks/components/shared/product-category-item.tsx +0 -0
  32. package/src/cms/blocks/components/shared/product-grid.tsx +0 -0
  33. package/src/cms/blocks/components/shared/top-categories-card.tsx +0 -0
  34. package/src/cms/blocks/components/shared/top-rating-product-card.tsx +0 -0
  35. package/src/cms/blocks/icons/components/category.tsx +0 -0
  36. package/src/cms/blocks/icons/components/dotted-star.tsx +0 -0
  37. package/src/cms/blocks/icons/components/gift-box.tsx +0 -0
  38. package/src/cms/blocks/icons/components/light.tsx +0 -0
  39. package/src/cms/blocks/icons/components/new-arrival.tsx +0 -0
  40. package/src/cms/blocks/icons/components/rank-badge.tsx +0 -0
  41. package/src/components/SearchInput.stories.tsx +12 -10
  42. package/src/components/base-layout.tsx +42 -0
  43. package/src/components/categories/category-list/category-list.tsx +32 -12
  44. package/src/components/header/__tests__/header.test.tsx +0 -24
  45. package/src/components/header/components/mobile-header.tsx +16 -8
  46. package/src/components/header/header.tsx +6 -3
  47. package/src/components/mini-cart/components/bottom-actions.tsx +7 -2
  48. package/src/components/mini-cart/components/cart-item.tsx +16 -13
  49. package/src/components/mini-cart/components/empty-view.tsx +12 -6
  50. package/src/components/mini-cart/components/top-header.tsx +9 -8
  51. package/src/components/mini-cart/mini-cart-trigger.tsx +11 -5
  52. package/src/components/mini-cart/mini-cart.tsx +30 -15
  53. package/src/components/mobile-navigation/mobile-navigation-bar.tsx +6 -2
  54. package/src/components/navbar/categories.tsx +8 -2
  55. package/src/components/navbar/category-based-menu/category-based-menu.tsx +6 -2
  56. package/src/components/navbar/mega-menu/mega-menu.tsx +22 -14
  57. package/src/components/navbar/mobile-menu/mobile-menu.test.tsx +8 -11
  58. package/src/components/navbar/mobile-menu/mobile-menu.tsx +13 -11
  59. package/src/components/navbar/nav-list/nav-list.tsx +3 -2
  60. package/src/components/navbar/navbar.tsx +4 -2
  61. package/src/components/product-cards/product-card/product-card.tsx +50 -26
  62. package/src/components/product-cards/product-card-plp/product-card.tsx +37 -16
  63. package/src/components/product-cards/product-card-plp-list/product-card.tsx +38 -16
  64. package/src/components/product-cards/product-card-search/product-card.tsx +34 -13
  65. package/src/components/product-dialog/ProductDialog.stories.tsx +20 -18
  66. package/src/components/product-dialog/compound/product-dialog.tsx +7 -4
  67. package/src/components/product-dimensions/compound/dimensions-group.tsx +4 -2
  68. package/src/components/product-dimensions/compound/dimensions.tsx +15 -6
  69. package/src/components/product-quantity-buttons/compound/quantity-buttons-root.tsx +21 -13
  70. package/src/components/products-view/compound/products-grid-view.tsx +11 -4
  71. package/src/components/products-view/compound/products-list-view.tsx +11 -4
  72. package/src/components/search-bar/compound/search-bar-root.tsx +6 -4
  73. package/src/components/search-bar/compound/textfield-adornment-category.tsx +25 -8
  74. package/src/components/search-bar/hooks/use-click-outside.ts +7 -1
  75. package/src/components/search-bar/hooks/use-search.ts +3 -3
  76. package/src/components/user/index.ts +3 -0
  77. package/src/components/user/use-user-auth.ts +163 -0
  78. package/src/components/user/user.tsx +215 -0
  79. package/src/components/wishlist-dialogs/add-to-wishlist/AddToWishlist.stories.tsx +20 -15
  80. package/src/components/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-dialog.tsx +11 -8
  81. package/src/components/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-list.tsx +18 -3
  82. package/src/components/wishlist-dialogs/add-to-wishlist/index.tsx +0 -1
  83. package/src/components/wishlist-dialogs/create-wishlist/compound/create-wishlist-dialog.tsx +6 -2
  84. package/src/hooks/use-overflow-detect.ts +4 -4
  85. package/src/lib/graphqlRequestSdk.ts +0 -0
  86. package/src/lib/page-slugs.ts +16 -0
  87. package/src/pages/account/account-navigation.tsx +7 -14
  88. package/src/pages/account/account-routes.ts +4 -9
  89. package/src/pages/account/addresses/address-form.tsx +38 -16
  90. package/src/pages/account/addresses/address-item.tsx +18 -8
  91. package/src/pages/account/dashboard-header.tsx +20 -13
  92. package/src/pages/account/orders/order-history-filters-panel.tsx +21 -20
  93. package/src/pages/account/orders/order-history-header.tsx +14 -4
  94. package/src/pages/account/orders/order-history-root.tsx +3 -1
  95. package/src/pages/account/orders/order-history-row.tsx +12 -4
  96. package/src/pages/account/orders/order-history-search-and-filter.tsx +88 -59
  97. package/src/pages/account/orders/order-history-search-dropdown.tsx +26 -9
  98. package/src/pages/account/orders/order-history-sort.tsx +3 -1
  99. package/src/pages/account/orders/order-history-table.tsx +27 -5
  100. package/src/pages/account/orders/order-progress.tsx +12 -6
  101. package/src/pages/account/orders/order-row.tsx +18 -6
  102. package/src/pages/account/orders/order-summary.tsx +24 -8
  103. package/src/pages/account/orders/ordered-products.tsx +15 -5
  104. package/src/pages/account/profile/user-info.tsx +11 -3
  105. package/src/pages/account/table-row-skeleton.tsx +1 -1
  106. package/src/pages/account/wishlist/create-new-list.tsx +33 -9
  107. package/src/pages/account/wishlist/wishlist-item.tsx +18 -6
  108. package/src/pages/cart/cart-item.tsx +21 -7
  109. package/src/pages/cart/checkout-form.tsx +55 -22
  110. package/src/pages/cart/coupon-entry.tsx +143 -36
  111. package/src/pages/cart/estimate-shipping.tsx +45 -21
  112. package/src/pages/checkout/checkout-alt-form/checkout-form.tsx +22 -14
  113. package/src/pages/checkout/checkout-alt-form/checkout-step.tsx +37 -16
  114. package/src/pages/checkout/checkout-alt-form/steps/address/address-card.tsx +9 -3
  115. package/src/pages/checkout/checkout-alt-form/steps/address/delivery-address.tsx +84 -51
  116. package/src/pages/checkout/checkout-alt-form/steps/address/new-address-form.tsx +41 -19
  117. package/src/pages/checkout/checkout-alt-form/steps/customer-info/customer-information.tsx +17 -10
  118. package/src/pages/checkout/checkout-alt-form/steps/payment/payment-details.tsx +15 -6
  119. package/src/pages/checkout/checkout-alt-form/steps/shipping/delivery-options.tsx +6 -2
  120. package/src/pages/checkout/checkout-alt-summary/cart-item.tsx +12 -4
  121. package/src/pages/checkout/checkout-alt-summary/checkout-alt-summary.tsx +12 -5
  122. package/src/pages/checkout/checkout-alt-summary/list-item.tsx +17 -10
  123. package/src/pages/confirmation/address.tsx +6 -2
  124. package/src/pages/confirmation/confirmation-summary.tsx +12 -4
  125. package/src/pages/confirmation/ordered-products.tsx +12 -4
  126. package/src/pages/product-details/bopis/store-card/shop-card.tsx +2 -2
  127. package/src/pages/product-details/bopis/store-card/utils/getDaysResources.ts +1 -1
  128. package/src/pages/product-details/product-intro/compound/product-info.tsx +41 -18
  129. package/src/pages/product-details/product-intro/compound/product-intro-images.tsx +18 -12
  130. package/src/pages/product-details/product-intro/compound/product-intro.tsx +20 -10
  131. package/src/pages/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +1 -1
  132. package/src/pages/product-details/product-tabs.tsx +20 -12
  133. package/src/pages/product-list/product-list-view.tsx +4 -2
  134. package/src/pages/product-list/search-bar.tsx +7 -7
  135. package/src/pages/product-list/side-nav.tsx +5 -3
  136. package/src/pages/quickorder/order-upload.tsx +1 -1
  137. package/src/pages/quickorder/provider.tsx +26 -14
  138. package/src/pages/quickorder/quick-order.tsx +49 -22
  139. package/src/providers/nav-provider/index.tsx +16 -11
  140. package/tsconfig.json +0 -5
  141. package/src/components/header/components/user.tsx +0 -322
  142. /package/src/components/{header → user}/__tests__/user.test.tsx +0 -0
@@ -4,7 +4,7 @@ import type {
4
4
  SalesStatus,
5
5
  } from "@msdyn365-commerce/retail-proxy";
6
6
  import { Box } from "@mui/material";
7
- import { createContext, useContext, useState } from "react";
7
+ import { createContext, useContext, useMemo, useState } from "react";
8
8
  import {
9
9
  type CreatedDateFilter,
10
10
  FilterSourceType,
@@ -226,10 +226,8 @@ type OrdersSearchAndFilterContextType = {
226
226
  selectedOrigins: OriginFilter[];
227
227
  handleSelectOrigin: (origin: OriginFilter) => void;
228
228
  createdDate?: CreatedDateFilter;
229
- handleSelectCreatedDate: (
230
- date: CreatedDateFilter | undefined,
231
- toggle?: boolean,
232
- ) => void;
229
+ handleSelectCreatedDate: (date: CreatedDateFilter | undefined) => void;
230
+ handleSetCreatedDate: (date: CreatedDateFilter | undefined) => void;
233
231
  orderStatus?: OrderStatusFilter;
234
232
  handleSelectOrderStatus: (status: OrderStatusFilter | undefined) => void;
235
233
 
@@ -291,15 +289,12 @@ const OrdersSearchAndFilter = ({ children }: { children: React.ReactNode }) => {
291
289
  });
292
290
  };
293
291
 
294
- const handleSelectCreatedDate = (
295
- date: CreatedDateFilter | undefined,
296
- toggle = true,
297
- ) => {
298
- toggle
299
- ? setCreatedDate((prev) =>
300
- prev?.label === date?.label ? undefined : date,
301
- )
302
- : setCreatedDate(date);
292
+ const handleSelectCreatedDate = (date: CreatedDateFilter | undefined) => {
293
+ setCreatedDate((prev) => (prev?.label === date?.label ? undefined : date));
294
+ };
295
+
296
+ const handleSetCreatedDate = (date: CreatedDateFilter | undefined) => {
297
+ setCreatedDate(date);
303
298
  };
304
299
 
305
300
  const handleSelectOrderStatus = (status: OrderStatusFilter | undefined) => {
@@ -313,6 +308,47 @@ const OrdersSearchAndFilter = ({ children }: { children: React.ReactNode }) => {
313
308
  setOrderSearchCriteria(searchCriteria);
314
309
  };
315
310
 
311
+ const applySearchTextCriteria = (
312
+ orderSearchCriteria: OrderSearchCriteria,
313
+ ): void => {
314
+ if (!searchText) {
315
+ return;
316
+ }
317
+
318
+ if (selectedSearchOption === 0) {
319
+ orderSearchCriteria.ChannelReferenceId = searchText;
320
+ return;
321
+ }
322
+
323
+ if (selectedSearchOption === 1) {
324
+ orderSearchCriteria.SalesId = searchText;
325
+ return;
326
+ }
327
+
328
+ if (selectedSearchOption === 2) {
329
+ const channelIds = stores
330
+ ?.filter((store) =>
331
+ store.location.OrgUnitName?.toLocaleLowerCase().includes(
332
+ searchText.toLowerCase(),
333
+ ),
334
+ )
335
+ .map((store) => store.location.ChannelId)
336
+ .filter((id): id is number => id !== undefined);
337
+
338
+ if (channelIds?.length) {
339
+ if (orderSearchCriteria.ChannelIds?.length) {
340
+ const intersectingChannelIds = channelIds.filter((id) =>
341
+ orderSearchCriteria.ChannelIds?.includes(id),
342
+ );
343
+
344
+ orderSearchCriteria.ChannelIds = intersectingChannelIds;
345
+ } else {
346
+ orderSearchCriteria.ChannelIds = channelIds;
347
+ }
348
+ }
349
+ }
350
+ };
351
+
316
352
  const createSearchCriteria = (): OrderSearchCriteria => {
317
353
  const orderSearchCriteria: OrderSearchCriteria = {};
318
354
 
@@ -322,7 +358,7 @@ const OrdersSearchAndFilter = ({ children }: { children: React.ReactNode }) => {
322
358
  }
323
359
  const salesStatus = orderStatus?.value ?? undefined;
324
360
  const salesStatuses: SalesStatus[] =
325
- salesStatus !== undefined ? [salesStatus] : [];
361
+ salesStatus === undefined ? [] : [salesStatus];
326
362
  if (salesStatuses.length > 0) {
327
363
  orderSearchCriteria.OrderStatusValues = salesStatuses;
328
364
  }
@@ -333,34 +369,7 @@ const OrdersSearchAndFilter = ({ children }: { children: React.ReactNode }) => {
333
369
  orderSearchCriteria.EndDateTime = endDate;
334
370
  }
335
371
 
336
- if (searchText) {
337
- if (selectedSearchOption === 0) {
338
- orderSearchCriteria.ChannelReferenceId = searchText;
339
- } else if (selectedSearchOption === 1) {
340
- orderSearchCriteria.SalesId = searchText;
341
- } else if (selectedSearchOption === 2) {
342
- const channelIds = stores
343
- ?.filter((store) =>
344
- store.location.OrgUnitName?.toLocaleLowerCase().includes(
345
- searchText.toLowerCase(),
346
- ),
347
- )
348
- .map((store) => store.location.ChannelId)
349
- .filter((id): id is number => id !== undefined);
350
-
351
- if (channelIds?.length) {
352
- if (orderSearchCriteria.ChannelIds?.length) {
353
- const intersectingChannelIds = channelIds.filter((id) =>
354
- orderSearchCriteria.ChannelIds?.includes(id),
355
- );
356
-
357
- orderSearchCriteria.ChannelIds = intersectingChannelIds;
358
- } else {
359
- orderSearchCriteria.ChannelIds = channelIds;
360
- }
361
- }
362
- }
363
- }
372
+ applySearchTextCriteria(orderSearchCriteria);
364
373
 
365
374
  return orderSearchCriteria;
366
375
  };
@@ -395,7 +404,9 @@ const OrdersSearchAndFilter = ({ children }: { children: React.ReactNode }) => {
395
404
  Number.isNaN(customStart.getTime()) ||
396
405
  Number.isNaN(customEnd.getTime())
397
406
  ) {
398
- throw new Error("Invalid date format in customized date range.");
407
+ throw new TypeError(
408
+ "Invalid date format in customized date range.",
409
+ );
399
410
  }
400
411
 
401
412
  startDate.setTime(customStart.getTime());
@@ -407,7 +418,9 @@ const OrdersSearchAndFilter = ({ children }: { children: React.ReactNode }) => {
407
418
  }
408
419
  break;
409
420
  default:
410
- throw new Error(`Unsupported date filter option: ${option}`);
421
+ throw new Error(
422
+ `Unsupported date filter option: ${option?.label ?? "unknown"}`,
423
+ );
411
424
  }
412
425
 
413
426
  return { startDate, endDate };
@@ -421,20 +434,36 @@ const OrdersSearchAndFilter = ({ children }: { children: React.ReactNode }) => {
421
434
  : new Date(year, month - 1, day, 0, 0, 0, 0);
422
435
  };
423
436
 
424
- const value = {
425
- searchText,
426
- setSearchText,
427
- selectedSearchOption,
428
- setSelectedSearchOption,
429
- originOptions,
430
- selectedOrigins,
431
- handleSelectOrigin,
432
- createdDate,
433
- handleSelectCreatedDate,
434
- orderStatus,
435
- handleSelectOrderStatus,
436
- executeSearch,
437
- };
437
+ const value = useMemo(
438
+ () => ({
439
+ searchText,
440
+ setSearchText,
441
+ selectedSearchOption,
442
+ setSelectedSearchOption,
443
+ originOptions,
444
+ selectedOrigins,
445
+ handleSelectOrigin,
446
+ createdDate,
447
+ handleSelectCreatedDate,
448
+ handleSetCreatedDate,
449
+ orderStatus,
450
+ handleSelectOrderStatus,
451
+ executeSearch,
452
+ }),
453
+ [
454
+ searchText,
455
+ selectedSearchOption,
456
+ originOptions,
457
+ selectedOrigins,
458
+ handleSelectOrigin,
459
+ createdDate,
460
+ handleSelectCreatedDate,
461
+ handleSetCreatedDate,
462
+ orderStatus,
463
+ handleSelectOrderStatus,
464
+ executeSearch,
465
+ ],
466
+ );
438
467
 
439
468
  return (
440
469
  <OrdersSearchAndFilterContext.Provider value={value}>
@@ -14,11 +14,31 @@ interface Props {
14
14
  searchOptions: DisplaySearchOption[];
15
15
  }
16
16
 
17
+ const SearchOptionItem = ({
18
+ item,
19
+ onClose,
20
+ handleChange,
21
+ }: {
22
+ item: DisplaySearchOption;
23
+ onClose: () => void;
24
+ handleChange: (optionId: number) => void;
25
+ }) => (
26
+ <MenuItem
27
+ key={item.id}
28
+ onClick={() => {
29
+ handleChange(item.id);
30
+ onClose();
31
+ }}
32
+ >
33
+ {item.name}
34
+ </MenuItem>
35
+ );
36
+
17
37
  export default function OrdersSearchDropdown({
18
38
  title,
19
39
  handleChange,
20
40
  searchOptions,
21
- }: Props) {
41
+ }: Readonly<Props>) {
22
42
  const { breakpoints } = useTheme();
23
43
  const _searchOptions = Array.isArray(searchOptions) ? searchOptions : [];
24
44
  const options: DisplaySearchOption[] = [
@@ -37,15 +57,12 @@ export default function OrdersSearchDropdown({
37
57
  )}
38
58
  options={(onClose) => {
39
59
  return options.map((item: DisplaySearchOption) => (
40
- <MenuItem
60
+ <SearchOptionItem
41
61
  key={item.id}
42
- onClick={() => {
43
- handleChange(item.id);
44
- onClose();
45
- }}
46
- >
47
- {item.name}
48
- </MenuItem>
62
+ item={item}
63
+ onClose={onClose}
64
+ handleChange={handleChange}
65
+ />
49
66
  ));
50
67
  }}
51
68
  />
@@ -41,7 +41,9 @@ interface OrderSortProps {
41
41
  setSortColumn: (selectedSortColumn: SortColumn) => void;
42
42
  }
43
43
 
44
- export default function OrdersSort({ setSortColumn }: OrderSortProps) {
44
+ export default function OrdersSort({
45
+ setSortColumn,
46
+ }: Readonly<OrderSortProps>) {
45
47
  const [selectedSort, setSelectedSort] = useState<number>(0);
46
48
  const t = useTranslations("Account.Orders");
47
49
 
@@ -1,6 +1,7 @@
1
+ import type { SalesOrder } from "@evenicanpm/storefront-core/src/api-manager/schemas/order.schema";
1
2
  import NoRecords from "@evenicanpm/storefront-core/src/components/no-records";
2
3
  import { Box, CircularProgress } from "@mui/material";
3
- import { cloneElement, Fragment } from "react";
4
+ import { cloneElement, Fragment, useMemo } from "react";
4
5
  import OrderHistoryHeader from "./order-history-header";
5
6
  import OrdersPagination from "./order-history-pagination";
6
7
  import { useOrderHistory } from "./order-history-root";
@@ -8,11 +9,30 @@ import OrderHistoryRow, {
8
9
  OrderHistoryTableRowContext,
9
10
  } from "./order-history-row";
10
11
 
12
+ const OrderHistoryTableRowProvider = ({
13
+ order,
14
+ children,
15
+ }: {
16
+ order: SalesOrder;
17
+ children: React.ReactNode;
18
+ }) => {
19
+ const contextValue = useMemo(() => ({ order }), [order]);
20
+ return (
21
+ <OrderHistoryTableRowContext.Provider value={contextValue}>
22
+ {children}
23
+ </OrderHistoryTableRowContext.Provider>
24
+ );
25
+ };
26
+
11
27
  const OrderHistoryTable = ({ children }: { children: React.ReactNode }) => {
12
28
  return <>{children}</>;
13
29
  };
14
30
 
15
- OrderHistoryTable.List = ({ children }: { children: React.ReactElement }) => {
31
+ const OrderHistoryTableList = ({
32
+ children,
33
+ }: {
34
+ children: React.ReactElement;
35
+ }) => {
16
36
  const { orders, isLoading } = useOrderHistory();
17
37
 
18
38
  if (isLoading) {
@@ -30,12 +50,12 @@ OrderHistoryTable.List = ({ children }: { children: React.ReactElement }) => {
30
50
  return (
31
51
  <Fragment>
32
52
  {orders.map((order, index) => (
33
- <OrderHistoryTableRowContext.Provider
53
+ <OrderHistoryTableRowProvider
34
54
  key={order.RecordId ?? index}
35
- value={{ order }}
55
+ order={order}
36
56
  >
37
57
  {cloneElement(children)}
38
- </OrderHistoryTableRowContext.Provider>
58
+ </OrderHistoryTableRowProvider>
39
59
  ))}
40
60
  <Box mt={4}>
41
61
  <OrderHistoryTable.Pagination>
@@ -47,6 +67,8 @@ OrderHistoryTable.List = ({ children }: { children: React.ReactElement }) => {
47
67
  );
48
68
  };
49
69
 
70
+ OrderHistoryTable.List = OrderHistoryTableList;
71
+
50
72
  OrderHistoryTable.Header = OrderHistoryHeader;
51
73
  OrderHistoryTable.Row = OrderHistoryRow;
52
74
  OrderHistoryTable.Pagination = OrdersPagination;
@@ -13,7 +13,7 @@ import Box from "@mui/material/Box";
13
13
  import Card from "@mui/material/Card";
14
14
  import styled from "@mui/material/styles/styled";
15
15
  import { useTranslations } from "next-intl";
16
- import { createContext, Fragment, useContext } from "react";
16
+ import { createContext, Fragment, useContext, useMemo } from "react";
17
17
  import { MdDone as Done } from "react-icons/md";
18
18
 
19
19
  // STYLED COMPONENTS
@@ -59,18 +59,20 @@ const OrderProgress = ({
59
59
  }: React.PropsWithChildren<Props>) => {
60
60
  const STEP_ICONS = [PackageBox, TruckFilled, Delivery];
61
61
  const STATUS_LIST = ["Packaging", "Shipping", "Delivering", "Complete"];
62
+ const contextValue = useMemo(
63
+ () => ({ status, stepIcons: STEP_ICONS, statusList: STATUS_LIST }),
64
+ [status],
65
+ );
62
66
 
63
67
  return (
64
- <OrderProgressContext.Provider
65
- value={{ status, stepIcons: STEP_ICONS, statusList: STATUS_LIST }}
66
- >
68
+ <OrderProgressContext.Provider value={contextValue}>
67
69
  <Card sx={{ p: "2rem 1.5rem", mb: 4 }}>{children}</Card>
68
70
  </OrderProgressContext.Provider>
69
71
  );
70
72
  };
71
73
 
72
74
  // SUBCOMPONENTS
73
- OrderProgress.Steps = () => {
75
+ const OrderProgressSteps = () => {
74
76
  const context = useContext(OrderProgressContext);
75
77
  if (!context) return null;
76
78
 
@@ -118,7 +120,9 @@ OrderProgress.Steps = () => {
118
120
  );
119
121
  };
120
122
 
121
- OrderProgress.DeliveryDate = () => {
123
+ OrderProgress.Steps = OrderProgressSteps;
124
+
125
+ const OrderProgressDeliveryDate = () => {
122
126
  const t = useTranslations("Account.OrderDetails");
123
127
  const context = useContext(OrderProgressContext);
124
128
  if (!context) return null;
@@ -150,4 +154,6 @@ OrderProgress.DeliveryDate = () => {
150
154
  );
151
155
  };
152
156
 
157
+ OrderProgress.DeliveryDate = OrderProgressDeliveryDate;
158
+
153
159
  export default OrderProgress;
@@ -12,7 +12,7 @@ import IconButton from "@mui/material/IconButton";
12
12
  import { format } from "date-fns";
13
13
  import Link from "next/link";
14
14
  import type React from "react";
15
- import { createContext, useContext } from "react";
15
+ import { createContext, useContext, useMemo } from "react";
16
16
  import { MdEast as East } from "react-icons/md";
17
17
 
18
18
  type Props = { order: SalesOrder };
@@ -36,9 +36,13 @@ const OrderRowContext = createContext<{
36
36
 
37
37
  const OrderRow = ({ order, children }: React.PropsWithChildren<Props>) => {
38
38
  const { formatCurrency } = useCurrencyFormatter();
39
+ const contextValue = useMemo(
40
+ () => ({ order, formatCurrency }),
41
+ [order, formatCurrency],
42
+ );
39
43
 
40
44
  return (
41
- <OrderRowContext.Provider value={{ order, formatCurrency }}>
45
+ <OrderRowContext.Provider value={contextValue}>
42
46
  <Link href={`/account/orders/${order.SalesId}`}>
43
47
  <TableRow sx={{ gridTemplateColumns: "2fr 1fr 1fr 1fr 1fr" }}>
44
48
  {children}
@@ -48,14 +52,16 @@ const OrderRow = ({ order, children }: React.PropsWithChildren<Props>) => {
48
52
  );
49
53
  };
50
54
 
51
- OrderRow.OrderNumber = () => {
55
+ const OrderRowOrderNumber = () => {
52
56
  const context = useContext(OrderRowContext);
53
57
  if (!context) return null;
54
58
  const { order } = context;
55
59
  return <H6 ellipsis>{order?.ChannelReferenceId}</H6>;
56
60
  };
57
61
 
58
- OrderRow.Status = () => {
62
+ OrderRow.OrderNumber = OrderRowOrderNumber;
63
+
64
+ const OrderRowStatus = () => {
59
65
  const context = useContext(OrderRowContext);
60
66
  if (!context) return null;
61
67
  const { order } = context;
@@ -67,7 +73,9 @@ OrderRow.Status = () => {
67
73
  );
68
74
  };
69
75
 
70
- OrderRow.Date = () => {
76
+ OrderRow.Status = OrderRowStatus;
77
+
78
+ const OrderRowDate = () => {
71
79
  const context = useContext(OrderRowContext);
72
80
  if (!context) return null;
73
81
  const { order } = context;
@@ -78,7 +86,9 @@ OrderRow.Date = () => {
78
86
  );
79
87
  };
80
88
 
81
- OrderRow.Total = () => {
89
+ OrderRow.Date = OrderRowDate;
90
+
91
+ const OrderRowTotal = () => {
82
92
  const context = useContext(OrderRowContext);
83
93
  if (!context) return null;
84
94
  const { order, formatCurrency } = context;
@@ -89,6 +99,8 @@ OrderRow.Total = () => {
89
99
  );
90
100
  };
91
101
 
102
+ OrderRow.Total = OrderRowTotal;
103
+
92
104
  OrderRow.Action = () => {
93
105
  return (
94
106
  <Box display={{ sm: "inline-flex", xs: "none" }} justifyContent="end">
@@ -11,7 +11,7 @@ import Divider from "@mui/material/Divider";
11
11
  import Grid from "@mui/material/Grid2";
12
12
  import { useTranslations } from "next-intl";
13
13
  import type React from "react";
14
- import { createContext, useContext } from "react";
14
+ import { createContext, useContext, useMemo } from "react";
15
15
 
16
16
  type Props = { order: SalesOrder };
17
17
 
@@ -23,9 +23,13 @@ const OrderSummaryContext = createContext<{
23
23
  // Compound Component
24
24
  const OrderSummary = ({ order, children }: React.PropsWithChildren<Props>) => {
25
25
  const { formatCurrency } = useCurrencyFormatter();
26
+ const contextValue = useMemo(
27
+ () => ({ order, formatCurrency }),
28
+ [order, formatCurrency],
29
+ );
26
30
 
27
31
  return (
28
- <OrderSummaryContext.Provider value={{ order, formatCurrency }}>
32
+ <OrderSummaryContext.Provider value={contextValue}>
29
33
  <Grid container spacing={3}>
30
34
  {children}
31
35
  </Grid>
@@ -47,7 +51,7 @@ OrderSummary.SummaryWrapper = ({ children }: { children: React.ReactNode }) => (
47
51
  );
48
52
 
49
53
  // Subcomponents
50
- OrderSummary.AddressHeading = () => {
54
+ const OrderSummaryAddressHeading = () => {
51
55
  const t = useTranslations("Account.OrderDetails");
52
56
  return (
53
57
  <H5 mt={0} mb={2}>
@@ -56,7 +60,9 @@ OrderSummary.AddressHeading = () => {
56
60
  );
57
61
  };
58
62
 
59
- OrderSummary.AddressContent = () => {
63
+ OrderSummary.AddressHeading = OrderSummaryAddressHeading;
64
+
65
+ const OrderSummaryAddressContent = () => {
60
66
  const context = useContext(OrderSummaryContext);
61
67
  if (!context) return null;
62
68
  const { order } = context;
@@ -70,7 +76,9 @@ OrderSummary.AddressContent = () => {
70
76
  );
71
77
  };
72
78
 
73
- OrderSummary.SummaryHeading = () => {
79
+ OrderSummary.AddressContent = OrderSummaryAddressContent;
80
+
81
+ const OrderSummarySummaryHeading = () => {
74
82
  const t = useTranslations("Account.OrderDetails");
75
83
  return (
76
84
  <H5 mt={0} mb={2}>
@@ -79,7 +87,9 @@ OrderSummary.SummaryHeading = () => {
79
87
  );
80
88
  };
81
89
 
82
- OrderSummary.ListItem = ({
90
+ OrderSummary.SummaryHeading = OrderSummarySummaryHeading;
91
+
92
+ const OrderSummaryListItem = ({
83
93
  title,
84
94
  property,
85
95
  }: {
@@ -101,9 +111,11 @@ OrderSummary.ListItem = ({
101
111
  );
102
112
  };
103
113
 
114
+ OrderSummary.ListItem = OrderSummaryListItem;
115
+
104
116
  OrderSummary.Divider = Divider;
105
117
 
106
- OrderSummary.Total = () => {
118
+ const OrderSummaryTotal = () => {
107
119
  const t = useTranslations("Account.OrderDetails");
108
120
  const context = useContext(OrderSummaryContext);
109
121
  if (!context) return null;
@@ -117,9 +129,13 @@ OrderSummary.Total = () => {
117
129
  );
118
130
  };
119
131
 
120
- OrderSummary.PaidBy = ({ children }: { children?: React.ReactNode }) => {
132
+ OrderSummary.Total = OrderSummaryTotal;
133
+
134
+ const OrderSummaryPaidBy = ({ children }: { children?: React.ReactNode }) => {
121
135
  const t = useTranslations("Account.OrderDetails");
122
136
  return <Paragraph>{children ?? t("paidBy")}</Paragraph>;
123
137
  };
124
138
 
139
+ OrderSummary.PaidBy = OrderSummaryPaidBy;
140
+
125
141
  export default OrderSummary;
@@ -22,7 +22,7 @@ import Grid from "@mui/material/Grid2";
22
22
  import Link from "next/link";
23
23
  import { useTranslations } from "next-intl";
24
24
  import type React from "react";
25
- import { createContext } from "react";
25
+ import { createContext, useMemo } from "react";
26
26
 
27
27
  type Props = { order: SalesOrder };
28
28
 
@@ -36,8 +36,12 @@ const OrderedProducts = ({
36
36
  children,
37
37
  }: React.PropsWithChildren<Props>) => {
38
38
  const { formatCurrency } = useCurrencyFormatter();
39
+ const contextValue = useMemo(
40
+ () => ({ order, formatCurrency }),
41
+ [order, formatCurrency],
42
+ );
39
43
  return (
40
- <OrderedProductsContext.Provider value={{ order, formatCurrency }}>
44
+ <OrderedProductsContext.Provider value={contextValue}>
41
45
  <Card sx={{ p: 0, mb: "30px" }}>{children}</Card>
42
46
  </OrderedProductsContext.Provider>
43
47
  );
@@ -50,7 +54,7 @@ OrderedProducts.Header = ({ children }: React.PropsWithChildren) => (
50
54
  </FlexBetween>
51
55
  );
52
56
 
53
- OrderedProducts.HeaderItem = ({
57
+ const OrderedProductsHeaderItem = ({
54
58
  title,
55
59
  value,
56
60
  }: {
@@ -66,6 +70,8 @@ OrderedProducts.HeaderItem = ({
66
70
  );
67
71
  };
68
72
 
73
+ OrderedProducts.HeaderItem = OrderedProductsHeaderItem;
74
+
69
75
  OrderedProducts.List = ({ children }: React.PropsWithChildren) => (
70
76
  <Grid container spacing={2} padding={"20px 15px 10px"} alignItems={"center"}>
71
77
  {children}
@@ -120,7 +126,7 @@ OrderedProducts.Title = ({ item }: { item: SalesLine }) => {
120
126
  return <H6>{item?.Product?.Name}</H6>;
121
127
  };
122
128
 
123
- OrderedProducts.Price = ({ item }: { item: SalesLine }) => {
129
+ const OrderedProductsPrice = ({ item }: { item: SalesLine }) => {
124
130
  const { formatCurrency } = useCurrencyFormatter();
125
131
  return (
126
132
  <Paragraph color="grey.600">
@@ -129,6 +135,8 @@ OrderedProducts.Price = ({ item }: { item: SalesLine }) => {
129
135
  );
130
136
  };
131
137
 
138
+ OrderedProducts.Price = OrderedProductsPrice;
139
+
132
140
  OrderedProducts.Dimensions = ({ item }: { item: SalesLine }) => {
133
141
  if (!item.Product?.Dimensions?.length) {
134
142
  return (
@@ -150,7 +158,7 @@ OrderedProducts.Dimensions = ({ item }: { item: SalesLine }) => {
150
158
  );
151
159
  };
152
160
 
153
- OrderedProducts.ReviewButton = () => {
161
+ const OrderedProductsReviewButton = () => {
154
162
  const t = useTranslations("Account.OrderDetails");
155
163
  return (
156
164
  <Grid size={{ xs: 4, sm: 3 }}>
@@ -163,4 +171,6 @@ OrderedProducts.ReviewButton = () => {
163
171
  );
164
172
  };
165
173
 
174
+ OrderedProducts.ReviewButton = OrderedProductsReviewButton;
175
+
166
176
  export default OrderedProducts;
@@ -12,7 +12,12 @@ import Card from "@mui/material/Card";
12
12
  import type { Theme } from "@mui/material/styles";
13
13
  import useMediaQuery from "@mui/material/useMediaQuery";
14
14
  import { useTranslations } from "next-intl";
15
- import { createContext, type PropsWithChildren, useContext } from "react";
15
+ import {
16
+ createContext,
17
+ type PropsWithChildren,
18
+ useContext,
19
+ useMemo,
20
+ } from "react";
16
21
 
17
22
  interface UserInfoContextValue {
18
23
  user: User;
@@ -26,9 +31,10 @@ interface UserInfoProps extends PropsWithChildren {
26
31
 
27
32
  const UserInfo = ({ user, children }: UserInfoProps) => {
28
33
  const downMd = useMediaQuery((theme: Theme) => theme.breakpoints.down("sm"));
34
+ const contextValue = useMemo(() => ({ user }), [user]);
29
35
 
30
36
  return (
31
- <UserInfoContext.Provider value={{ user }}>
37
+ <UserInfoContext.Provider value={contextValue}>
32
38
  <Card
33
39
  sx={{
34
40
  mt: 3,
@@ -59,7 +65,7 @@ interface ItemProps {
59
65
  transform?: (val: string) => string;
60
66
  }
61
67
 
62
- UserInfo.Item = ({ title, field, value, transform }: ItemProps) => {
68
+ const UserInfoItem = ({ title, field, value, transform }: ItemProps) => {
63
69
  const ctx = useContext(UserInfoContext);
64
70
  const t = useTranslations("Account.Profile");
65
71
  if (!ctx) return null;
@@ -85,4 +91,6 @@ UserInfo.Item = ({ title, field, value, transform }: ItemProps) => {
85
91
  );
86
92
  };
87
93
 
94
+ UserInfo.Item = UserInfoItem;
95
+
88
96
  export default UserInfo;
@@ -9,7 +9,7 @@ interface TableRowSkeletonProps {
9
9
 
10
10
  export default function TableRowSkeleton({
11
11
  sx = { gridTemplateColumns: "2fr 1fr 1fr 1fr 1fr" },
12
- }: TableRowSkeletonProps) {
12
+ }: Readonly<TableRowSkeletonProps>) {
13
13
  return (
14
14
  <TableRow sx={sx}>
15
15
  <Skeleton variant="text" width="60%" />