@evenicanpm/storefront-core 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__mocks__/next-image.tsx +3 -1
- package/package.json +3 -3
- package/src/api-manager/datasources/d365/d365-product.datasource.ts +1 -1
- package/src/api-manager/datasources/d365/utils/product-inventory-utils.ts +1 -3
- package/src/api-manager/datasources/e4/cart/e4-cart.remaps.ts +7 -5
- package/src/api-manager/datasources/e4/product/e4-product.datasource.ts +1 -4
- package/src/api-manager/datasources/e4/product/e4-product.translator.ts +13 -19
- package/src/api-manager/datasources/e4/utils/unwrap-e4-variants.ts +10 -13
- package/src/auth/auth-options.ts +34 -1
- package/src/auth/providers/entra-external-id-provider.ts +50 -0
- package/src/auth/providers/index.ts +8 -1
- package/src/auth/refresh-token.ts +1 -1
- package/src/cms/blocks/interfaces.ts +2 -0
- package/src/components-v2/BazaarMenu.stories.tsx +1 -1
- package/src/components-v2/BazaarMenu.tsx +4 -3
- package/src/components-v2/T/__tests__/T.test.tsx +91 -0
- package/src/components-v2/accordion/__tests__/accordion-header.test.tsx +28 -0
- package/src/components-v2/carousel/__tests__/carousel.test.tsx +208 -0
- package/src/components-v2/carousel-cards/carousel-card-1/__tests__/carousel-card-1.test.tsx +81 -0
- package/src/components-v2/categories/__tests__/category-menu.test.tsx +115 -0
- package/src/components-v2/categories/category-list/category-list.tsx +5 -1
- package/src/components-v2/categories/category-menu.tsx +11 -5
- package/src/components-v2/flex-box/__tests__/flex-box.test.tsx +88 -0
- package/src/components-v2/header/__tests__/header.test.tsx +122 -0
- package/src/components-v2/icons/__tests__/icons.test.tsx +53 -0
- package/src/components-v2/mobile-navigation/__tests__/mobile-navigation-bar.test.tsx +94 -0
- package/src/components-v2/nav-link/__tests__/nav-link.test.tsx +75 -0
- package/src/components-v2/navbar/__tests__/navbar.test.tsx +96 -0
- package/src/components-v2/product-cards/__tests__/product-cards.test.tsx +91 -0
- package/src/components-v2/product-dialog/__tests__/product-dialog.test.tsx +129 -0
- package/src/components-v2/product-dimensions/__tests__/product-dimensions.test.tsx +130 -0
- package/src/components-v2/product-dimensions/compound/dimensions-group-list-chip.tsx +36 -37
- package/src/components-v2/product-quantity-buttons/__tests__/product-quantity-buttons.test.tsx +77 -0
- package/src/components-v2/product-quantity-variants/__tests__/product-quantity-variants.test.tsx +109 -0
- package/src/components-v2/products-view/__tests__/products-view.test.tsx +147 -0
- package/src/components-v2/progress/__tests__/progress.test.tsx +62 -0
- package/src/components-v2/scrollbar/Scrollbar.stories.tsx +2 -2
- package/src/components-v2/scrollbar/__tests__/scrollbar.test.tsx +93 -0
- package/src/components-v2/search-bar/__tests__/search-bar.test.tsx +142 -0
- package/src/components-v2/search-bar/compound/results.tsx +1 -1
- package/src/components-v2/section/__tests__/section.test.tsx +100 -0
- package/src/components-v2/side-nav/__tests__/side-nav.test.tsx +156 -0
- package/src/components-v2/wishlist-dialogs/add-to-wishlist/add-to-wishlist-button.tsx +14 -15
- package/src/components-v2/wishlist-dialogs/styles.ts +8 -10
- package/src/pages-v2/account/addresses/address-item.tsx +2 -1
- package/src/pages-v2/checkout/checkout-alt-form/checkout-form.tsx +6 -1
- package/src/pages-v2/checkout/checkout-alt-form/steps/address/new-address-form.tsx +9 -8
- package/src/pages-v2/product-details/bopis/find-in-store-modal.tsx +1 -1
- package/src/pages-v2/product-details/product-intro/compound/thumbnail-with-skeleton.tsx +1 -0
- package/src/pages-v2/product-list/product-list-context.tsx +123 -44
- package/src/pages-v2/product-list/range-filter.tsx +36 -25
- package/src/pages-v2/product-list/selected-facets.tsx +15 -8
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { render } from "@testing-library/react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import { vi } from "vitest";
|
|
4
|
+
import { SearchBarViewLg, SearchBarViewSm } from "../index";
|
|
5
|
+
|
|
6
|
+
vi.mock("next-intl", () => ({
|
|
7
|
+
useTranslations: () => (key: string) => key,
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
vi.mock(
|
|
11
|
+
"@evenicanpm/storefront-core/src/components-v2/search-bar/compound/search-bar-root",
|
|
12
|
+
() => ({
|
|
13
|
+
default: Object.assign(
|
|
14
|
+
({
|
|
15
|
+
children,
|
|
16
|
+
handleCloseDrawer,
|
|
17
|
+
}: {
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
handleCloseDrawer?: () => void;
|
|
20
|
+
}) => (
|
|
21
|
+
<button
|
|
22
|
+
type="button"
|
|
23
|
+
data-testid="search-bar"
|
|
24
|
+
onClick={handleCloseDrawer}
|
|
25
|
+
>
|
|
26
|
+
{children}
|
|
27
|
+
</button>
|
|
28
|
+
),
|
|
29
|
+
{
|
|
30
|
+
TextField: () => <input data-testid="search-input" />,
|
|
31
|
+
Results: Object.assign(
|
|
32
|
+
({ children }: { children: ReactNode }) => (
|
|
33
|
+
<div data-testid="results">{children}</div>
|
|
34
|
+
),
|
|
35
|
+
{
|
|
36
|
+
ItemCardLg: () => <div data-testid="item-card-lg">Item</div>,
|
|
37
|
+
ItemCardSm: () => <div data-testid="item-card-sm">Item</div>,
|
|
38
|
+
},
|
|
39
|
+
),
|
|
40
|
+
},
|
|
41
|
+
),
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
describe("SearchBar components", () => {
|
|
46
|
+
describe("SearchBarViewLg", () => {
|
|
47
|
+
it("renders large search bar view", () => {
|
|
48
|
+
const { container } = render(<SearchBarViewLg />);
|
|
49
|
+
expect(
|
|
50
|
+
container.querySelector("[data-testid='search-bar']"),
|
|
51
|
+
).toBeTruthy();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("accepts handleCloseDrawer prop", () => {
|
|
55
|
+
const handleClose = vi.fn();
|
|
56
|
+
const { container } = render(
|
|
57
|
+
<SearchBarViewLg handleCloseDrawer={handleClose} />,
|
|
58
|
+
);
|
|
59
|
+
expect(
|
|
60
|
+
container.querySelector("[data-testid='search-bar']"),
|
|
61
|
+
).toBeTruthy();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("renders search bar structure", () => {
|
|
65
|
+
const { container } = render(<SearchBarViewLg />);
|
|
66
|
+
const searchBar = container.querySelector("[data-testid='search-bar']");
|
|
67
|
+
expect(searchBar).toBeTruthy();
|
|
68
|
+
expect(searchBar?.children.length).toBeGreaterThan(0);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it("renders with results container", () => {
|
|
72
|
+
const { container } = render(<SearchBarViewLg />);
|
|
73
|
+
const searchBar = container.querySelector("[data-testid='search-bar']");
|
|
74
|
+
expect(searchBar).toBeTruthy();
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe("SearchBarViewSm", () => {
|
|
79
|
+
it("renders small search bar view", () => {
|
|
80
|
+
const { container } = render(<SearchBarViewSm />);
|
|
81
|
+
expect(
|
|
82
|
+
container.querySelector("[data-testid='search-bar']"),
|
|
83
|
+
).toBeTruthy();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("accepts handleCloseDrawer prop", () => {
|
|
87
|
+
const handleClose = vi.fn();
|
|
88
|
+
const { container } = render(
|
|
89
|
+
<SearchBarViewSm handleCloseDrawer={handleClose} />,
|
|
90
|
+
);
|
|
91
|
+
expect(
|
|
92
|
+
container.querySelector("[data-testid='search-bar']"),
|
|
93
|
+
).toBeTruthy();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("renders search bar structure", () => {
|
|
97
|
+
const { container } = render(<SearchBarViewSm />);
|
|
98
|
+
const searchBar = container.querySelector("[data-testid='search-bar']");
|
|
99
|
+
expect(searchBar).toBeTruthy();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("renders with results container", () => {
|
|
103
|
+
const { container } = render(<SearchBarViewSm />);
|
|
104
|
+
const searchBar = container.querySelector("[data-testid='search-bar']");
|
|
105
|
+
expect(searchBar?.children.length).toBeGreaterThan(0);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("renders different from large view", () => {
|
|
109
|
+
const { container: lgContainer } = render(<SearchBarViewLg />);
|
|
110
|
+
const { container: smContainer } = render(<SearchBarViewSm />);
|
|
111
|
+
expect(
|
|
112
|
+
lgContainer.querySelector("[data-testid='search-bar']"),
|
|
113
|
+
).toBeTruthy();
|
|
114
|
+
expect(
|
|
115
|
+
smContainer.querySelector("[data-testid='search-bar']"),
|
|
116
|
+
).toBeTruthy();
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe("SearchBar integration", () => {
|
|
121
|
+
it("renders search bar without close handler", () => {
|
|
122
|
+
const { container } = render(
|
|
123
|
+
<SearchBarViewLg handleCloseDrawer={undefined} />,
|
|
124
|
+
);
|
|
125
|
+
expect(
|
|
126
|
+
container.querySelector("[data-testid='search-bar']"),
|
|
127
|
+
).toBeTruthy();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("both views render successfully", () => {
|
|
131
|
+
const { container: lgContainer } = render(<SearchBarViewLg />);
|
|
132
|
+
expect(
|
|
133
|
+
lgContainer.querySelector("[data-testid='search-bar']"),
|
|
134
|
+
).toBeTruthy();
|
|
135
|
+
|
|
136
|
+
const { container: smContainer } = render(<SearchBarViewSm />);
|
|
137
|
+
expect(
|
|
138
|
+
smContainer.querySelector("[data-testid='search-bar']"),
|
|
139
|
+
).toBeTruthy();
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -29,7 +29,7 @@ export default function SearchResultsContainer({
|
|
|
29
29
|
category: state.searchCategory,
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
if (!results || results.length === 0) {
|
|
32
|
+
if (!results || !Array.isArray(results) || results.length === 0) {
|
|
33
33
|
return <SearchResultCard>{t("Search.noResults")}</SearchResultCard>;
|
|
34
34
|
}
|
|
35
35
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { vi } from "vitest";
|
|
3
|
+
import { Section } from "../compound/section";
|
|
4
|
+
|
|
5
|
+
vi.mock("next-intl", () => ({
|
|
6
|
+
useTranslations: () => (key: string) => key,
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
vi.mock(
|
|
10
|
+
"@evenicanpm/storefront-core/src/components-v2/section/compound/section-header",
|
|
11
|
+
() => ({
|
|
12
|
+
SectionHeader: () => <div data-testid="section-header">Header</div>,
|
|
13
|
+
}),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
vi.mock("@mui/material/Container", () => ({
|
|
17
|
+
default: ({ className, children }: any) => (
|
|
18
|
+
<div data-testid="mui-container" className={className}>
|
|
19
|
+
{children}
|
|
20
|
+
</div>
|
|
21
|
+
),
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
describe("Section", () => {
|
|
25
|
+
it("renders section with children", () => {
|
|
26
|
+
render(
|
|
27
|
+
<Section>
|
|
28
|
+
<div>Section Content</div>
|
|
29
|
+
</Section>,
|
|
30
|
+
);
|
|
31
|
+
expect(screen.getByText("Section Content")).toBeInTheDocument();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("renders with Container component", () => {
|
|
35
|
+
const { container } = render(
|
|
36
|
+
<Section>
|
|
37
|
+
<div>Content</div>
|
|
38
|
+
</Section>,
|
|
39
|
+
);
|
|
40
|
+
expect(
|
|
41
|
+
container.querySelector("[data-testid='mui-container']"),
|
|
42
|
+
).toBeTruthy();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("passes className to Container", () => {
|
|
46
|
+
const { container } = render(
|
|
47
|
+
<Section>
|
|
48
|
+
<div>Content</div>
|
|
49
|
+
</Section>,
|
|
50
|
+
);
|
|
51
|
+
const containerElement = container.querySelector(
|
|
52
|
+
"[data-testid='mui-container']",
|
|
53
|
+
);
|
|
54
|
+
expect(containerElement?.className).toContain("pb-1");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("accepts Box props", () => {
|
|
58
|
+
const { container } = render(
|
|
59
|
+
<Section sx={{ backgroundColor: "red" }}>
|
|
60
|
+
<div>Content</div>
|
|
61
|
+
</Section>,
|
|
62
|
+
);
|
|
63
|
+
expect(container.firstChild).toBeTruthy();
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("renders with spacing", () => {
|
|
67
|
+
render(
|
|
68
|
+
<Section>
|
|
69
|
+
<div>Spaced Content</div>
|
|
70
|
+
</Section>,
|
|
71
|
+
);
|
|
72
|
+
expect(screen.getByText("Spaced Content")).toBeInTheDocument();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("exposes Header subcomponent", () => {
|
|
76
|
+
expect(Section.Header).toBeDefined();
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it("renders multiple children inside container", () => {
|
|
80
|
+
render(
|
|
81
|
+
<Section>
|
|
82
|
+
<div>Child 1</div>
|
|
83
|
+
<div>Child 2</div>
|
|
84
|
+
<div>Child 3</div>
|
|
85
|
+
</Section>,
|
|
86
|
+
);
|
|
87
|
+
expect(screen.getByText("Child 1")).toBeInTheDocument();
|
|
88
|
+
expect(screen.getByText("Child 2")).toBeInTheDocument();
|
|
89
|
+
expect(screen.getByText("Child 3")).toBeInTheDocument();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("accepts custom sx styling", () => {
|
|
93
|
+
const { container } = render(
|
|
94
|
+
<Section sx={{ padding: 2, margin: 1 }}>
|
|
95
|
+
<div>Styled Section</div>
|
|
96
|
+
</Section>,
|
|
97
|
+
);
|
|
98
|
+
expect(container.firstChild).toBeTruthy();
|
|
99
|
+
});
|
|
100
|
+
});
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import { vi } from "vitest";
|
|
4
|
+
import SideNav from "../side-nav";
|
|
5
|
+
|
|
6
|
+
vi.mock("@evenicanpm/storefront-core/src/components-v2/scrollbar", () => ({
|
|
7
|
+
default: ({
|
|
8
|
+
children,
|
|
9
|
+
autoHide,
|
|
10
|
+
}: {
|
|
11
|
+
children: ReactNode;
|
|
12
|
+
autoHide?: boolean;
|
|
13
|
+
}) => (
|
|
14
|
+
<div data-testid="scrollbar" data-autohide={autoHide}>
|
|
15
|
+
{children}
|
|
16
|
+
</div>
|
|
17
|
+
),
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
vi.mock("@mui/material/Drawer", () => ({
|
|
21
|
+
default: ({
|
|
22
|
+
open,
|
|
23
|
+
onClose,
|
|
24
|
+
children,
|
|
25
|
+
anchor,
|
|
26
|
+
}: {
|
|
27
|
+
open: boolean;
|
|
28
|
+
onClose?: () => void;
|
|
29
|
+
children: ReactNode;
|
|
30
|
+
anchor: string;
|
|
31
|
+
}) => (
|
|
32
|
+
<button
|
|
33
|
+
type="button"
|
|
34
|
+
data-testid="drawer"
|
|
35
|
+
data-open={open}
|
|
36
|
+
data-anchor={anchor}
|
|
37
|
+
onClick={() => onClose?.()}
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
</button>
|
|
41
|
+
),
|
|
42
|
+
}));
|
|
43
|
+
|
|
44
|
+
describe("SideNav", () => {
|
|
45
|
+
const mockHandler = (toggle: () => void) => (
|
|
46
|
+
<button type="button" data-testid="toggle-button" onClick={toggle}>
|
|
47
|
+
Toggle
|
|
48
|
+
</button>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
it("renders side nav with handler and children", () => {
|
|
52
|
+
render(
|
|
53
|
+
<SideNav handler={mockHandler}>
|
|
54
|
+
<div>Side Nav Content</div>
|
|
55
|
+
</SideNav>,
|
|
56
|
+
);
|
|
57
|
+
expect(screen.getByText("Side Nav Content")).toBeInTheDocument();
|
|
58
|
+
expect(screen.getByTestId("toggle-button")).toBeInTheDocument();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("renders drawer component", () => {
|
|
62
|
+
const { container } = render(
|
|
63
|
+
<SideNav handler={mockHandler}>
|
|
64
|
+
<div>Content</div>
|
|
65
|
+
</SideNav>,
|
|
66
|
+
);
|
|
67
|
+
expect(container.querySelector("[data-testid='drawer']")).toBeTruthy();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("renders with default position left", () => {
|
|
71
|
+
const { container } = render(
|
|
72
|
+
<SideNav handler={mockHandler}>
|
|
73
|
+
<div>Content</div>
|
|
74
|
+
</SideNav>,
|
|
75
|
+
);
|
|
76
|
+
const drawer = container.querySelector("[data-testid='drawer']");
|
|
77
|
+
expect(drawer?.getAttribute("data-anchor")).toBe("left");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("renders with custom position right", () => {
|
|
81
|
+
const { container } = render(
|
|
82
|
+
<SideNav position="right" handler={mockHandler}>
|
|
83
|
+
<div>Content</div>
|
|
84
|
+
</SideNav>,
|
|
85
|
+
);
|
|
86
|
+
const drawer = container.querySelector("[data-testid='drawer']");
|
|
87
|
+
expect(drawer?.getAttribute("data-anchor")).toBe("right");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("manages drawer state", () => {
|
|
91
|
+
const { container } = render(
|
|
92
|
+
<SideNav handler={mockHandler}>
|
|
93
|
+
<div>Content</div>
|
|
94
|
+
</SideNav>,
|
|
95
|
+
);
|
|
96
|
+
const drawer = container.querySelector("[data-testid='drawer']");
|
|
97
|
+
expect(drawer?.getAttribute("data-open")).toBe("false");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("accepts custom width", () => {
|
|
101
|
+
const { container } = render(
|
|
102
|
+
<SideNav width={300} handler={mockHandler}>
|
|
103
|
+
<div>Content</div>
|
|
104
|
+
</SideNav>,
|
|
105
|
+
);
|
|
106
|
+
expect(container.querySelector("[data-testid='drawer']")).toBeTruthy();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("uses scrollbar for children", () => {
|
|
110
|
+
const { container } = render(
|
|
111
|
+
<SideNav handler={mockHandler}>
|
|
112
|
+
<div>Scrollable Content</div>
|
|
113
|
+
</SideNav>,
|
|
114
|
+
);
|
|
115
|
+
expect(container.querySelector("[data-testid='scrollbar']")).toBeTruthy();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it("handles drawer close", () => {
|
|
119
|
+
const { container } = render(
|
|
120
|
+
<SideNav handler={mockHandler}>
|
|
121
|
+
<div>Content</div>
|
|
122
|
+
</SideNav>,
|
|
123
|
+
);
|
|
124
|
+
const drawer = container.querySelector("[data-testid='drawer']");
|
|
125
|
+
if (drawer) fireEvent.click(drawer);
|
|
126
|
+
expect(screen.getByTestId("toggle-button")).toBeInTheDocument();
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("accepts external toggle function", () => {
|
|
130
|
+
const externalToggle = vi.fn();
|
|
131
|
+
const { container } = render(
|
|
132
|
+
<SideNav toggle={externalToggle} handler={mockHandler}>
|
|
133
|
+
<div>Content</div>
|
|
134
|
+
</SideNav>,
|
|
135
|
+
);
|
|
136
|
+
expect(container.querySelector("[data-testid='drawer']")).toBeTruthy();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("syncs external and internal state", () => {
|
|
140
|
+
const { rerender, container } = render(
|
|
141
|
+
<SideNav open={true} handler={mockHandler}>
|
|
142
|
+
<div>Content</div>
|
|
143
|
+
</SideNav>,
|
|
144
|
+
);
|
|
145
|
+
let drawer = container.querySelector("[data-testid='drawer']");
|
|
146
|
+
expect(drawer?.getAttribute("data-open")).toBe("true");
|
|
147
|
+
|
|
148
|
+
rerender(
|
|
149
|
+
<SideNav open={false} handler={mockHandler}>
|
|
150
|
+
<div>Content</div>
|
|
151
|
+
</SideNav>,
|
|
152
|
+
);
|
|
153
|
+
drawer = container.querySelector("[data-testid='drawer']");
|
|
154
|
+
expect(drawer?.getAttribute("data-open")).toBe("false");
|
|
155
|
+
});
|
|
156
|
+
});
|
|
@@ -23,23 +23,22 @@ 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: any;
|
|
27
|
+
let btnFullwidth: boolean;
|
|
27
28
|
let btnColor: ButtonProps["color"];
|
|
28
29
|
let btnVariant: ButtonProps["variant"];
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
btnColor = "secondary";
|
|
42
|
-
break;
|
|
30
|
+
|
|
31
|
+
if (props.variant === "minicart") {
|
|
32
|
+
style = {
|
|
33
|
+
px: 4,
|
|
34
|
+
};
|
|
35
|
+
btnFullwidth = true;
|
|
36
|
+
btnVariant = "outlined";
|
|
37
|
+
btnColor = "primary";
|
|
38
|
+
} else {
|
|
39
|
+
btnFullwidth = false;
|
|
40
|
+
btnVariant = "contained";
|
|
41
|
+
btnColor = "secondary";
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
return (
|
|
@@ -9,16 +9,14 @@ type ExtendedNavLinkProps = NavLinkProps & {
|
|
|
9
9
|
isCurrentPath?: boolean;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
export const MainContainer
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}),
|
|
21
|
-
) as typeof Card;
|
|
12
|
+
export const MainContainer = styled(Card)(({ theme }) => ({
|
|
13
|
+
paddingBottom: "1.5rem",
|
|
14
|
+
[theme.breakpoints.down("md")]: {
|
|
15
|
+
boxShadow: "none",
|
|
16
|
+
overflowY: "auto",
|
|
17
|
+
height: "calc(100vh - 64px)",
|
|
18
|
+
},
|
|
19
|
+
}));
|
|
22
20
|
|
|
23
21
|
export const StyledNavLink: ComponentType<ExtendedNavLinkProps> = styled(
|
|
24
22
|
NavLink,
|
|
@@ -83,9 +83,10 @@ const AddressListItem = ({ address, children, sx }: RootProps) => {
|
|
|
83
83
|
};
|
|
84
84
|
|
|
85
85
|
// ----------------- Subcomponents -----------------
|
|
86
|
+
type FieldValue = string | number | boolean;
|
|
86
87
|
interface FieldProps {
|
|
87
88
|
field: keyof Address; // "Name" | "FullAddress" | "Phone" etc.
|
|
88
|
-
render?: (value:
|
|
89
|
+
render?: (value: FieldValue, address: Address) => ReactNode;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
AddressListItem.Field = ({ field, render }: FieldProps) => {
|
|
@@ -166,10 +166,15 @@ CheckoutForm.Step = <T extends object>({
|
|
|
166
166
|
const t = useTranslations("Checkout");
|
|
167
167
|
if (!ctx) return null;
|
|
168
168
|
const { activeStep, setActiveStep, cart } = ctx;
|
|
169
|
+
|
|
170
|
+
if (stepNumber === undefined) {
|
|
171
|
+
throw new Error("CheckoutForm.Step must be used inside CheckoutForm.Steps");
|
|
172
|
+
}
|
|
173
|
+
|
|
169
174
|
return (
|
|
170
175
|
<CheckoutStep
|
|
171
176
|
title={t(title)}
|
|
172
|
-
stepNumber={stepNumber
|
|
177
|
+
stepNumber={stepNumber}
|
|
173
178
|
activeStep={activeStep}
|
|
174
179
|
setActiveStep={setActiveStep}
|
|
175
180
|
cart={cart}
|
|
@@ -179,12 +179,12 @@ const NewAddressForm = ({
|
|
|
179
179
|
const ctx: NewAddressFormCtx = {
|
|
180
180
|
form,
|
|
181
181
|
countries,
|
|
182
|
-
states: states
|
|
183
|
-
? states
|
|
182
|
+
states: Array.isArray(states)
|
|
183
|
+
? states.map((s) => ({
|
|
184
184
|
StateName: s.StateName ?? "",
|
|
185
185
|
StateId: s.StateId ?? "",
|
|
186
186
|
}))
|
|
187
|
-
:
|
|
187
|
+
: [],
|
|
188
188
|
selectedCountry,
|
|
189
189
|
setSelectedCountry,
|
|
190
190
|
errors,
|
|
@@ -312,11 +312,12 @@ NewAddressForm.StateSelect = () => {
|
|
|
312
312
|
render={({ field }) => (
|
|
313
313
|
<Select labelId="state-label" {...field}>
|
|
314
314
|
<MenuItem value="0">Select a state</MenuItem>
|
|
315
|
-
{states
|
|
316
|
-
|
|
317
|
-
{
|
|
318
|
-
|
|
319
|
-
|
|
315
|
+
{Array.isArray(states) &&
|
|
316
|
+
states?.map(({ StateName, StateId }) => (
|
|
317
|
+
<MenuItem key={StateId} value={StateId}>
|
|
318
|
+
{StateName}
|
|
319
|
+
</MenuItem>
|
|
320
|
+
))}
|
|
320
321
|
</Select>
|
|
321
322
|
)}
|
|
322
323
|
/>
|
|
@@ -155,7 +155,7 @@ const FindInStoreModal = ({
|
|
|
155
155
|
if (!stores) {
|
|
156
156
|
return [];
|
|
157
157
|
}
|
|
158
|
-
const _stores =
|
|
158
|
+
const _stores = Object.values(stores);
|
|
159
159
|
if (hideOutOfStock) {
|
|
160
160
|
return _stores.filter(
|
|
161
161
|
(store) => !isOutOfStock(store.location.OrgUnitNumber || ""),
|
|
@@ -13,6 +13,7 @@ function ThumbnailWithSkeleton({ src }: Readonly<{ src: string }>) {
|
|
|
13
13
|
{!loaded && <Skeleton variant="rounded" width={50} height={50} />}
|
|
14
14
|
<img
|
|
15
15
|
src={src}
|
|
16
|
+
alt="Product thumbnail"
|
|
16
17
|
onLoad={() => setLoaded(true)}
|
|
17
18
|
style={{
|
|
18
19
|
display: loaded ? "block" : "none",
|