@faststore/core 2.0.140-alpha.0 → 2.0.142-alpha.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/.turbo/turbo-build.log +6 -6
- package/CHANGELOG.md +12 -0
- package/cms/faststore/content-types.json +5 -0
- package/cms/faststore/sections.json +42 -1
- package/package.json +4 -4
- package/src/components/cart/CartToggle/CartToggle.tsx +4 -4
- package/src/components/cms/GlobalSections.tsx +3 -3
- package/src/components/navigation/Navbar/Navbar.tsx +120 -64
- package/src/components/navigation/Navbar/index.ts +1 -0
- package/src/components/navigation/NavbarLinks/NavbarLinks.tsx +20 -33
- package/src/components/navigation/NavbarSlider/NavbarSlider.tsx +23 -7
- package/src/components/region/RegionButton/RegionButton.tsx +3 -3
- package/src/components/sections/Alert/index.ts +1 -0
- package/src/components/sections/Breadcrumb/Breadcrumb.tsx +30 -10
- package/src/components/sections/Footer/Footer.tsx +2 -9
- package/src/components/sections/Navbar/Navbar.tsx +85 -0
- package/src/components/sections/Navbar/index.ts +2 -0
- package/src/components/sections/ProductDetails/ProductDetails.tsx +1 -3
- package/src/components/sections/Section/Section.tsx +10 -4
- package/src/components/ui/Breadcrumb/Breadcrumb.tsx +15 -17
- package/src/components/ui/Button/ButtonSignIn/ButtonSignIn.tsx +12 -3
- package/src/components/ui/Image/Image.tsx +3 -1
- package/src/components/ui/Image/index.ts +1 -0
- package/src/components/ui/Logo/Logo.tsx +23 -2
- package/src/pages/[...slug].tsx +41 -22
- package/src/pages/[slug]/p.tsx +9 -8
- package/src/pages/index.tsx +10 -9
- package/src/pages/s.tsx +29 -10
- package/src/server/cms.ts +3 -1
- package/src/styles/themes/midnight.scss +0 -1
- package/src/styles/themes/soft-blue.scss +0 -1
- /package/src/components/{navigation → sections}/Navbar/section.module.scss +0 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -26,10 +26,10 @@ Route (pages) Size First Load JS
|
|
|
26
26
|
┌ ● / 2.97 kB 126 kB
|
|
27
27
|
├ └ css/13a4da555ff5e3be.css 7.19 kB
|
|
28
28
|
├ /_app 0 B 77.9 kB
|
|
29
|
-
├ ● /[...slug]
|
|
29
|
+
├ ● /[...slug] 10 kB 133 kB
|
|
30
30
|
├ └ css/2e9de35e0cb999e0.css 7.9 kB
|
|
31
|
-
├ ● /[slug]/p 11.
|
|
32
|
-
├ └ css/
|
|
31
|
+
├ ● /[slug]/p 11.4 kB 134 kB
|
|
32
|
+
├ └ css/7701d01af31e31d1.css 10.9 kB
|
|
33
33
|
├ ○ /404 1.09 kB 113 kB
|
|
34
34
|
├ ● /500 1.11 kB 113 kB
|
|
35
35
|
├ ● /account 672 B 113 kB
|
|
@@ -37,13 +37,13 @@ Route (pages) Size First Load JS
|
|
|
37
37
|
├ λ /api/preview 0 B 77.9 kB
|
|
38
38
|
├ ● /checkout 659 B 113 kB
|
|
39
39
|
├ ● /login 1.01 kB 113 kB
|
|
40
|
-
└ ● /s
|
|
40
|
+
└ ● /s 995 B 124 kB
|
|
41
41
|
+ First Load JS shared by all 80.7 kB
|
|
42
42
|
├ chunks/framework-dfd14d7ce6600b03.js 45.3 kB
|
|
43
43
|
├ chunks/main-fd466221927468fd.js 23.9 kB
|
|
44
44
|
├ chunks/pages/_app-3e4e7e579cb0681a.js 6.43 kB
|
|
45
|
-
├ chunks/webpack-
|
|
46
|
-
└ css/
|
|
45
|
+
├ chunks/webpack-3c331de8004e61a7.js 2.27 kB
|
|
46
|
+
└ css/923c4a942e57bc91.css 2.81 kB
|
|
47
47
|
|
|
48
48
|
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
|
|
49
49
|
○ (Static) automatically rendered as static HTML (uses no initial props)
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.0.142-alpha.0](https://github.com/vtex/faststore/compare/v2.0.141-alpha.0...v2.0.142-alpha.0) (2023-05-16)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- Adjust `Navbar` for CMS ([#1756](https://github.com/vtex/faststore/issues/1756)) ([105a8b2](https://github.com/vtex/faststore/commit/105a8b2f69ffd8438532d7c9eb959ed26a567675))
|
|
11
|
+
|
|
12
|
+
## [2.0.141-alpha.0](https://github.com/vtex/faststore/compare/v2.0.140-alpha.0...v2.0.141-alpha.0) (2023-05-16)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- Pages with `RenderSection` + `Breadcrumb` section CMS ([#1747](https://github.com/vtex/faststore/issues/1747)) ([63f1b6a](https://github.com/vtex/faststore/commit/63f1b6a3b6da30b0c24ba78a8bffbc62470eac0a))
|
|
17
|
+
|
|
6
18
|
## [2.0.140-alpha.0](https://github.com/vtex/faststore/compare/v2.0.139-alpha.0...v2.0.140-alpha.0) (2023-05-16)
|
|
7
19
|
|
|
8
20
|
**Note:** Version bump only for package @faststore/core
|
|
@@ -149,11 +149,12 @@
|
|
|
149
149
|
"title": "Navbar",
|
|
150
150
|
"type": "object",
|
|
151
151
|
"description": "Navbar configuration",
|
|
152
|
-
"required": ["
|
|
152
|
+
"required": ["logo"],
|
|
153
153
|
"properties": {
|
|
154
154
|
"logo": {
|
|
155
155
|
"title": "Logo",
|
|
156
156
|
"type": "object",
|
|
157
|
+
"required": ["src"],
|
|
157
158
|
"properties": {
|
|
158
159
|
"src": {
|
|
159
160
|
"title": "Image",
|
|
@@ -194,6 +195,11 @@
|
|
|
194
195
|
"title": "Call to Action",
|
|
195
196
|
"type": "string",
|
|
196
197
|
"default": "Sign In"
|
|
198
|
+
},
|
|
199
|
+
"myAccountLabel": {
|
|
200
|
+
"title": "My Account Label",
|
|
201
|
+
"type": "string",
|
|
202
|
+
"default": "My Account"
|
|
197
203
|
}
|
|
198
204
|
}
|
|
199
205
|
},
|
|
@@ -272,6 +278,41 @@
|
|
|
272
278
|
}
|
|
273
279
|
}
|
|
274
280
|
}
|
|
281
|
+
},
|
|
282
|
+
"menu": {
|
|
283
|
+
"type": "object",
|
|
284
|
+
"title": "Menu",
|
|
285
|
+
"properties": {
|
|
286
|
+
"icon": {
|
|
287
|
+
"title": "Icon",
|
|
288
|
+
"type": "object",
|
|
289
|
+
"properties": {
|
|
290
|
+
"icon": {
|
|
291
|
+
"title": "Icon",
|
|
292
|
+
"type": "string",
|
|
293
|
+
"enumNames": ["List"],
|
|
294
|
+
"enum": ["List"],
|
|
295
|
+
"default": "List"
|
|
296
|
+
},
|
|
297
|
+
"alt": {
|
|
298
|
+
"title": "Alternative Label",
|
|
299
|
+
"type": "string",
|
|
300
|
+
"default": "List"
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
"home": {
|
|
307
|
+
"title": "Home",
|
|
308
|
+
"type": "object",
|
|
309
|
+
"properties": {
|
|
310
|
+
"label": {
|
|
311
|
+
"title": "Go to Home Label",
|
|
312
|
+
"type": "string",
|
|
313
|
+
"default": "Go to Home"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
275
316
|
}
|
|
276
317
|
}
|
|
277
318
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.142-alpha.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"browserslist": "supports es6-module and not dead",
|
|
6
6
|
"scripts": {
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"@envelop/parser-cache": "^2.2.0",
|
|
31
31
|
"@envelop/validation-cache": "^2.2.0",
|
|
32
32
|
"@faststore/api": "^2.0.140-alpha.0",
|
|
33
|
-
"@faststore/components": "^2.0.
|
|
33
|
+
"@faststore/components": "^2.0.142-alpha.0",
|
|
34
34
|
"@faststore/graphql-utils": "^2.0.3-alpha.0",
|
|
35
35
|
"@faststore/sdk": "^2.0.118-alpha.0",
|
|
36
|
-
"@faststore/ui": "^2.0.
|
|
36
|
+
"@faststore/ui": "^2.0.142-alpha.0",
|
|
37
37
|
"@types/react": "^18.0.14",
|
|
38
38
|
"@vtex/client-cms": "^0.2.12",
|
|
39
39
|
"autoprefixer": "^10.4.0",
|
|
@@ -108,5 +108,5 @@
|
|
|
108
108
|
"msw": {
|
|
109
109
|
"workerDirectory": "public"
|
|
110
110
|
},
|
|
111
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "d03c47af5c1e66cec599d8dec1fd211c5ec01afc"
|
|
112
112
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Icon as UIIcon,
|
|
2
3
|
Badge as UIBadge,
|
|
3
|
-
Icon,
|
|
4
4
|
IconButton as UIIconButton,
|
|
5
5
|
} from '@faststore/ui'
|
|
6
6
|
|
|
7
7
|
import { useCartToggleButton } from 'src/sdk/cart/useCartToggleButton'
|
|
8
8
|
|
|
9
|
-
function CartToggle() {
|
|
9
|
+
function CartToggle({ alt, icon }: { alt: string; icon: string }) {
|
|
10
10
|
const btnProps = useCartToggleButton()
|
|
11
11
|
const totalItems = btnProps['data-items']
|
|
12
12
|
|
|
13
13
|
return (
|
|
14
14
|
<UIIconButton
|
|
15
15
|
data-fs-cart-toggle
|
|
16
|
-
aria-label={
|
|
17
|
-
icon={<
|
|
16
|
+
aria-label={alt}
|
|
17
|
+
icon={<UIIcon name={icon} width={32} height={32} />}
|
|
18
18
|
{...btnProps}
|
|
19
19
|
>
|
|
20
20
|
<UIBadge counter>{totalItems}</UIBadge>
|
|
@@ -7,11 +7,11 @@ import { PageContentType, getPage } from 'src/server/cms'
|
|
|
7
7
|
|
|
8
8
|
import RegionBar from 'src/components/common/RegionBar'
|
|
9
9
|
import Toast from 'src/components/common/Toast'
|
|
10
|
-
import Navbar from 'src/components/navigation/Navbar'
|
|
11
10
|
import RenderSections from './RenderSections'
|
|
12
11
|
|
|
12
|
+
import Alert from 'src/components/sections/Alert'
|
|
13
|
+
import Navbar from 'src/components/sections/Navbar'
|
|
13
14
|
import Footer from 'src/components/sections/Footer'
|
|
14
|
-
import Alert from 'src/components/sections/Alert/Alert'
|
|
15
15
|
|
|
16
16
|
export const GLOBAL_SECTIONS_CONTENT_TYPE = 'globalSections'
|
|
17
17
|
|
|
@@ -23,6 +23,7 @@ export type GlobalSectionsData = {
|
|
|
23
23
|
const COMPONENTS: Record<string, ComponentType<any>> = {
|
|
24
24
|
Alert,
|
|
25
25
|
Footer,
|
|
26
|
+
Navbar,
|
|
26
27
|
...CUSTOM_COMPONENTS,
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -49,7 +50,6 @@ function GlobalSections({
|
|
|
49
50
|
return (
|
|
50
51
|
<>
|
|
51
52
|
<RenderSections sections={firstSections} components={COMPONENTS} />
|
|
52
|
-
<Navbar />
|
|
53
53
|
|
|
54
54
|
<Toast />
|
|
55
55
|
|
|
@@ -1,30 +1,80 @@
|
|
|
1
1
|
import { Suspense, useRef, useState } from 'react'
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
useUI,
|
|
5
|
+
useScrollDirection,
|
|
4
6
|
Icon as UIIcon,
|
|
5
|
-
IconButton as UIIconButton,
|
|
6
7
|
Navbar as UINavbar,
|
|
8
|
+
NavbarRow as UINavbarRow,
|
|
9
|
+
IconButton as UIIconButton,
|
|
7
10
|
NavbarButtons as UINavbarButtons,
|
|
8
11
|
NavbarHeader as UINavbarHeader,
|
|
9
|
-
NavbarRow as UINavbarRow,
|
|
10
|
-
useScrollDirection,
|
|
11
|
-
useUI,
|
|
12
12
|
} from '@faststore/ui'
|
|
13
13
|
|
|
14
|
+
import { mark } from 'src/sdk/tests/mark'
|
|
15
|
+
|
|
14
16
|
import CartToggle from 'src/components/cart/CartToggle'
|
|
15
|
-
import type { SearchInputRef } from 'src/components/search/SearchInput'
|
|
16
17
|
import SearchInput from 'src/components/search/SearchInput'
|
|
17
|
-
import {
|
|
18
|
+
import type { SearchInputRef } from 'src/components/search/SearchInput'
|
|
19
|
+
|
|
18
20
|
import Link from 'src/components/ui/Link'
|
|
19
21
|
import Logo from 'src/components/ui/Logo'
|
|
20
|
-
import {
|
|
22
|
+
import { ButtonSignIn, ButtonSignInFallback } from 'src/components/ui/Button'
|
|
21
23
|
|
|
22
24
|
import NavbarLinks from '../NavbarLinks'
|
|
23
25
|
import NavbarSlider from '../NavbarSlider'
|
|
26
|
+
import type { NavbarProps as SectionNavbarProps } from '../../sections/Navbar'
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
export interface NavbarProps {
|
|
29
|
+
/**
|
|
30
|
+
* Logo props.
|
|
31
|
+
*/
|
|
32
|
+
logo: SectionNavbarProps['logo']
|
|
33
|
+
/**
|
|
34
|
+
* Cart props.
|
|
35
|
+
*/
|
|
36
|
+
cart: SectionNavbarProps['cartIcon']
|
|
37
|
+
/**
|
|
38
|
+
* Sign In props.
|
|
39
|
+
*/
|
|
40
|
+
signIn: {
|
|
41
|
+
button: SectionNavbarProps['signInButton']
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Region props.
|
|
45
|
+
*/
|
|
46
|
+
region: {
|
|
47
|
+
icon: string
|
|
48
|
+
label: string
|
|
49
|
+
shouldDisplayRegion: boolean
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Page links.
|
|
53
|
+
*/
|
|
54
|
+
links: SectionNavbarProps['navigation']['pageLinks']
|
|
55
|
+
/**
|
|
56
|
+
* Home props.
|
|
57
|
+
*/
|
|
58
|
+
home: SectionNavbarProps['navigation']['home']
|
|
59
|
+
/**
|
|
60
|
+
* Menu props.
|
|
61
|
+
*/
|
|
62
|
+
menu: SectionNavbarProps['navigation']['menu']
|
|
63
|
+
}
|
|
26
64
|
|
|
27
|
-
function Navbar(
|
|
65
|
+
function Navbar({
|
|
66
|
+
cart,
|
|
67
|
+
logo,
|
|
68
|
+
home,
|
|
69
|
+
links,
|
|
70
|
+
signIn,
|
|
71
|
+
region,
|
|
72
|
+
home: { label: homeLabel },
|
|
73
|
+
signIn: { button: signInButton },
|
|
74
|
+
menu: {
|
|
75
|
+
icon: { icon: menuIcon, alt: menuIconAlt },
|
|
76
|
+
},
|
|
77
|
+
}: NavbarProps) {
|
|
28
78
|
const scrollDirection = useScrollDirection()
|
|
29
79
|
const { openNavbar, navbar: displayNavbar } = useUI()
|
|
30
80
|
const searchMobileRef = useRef<SearchInputRef>(null)
|
|
@@ -36,67 +86,73 @@ function Navbar() {
|
|
|
36
86
|
}
|
|
37
87
|
|
|
38
88
|
return (
|
|
39
|
-
<
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)}
|
|
89
|
+
<UINavbar scrollDirection={scrollDirection}>
|
|
90
|
+
<UINavbarHeader>
|
|
91
|
+
<UINavbarRow className="layout__content">
|
|
92
|
+
{!searchExpanded && (
|
|
93
|
+
<>
|
|
94
|
+
<UIIconButton
|
|
95
|
+
data-fs-navbar-button-menu
|
|
96
|
+
onClick={openNavbar}
|
|
97
|
+
aria-label={menuIconAlt}
|
|
98
|
+
icon={<UIIcon name={menuIcon} width={32} height={32} />}
|
|
99
|
+
/>
|
|
100
|
+
<Link
|
|
101
|
+
href="/"
|
|
102
|
+
data-fs-navbar-logo
|
|
103
|
+
prefetch={false}
|
|
104
|
+
title={homeLabel}
|
|
105
|
+
aria-label={homeLabel}
|
|
106
|
+
>
|
|
107
|
+
<Logo {...logo} />
|
|
108
|
+
</Link>
|
|
109
|
+
</>
|
|
110
|
+
)}
|
|
62
111
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
/>
|
|
76
|
-
)}
|
|
77
|
-
|
|
78
|
-
<SearchInput
|
|
79
|
-
placeholder=""
|
|
80
|
-
ref={searchMobileRef}
|
|
81
|
-
testId="store-input-mobile"
|
|
82
|
-
buttonTestId="store-input-mobile-button"
|
|
83
|
-
onSearchClick={handlerExpandSearch}
|
|
112
|
+
<SearchInput />
|
|
113
|
+
|
|
114
|
+
<UINavbarButtons searchExpanded={searchExpanded}>
|
|
115
|
+
{searchExpanded && (
|
|
116
|
+
<UIIconButton
|
|
117
|
+
data-fs-button-collapse
|
|
118
|
+
aria-label="Collapse search bar"
|
|
119
|
+
icon={<UIIcon name="CaretLeft" width={32} height={32} />}
|
|
120
|
+
onClick={() => {
|
|
121
|
+
setSearchExpanded(false)
|
|
122
|
+
searchMobileRef.current?.resetSearchInput()
|
|
123
|
+
}}
|
|
84
124
|
/>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
<SearchInput
|
|
128
|
+
placeholder=""
|
|
129
|
+
ref={searchMobileRef}
|
|
130
|
+
testId="store-input-mobile"
|
|
131
|
+
buttonTestId="store-input-mobile-button"
|
|
132
|
+
onSearchClick={handlerExpandSearch}
|
|
133
|
+
/>
|
|
85
134
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
135
|
+
<Suspense fallback={<ButtonSignInFallback />}>
|
|
136
|
+
<ButtonSignIn {...signInButton} />
|
|
137
|
+
</Suspense>
|
|
89
138
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
139
|
+
<CartToggle {...cart} />
|
|
140
|
+
</UINavbarButtons>
|
|
141
|
+
</UINavbarRow>
|
|
142
|
+
</UINavbarHeader>
|
|
94
143
|
|
|
95
|
-
|
|
144
|
+
<NavbarLinks links={links} region={region} className="hidden-mobile" />
|
|
96
145
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
146
|
+
{displayNavbar && (
|
|
147
|
+
<NavbarSlider
|
|
148
|
+
home={home}
|
|
149
|
+
logo={logo}
|
|
150
|
+
links={links}
|
|
151
|
+
signIn={signIn}
|
|
152
|
+
region={region}
|
|
153
|
+
/>
|
|
154
|
+
)}
|
|
155
|
+
</UINavbar>
|
|
100
156
|
)
|
|
101
157
|
}
|
|
102
158
|
|
|
@@ -1,57 +1,44 @@
|
|
|
1
1
|
import type { AnchorHTMLAttributes } from 'react'
|
|
2
2
|
|
|
3
|
-
import type { NavbarLinksProps as UINavbarLinksProps } from '@faststore/ui'
|
|
4
3
|
import {
|
|
5
4
|
NavbarLinks as UINavbarLinks,
|
|
6
5
|
NavbarLinksList as UINavbarLinksList,
|
|
7
6
|
NavbarLinksListItem as UINavbarLinksListItem,
|
|
8
7
|
} from '@faststore/ui'
|
|
8
|
+
import type { NavbarLinksProps as UINavbarLinksProps } from '@faststore/ui'
|
|
9
9
|
|
|
10
|
-
import RegionButton from 'src/components/region/RegionButton'
|
|
11
10
|
import Link from 'src/components/ui/Link'
|
|
11
|
+
import RegionButton from 'src/components/region/RegionButton'
|
|
12
|
+
import type { NavbarProps } from 'src/components/navigation/Navbar'
|
|
13
|
+
|
|
12
14
|
import { mark } from 'src/sdk/tests/mark'
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
interface NavbarLinksProps extends UINavbarLinksProps {
|
|
17
|
+
links: NavbarProps['links']
|
|
18
|
+
region: NavbarProps['region']
|
|
15
19
|
/**
|
|
16
20
|
* Callback function when a link is clicked.
|
|
17
21
|
*/
|
|
18
22
|
onClickLink?: AnchorHTMLAttributes<HTMLAnchorElement>['onClick']
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
name: 'Home Appliances',
|
|
28
|
-
href: '/kitchen---home-appliances',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: 'Computer and Software',
|
|
32
|
-
href: '/computer---software',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
name: 'Technology',
|
|
36
|
-
href: '/technology',
|
|
37
|
-
},
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
function NavbarLinks({ onClickLink, ...otherProps }: NavbarLinksProps) {
|
|
25
|
+
function NavbarLinks({
|
|
26
|
+
links,
|
|
27
|
+
onClickLink,
|
|
28
|
+
region: { icon: regionIcon, label: regionLabel, shouldDisplayRegion },
|
|
29
|
+
...otherProps
|
|
30
|
+
}: NavbarLinksProps) {
|
|
41
31
|
return (
|
|
42
32
|
<UINavbarLinks {...otherProps}>
|
|
43
33
|
<div className="layout__content">
|
|
44
|
-
|
|
34
|
+
{shouldDisplayRegion && (
|
|
35
|
+
<RegionButton icon={regionIcon} label={regionLabel} />
|
|
36
|
+
)}
|
|
45
37
|
<UINavbarLinksList>
|
|
46
|
-
{
|
|
47
|
-
<UINavbarLinksListItem key={
|
|
48
|
-
<Link
|
|
49
|
-
|
|
50
|
-
href={href}
|
|
51
|
-
prefetch={false}
|
|
52
|
-
onClick={onClickLink}
|
|
53
|
-
>
|
|
54
|
-
{name}
|
|
38
|
+
{links.map(({ url, text }) => (
|
|
39
|
+
<UINavbarLinksListItem key={text}>
|
|
40
|
+
<Link variant="display" href={url} onClick={onClickLink}>
|
|
41
|
+
{text}
|
|
55
42
|
</Link>
|
|
56
43
|
</UINavbarLinksListItem>
|
|
57
44
|
))}
|
|
@@ -12,11 +12,27 @@ import { ButtonSignIn, ButtonSignInFallback } from 'src/components/ui/Button'
|
|
|
12
12
|
import Link from 'src/components/ui/Link'
|
|
13
13
|
import Logo from 'src/components/ui/Logo'
|
|
14
14
|
import { mark } from 'src/sdk/tests/mark'
|
|
15
|
+
|
|
15
16
|
import NavbarLinks from '../NavbarLinks'
|
|
17
|
+
import type { NavbarProps } from '../Navbar'
|
|
18
|
+
|
|
19
|
+
import styles from '../../sections/Navbar/section.module.scss'
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
interface NavbarSliderProps {
|
|
22
|
+
logo: NavbarProps['logo']
|
|
23
|
+
home: NavbarProps['home']
|
|
24
|
+
links: NavbarProps['links']
|
|
25
|
+
region: NavbarProps['region']
|
|
26
|
+
signIn: NavbarProps['signIn']
|
|
27
|
+
}
|
|
18
28
|
|
|
19
|
-
function NavbarSlider(
|
|
29
|
+
function NavbarSlider({
|
|
30
|
+
logo,
|
|
31
|
+
links,
|
|
32
|
+
region,
|
|
33
|
+
home: { label: homeLabel },
|
|
34
|
+
signIn: { button: signInButton },
|
|
35
|
+
}: NavbarSliderProps) {
|
|
20
36
|
const { closeNavbar } = useUI()
|
|
21
37
|
const { fade, fadeOut } = useFadeEffect()
|
|
22
38
|
|
|
@@ -33,19 +49,19 @@ function NavbarSlider() {
|
|
|
33
49
|
<Link
|
|
34
50
|
href="/"
|
|
35
51
|
onClick={fadeOut}
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
title={homeLabel}
|
|
53
|
+
aria-label={homeLabel}
|
|
38
54
|
data-fs-navbar-slider-logo
|
|
39
55
|
>
|
|
40
|
-
<Logo />
|
|
56
|
+
<Logo {...logo} />
|
|
41
57
|
</Link>
|
|
42
58
|
</UINavbarSliderHeader>
|
|
43
59
|
<UINavbarSliderContent>
|
|
44
|
-
<NavbarLinks onClickLink={fadeOut} />
|
|
60
|
+
<NavbarLinks onClickLink={fadeOut} links={links} region={region} />
|
|
45
61
|
</UINavbarSliderContent>
|
|
46
62
|
<UINavbarSliderFooter>
|
|
47
63
|
<Suspense fallback={<ButtonSignInFallback />}>
|
|
48
|
-
<ButtonSignIn />
|
|
64
|
+
<ButtonSignIn {...signInButton} />
|
|
49
65
|
</Suspense>
|
|
50
66
|
</UINavbarSliderFooter>
|
|
51
67
|
</UINavbarSlider>
|
|
@@ -3,7 +3,7 @@ import { Button as UIButton } from '@faststore/ui'
|
|
|
3
3
|
import { Icon, useUI } from '@faststore/ui'
|
|
4
4
|
import { useSession } from 'src/sdk/session'
|
|
5
5
|
|
|
6
|
-
function RegionButton() {
|
|
6
|
+
function RegionButton({ icon, label }: { icon: string; label: string }) {
|
|
7
7
|
const { openModal } = useUI()
|
|
8
8
|
const { postalCode } = useSession()
|
|
9
9
|
|
|
@@ -11,11 +11,11 @@ function RegionButton() {
|
|
|
11
11
|
<UIButton
|
|
12
12
|
variant="tertiary"
|
|
13
13
|
size="small"
|
|
14
|
-
icon={<Icon name=
|
|
14
|
+
icon={<Icon name={icon} width={18} height={18} weight="bold" />}
|
|
15
15
|
iconPosition="left"
|
|
16
16
|
onClick={openModal}
|
|
17
17
|
>
|
|
18
|
-
{postalCode ??
|
|
18
|
+
{postalCode ?? label}
|
|
19
19
|
</UIButton>
|
|
20
20
|
)
|
|
21
21
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './Alert'
|
|
@@ -1,26 +1,46 @@
|
|
|
1
1
|
import { memo } from 'react'
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import UIBreadcrumb from 'src/components/ui/Breadcrumb'
|
|
3
|
+
import Breadcrumb from 'src/components/ui/Breadcrumb'
|
|
5
4
|
|
|
6
5
|
import Section from '../Section'
|
|
7
6
|
|
|
7
|
+
import {
|
|
8
|
+
ServerCollectionPageQueryQuery,
|
|
9
|
+
ServerProductPageQueryQuery,
|
|
10
|
+
} from '@generated/graphql'
|
|
8
11
|
import styles from './section.module.scss'
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
type BreadcrumbContext =
|
|
14
|
+
| ServerProductPageQueryQuery['product']
|
|
15
|
+
| ServerCollectionPageQueryQuery['collection']
|
|
16
|
+
|
|
17
|
+
interface BreadcrumbSectionProps {
|
|
18
|
+
context?: BreadcrumbContext
|
|
19
|
+
icon: string
|
|
20
|
+
alt: string
|
|
13
21
|
}
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
23
|
+
const isProduct = (x: any): x is ServerProductPageQueryQuery['product'] =>
|
|
24
|
+
x?.sku != undefined && x?.sku != null
|
|
25
|
+
const isCollection = (
|
|
26
|
+
x: any
|
|
27
|
+
): x is ServerCollectionPageQueryQuery['collection'] =>
|
|
28
|
+
x?.seo != undefined && x?.seo != null && x?.sku == undefined
|
|
29
|
+
|
|
30
|
+
function BreadcrumbSection({ context, ...otherProps }: BreadcrumbSectionProps) {
|
|
31
|
+
const title = isCollection(context) ? context?.seo?.title : 'All Products'
|
|
32
|
+
const fallback = [{ item: '/', name: title, position: 1 }]
|
|
33
|
+
const breadcrumbList = isProduct(context)
|
|
34
|
+
? context?.breadcrumbList?.itemListElement
|
|
35
|
+
: isCollection(context)
|
|
36
|
+
? context?.breadcrumbList?.itemListElement
|
|
37
|
+
: fallback
|
|
18
38
|
|
|
19
39
|
return (
|
|
20
40
|
<Section className={`${styles.section} section-breadcrumb layout__content`}>
|
|
21
|
-
<
|
|
41
|
+
<Breadcrumb breadcrumbList={breadcrumbList} {...otherProps} />
|
|
22
42
|
</Section>
|
|
23
43
|
)
|
|
24
44
|
}
|
|
25
45
|
|
|
26
|
-
export default memo(
|
|
46
|
+
export default memo(BreadcrumbSection)
|
|
@@ -11,7 +11,7 @@ import UIFooter, {
|
|
|
11
11
|
} from '../../common/Footer'
|
|
12
12
|
import type { FooterLinksProps, FooterSocialProps } from '../../common/Footer'
|
|
13
13
|
|
|
14
|
-
import
|
|
14
|
+
import Logo from 'src/components/ui/Logo'
|
|
15
15
|
import UIIncentives from '../../ui/Incentives'
|
|
16
16
|
import type { Incentive } from '../../ui/Incentives'
|
|
17
17
|
|
|
@@ -61,14 +61,7 @@ const Footer = ({
|
|
|
61
61
|
/>
|
|
62
62
|
</UIFooterNavigation>
|
|
63
63
|
<UIFooterInfo>
|
|
64
|
-
<
|
|
65
|
-
data-fs-footer-logo
|
|
66
|
-
loading="lazy"
|
|
67
|
-
src={logoSrc}
|
|
68
|
-
alt={logoAlt}
|
|
69
|
-
width={112}
|
|
70
|
-
height={119}
|
|
71
|
-
/>
|
|
64
|
+
<Logo alt={logoAlt} src={logoSrc} />
|
|
72
65
|
{showPaymentMethods && (
|
|
73
66
|
<UIPaymentMethods
|
|
74
67
|
flagList={paymentMethods}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import UINavbar from '../../navigation/Navbar'
|
|
2
|
+
|
|
3
|
+
import Section from '../Section'
|
|
4
|
+
|
|
5
|
+
import styles from './section.module.scss'
|
|
6
|
+
|
|
7
|
+
type PageLinks = {
|
|
8
|
+
url: string
|
|
9
|
+
text: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface NavbarProps {
|
|
13
|
+
logo: {
|
|
14
|
+
alt: string
|
|
15
|
+
src: string
|
|
16
|
+
}
|
|
17
|
+
signInButton: {
|
|
18
|
+
icon: {
|
|
19
|
+
alt: string
|
|
20
|
+
icon: string
|
|
21
|
+
}
|
|
22
|
+
label: string
|
|
23
|
+
myAccountLabel: string
|
|
24
|
+
}
|
|
25
|
+
cartIcon: {
|
|
26
|
+
alt: string
|
|
27
|
+
icon: string
|
|
28
|
+
}
|
|
29
|
+
navigation: {
|
|
30
|
+
regionalization: {
|
|
31
|
+
enabled: boolean
|
|
32
|
+
icon: {
|
|
33
|
+
alt: string
|
|
34
|
+
icon: string
|
|
35
|
+
}
|
|
36
|
+
label: string
|
|
37
|
+
}
|
|
38
|
+
pageLinks: PageLinks[]
|
|
39
|
+
menu: {
|
|
40
|
+
icon: {
|
|
41
|
+
alt: string
|
|
42
|
+
icon: string
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
home: {
|
|
46
|
+
label: string
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function Navbar({
|
|
52
|
+
logo,
|
|
53
|
+
cartIcon,
|
|
54
|
+
signInButton,
|
|
55
|
+
navigation: {
|
|
56
|
+
menu,
|
|
57
|
+
home,
|
|
58
|
+
pageLinks,
|
|
59
|
+
regionalization: {
|
|
60
|
+
label: regionLabel,
|
|
61
|
+
icon: { icon: regionIcon },
|
|
62
|
+
enabled: shouldDisplayRegion,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
}: NavbarProps) {
|
|
66
|
+
return (
|
|
67
|
+
<Section as="header" className={`${styles.section} section-navbar`}>
|
|
68
|
+
<UINavbar
|
|
69
|
+
home={home}
|
|
70
|
+
menu={menu}
|
|
71
|
+
logo={logo}
|
|
72
|
+
cart={cartIcon}
|
|
73
|
+
links={pageLinks}
|
|
74
|
+
signIn={{ button: signInButton }}
|
|
75
|
+
region={{
|
|
76
|
+
icon: regionIcon,
|
|
77
|
+
label: regionLabel,
|
|
78
|
+
shouldDisplayRegion,
|
|
79
|
+
}}
|
|
80
|
+
/>
|
|
81
|
+
</Section>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default Navbar
|
|
@@ -3,8 +3,8 @@ import type { CurrencyCode, ViewItemEvent } from '@faststore/sdk'
|
|
|
3
3
|
import { sendAnalyticsEvent } from '@faststore/sdk'
|
|
4
4
|
import {
|
|
5
5
|
BuyButton as UIBuyButton,
|
|
6
|
-
QuantitySelector as UIQuantitySelector,
|
|
7
6
|
ProductTitle as UIProductTitle,
|
|
7
|
+
QuantitySelector as UIQuantitySelector,
|
|
8
8
|
} from '@faststore/ui'
|
|
9
9
|
import { useEffect, useState } from 'react'
|
|
10
10
|
|
|
@@ -13,7 +13,6 @@ const { Price, DiscountBadge } = Components
|
|
|
13
13
|
|
|
14
14
|
import type { ProductDetailsFragment_ProductFragment } from '@generated/graphql'
|
|
15
15
|
import OutOfStock from 'src/components/product/OutOfStock'
|
|
16
|
-
import Breadcrumb from 'src/components/ui/Breadcrumb'
|
|
17
16
|
import ImageGallery from 'src/components/ui/ImageGallery'
|
|
18
17
|
import ShippingSimulation from 'src/components/ui/ShippingSimulation'
|
|
19
18
|
import Selectors from 'src/components/ui/SkuSelector'
|
|
@@ -170,7 +169,6 @@ function ProductDetails({ context: staleProduct }: Props) {
|
|
|
170
169
|
className={`${styles.section} section-product-details layout__content layout__section`}
|
|
171
170
|
>
|
|
172
171
|
<section data-fs-product-details>
|
|
173
|
-
<Breadcrumb breadcrumbList={breadcrumbs.itemListElement} />
|
|
174
172
|
<section data-fs-product-details-body>
|
|
175
173
|
<header data-fs-product-details-title data-fs-product-details-section>
|
|
176
174
|
<UIProductTitle
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import { forwardRef } from 'react'
|
|
2
2
|
import type { DetailedHTMLProps, HTMLAttributes } from 'react'
|
|
3
3
|
|
|
4
|
-
type
|
|
4
|
+
type BaseProps = DetailedHTMLProps<HTMLAttributes<HTMLElement>, HTMLElement>
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
type SectionProps = BaseProps & {
|
|
7
|
+
as?: 'section' | 'header' | 'footer' | 'aside'
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Section = forwardRef<HTMLDivElement, SectionProps>(function Section(
|
|
11
|
+
{ as, className = '', ...otherProps },
|
|
8
12
|
ref
|
|
9
13
|
) {
|
|
14
|
+
const Component = as ?? 'section'
|
|
15
|
+
|
|
10
16
|
return (
|
|
11
|
-
<
|
|
17
|
+
<Component ref={ref} className={`section ${className}`} {...otherProps} />
|
|
12
18
|
)
|
|
13
19
|
})
|
|
14
20
|
|
|
@@ -4,28 +4,26 @@ import { memo } from 'react'
|
|
|
4
4
|
|
|
5
5
|
import Link from 'src/components/ui/Link'
|
|
6
6
|
|
|
7
|
-
type ItemElement = {
|
|
8
|
-
item: string
|
|
9
|
-
name: string
|
|
10
|
-
position: number
|
|
11
|
-
}
|
|
12
7
|
export interface BreadcrumbProps extends UIBreadcrumbProps {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
*/
|
|
16
|
-
breadcrumbList: ItemElement[]
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
interface BaseBreadcrumbProps extends BreadcrumbProps {
|
|
20
|
-
isDesktop?: boolean
|
|
8
|
+
icon: string
|
|
9
|
+
alt: string
|
|
21
10
|
}
|
|
22
11
|
|
|
23
|
-
const Breadcrumb = ({
|
|
12
|
+
const Breadcrumb = ({
|
|
13
|
+
icon = 'Home',
|
|
14
|
+
alt = 'Go to homepage',
|
|
15
|
+
...otherProps
|
|
16
|
+
}: BreadcrumbProps) => (
|
|
24
17
|
<UIBreadcrumb
|
|
25
|
-
breadcrumbList={breadcrumbList}
|
|
26
18
|
homeLink={
|
|
27
|
-
<Link
|
|
28
|
-
|
|
19
|
+
<Link
|
|
20
|
+
data-fs-breadcrumb-link
|
|
21
|
+
data-fs-breadcrumb-link-home
|
|
22
|
+
aria-label={alt}
|
|
23
|
+
href="/"
|
|
24
|
+
prefetch={false}
|
|
25
|
+
>
|
|
26
|
+
<Icon name={icon} width={18} height={18} weight="bold" />
|
|
29
27
|
</Link>
|
|
30
28
|
}
|
|
31
29
|
renderLink={({ itemProps: { item: link, name } }) => (
|
|
@@ -3,7 +3,15 @@ import { Icon, LinkButton } from '@faststore/ui'
|
|
|
3
3
|
import { useSession } from 'src/sdk/session'
|
|
4
4
|
import { useCart } from '../../../../sdk/cart/index'
|
|
5
5
|
|
|
6
|
-
const ButtonSignIn = (
|
|
6
|
+
const ButtonSignIn = ({
|
|
7
|
+
label,
|
|
8
|
+
myAccountLabel,
|
|
9
|
+
icon: { alt, icon },
|
|
10
|
+
}: {
|
|
11
|
+
label: string
|
|
12
|
+
myAccountLabel: string
|
|
13
|
+
icon: { alt: string; icon: string }
|
|
14
|
+
}) => {
|
|
7
15
|
const { id } = useCart()
|
|
8
16
|
const { person } = useSession()
|
|
9
17
|
|
|
@@ -14,11 +22,12 @@ const ButtonSignIn = () => {
|
|
|
14
22
|
person?.id ? `/account?orderFormId=${id}` : `/login?orderFormId=${id}`
|
|
15
23
|
}
|
|
16
24
|
className="text__title-mini"
|
|
25
|
+
aria-label={alt}
|
|
17
26
|
variant="tertiary"
|
|
18
|
-
icon={<Icon name=
|
|
27
|
+
icon={<Icon name={icon} width={18} height={18} weight="bold" />}
|
|
19
28
|
iconPosition="left"
|
|
20
29
|
>
|
|
21
|
-
{person?.id ?
|
|
30
|
+
{person?.id ? myAccountLabel : label}
|
|
22
31
|
</LinkButton>
|
|
23
32
|
)
|
|
24
33
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { memo } from 'react'
|
|
2
2
|
|
|
3
|
-
import NextImage, { ImageProps } from 'next/future/image'
|
|
3
|
+
import NextImage, { ImageProps as NextImageProps } from 'next/future/image'
|
|
4
4
|
import loader from './loader'
|
|
5
5
|
|
|
6
|
+
export type ImageProps = NextImageProps
|
|
7
|
+
|
|
6
8
|
// Next loader function does not handle all props as height and options
|
|
7
9
|
// so we use a custom loader to handle images using thumbor server with VTEX CDN
|
|
8
10
|
// https://nextjs.org/docs/api-reference/next/image#loader
|
|
@@ -1,5 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { Image } from 'src/components/ui/Image'
|
|
2
|
+
import type { ImageProps } from 'src/components/ui/Image'
|
|
3
|
+
|
|
4
|
+
interface LogoProps {
|
|
5
|
+
alt: string
|
|
6
|
+
src: string
|
|
7
|
+
loading?: ImageProps['loading']
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function Logo({ alt, src, loading = 'lazy' }: LogoProps) {
|
|
11
|
+
return (
|
|
12
|
+
<div data-fs-logo>
|
|
13
|
+
<Image
|
|
14
|
+
alt={alt}
|
|
15
|
+
src={src}
|
|
16
|
+
width={0}
|
|
17
|
+
height={0}
|
|
18
|
+
sizes="15vw"
|
|
19
|
+
loading={loading}
|
|
20
|
+
style={{ width: '100%', height: 'auto' }}
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
3
24
|
}
|
|
4
25
|
|
|
5
26
|
export default Logo
|
package/src/pages/[...slug].tsx
CHANGED
|
@@ -25,15 +25,29 @@ import { useApplySearchState } from 'src/sdk/search/state'
|
|
|
25
25
|
import { mark } from 'src/sdk/tests/mark'
|
|
26
26
|
import { execute } from 'src/server'
|
|
27
27
|
|
|
28
|
-
import
|
|
28
|
+
import { Locator } from '@vtex/client-cms'
|
|
29
|
+
import type { ComponentType } from 'react'
|
|
29
30
|
import GlobalSections, {
|
|
30
31
|
getGlobalSectionsData,
|
|
31
32
|
GlobalSectionsData,
|
|
32
33
|
} from 'src/components/cms/GlobalSections'
|
|
33
|
-
import
|
|
34
|
+
import RenderSections from 'src/components/cms/RenderSections'
|
|
35
|
+
import CUSTOM_COMPONENTS from 'src/customizations/components'
|
|
36
|
+
import { getPage, PLPContentType } from 'src/server/cms'
|
|
37
|
+
import storeConfig from '../../faststore.config'
|
|
34
38
|
|
|
35
|
-
type Props = ServerCollectionPageQueryQuery &
|
|
36
|
-
|
|
39
|
+
type Props = ServerCollectionPageQueryQuery &
|
|
40
|
+
PLPContentType & {
|
|
41
|
+
globalSections: GlobalSectionsData
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Sections: Components imported from each store's custom components and '../components/sections' only.
|
|
46
|
+
* Do not import or render components from any other folder in here.
|
|
47
|
+
*/
|
|
48
|
+
const COMPONENTS: Record<string, ComponentType<any>> = {
|
|
49
|
+
Breadcrumb,
|
|
50
|
+
...CUSTOM_COMPONENTS,
|
|
37
51
|
}
|
|
38
52
|
|
|
39
53
|
const useSearchParams = ({
|
|
@@ -56,11 +70,11 @@ const useSearchParams = ({
|
|
|
56
70
|
return useMemo(() => parseSearchState(new URL(hrefState)), [hrefState])
|
|
57
71
|
}
|
|
58
72
|
|
|
59
|
-
function Page({ globalSections, ...
|
|
60
|
-
const { collection } =
|
|
73
|
+
function Page({ sections, globalSections, ...otherProps }: Props) {
|
|
74
|
+
const { collection } = otherProps
|
|
61
75
|
const router = useRouter()
|
|
62
76
|
const applySearchState = useApplySearchState()
|
|
63
|
-
const searchParams = useSearchParams(
|
|
77
|
+
const searchParams = useSearchParams(otherProps)
|
|
64
78
|
|
|
65
79
|
const { page } = searchParams
|
|
66
80
|
const title = collection?.seo.title ?? storeConfig.seo.title
|
|
@@ -103,9 +117,10 @@ function Page({ globalSections, ...props }: Props) {
|
|
|
103
117
|
If needed, wrap your component in a <Section /> component
|
|
104
118
|
(not the HTML tag) before rendering it here.
|
|
105
119
|
*/}
|
|
106
|
-
<
|
|
107
|
-
|
|
108
|
-
|
|
120
|
+
<RenderSections
|
|
121
|
+
context={collection}
|
|
122
|
+
sections={sections}
|
|
123
|
+
components={COMPONENTS}
|
|
109
124
|
/>
|
|
110
125
|
|
|
111
126
|
<Hero
|
|
@@ -161,16 +176,21 @@ export const getStaticProps: GetStaticProps<
|
|
|
161
176
|
Props,
|
|
162
177
|
{ slug: string[] },
|
|
163
178
|
Locator
|
|
164
|
-
> = async (
|
|
165
|
-
const {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
179
|
+
> = async ({ params, previewData }) => {
|
|
180
|
+
const [{ data, errors = [] }, cmsPage, globalSections] = await Promise.all([
|
|
181
|
+
execute<
|
|
182
|
+
ServerCollectionPageQueryQueryVariables,
|
|
183
|
+
ServerCollectionPageQueryQuery
|
|
184
|
+
>({
|
|
185
|
+
variables: { slug: params?.slug.join('/') ?? '' },
|
|
186
|
+
operationName: query,
|
|
187
|
+
}),
|
|
188
|
+
getPage<PLPContentType>({
|
|
189
|
+
...(previewData?.contentType === 'plp' ? previewData : null),
|
|
190
|
+
contentType: 'plp',
|
|
191
|
+
}),
|
|
192
|
+
getGlobalSectionsData(previewData),
|
|
193
|
+
])
|
|
174
194
|
|
|
175
195
|
const notFound = errors.find(isNotFoundError)
|
|
176
196
|
|
|
@@ -184,11 +204,10 @@ export const getStaticProps: GetStaticProps<
|
|
|
184
204
|
throw errors[0]
|
|
185
205
|
}
|
|
186
206
|
|
|
187
|
-
const globalSections = await getGlobalSectionsData(context.previewData)
|
|
188
|
-
|
|
189
207
|
return {
|
|
190
208
|
props: {
|
|
191
209
|
...data,
|
|
210
|
+
...cmsPage,
|
|
192
211
|
globalSections,
|
|
193
212
|
},
|
|
194
213
|
}
|
package/src/pages/[slug]/p.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
} from '@generated/graphql'
|
|
12
12
|
import RenderSections from 'src/components/cms/RenderSections'
|
|
13
13
|
import BannerNewsletter from 'src/components/sections/BannerNewsletter/BannerNewsletter'
|
|
14
|
+
import Breadcrumb from 'src/components/sections/Breadcrumb'
|
|
14
15
|
import CrossSellingShelf from 'src/components/sections/CrossSellingShelf'
|
|
15
16
|
import ProductDetails from 'src/components/sections/ProductDetails'
|
|
16
17
|
import CUSTOM_COMPONENTS from 'src/customizations/components'
|
|
@@ -20,17 +21,18 @@ import { execute } from 'src/server'
|
|
|
20
21
|
import type { PDPContentType } from 'src/server/cms'
|
|
21
22
|
import { getPage } from 'src/server/cms'
|
|
22
23
|
|
|
23
|
-
import storeConfig from '../../../faststore.config'
|
|
24
24
|
import GlobalSections, {
|
|
25
25
|
GlobalSectionsData,
|
|
26
26
|
getGlobalSectionsData,
|
|
27
27
|
} from 'src/components/cms/GlobalSections'
|
|
28
|
+
import storeConfig from '../../../faststore.config'
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Sections: Components imported from each store's custom components and '../components/sections' only.
|
|
31
32
|
* Do not import or render components from any other folder in here.
|
|
32
33
|
*/
|
|
33
34
|
const COMPONENTS: Record<string, ComponentType<any>> = {
|
|
35
|
+
Breadcrumb,
|
|
34
36
|
ProductDetails,
|
|
35
37
|
CrossSellingShelf,
|
|
36
38
|
BannerNewsletter,
|
|
@@ -181,15 +183,16 @@ export const getStaticProps: GetStaticProps<
|
|
|
181
183
|
Locator
|
|
182
184
|
> = async ({ params, previewData }) => {
|
|
183
185
|
const slug = params?.slug ?? ''
|
|
184
|
-
const [cmsPage,
|
|
185
|
-
getPage<PDPContentType>({
|
|
186
|
-
...(previewData?.contentType === 'pdp' ? previewData : null),
|
|
187
|
-
contentType: 'pdp',
|
|
188
|
-
}),
|
|
186
|
+
const [searchResult, cmsPage, globalSections] = await Promise.all([
|
|
189
187
|
execute<ServerProductPageQueryQueryVariables, ServerProductPageQueryQuery>({
|
|
190
188
|
variables: { slug },
|
|
191
189
|
operationName: query,
|
|
192
190
|
}),
|
|
191
|
+
getPage<PDPContentType>({
|
|
192
|
+
...(previewData?.contentType === 'pdp' ? previewData : null),
|
|
193
|
+
contentType: 'pdp',
|
|
194
|
+
}),
|
|
195
|
+
getGlobalSectionsData(previewData),
|
|
193
196
|
])
|
|
194
197
|
|
|
195
198
|
const { data, errors = [] } = searchResult
|
|
@@ -206,8 +209,6 @@ export const getStaticProps: GetStaticProps<
|
|
|
206
209
|
throw errors[0]
|
|
207
210
|
}
|
|
208
211
|
|
|
209
|
-
const globalSections = await getGlobalSectionsData(previewData)
|
|
210
|
-
|
|
211
212
|
return {
|
|
212
213
|
props: {
|
|
213
214
|
...data,
|
package/src/pages/index.tsx
CHANGED
|
@@ -15,11 +15,11 @@ import { mark } from 'src/sdk/tests/mark'
|
|
|
15
15
|
import type { PageContentType } from 'src/server/cms'
|
|
16
16
|
import { getPage } from 'src/server/cms'
|
|
17
17
|
|
|
18
|
-
import storeConfig from '../../faststore.config'
|
|
19
18
|
import GlobalSections, {
|
|
20
19
|
GlobalSectionsData,
|
|
21
20
|
getGlobalSectionsData,
|
|
22
21
|
} from 'src/components/cms/GlobalSections'
|
|
22
|
+
import storeConfig from '../../faststore.config'
|
|
23
23
|
|
|
24
24
|
/* A list of components that can be used in the CMS. */
|
|
25
25
|
const COMPONENTS: Record<string, ComponentType<any>> = {
|
|
@@ -85,14 +85,15 @@ export const getStaticProps: GetStaticProps<
|
|
|
85
85
|
Record<string, string>,
|
|
86
86
|
Locator
|
|
87
87
|
> = async ({ previewData }) => {
|
|
88
|
-
const page = await
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
const [page, globalSections] = await Promise.all([
|
|
89
|
+
getPage<PageContentType>({
|
|
90
|
+
...(previewData?.contentType === 'page'
|
|
91
|
+
? previewData
|
|
92
|
+
: { filters: { 'settings.seo.slug': '/' } }),
|
|
93
|
+
contentType: 'page',
|
|
94
|
+
}),
|
|
95
|
+
getGlobalSectionsData(previewData),
|
|
96
|
+
])
|
|
96
97
|
|
|
97
98
|
return {
|
|
98
99
|
props: { page, globalSections },
|
package/src/pages/s.tsx
CHANGED
|
@@ -1,25 +1,38 @@
|
|
|
1
|
+
import type { SearchState } from '@faststore/sdk'
|
|
1
2
|
import { parseSearchState, SearchProvider } from '@faststore/sdk'
|
|
3
|
+
import { SROnly as UISROnly } from '@faststore/ui'
|
|
2
4
|
import { NextSeo } from 'next-seo'
|
|
3
5
|
import { useRouter } from 'next/router'
|
|
6
|
+
import type { ComponentType } from 'react'
|
|
4
7
|
import { useEffect, useState } from 'react'
|
|
5
|
-
import type { SearchState } from '@faststore/sdk'
|
|
6
|
-
import { SROnly as UISROnly } from '@faststore/ui'
|
|
7
8
|
|
|
8
9
|
import Breadcrumb from 'src/components/sections/Breadcrumb'
|
|
9
10
|
import ProductGallery from 'src/components/sections/ProductGallery'
|
|
10
11
|
import { ITEMS_PER_PAGE } from 'src/constants'
|
|
12
|
+
import CUSTOM_COMPONENTS from 'src/customizations/components'
|
|
11
13
|
import { useApplySearchState } from 'src/sdk/search/state'
|
|
12
14
|
import { mark } from 'src/sdk/tests/mark'
|
|
13
15
|
|
|
14
|
-
import
|
|
16
|
+
import { Locator } from '@vtex/client-cms'
|
|
17
|
+
import { GetStaticProps } from 'next'
|
|
15
18
|
import GlobalSections, {
|
|
16
19
|
getGlobalSectionsData,
|
|
17
20
|
GlobalSectionsData,
|
|
18
21
|
} from 'src/components/cms/GlobalSections'
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
22
|
+
import RenderSections from 'src/components/cms/RenderSections'
|
|
23
|
+
import { getPage, SearchContentType } from 'src/server/cms'
|
|
24
|
+
import storeConfig from '../../faststore.config'
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Sections: Components imported from each store's custom components and '../components/sections' only.
|
|
28
|
+
* Do not import or render components from any other folder in here.
|
|
29
|
+
*/
|
|
30
|
+
const COMPONENTS: Record<string, ComponentType<any>> = {
|
|
31
|
+
Breadcrumb,
|
|
32
|
+
...CUSTOM_COMPONENTS,
|
|
33
|
+
}
|
|
21
34
|
|
|
22
|
-
type Props = {
|
|
35
|
+
type Props = SearchContentType & {
|
|
23
36
|
globalSections: GlobalSectionsData
|
|
24
37
|
}
|
|
25
38
|
|
|
@@ -36,7 +49,7 @@ const useSearchParams = () => {
|
|
|
36
49
|
return params
|
|
37
50
|
}
|
|
38
51
|
|
|
39
|
-
function Page({ globalSections }: Props) {
|
|
52
|
+
function Page({ sections, globalSections }: Props) {
|
|
40
53
|
const searchParams = useSearchParams()
|
|
41
54
|
const applySearchState = useApplySearchState()
|
|
42
55
|
const title = 'Search Results'
|
|
@@ -79,7 +92,7 @@ function Page({ globalSections }: Props) {
|
|
|
79
92
|
If needed, wrap your component in a <Section /> component
|
|
80
93
|
(not the HTML tag) before rendering it here.
|
|
81
94
|
*/}
|
|
82
|
-
<
|
|
95
|
+
<RenderSections sections={sections} components={COMPONENTS} />
|
|
83
96
|
|
|
84
97
|
<ProductGallery
|
|
85
98
|
title="Search Results"
|
|
@@ -95,10 +108,16 @@ export const getStaticProps: GetStaticProps<
|
|
|
95
108
|
Record<string, string>,
|
|
96
109
|
Locator
|
|
97
110
|
> = async ({ previewData }) => {
|
|
98
|
-
const globalSections = await
|
|
111
|
+
const [cmsPage, globalSections] = await Promise.all([
|
|
112
|
+
getPage<SearchContentType>({
|
|
113
|
+
...(previewData?.contentType === 'search' ? previewData : null),
|
|
114
|
+
contentType: 'search',
|
|
115
|
+
}),
|
|
116
|
+
getGlobalSectionsData(previewData),
|
|
117
|
+
])
|
|
99
118
|
|
|
100
119
|
return {
|
|
101
|
-
props: { globalSections },
|
|
120
|
+
props: { ...cmsPage, globalSections },
|
|
102
121
|
}
|
|
103
122
|
}
|
|
104
123
|
|
package/src/server/cms.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import ClientCMS from '@vtex/client-cms'
|
|
2
1
|
import type { ContentData, Locator } from '@vtex/client-cms'
|
|
2
|
+
import ClientCMS from '@vtex/client-cms'
|
|
3
3
|
|
|
4
4
|
import config from '../../faststore.config'
|
|
5
5
|
|
|
@@ -54,6 +54,8 @@ export const getPage = async <T extends ContentData>(options: Options) => {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
export type PDPContentType = ContentData
|
|
57
|
+
export type PLPContentType = ContentData
|
|
58
|
+
export type SearchContentType = ContentData
|
|
57
59
|
|
|
58
60
|
export type PageContentType = ContentData & {
|
|
59
61
|
settings: {
|
|
File without changes
|