@akinon/projectzero 1.73.0-rc.8 → 1.73.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/CHANGELOG.md +1 -26
- package/app-template/.gitignore +0 -2
- package/app-template/CHANGELOG.md +147 -2801
- package/app-template/next.config.mjs +1 -2
- package/app-template/package.json +20 -20
- package/app-template/sentry.edge.config.ts +3 -0
- package/app-template/sentry.server.config.ts +3 -0
- package/app-template/src/app/[commerce]/[locale]/[currency]/basket/page.tsx +82 -9
- package/app-template/src/components/pagination.tsx +35 -55
- package/app-template/src/components/types/index.ts +0 -1
- package/app-template/src/settings.js +1 -9
- package/app-template/src/views/basket/basket-item.tsx +13 -16
- package/app-template/src/views/basket/summary.tsx +7 -10
- package/app-template/src/views/category/category-active-filters.tsx +3 -3
- package/app-template/src/views/category/filters/filter-item.tsx +1 -1
- package/app-template/src/views/category/filters/index.tsx +1 -1
- package/app-template/src/views/category/layout.tsx +3 -3
- package/app-template/src/views/product/variant.tsx +38 -37
- package/package.json +1 -1
- package/app-template/src/views/basket/basket-content.tsx +0 -106
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projectzeronext",
|
|
3
|
-
"version": "1.73.0
|
|
3
|
+
"version": "1.73.0",
|
|
4
4
|
"private": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -22,25 +22,25 @@
|
|
|
22
22
|
"prestart": "pz-prestart"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@akinon/next": "1.73.0
|
|
26
|
-
"@akinon/pz-akifast": "1.73.0
|
|
27
|
-
"@akinon/pz-b2b": "1.73.0
|
|
28
|
-
"@akinon/pz-basket-gift-pack": "1.73.0
|
|
29
|
-
"@akinon/pz-bkm": "1.73.0
|
|
30
|
-
"@akinon/pz-checkout-gift-pack": "1.73.0
|
|
31
|
-
"@akinon/pz-click-collect": "1.73.0
|
|
32
|
-
"@akinon/pz-credit-payment": "1.73.0
|
|
33
|
-
"@akinon/pz-gpay": "1.73.0
|
|
34
|
-
"@akinon/pz-masterpass": "1.73.0
|
|
35
|
-
"@akinon/pz-one-click-checkout": "1.73.0
|
|
36
|
-
"@akinon/pz-otp": "1.73.0
|
|
37
|
-
"@akinon/pz-pay-on-delivery": "1.73.0
|
|
38
|
-
"@akinon/pz-saved-card": "1.73.0
|
|
39
|
-
"@akinon/pz-tabby-extension": "1.73.0
|
|
25
|
+
"@akinon/next": "1.73.0",
|
|
26
|
+
"@akinon/pz-akifast": "1.73.0",
|
|
27
|
+
"@akinon/pz-b2b": "1.73.0",
|
|
28
|
+
"@akinon/pz-basket-gift-pack": "1.73.0",
|
|
29
|
+
"@akinon/pz-bkm": "1.73.0",
|
|
30
|
+
"@akinon/pz-checkout-gift-pack": "1.73.0",
|
|
31
|
+
"@akinon/pz-click-collect": "1.73.0",
|
|
32
|
+
"@akinon/pz-credit-payment": "1.73.0",
|
|
33
|
+
"@akinon/pz-gpay": "1.73.0",
|
|
34
|
+
"@akinon/pz-masterpass": "1.73.0",
|
|
35
|
+
"@akinon/pz-one-click-checkout": "1.73.0",
|
|
36
|
+
"@akinon/pz-otp": "1.73.0",
|
|
37
|
+
"@akinon/pz-pay-on-delivery": "1.73.0",
|
|
38
|
+
"@akinon/pz-saved-card": "1.73.0",
|
|
39
|
+
"@akinon/pz-tabby-extension": "1.73.0",
|
|
40
40
|
"@hookform/resolvers": "2.9.0",
|
|
41
41
|
"@next/third-parties": "14.1.0",
|
|
42
42
|
"@react-google-maps/api": "2.17.1",
|
|
43
|
-
"@sentry/nextjs": "
|
|
43
|
+
"@sentry/nextjs": "7.116.0",
|
|
44
44
|
"dayjs": "1.11.5",
|
|
45
45
|
"lossless-json": "2.0.5",
|
|
46
46
|
"next": "14.2.5",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"yup": "0.32.11"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@akinon/eslint-plugin-projectzero": "1.73.0
|
|
63
|
+
"@akinon/eslint-plugin-projectzero": "1.73.0",
|
|
64
64
|
"@semantic-release/changelog": "6.0.2",
|
|
65
65
|
"@semantic-release/exec": "6.0.3",
|
|
66
66
|
"@semantic-release/git": "10.0.1",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@types/react-dom": "18.2.12",
|
|
76
76
|
"@typescript-eslint/eslint-plugin": "6.7.4",
|
|
77
77
|
"@typescript-eslint/parser": "6.7.4",
|
|
78
|
-
"autoprefixer": "10.4.
|
|
78
|
+
"autoprefixer": "10.4.13",
|
|
79
79
|
"client-only": "0.0.1",
|
|
80
80
|
"clsx": "1.1.1",
|
|
81
81
|
"currency-symbol-map": "5.1.0",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"stylelint-config-standard": "25.0.0",
|
|
97
97
|
"stylelint-scss": "4.2.0",
|
|
98
98
|
"stylelint-selector-bem-pattern": "2.1.1",
|
|
99
|
-
"tailwindcss": "3.4.
|
|
99
|
+
"tailwindcss": "3.4.12",
|
|
100
100
|
"ts-jest": "29.1.1",
|
|
101
101
|
"ts-node": "10.7.0",
|
|
102
102
|
"typescript": "5.2.2"
|
|
@@ -1,14 +1,87 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import { ROUTES } from '@theme/routes';
|
|
5
|
+
import { useGetBasketQuery } from '@akinon/next/data/client/basket';
|
|
6
|
+
import { pushCartView } from '@theme/utils/gtm';
|
|
7
|
+
import { Button, LoaderSpinner, Link } from '@theme/components';
|
|
8
|
+
import { BasketItem, Summary } from '@theme/views/basket';
|
|
9
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
10
|
+
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
3
11
|
import settings from '@theme/settings';
|
|
4
12
|
|
|
5
|
-
export default
|
|
6
|
-
const { basket } =
|
|
13
|
+
export default function Page() {
|
|
14
|
+
const { data: basket, isLoading, isSuccess } = useGetBasketQuery();
|
|
15
|
+
const { t } = useLocalization();
|
|
16
|
+
const multiBasket = settings.plugins?.multiBasket ?? false;
|
|
17
|
+
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (isSuccess) {
|
|
20
|
+
const products = basket.basketitem_set.map((basketItem) => ({
|
|
21
|
+
...basketItem.product
|
|
22
|
+
}));
|
|
23
|
+
pushCartView(products);
|
|
24
|
+
}
|
|
25
|
+
}, [basket, isSuccess]);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="max-w-screen-xl p-4 flex flex-col text-primary-800 lg:p-8 xl:flex-row xl:mx-auto">
|
|
29
|
+
{isLoading && (
|
|
30
|
+
<div className="flex justify-center w-full">
|
|
31
|
+
<LoaderSpinner />
|
|
32
|
+
</div>
|
|
33
|
+
)}
|
|
34
|
+
{isSuccess &&
|
|
35
|
+
(basket && basket.basketitem_set && basket.basketitem_set.length > 0 ? (
|
|
36
|
+
<>
|
|
37
|
+
<div className="flex-1 xl:mr-16">
|
|
38
|
+
<div className="flex items-center justify-between py-2 border-b border-gray-200 lg:py-3">
|
|
39
|
+
<h2 className="text-xl lg:text-2xl font-light">
|
|
40
|
+
{t('basket.my_cart')}
|
|
41
|
+
</h2>
|
|
42
|
+
<Link
|
|
43
|
+
href={ROUTES.HOME}
|
|
44
|
+
className="text-xs hover:text-secondary-500"
|
|
45
|
+
>
|
|
46
|
+
{t('basket.back_to_shopping')}
|
|
47
|
+
</Link>
|
|
48
|
+
</div>
|
|
49
|
+
<ul>
|
|
50
|
+
{multiBasket ? (
|
|
51
|
+
<PluginModule
|
|
52
|
+
component={Component.MultiBasket}
|
|
53
|
+
props={{ BasketItem }}
|
|
54
|
+
/>
|
|
55
|
+
) : (
|
|
56
|
+
basket.basketitem_set.map((basketItem, index) => (
|
|
57
|
+
<BasketItem basketItem={basketItem} key={index} />
|
|
58
|
+
))
|
|
59
|
+
)}
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
|
62
|
+
<Summary basket={basket} />
|
|
63
|
+
</>
|
|
64
|
+
) : (
|
|
65
|
+
<div className="flex flex-col items-center container max-w-screen-sm py-4 px-4 xs:py-6 xs:px-6 sm:py-8 sm:px-8 lg:max-w-screen-xl">
|
|
66
|
+
<h1
|
|
67
|
+
className="w-full text-xl font-light text-secondary text-center sm:text-2xl"
|
|
68
|
+
data-testid="basket-empty"
|
|
69
|
+
>
|
|
70
|
+
{t('basket.empty.title')}
|
|
71
|
+
</h1>
|
|
7
72
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
73
|
+
<div className="w-full text-sm text-black-800 text-center my-4 mb-2 sm:text-base">
|
|
74
|
+
<p>{t('basket.empty.content_first')}</p>
|
|
75
|
+
<p>{t('basket.empty.content_second')}.</p>
|
|
76
|
+
</div>
|
|
12
77
|
|
|
13
|
-
|
|
78
|
+
<Link href={ROUTES.HOME} passHref>
|
|
79
|
+
<Button className="px-10 mt-2" appearance="filled">
|
|
80
|
+
{t('basket.empty.button')}
|
|
81
|
+
</Button>
|
|
82
|
+
</Link>
|
|
83
|
+
</div>
|
|
84
|
+
))}
|
|
85
|
+
</div>
|
|
86
|
+
);
|
|
14
87
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import { PaginationProps } from '@theme/components/types';
|
|
3
3
|
import { twMerge } from 'tailwind-merge';
|
|
4
4
|
import clsx from 'clsx';
|
|
5
|
-
import {
|
|
5
|
+
import { Button } from '@theme/components';
|
|
6
6
|
import usePagination from '@akinon/next/hooks/use-pagination';
|
|
7
7
|
import { useLocalization } from '@akinon/next/hooks';
|
|
8
8
|
import { useRouter } from '@akinon/next/hooks';
|
|
@@ -25,8 +25,7 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
25
25
|
type = 'list',
|
|
26
26
|
onPageChange,
|
|
27
27
|
direction,
|
|
28
|
-
render
|
|
29
|
-
isLoading
|
|
28
|
+
render
|
|
30
29
|
} = props;
|
|
31
30
|
|
|
32
31
|
const pagination = usePagination(total, limit, currentPage, numberOfPages);
|
|
@@ -93,9 +92,7 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
93
92
|
}
|
|
94
93
|
}, [numberOfPages, page, pageList, threshold]);
|
|
95
94
|
|
|
96
|
-
const handleClick = (
|
|
97
|
-
e.preventDefault();
|
|
98
|
-
|
|
95
|
+
const handleClick = (url: string) => {
|
|
99
96
|
const newUrl = new URL(url, window.location.origin);
|
|
100
97
|
const page = newUrl.searchParams.get('page');
|
|
101
98
|
|
|
@@ -120,13 +117,6 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
120
117
|
onPageChange(changingPage);
|
|
121
118
|
};
|
|
122
119
|
|
|
123
|
-
useEffect(() => {
|
|
124
|
-
if (type === 'infinite' && page === 1) {
|
|
125
|
-
setPrevPage(1);
|
|
126
|
-
setNextPage(1);
|
|
127
|
-
}
|
|
128
|
-
}, [page]);
|
|
129
|
-
|
|
130
120
|
useEffect(() => {
|
|
131
121
|
if (inView) {
|
|
132
122
|
handlePageChange();
|
|
@@ -137,7 +127,7 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
137
127
|
if (type === 'list') {
|
|
138
128
|
createListItems();
|
|
139
129
|
}
|
|
140
|
-
}, [
|
|
130
|
+
}, [createListItems, type]);
|
|
141
131
|
|
|
142
132
|
useEffect(() => {
|
|
143
133
|
if (total && total !== paginationTotal) {
|
|
@@ -157,23 +147,21 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
157
147
|
|
|
158
148
|
return direction === 'prev' && type !== 'list' ? (
|
|
159
149
|
<>
|
|
160
|
-
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
</Button>
|
|
171
|
-
</div>
|
|
150
|
+
{Number(prevPage) !== 1 && (
|
|
151
|
+
<div className="flex justify-center items-center">
|
|
152
|
+
<Button
|
|
153
|
+
className={twMerge('px-5', moreButtonClassName)}
|
|
154
|
+
onClick={() => handlePageChange()}
|
|
155
|
+
>
|
|
156
|
+
{t('category.pagination.load_previous_page')}
|
|
157
|
+
</Button>
|
|
158
|
+
</div>
|
|
159
|
+
)}
|
|
172
160
|
</>
|
|
173
161
|
) : (
|
|
174
162
|
<>
|
|
175
163
|
{type === 'more' && (
|
|
176
|
-
<div className="flex
|
|
164
|
+
<div className="flex justify-center items-center">
|
|
177
165
|
<Button
|
|
178
166
|
className={twMerge(
|
|
179
167
|
'px-5',
|
|
@@ -185,11 +173,7 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
185
173
|
onClick={() => handlePageChange()}
|
|
186
174
|
disabled={Number(nextPage) === Number(last)}
|
|
187
175
|
>
|
|
188
|
-
{
|
|
189
|
-
<LoaderSpinner className="h-4 w-4" />
|
|
190
|
-
) : (
|
|
191
|
-
t('category.pagination.more')
|
|
192
|
-
)}
|
|
176
|
+
{t('category.pagination.more')}
|
|
193
177
|
</Button>
|
|
194
178
|
</div>
|
|
195
179
|
)}
|
|
@@ -199,9 +183,8 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
199
183
|
)}
|
|
200
184
|
|
|
201
185
|
{(type === 'infinite' || type === 'more') &&
|
|
202
|
-
Number(nextPage) === last &&
|
|
203
|
-
|
|
204
|
-
<p className="mt-8 text-center">
|
|
186
|
+
Number(nextPage) === last && (
|
|
187
|
+
<p className="text-center mt-8">
|
|
205
188
|
{t('category.pagination.shown_items')}
|
|
206
189
|
</p>
|
|
207
190
|
)}
|
|
@@ -209,37 +192,35 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
209
192
|
{type === 'list' && (
|
|
210
193
|
<ul
|
|
211
194
|
className={twMerge(
|
|
212
|
-
'
|
|
195
|
+
'flex mt-8 mb-4 justify-center items-center',
|
|
213
196
|
containerClassName
|
|
214
197
|
)}
|
|
215
198
|
>
|
|
216
199
|
{prev && currentPage !== 1 && (
|
|
217
200
|
<li>
|
|
218
|
-
<
|
|
219
|
-
onClick={(
|
|
220
|
-
href={prev}
|
|
201
|
+
<button
|
|
202
|
+
onClick={() => handleClick(prev)}
|
|
221
203
|
className={twMerge(
|
|
222
|
-
'flex cursor-pointer
|
|
204
|
+
'flex cursor-pointer text-sm px-2',
|
|
223
205
|
prevClassName
|
|
224
206
|
)}
|
|
225
207
|
>
|
|
226
208
|
<span><</span>
|
|
227
|
-
<span className="
|
|
209
|
+
<span className="hidden lg:inline-block ms-4">
|
|
228
210
|
{t('category.pagination.previous')}
|
|
229
211
|
</span>
|
|
230
|
-
</
|
|
212
|
+
</button>
|
|
231
213
|
</li>
|
|
232
214
|
)}
|
|
233
215
|
|
|
234
216
|
{paginationItems.map((item, i) => (
|
|
235
217
|
<li key={i}>
|
|
236
218
|
{item?.url != '#' ? (
|
|
237
|
-
<
|
|
238
|
-
onClick={(
|
|
239
|
-
href={item.url}
|
|
219
|
+
<button
|
|
220
|
+
onClick={() => handleClick(item.url)}
|
|
240
221
|
className={twMerge(
|
|
241
222
|
clsx(
|
|
242
|
-
'
|
|
223
|
+
'text-xs px-2 cursor-pointer',
|
|
243
224
|
{ 'pointer-events-none': item.url === null },
|
|
244
225
|
Number(page) === Number(item?.page)
|
|
245
226
|
? 'font-semibold text-black-800'
|
|
@@ -249,9 +230,9 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
249
230
|
)}
|
|
250
231
|
>
|
|
251
232
|
{item?.page}
|
|
252
|
-
</
|
|
233
|
+
</button>
|
|
253
234
|
) : (
|
|
254
|
-
<span className="
|
|
235
|
+
<span className="cursor-default text-xs flex items-center justify-center">
|
|
255
236
|
{item?.page}
|
|
256
237
|
</span>
|
|
257
238
|
)}
|
|
@@ -260,19 +241,18 @@ export const Pagination = (props: PaginationProps) => {
|
|
|
260
241
|
|
|
261
242
|
{showNext && (
|
|
262
243
|
<li>
|
|
263
|
-
<
|
|
264
|
-
onClick={(
|
|
265
|
-
href={next}
|
|
244
|
+
<button
|
|
245
|
+
onClick={() => handleClick(next)}
|
|
266
246
|
className={twMerge(
|
|
267
|
-
'flex cursor-pointer
|
|
247
|
+
'flex cursor-pointer text-xs px-2',
|
|
268
248
|
nextClassName
|
|
269
249
|
)}
|
|
270
250
|
>
|
|
271
|
-
<span className="
|
|
251
|
+
<span className="hidden lg:inline-block me-4">
|
|
272
252
|
{t('category.pagination.next')}
|
|
273
253
|
</span>
|
|
274
254
|
<span>></span>
|
|
275
|
-
</
|
|
255
|
+
</button>
|
|
276
256
|
</li>
|
|
277
257
|
)}
|
|
278
258
|
</ul>
|
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
const { LocaleUrlStrategy } = require('@akinon/next/localization');
|
|
2
2
|
const { ROUTES } = require('@theme/routes');
|
|
3
3
|
|
|
4
|
-
/* IMPORTANT *
|
|
5
|
-
* In order to use one locale in the locales array and hide the default locale in the URL, you need to set the localeUrlStrategy to LocaleUrlStrategy.ShowAllLocales.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
4
|
const commerceUrl = encodeURI(process.env.SERVICE_BACKEND_URL ?? 'default');
|
|
9
5
|
|
|
10
6
|
/** @type {import('@akinon/next/types').Settings} */
|
|
11
7
|
module.exports = {
|
|
12
|
-
webVitals: {
|
|
13
|
-
enabled: true
|
|
14
|
-
},
|
|
15
8
|
commerceUrl,
|
|
16
9
|
commonProductAttributes: [
|
|
17
10
|
{ translationKey: 'color', key: 'color' },
|
|
18
11
|
{ translationKey: 'size', key: 'size' }
|
|
19
12
|
],
|
|
20
13
|
localization: {
|
|
21
|
-
// If there is one locale in the locales array, the default locale will be hidden in the URL.
|
|
22
14
|
locales: [
|
|
23
15
|
{
|
|
24
16
|
label: 'EN',
|
|
@@ -46,7 +38,7 @@ module.exports = {
|
|
|
46
38
|
}
|
|
47
39
|
],
|
|
48
40
|
defaultLocaleValue: 'en',
|
|
49
|
-
localeUrlStrategy: LocaleUrlStrategy.HideDefaultLocale,
|
|
41
|
+
localeUrlStrategy: LocaleUrlStrategy.HideDefaultLocale,
|
|
50
42
|
redirectToDefaultLocale: true,
|
|
51
43
|
defaultCurrencyCode: 'usd'
|
|
52
44
|
},
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
useUpdateQuantityMutation
|
|
4
4
|
} from '@akinon/next/data/client/basket';
|
|
5
5
|
import { useAppDispatch } from '@akinon/next/redux/hooks';
|
|
6
|
-
import {
|
|
6
|
+
import { BasketItem as BasketItemType } from '@akinon/next/types';
|
|
7
7
|
import { Price, Button, Icon, Modal, Select, Link } from '@theme/components';
|
|
8
8
|
import { useState } from 'react';
|
|
9
9
|
import { useAddFavoriteMutation } from '@akinon/next/data/client/wishlist';
|
|
@@ -19,12 +19,11 @@ import { pushRemoveFromCart } from '@theme/utils/gtm';
|
|
|
19
19
|
interface Props {
|
|
20
20
|
basketItem?: BasketItemType;
|
|
21
21
|
namespace?: string;
|
|
22
|
-
onBasketUpdate?: (basket: Basket) => void;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export const BasketItem = (props: Props) => {
|
|
26
25
|
const { t } = useLocalization();
|
|
27
|
-
const { basketItem, namespace
|
|
26
|
+
const { basketItem, namespace } = props;
|
|
28
27
|
const [updateQuantityMutation] = useUpdateQuantityMutation();
|
|
29
28
|
const dispatch = useAppDispatch();
|
|
30
29
|
const [isRemoveBasketModalOpen, setRemoveBasketModalOpen] = useState(false);
|
|
@@ -50,21 +49,19 @@ export const BasketItem = (props: Props) => {
|
|
|
50
49
|
requestParams.namespace = namespace;
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
await updateQuantityMutation(requestParams)
|
|
53
|
+
.unwrap()
|
|
54
|
+
.then((data) =>
|
|
55
|
+
dispatch(
|
|
56
|
+
basketApi.util.updateQueryData(
|
|
57
|
+
'getBasket',
|
|
58
|
+
undefined,
|
|
59
|
+
(draftBasket) => {
|
|
60
|
+
Object.assign(draftBasket, data.basket);
|
|
61
|
+
}
|
|
62
|
+
)
|
|
62
63
|
)
|
|
63
64
|
);
|
|
64
|
-
onBasketUpdate?.(response.basket);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
console.error('Error updating quantity:', error);
|
|
67
|
-
}
|
|
68
65
|
};
|
|
69
66
|
|
|
70
67
|
const deleteProduct = async (productPk?: number) => {
|
|
@@ -18,7 +18,6 @@ import clsx from 'clsx';
|
|
|
18
18
|
|
|
19
19
|
interface Props {
|
|
20
20
|
basket: Basket;
|
|
21
|
-
onBasketUpdate?: (basket: Basket) => void;
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
const voucherCodeFormSchema = (t) =>
|
|
@@ -28,7 +27,7 @@ const voucherCodeFormSchema = (t) =>
|
|
|
28
27
|
|
|
29
28
|
export const Summary = (props: Props) => {
|
|
30
29
|
const { t } = useLocalization();
|
|
31
|
-
const { basket
|
|
30
|
+
const { basket } = props;
|
|
32
31
|
const router = useRouter();
|
|
33
32
|
const {
|
|
34
33
|
register,
|
|
@@ -54,7 +53,7 @@ export const Summary = (props: Props) => {
|
|
|
54
53
|
const removeVoucherCode = () => {
|
|
55
54
|
removeVoucherCodeMutation()
|
|
56
55
|
.unwrap()
|
|
57
|
-
.then((basket) =>
|
|
56
|
+
.then((basket) =>
|
|
58
57
|
dispatch(
|
|
59
58
|
basketApi.util.updateQueryData(
|
|
60
59
|
'getBasket',
|
|
@@ -63,9 +62,8 @@ export const Summary = (props: Props) => {
|
|
|
63
62
|
Object.assign(draftBasket, basket);
|
|
64
63
|
}
|
|
65
64
|
)
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
})
|
|
65
|
+
)
|
|
66
|
+
)
|
|
69
67
|
.catch((error: Error) => {
|
|
70
68
|
setError('voucherCode', { message: error.data.non_field_errors });
|
|
71
69
|
});
|
|
@@ -76,7 +74,7 @@ export const Summary = (props: Props) => {
|
|
|
76
74
|
voucher_code: data.voucherCode
|
|
77
75
|
})
|
|
78
76
|
.unwrap()
|
|
79
|
-
.then((basket) =>
|
|
77
|
+
.then((basket) =>
|
|
80
78
|
dispatch(
|
|
81
79
|
basketApi.util.updateQueryData(
|
|
82
80
|
'getBasket',
|
|
@@ -85,9 +83,8 @@ export const Summary = (props: Props) => {
|
|
|
85
83
|
Object.assign(draftBasket, basket);
|
|
86
84
|
}
|
|
87
85
|
)
|
|
88
|
-
)
|
|
89
|
-
|
|
90
|
-
})
|
|
86
|
+
)
|
|
87
|
+
)
|
|
91
88
|
.catch((error: Error) => {
|
|
92
89
|
setError('voucherCode', { message: error.data.non_field_errors });
|
|
93
90
|
});
|
|
@@ -70,9 +70,9 @@ const CategoryActiveFilters = () => {
|
|
|
70
70
|
return (
|
|
71
71
|
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-2 mb-4">
|
|
72
72
|
{facets.map((facet) =>
|
|
73
|
-
facet
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
facet.data.choices
|
|
74
|
+
.filter((choice) => choice.is_selected)
|
|
75
|
+
.map(
|
|
76
76
|
(choice) =>
|
|
77
77
|
Number(choice.real_depth) !== 2 && (
|
|
78
78
|
<div
|
|
@@ -112,7 +112,7 @@ export const FilterItem = ({ facet, isPending, startTransition }: Props) => {
|
|
|
112
112
|
};
|
|
113
113
|
|
|
114
114
|
const Component = getComponentByWidgetType(facet.widget_type, facet.key);
|
|
115
|
-
const choices = sortChoices(facet
|
|
115
|
+
const choices = sortChoices(facet.key, [...facet.data.choices]);
|
|
116
116
|
|
|
117
117
|
return (
|
|
118
118
|
<Accordion
|
|
@@ -24,7 +24,7 @@ export const Filters = (props: Props) => {
|
|
|
24
24
|
|
|
25
25
|
const haveFilter = useMemo(() => {
|
|
26
26
|
return facets.some((facet) =>
|
|
27
|
-
facet
|
|
27
|
+
facet.data.choices.some((choice) => choice.is_selected)
|
|
28
28
|
);
|
|
29
29
|
}, [facets]);
|
|
30
30
|
|
|
@@ -17,7 +17,7 @@ export default async function Layout({
|
|
|
17
17
|
<>
|
|
18
18
|
<div
|
|
19
19
|
className={clsx(
|
|
20
|
-
data
|
|
20
|
+
data.category?.attributes?.category_banner
|
|
21
21
|
? 'relative w-full'
|
|
22
22
|
: 'container px-4 mx-auto lg:px-0 lg:my-4'
|
|
23
23
|
)}
|
|
@@ -26,13 +26,13 @@ export default async function Layout({
|
|
|
26
26
|
<div
|
|
27
27
|
className={clsx(
|
|
28
28
|
'my-4 lg:mt-7',
|
|
29
|
-
data
|
|
29
|
+
data.category?.attributes?.category_banner &&
|
|
30
30
|
'lg:absolute lg:inset-x-0 z-10 container lg:my-4 mx-auto'
|
|
31
31
|
)}
|
|
32
32
|
>
|
|
33
33
|
<Breadcrumb breadcrumbList={breadcrumbData} />
|
|
34
34
|
</div>
|
|
35
|
-
<CategoryBanner {...data
|
|
35
|
+
<CategoryBanner {...data.category?.attributes?.category_banner} />
|
|
36
36
|
</div>
|
|
37
37
|
<ListPage data={data} />
|
|
38
38
|
</>
|