@evenicanpm/storefront-core 2.0.0 → 2.1.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 (125) hide show
  1. package/.storybook/main.ts +2 -3
  2. package/.storybook/preview.tsx +0 -2
  3. package/__mocks__/create-mutation.ts +16 -8
  4. package/__mocks__/next-image.tsx +12 -3
  5. package/package.json +2 -2
  6. package/src/api-manager/datasources/d365/d365-categories.datasource.ts +2 -3
  7. package/src/api-manager/datasources/d365/d365-order.datasource.ts +4 -4
  8. package/src/api-manager/datasources/d365/d365-organization.datasource.ts +15 -8
  9. package/src/api-manager/datasources/d365/d365-product.datasource.ts +31 -19
  10. package/src/api-manager/datasources/d365/d365-user.datasource.ts +47 -19
  11. package/src/api-manager/datasources/e4/address/e4-address.remaps.ts +2 -2
  12. package/src/api-manager/datasources/e4/cart/e4-cart.remaps.ts +1 -1
  13. package/src/api-manager/datasources/e4/product/e4-product.remaps.ts +3 -3
  14. package/src/api-manager/datasources/e4/user/e4-user.datasource.ts +4 -8
  15. package/src/api-manager/index.ts +10 -127
  16. package/src/api-manager/lib/get-graphql-client.ts +2 -2
  17. package/src/api-manager/schemas/product.schema.ts +9 -0
  18. package/src/api-manager/services/create-extension-query.ts +1 -1
  19. package/src/api-manager/services/create-query.ts +106 -266
  20. package/src/api-manager/types/Datasource.ts +0 -3
  21. package/src/cms/blocks/components/category-card.tsx +0 -1
  22. package/src/cms/blocks/components/category-carousel/index.tsx +0 -1
  23. package/src/cms/blocks/components/featured-categories.tsx +1 -2
  24. package/src/cms/blocks/components/featured-products.tsx +1 -2
  25. package/src/cms/blocks/components/footer/index.tsx +0 -1
  26. package/src/cms/blocks/components/footer/sections/footer-app-store.tsx +1 -1
  27. package/src/cms/blocks/components/footer/sections/footer-contact.tsx +0 -1
  28. package/src/cms/blocks/components/footer/sections/footer-links.tsx +1 -1
  29. package/src/cms/blocks/components/footer/sections/footer-logo.tsx +0 -1
  30. package/src/cms/blocks/components/footer/sections/footer-social-links.tsx +0 -1
  31. package/src/cms/blocks/components/footer.tsx +0 -1
  32. package/src/cms/blocks/components/hero-carousel/index.tsx +0 -1
  33. package/src/cms/blocks/components/hero.tsx +0 -1
  34. package/src/cms/blocks/components/image.tsx +0 -1
  35. package/src/cms/blocks/components/media-card.tsx +0 -1
  36. package/src/cms/blocks/components/product-carousel/index.tsx +0 -1
  37. package/src/cms/blocks/components/product-section-fullwidth/index.tsx +0 -1
  38. package/src/cms/blocks/components/rich-text.tsx +0 -1
  39. package/src/cms/blocks/components/seo/index.tsx +1 -2
  40. package/src/cms/blocks/components/services/index.tsx +0 -1
  41. package/src/cms/blocks/components/services/service-card.tsx +0 -1
  42. package/src/cms/blocks/components/shared/featured-product-card.tsx +0 -1
  43. package/src/cms/blocks/components/shared/product-category-item.tsx +1 -1
  44. package/src/cms/blocks/components/shared/product-grid.tsx +0 -1
  45. package/src/cms/blocks/components/shared/top-categories-card.tsx +0 -1
  46. package/src/cms/blocks/components/shared/top-rating-product-card.tsx +0 -1
  47. package/src/cms/blocks/icons/components/category.tsx +0 -1
  48. package/src/cms/blocks/icons/components/dotted-star.tsx +0 -1
  49. package/src/cms/blocks/icons/components/fallback-icon.tsx +0 -1
  50. package/src/cms/blocks/icons/components/gift-box.tsx +0 -1
  51. package/src/cms/blocks/icons/components/light.tsx +0 -1
  52. package/src/cms/blocks/icons/components/new-arrival.tsx +0 -1
  53. package/src/cms/blocks/icons/components/rank-badge.tsx +0 -1
  54. package/src/components/BazaarTextField.tsx +7 -7
  55. package/src/components/CountryInput.stories.tsx +4 -2
  56. package/src/components/T/__tests__/T.test.tsx +9 -13
  57. package/src/components/T/index.tsx +0 -1
  58. package/src/components/Typography.tsx +0 -1
  59. package/src/components/_tests_/site-logo.test.tsx +4 -5
  60. package/src/components/categories/category-list/category-list.tsx +1 -1
  61. package/src/components/countries-input.tsx +1 -1
  62. package/src/components/nav-link/nav-link.tsx +2 -8
  63. package/src/components/navbar/mega-menu/mega-menu.tsx +7 -1
  64. package/src/components/navbar/mobile-menu/mobile-menu.test.tsx +2 -1
  65. package/src/components/navbar/nav-list/cms-nav.test.tsx +0 -1
  66. package/src/components/no-records.tsx +0 -1
  67. package/src/components/product-cards/favorite-button.tsx +0 -1
  68. package/src/components/product-cards/product-card/styles/index.ts +2 -2
  69. package/src/components/product-cards/product-card-plp-list/ProductCardPlpList.stories.tsx +0 -1
  70. package/src/components/product-cards/product-card-search/ProductCardSearch.stories.tsx +0 -1
  71. package/src/components/product-dimensions/Dimensions.stories.tsx +2 -4
  72. package/src/components/product-dimensions/compound/dimensions-group-list-chip.tsx +1 -1
  73. package/src/components/product-dimensions/compound/dimensions.tsx +1 -1
  74. package/src/components/product-quantity-buttons/ProductQuantity.stories.tsx +1 -3
  75. package/src/components/product-quantity-buttons/__tests__/product-quantity-buttons.test.tsx +3 -2
  76. package/src/components/product-quantity-buttons/compound/quantity-buttons-root.tsx +1 -1
  77. package/src/components/product-quantity-buttons/index.tsx +0 -1
  78. package/src/components/product-quantity-variants/ProductQuantity.stories.tsx +1 -3
  79. package/src/components/products-view/ProductsGrid.stories.tsx +1 -3
  80. package/src/components/products-view/ProductsList.stories.tsx +1 -3
  81. package/src/components/products-view/__tests__/products-view.test.tsx +20 -9
  82. package/src/components/products-view/index.tsx +1 -1
  83. package/src/components/scrollbar/Scrollbar.stories.tsx +1 -3
  84. package/src/components/scrollbar/__tests__/scrollbar.test.tsx +7 -1
  85. package/src/components/search-bar/SearchBarLarge.stories.tsx +1 -3
  86. package/src/components/search-bar/compound/results-item-lg.tsx +0 -1
  87. package/src/components/search-bar/compound/results-item-sm.tsx +0 -1
  88. package/src/components/search-bar/compound/textfield-adornment-category.tsx +0 -1
  89. package/src/components/search-bar/compound/textfield.tsx +0 -1
  90. package/src/components/search-bar/utils/findCategoryNameById.ts +3 -3
  91. package/src/components/section/__tests__/section.test.tsx +14 -7
  92. package/src/components/side-nav/SideNav.stories.tsx +1 -1
  93. package/src/components/site-logo.tsx +8 -1
  94. package/src/components/wishlist-dialogs/add-to-wishlist/add-to-wishlist-button.tsx +1 -1
  95. package/src/components/wishlist-dialogs/add-to-wishlist/compound/add-to-wishlist-bottom-ui.tsx +1 -1
  96. package/src/components/wishlist-dialogs/add-to-wishlist/compound/wishlist-dialog-header.tsx +0 -1
  97. package/src/components/wishlist-dialogs/create-wishlist/compound/create-wishlist-bottom-ui.tsx +1 -1
  98. package/src/hooks/use-nextauth-session.ts +4 -1
  99. package/src/lib/lib.ts +1 -1
  100. package/src/lib/page-slugs.ts +0 -2
  101. package/src/lib/refiner-utils.ts +3 -3
  102. package/src/pages/account/account-navigation.tsx +17 -20
  103. package/src/pages/account/addresses/address-form.tsx +15 -7
  104. package/src/pages/account/dashboard-header.tsx +1 -1
  105. package/src/pages/cart/checkout-form.tsx +1 -1
  106. package/src/pages/checkout/checkout-alt-form/checkout-step.tsx +1 -1
  107. package/src/pages/checkout/checkout-alt-form/steps/address/new-address-form.tsx +1 -1
  108. package/src/pages/checkout/checkout-alt-form/steps/payment/payment-details.tsx +5 -2
  109. package/src/pages/checkout/checkout-alt-summary/cart-item.tsx +1 -1
  110. package/src/pages/checkout/checkout-alt-summary/checkout-alt-summary.tsx +1 -1
  111. package/src/pages/confirmation/address.tsx +1 -1
  112. package/src/pages/confirmation/confirmation-summary.tsx +1 -1
  113. package/src/pages/product-details/currency.ts +1 -1
  114. package/src/pages/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +4 -1
  115. package/src/pages/product-list/breadcrumbs.tsx +0 -1
  116. package/src/pages/product-list/list-filter.tsx +0 -1
  117. package/src/pages/product-list/product-list-context.tsx +1 -1
  118. package/src/pages/product-list/product-list-view.tsx +2 -2
  119. package/src/pages/product-list/selected-facets.tsx +1 -1
  120. package/src/pages/quickorder/context.ts +8 -2
  121. package/src/pages/quickorder/order-upload.tsx +26 -8
  122. package/src/pages/quickorder/provider.tsx +8 -9
  123. package/src/pages/quickorder/quick-order.tsx +17 -11
  124. package/src/providers/nav-provider/index.tsx +1 -1
  125. package/tsconfig.json +0 -1
@@ -1,6 +1,7 @@
1
+ import type { CartLine } from "@evenicanpm/storefront-core/src/api-manager/schemas/cart.schema";
1
2
  import { render } from "@testing-library/react";
2
3
  import type { ReactNode } from "react";
3
- import { vi } from "vitest";
4
+ import { describe, expect, it, vi } from "vitest";
4
5
  import ProductQuantityButtons from "../index";
5
6
 
6
7
  vi.mock("next-intl", () => ({
@@ -12,7 +13,7 @@ vi.mock("@evenicanpm/storefront-core/src/hooks/use-cart", () => ({
12
13
  handleAddToCart: vi.fn(),
13
14
  handleCartAmountChange: vi.fn(),
14
15
  loading: false,
15
- currentCartLine: { Quantity: 1 } as any,
16
+ currentCartLine: { Quantity: 1 } as CartLine | undefined,
16
17
  })),
17
18
  }));
18
19
 
@@ -9,7 +9,7 @@ import type { CartLine } from "@msdyn365-commerce/retail-proxy";
9
9
  import Button from "@mui/material/Button";
10
10
  import CircularProgress from "@mui/material/CircularProgress";
11
11
  import { useTranslations } from "next-intl";
12
- import React, { createContext, type ReactNode, useContext } from "react";
12
+ import { createContext, type ReactNode, useContext } from "react";
13
13
  import { MdAdd as Add, MdRemove as Remove } from "react-icons/md";
14
14
  // TODO: Encapsulate the addToCart api calls inside this component
15
15
  // so no need to pass in props.
@@ -7,7 +7,6 @@ import {
7
7
  type QuantityButtonProps,
8
8
  QuantityButtons,
9
9
  } from "@evenicanpm/storefront-core/src/components/product-quantity-buttons/compound/quantity-buttons-root";
10
- import React from "react";
11
10
 
12
11
  /**
13
12
  * Pre-composed version of quantity buttons.
@@ -1,7 +1,6 @@
1
1
  // Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
2
2
 
3
- import type { Meta, StoryObj } from "@storybook/react";
4
- import React from "react";
3
+ import type { Meta } from "@storybook/react";
5
4
  import { product } from "../../../__mocks__/product-dimensions";
6
5
  import QuantityButtons from "./index";
7
6
 
@@ -12,7 +11,6 @@ const meta = {
12
11
  } satisfies Meta<typeof QuantityButtons>;
13
12
 
14
13
  export default meta;
15
- type Story = StoryObj<typeof meta>;
16
14
 
17
15
  export const Interactive = () => {
18
16
  return <QuantityButtons product={product} />;
@@ -1,7 +1,6 @@
1
1
  // Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
2
2
 
3
- import type { Meta, StoryObj } from "@storybook/react";
4
- import React from "react";
3
+ import type { Meta } from "@storybook/react";
5
4
  import { data, prices } from "../../../__mocks__/products";
6
5
  import { ProductsGrid } from "./index";
7
6
 
@@ -12,7 +11,6 @@ const meta = {
12
11
  } satisfies Meta<typeof ProductsGrid>;
13
12
 
14
13
  export default meta;
15
- type Story = StoryObj<typeof meta>;
16
14
 
17
15
  export const Interactive = () => {
18
16
  return <ProductsGrid products={data.products} productPrices={prices} />;
@@ -1,7 +1,6 @@
1
1
  // Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
2
2
 
3
- import type { Meta, StoryObj } from "@storybook/react";
4
- import React from "react";
3
+ import type { Meta } from "@storybook/react";
5
4
  import { data, prices } from "../../../__mocks__/products";
6
5
  import { ProductsList } from "./index";
7
6
 
@@ -12,7 +11,6 @@ const meta = {
12
11
  } satisfies Meta<typeof ProductsList>;
13
12
 
14
13
  export default meta;
15
- type Story = StoryObj<typeof meta>;
16
14
 
17
15
  export const Interactive = () => {
18
16
  return <ProductsList products={data.products} productPrices={prices} />;
@@ -1,7 +1,14 @@
1
1
  import type { ProductSearchResult as Product } from "@msdyn365-commerce/retail-proxy";
2
2
  import { render } from "@testing-library/react";
3
+ import type { ReactNode } from "react";
3
4
  import { vi } from "vitest";
4
- import { ProductsGrid, ProductsList } from "../index";
5
+ import {
6
+ ProductsGrid,
7
+ ProductsList,
8
+ type Props as ProductsViewProps,
9
+ } from "../index";
10
+
11
+ type MockChildrenProps = { children?: ReactNode };
5
12
 
6
13
  vi.mock("next-intl", () => ({
7
14
  useTranslations: () => (key: string) => key,
@@ -19,11 +26,11 @@ vi.mock(
19
26
  "@evenicanpm/storefront-core/src/components/products-view/compound/products-grid-view",
20
27
  () => ({
21
28
  default: Object.assign(
22
- ({ children }: any) => (
29
+ ({ children }: MockChildrenProps) => (
23
30
  <div data-testid="products-grid-view">{children}</div>
24
31
  ),
25
32
  {
26
- Grid: ({ children }: any) => (
33
+ Grid: ({ children }: MockChildrenProps) => (
27
34
  <div data-testid="products-grid">{children}</div>
28
35
  ),
29
36
  Card: () => <div data-testid="product-card">Card</div>,
@@ -36,11 +43,11 @@ vi.mock(
36
43
  "@evenicanpm/storefront-core/src/components/products-view/compound/products-list-view",
37
44
  () => ({
38
45
  default: Object.assign(
39
- ({ children }: any) => (
46
+ ({ children }: MockChildrenProps) => (
40
47
  <div data-testid="products-list-view">{children}</div>
41
48
  ),
42
49
  {
43
- List: ({ children }: any) => (
50
+ List: ({ children }: MockChildrenProps) => (
44
51
  <div data-testid="products-list">{children}</div>
45
52
  ),
46
53
  Card: () => <div data-testid="product-card">Card</div>,
@@ -80,9 +87,11 @@ describe("ProductsView components", () => {
80
87
  });
81
88
 
82
89
  it("renders with product prices", () => {
83
- const prices = [{ price: 100, adjustedPrice: 80, productId: 1 }];
90
+ const prices = [
91
+ { price: 100, adjustedPrice: 80, productId: 1 },
92
+ ] as NonNullable<ProductsViewProps["productPrices"]>;
84
93
  const { container } = render(
85
- <ProductsGrid products={mockProducts} productPrices={prices as any} />,
94
+ <ProductsGrid products={mockProducts} productPrices={prices} />,
86
95
  );
87
96
  expect(
88
97
  container.querySelector("[data-testid='products-grid-view']"),
@@ -126,9 +135,11 @@ describe("ProductsView components", () => {
126
135
  });
127
136
 
128
137
  it("renders with product prices", () => {
129
- const prices = [{ price: 100, adjustedPrice: 80, productId: 1 }];
138
+ const prices = [
139
+ { price: 100, adjustedPrice: 80, productId: 1 },
140
+ ] as NonNullable<ProductsViewProps["productPrices"]>;
130
141
  const { container } = render(
131
- <ProductsList products={mockProducts} productPrices={prices as any} />,
142
+ <ProductsList products={mockProducts} productPrices={prices} />,
132
143
  );
133
144
  expect(
134
145
  container.querySelector("[data-testid='products-list-view']"),
@@ -3,7 +3,7 @@ import ProductsGridView from "@evenicanpm/storefront-core/src/components/product
3
3
  import ProductsListView from "@evenicanpm/storefront-core/src/components/products-view/compound/products-list-view";
4
4
  // DATA MODEL
5
5
  import type { ProductSearchResult as Product } from "@msdyn365-commerce/retail-proxy";
6
- import React, { type ReactNode } from "react";
6
+ import type { ReactNode } from "react";
7
7
 
8
8
  export interface Props {
9
9
  /** List of products to display */
@@ -1,7 +1,6 @@
1
1
  // Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
2
2
 
3
- import type { Meta, StoryObj } from "@storybook/react";
4
- import React from "react";
3
+ import type { Meta } from "@storybook/react";
5
4
  import Scrollbar from "./index";
6
5
 
7
6
  const meta = {
@@ -11,7 +10,6 @@ const meta = {
11
10
  } satisfies Meta<typeof Scrollbar>;
12
11
 
13
12
  export default meta;
14
- type Story = StoryObj<typeof meta>;
15
13
 
16
14
  export const WithLink = () => (
17
15
  <div style={{ height: "500px" }}>
@@ -1,9 +1,15 @@
1
1
  import { render, screen } from "@testing-library/react";
2
+ import type { HTMLAttributes, ReactNode } from "react";
2
3
  import { vi } from "vitest";
3
4
  import Scrollbar from "../scrollbar";
4
5
 
6
+ type SimplebarMockProps = HTMLAttributes<HTMLDivElement> & {
7
+ children?: ReactNode;
8
+ autoHide?: boolean;
9
+ };
10
+
5
11
  vi.mock("simplebar-react", () => ({
6
- default: ({ children, autoHide, ...props }: any) => (
12
+ default: ({ children, autoHide, ...props }: SimplebarMockProps) => (
7
13
  <div data-testid="custom-scrollbar" data-autohide={autoHide} {...props}>
8
14
  {children}
9
15
  </div>
@@ -1,7 +1,6 @@
1
1
  // Replace your-framework with the framework you are using, e.g. react-vite, nextjs, nextjs-vite, etc.
2
2
 
3
- import type { Meta, StoryObj } from "@storybook/react";
4
- import React from "react";
3
+ import type { Meta } from "@storybook/react";
5
4
  import { SearchBarViewLg } from "./index";
6
5
 
7
6
  const meta = {
@@ -12,6 +11,5 @@ const meta = {
12
11
  } satisfies Meta<typeof SearchBarViewLg>;
13
12
 
14
13
  export default meta;
15
- type Story = StoryObj<typeof meta>;
16
14
 
17
15
  export const WithLink = () => <SearchBarViewLg></SearchBarViewLg>;
@@ -8,7 +8,6 @@ import {
8
8
  useSearchResultItem,
9
9
  } from "@evenicanpm/storefront-core/src/components/search-bar/compound/context";
10
10
  import Grid from "@mui/material/Grid";
11
- import React from "react";
12
11
 
13
12
  /**
14
13
  * Large, vertical result item card, used for desktop view.
@@ -16,7 +16,6 @@ import { getProductDetailUrl } from "@evenicanpm/storefront-core/src/lib/build-p
16
16
  import { currency } from "@evenicanpm/storefront-core/src/lib/lib";
17
17
  import { Box, Grid } from "@mui/material";
18
18
  import MenuItem from "@mui/material/MenuItem";
19
- import React from "react";
20
19
 
21
20
  /**
22
21
  * Small, horizontal result item card, used for mobile view.
@@ -10,7 +10,6 @@ import TouchRipple from "@mui/material/ButtonBase";
10
10
  import MenuItem from "@mui/material/MenuItem";
11
11
  import useTheme from "@mui/material/styles/useTheme";
12
12
  import { useTranslations } from "next-intl";
13
- import React from "react";
14
13
  import { MdKeyboardArrowDown as KeyboardArrowDownOutlined } from "react-icons/md";
15
14
 
16
15
  type DisplayCategory = {
@@ -10,7 +10,6 @@ import { INPUT_SX } from "@evenicanpm/storefront-core/src/components/search-bar/
10
10
  import { useMediaQuery, useTheme } from "@mui/material";
11
11
  import TextField from "@mui/material/TextField";
12
12
  import { useTranslations } from "next-intl";
13
- import React from "react";
14
13
 
15
14
  /**
16
15
  * The actual input field for the search bar.
@@ -5,9 +5,9 @@ import type { Category } from "@msdyn365-commerce/retail-proxy";
5
5
  */
6
6
  export const findCategoryNameById = (
7
7
  searchCategory: number,
8
- categories: any,
9
- t: Function,
10
- ) => {
8
+ categories: Category[] | undefined,
9
+ t: (key: string) => string,
10
+ ): string => {
11
11
  if (searchCategory === 0) {
12
12
  return t("Navigation.allCategoriesLabel");
13
13
  }
@@ -1,5 +1,6 @@
1
1
  import { render, screen } from "@testing-library/react";
2
- import { vi } from "vitest";
2
+ import type { ReactNode } from "react";
3
+ import { describe, expect, it, vi } from "vitest";
3
4
  import { Section } from "../compound/section";
4
5
 
5
6
  vi.mock("next-intl", () => ({
@@ -14,7 +15,13 @@ vi.mock(
14
15
  );
15
16
 
16
17
  vi.mock("@mui/material/Container", () => ({
17
- default: ({ className, children }: any) => (
18
+ default: ({
19
+ className,
20
+ children,
21
+ }: {
22
+ className?: string;
23
+ children?: ReactNode;
24
+ }) => (
18
25
  <div data-testid="mui-container" className={className}>
19
26
  {children}
20
27
  </div>
@@ -28,7 +35,7 @@ describe("Section", () => {
28
35
  <div>Section Content</div>
29
36
  </Section>,
30
37
  );
31
- expect(screen.getByText("Section Content")).toBeInTheDocument();
38
+ expect(screen.getByText("Section Content")).toBeTruthy();
32
39
  });
33
40
 
34
41
  it("renders with Container component", () => {
@@ -69,7 +76,7 @@ describe("Section", () => {
69
76
  <div>Spaced Content</div>
70
77
  </Section>,
71
78
  );
72
- expect(screen.getByText("Spaced Content")).toBeInTheDocument();
79
+ expect(screen.getByText("Spaced Content")).toBeTruthy();
73
80
  });
74
81
 
75
82
  it("exposes Header subcomponent", () => {
@@ -84,9 +91,9 @@ describe("Section", () => {
84
91
  <div>Child 3</div>
85
92
  </Section>,
86
93
  );
87
- expect(screen.getByText("Child 1")).toBeInTheDocument();
88
- expect(screen.getByText("Child 2")).toBeInTheDocument();
89
- expect(screen.getByText("Child 3")).toBeInTheDocument();
94
+ expect(screen.getByText("Child 1")).toBeTruthy();
95
+ expect(screen.getByText("Child 2")).toBeTruthy();
96
+ expect(screen.getByText("Child 3")).toBeTruthy();
90
97
  });
91
98
 
92
99
  it("accepts custom sx styling", () => {
@@ -94,7 +94,7 @@ export const ControlledState: Story = {
94
94
  open={open}
95
95
  position="left"
96
96
  width={300}
97
- handler={(toggle) => (
97
+ handler={(_toggle) => (
98
98
  <Button variant="contained" onClick={() => setOpen(true)}>
99
99
  Open Controlled Menu
100
100
  </Button>
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
 
3
+ import Image from "next/image";
3
4
  import Link from "next/link";
4
5
 
5
6
  interface SiteLogoProps {
@@ -9,7 +10,13 @@ interface SiteLogoProps {
9
10
  const SiteLogo: React.FC<SiteLogoProps> = () => {
10
11
  return (
11
12
  <Link href="/">
12
- <img src={"/logo-blue.png"} alt="E4 Logo" height={54} />
13
+ <Image
14
+ src="/logo-blue.png"
15
+ alt="E4 Logo"
16
+ width={180}
17
+ height={54}
18
+ style={{ width: "auto", height: 54 }}
19
+ />
13
20
  </Link>
14
21
  );
15
22
  };
@@ -23,7 +23,7 @@ const AddToWishlistButton = (props: Props) => {
23
23
  };
24
24
 
25
25
  // conditionally render button styles based on variant (pdp or minicart)
26
- let style: any;
26
+ let style: ButtonProps["sx"];
27
27
  let btnFullwidth: boolean;
28
28
  let btnColor: ButtonProps["color"];
29
29
  let btnVariant: ButtonProps["variant"];
@@ -1,7 +1,7 @@
1
1
  import { AddToWishListDialogContext } from "@evenicanpm/storefront-core/src/components/wishlist-dialogs/add-to-wishlist/compound/context";
2
2
  import { Button, Grid } from "@mui/material";
3
3
  import { useTranslations } from "next-intl";
4
- import React, { useContext } from "react";
4
+ import { useContext } from "react";
5
5
 
6
6
  const AddToWishListBottomUI = () => {
7
7
  const t = useTranslations("Account.Wishlists");
@@ -11,7 +11,6 @@ import { IconButton, styled, type Theme } from "@mui/material";
11
11
  import useMediaQuery from "@mui/material/useMediaQuery";
12
12
  import { useSession } from "next-auth/react";
13
13
  import { useTranslations } from "next-intl";
14
- import React from "react";
15
14
  // ICONS
16
15
  import { MdFavorite } from "react-icons/md";
17
16
 
@@ -2,7 +2,7 @@ import { CreateNewWishlistContext } from "@evenicanpm/storefront-core/src/compon
2
2
  import { Button } from "@mui/material";
3
3
  import Grid from "@mui/material/Grid2";
4
4
  import { useTranslations } from "next-intl";
5
- import React, { useContext } from "react";
5
+ import { useContext } from "react";
6
6
 
7
7
  function BottomUI() {
8
8
  const t = useTranslations("Account.Wishlists");
@@ -42,7 +42,10 @@ export function useAppSession() {
42
42
  await initializeMsal();
43
43
  const res = await getMsalInstance().handleRedirectPromise();
44
44
  if (res) {
45
- const { given_name, family_name } = res.idTokenClaims as any;
45
+ const { given_name, family_name } = res.idTokenClaims as {
46
+ given_name?: string;
47
+ family_name?: string;
48
+ };
46
49
  if (given_name && family_name) {
47
50
  updateUser({
48
51
  AccountNumber: "",
package/src/lib/lib.ts CHANGED
@@ -9,7 +9,7 @@ import { formatDistanceStrict } from "date-fns";
9
9
 
10
10
  function getDateDifference(date: string | number | Date) {
11
11
  const distance = formatDistanceStrict(new Date(), new Date(date));
12
- return distance + " ago";
12
+ return `${distance} ago`;
13
13
  }
14
14
 
15
15
  /**
@@ -6,5 +6,3 @@ export const PageSlug = {
6
6
  Confirmation: "confirmation",
7
7
  Content: "content",
8
8
  } as const;
9
-
10
- type PageSlug = keyof typeof PageSlug;
@@ -12,11 +12,11 @@ const convertParameterToRefiner = (parameter: string): ProductRefinerValue => {
12
12
  sourceValue,
13
13
  ] = parameter.split("|");
14
14
  return {
15
- RefinerRecordId: Number.parseInt(recordId),
16
- DataTypeValue: Number.parseInt(dataTypeValue),
15
+ RefinerRecordId: Number.parseInt(recordId, 10),
16
+ DataTypeValue: Number.parseInt(dataTypeValue, 10),
17
17
  LeftValueBoundString: leftBoundString,
18
18
  RightValueBoundString: rightBoundString,
19
- RefinerSourceValue: Number.parseInt(sourceValue),
19
+ RefinerSourceValue: Number.parseInt(sourceValue, 10),
20
20
  };
21
21
  };
22
22
 
@@ -114,25 +114,22 @@ const AccountNavigation = ({ items, children }: AccountNavigationProps) => {
114
114
  return (
115
115
  <AccountNavigationContext.Provider value={{ items: mergedItems }}>
116
116
  <MainContainer>
117
- {children || (
118
- <>
119
- {mergedItems.map((section) => (
120
- <AccountNavigation.Section
121
- key={section.title}
122
- title={section.title}
123
- >
124
- {section.list.map((item) => (
125
- <AccountNavigation.Item
126
- key={item.title}
127
- {...item}
128
- isActive={pathname?.includes(item.href) ?? false}
129
- label={t(item.title)}
130
- />
131
- ))}
132
- </AccountNavigation.Section>
133
- ))}
134
- </>
135
- )}
117
+ {children ||
118
+ mergedItems.map((section) => (
119
+ <AccountNavigation.Section
120
+ key={section.title}
121
+ title={section.title}
122
+ >
123
+ {section.list.map((item) => (
124
+ <AccountNavigation.Item
125
+ key={item.title}
126
+ {...item}
127
+ isActive={pathname?.includes(item.href) ?? false}
128
+ label={t(item.title)}
129
+ />
130
+ ))}
131
+ </AccountNavigation.Section>
132
+ ))}
136
133
  </MainContainer>
137
134
  </AccountNavigationContext.Provider>
138
135
  );
@@ -156,7 +153,7 @@ AccountNavigation.Section = ({ title, children }: SectionProps) => {
156
153
 
157
154
  interface ItemProps {
158
155
  href: string;
159
- Icon: React.ComponentType<any>;
156
+ Icon: React.ComponentType<React.SVGProps<SVGSVGElement>>;
160
157
  count?: number;
161
158
  label: string;
162
159
  isActive?: boolean;
@@ -28,8 +28,18 @@ import { useLocale, useTranslations } from "next-intl";
28
28
  import React, { createContext, useContext } from "react";
29
29
  import { z } from "zod";
30
30
 
31
+ interface AddressFormValues {
32
+ Name: string;
33
+ Street: string;
34
+ City: string;
35
+ State: string;
36
+ ZipCode: string;
37
+ Country: string;
38
+ Phone: string;
39
+ }
40
+
31
41
  interface FormContextValue {
32
- formik: ReturnType<typeof useFormik<any>>;
42
+ formik: ReturnType<typeof useFormik<AddressFormValues>>;
33
43
  countries: CountryRegionInfo[] | undefined;
34
44
  states: { StateId?: string; StateName?: string }[] | undefined;
35
45
  selectedCountry: CountryRegionInfo | null;
@@ -78,9 +88,7 @@ const AddressForm = ({ address, children }: RootProps) => {
78
88
  Phone: z.string().optional().default(""),
79
89
  });
80
90
 
81
- type FormSchemaType = z.infer<typeof FormSchema>;
82
-
83
- const initialValues: FormSchemaType = {
91
+ const initialValues: AddressFormValues = {
84
92
  Name: address?.Name ?? "",
85
93
  Street: address?.Street ?? "",
86
94
  City: address?.City ?? "",
@@ -90,7 +98,7 @@ const AddressForm = ({ address, children }: RootProps) => {
90
98
  Phone: address?.Phone ?? "",
91
99
  };
92
100
 
93
- const handleSubmit = async (values: FormSchemaType) => {
101
+ const handleSubmit = async (values: AddressFormValues) => {
94
102
  let newAddress: Address = {
95
103
  Name: values.Name,
96
104
  Street: values.Street,
@@ -123,7 +131,7 @@ const AddressForm = ({ address, children }: RootProps) => {
123
131
  }
124
132
  };
125
133
 
126
- const formik = useFormik<FormSchemaType>({
134
+ const formik = useFormik<AddressFormValues>({
127
135
  initialValues,
128
136
  onSubmit: handleSubmit,
129
137
  validate: withZodSchema(FormSchema),
@@ -140,7 +148,7 @@ const AddressForm = ({ address, children }: RootProps) => {
140
148
 
141
149
  // ------------------- Fields -------------------
142
150
  interface FieldProps {
143
- name: keyof Address;
151
+ name: keyof AddressFormValues;
144
152
  label?: string;
145
153
  required?: boolean;
146
154
  }
@@ -15,7 +15,7 @@ import {
15
15
  } from "@mui/material";
16
16
  import Link from "next/link";
17
17
  import { useTranslations } from "next-intl";
18
- import React, { createContext, type ReactNode, useContext } from "react";
18
+ import { createContext, type ReactNode, useContext } from "react";
19
19
  import type { IconType } from "react-icons";
20
20
  import { MdMenu as Menu } from "react-icons/md";
21
21
 
@@ -141,7 +141,7 @@ CheckoutForm.Notes = () => {
141
141
  multiline
142
142
  onChange={debounceCommentUpdate}
143
143
  inputRef={textRef}
144
- inputProps={{ ["data-testid"]: "cart-comment" }}
144
+ inputProps={{ "data-testid": "cart-comment" }}
145
145
  />
146
146
  <Divider sx={{ mb: 2 }} />
147
147
  </>
@@ -117,7 +117,7 @@ CheckoutStep.Header = () => {
117
117
  );
118
118
  };
119
119
 
120
- CheckoutStep.Body = <P extends object = {}>({
120
+ CheckoutStep.Body = <P extends object = object>({
121
121
  component: Component,
122
122
  componentProps,
123
123
  }: {
@@ -44,7 +44,7 @@ interface NewAddressFormCtx {
44
44
  states: { StateName: string; StateId: string }[] | undefined;
45
45
  selectedCountry: CountryRegionInfo | null;
46
46
  setSelectedCountry: (c: CountryRegionInfo | null) => void;
47
- errors: Record<string, any>;
47
+ errors: Partial<Record<keyof AddressFormInput, { message?: string }>>;
48
48
  t: ReturnType<typeof useTranslations>;
49
49
  onCancel: () => void;
50
50
  }
@@ -8,7 +8,10 @@ import {
8
8
  Small,
9
9
  } from "@evenicanpm/storefront-core/src/components/Typography";
10
10
  import type { CheckoutStepComponentProps } from "@evenicanpm/storefront-core/src/pages/checkout/checkout-alt-form/checkout-step";
11
- import type { CardPaymentAcceptResult } from "@msdyn365-commerce/retail-proxy";
11
+ import type {
12
+ CardPaymentAcceptPoint,
13
+ CardPaymentAcceptResult,
14
+ } from "@msdyn365-commerce/retail-proxy";
12
15
  import { Alert, Box, Card } from "@mui/material";
13
16
  import { useTranslations } from "next-intl";
14
17
  import React from "react";
@@ -43,7 +46,7 @@ type PaymentDetailsCompound = React.FC<CheckoutStepComponentProps> & {
43
46
  iframeReference: React.RefObject<HTMLIFrameElement>;
44
47
  iframeHeight: number;
45
48
  errorState: PaymentError[];
46
- paymentAcceptPointData: any;
49
+ paymentAcceptPointData: CardPaymentAcceptPoint | null | undefined;
47
50
  }>;
48
51
  };
49
52
 
@@ -7,7 +7,7 @@ import {
7
7
  Span,
8
8
  } from "@evenicanpm/storefront-core/src/components/Typography";
9
9
  import useCurrencyFormatter from "@evenicanpm/storefront-core/src/lib/currency-formatter";
10
- import React, { createContext, type ReactNode, useContext } from "react";
10
+ import { createContext, type ReactNode, useContext } from "react";
11
11
 
12
12
  interface CartItemContextValue {
13
13
  cartLine: CartLine;
@@ -13,7 +13,7 @@ import ListItem from "@evenicanpm/storefront-core/src/pages/checkout/checkout-al
13
13
  import Box from "@mui/material/Box";
14
14
  import Divider from "@mui/material/Divider";
15
15
  import { useTranslations } from "next-intl";
16
- import React, { createContext, type ReactNode, useContext } from "react";
16
+ import { createContext, type ReactNode, useContext } from "react";
17
17
 
18
18
  interface Props {
19
19
  cart: Cart;
@@ -7,7 +7,7 @@ import {
7
7
  } from "@evenicanpm/storefront-core/src/components/Typography";
8
8
  import { Card } from "@mui/material";
9
9
  import { useTranslations } from "next-intl";
10
- import React, { createContext, type ReactNode, useContext } from "react";
10
+ import { createContext, type ReactNode, useContext } from "react";
11
11
 
12
12
  const AddressContext = createContext<Address | null>(null);
13
13