@akinon/projectzero 1.73.0-rc.0 → 1.73.0-rc.10
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 +24 -0
- package/app-template/CHANGELOG.md +221 -0
- package/app-template/package.json +17 -17
- package/app-template/src/app/[commerce]/[locale]/[currency]/basket/page.tsx +9 -82
- package/app-template/src/components/link.tsx +17 -21
- package/app-template/src/views/basket/basket-content.tsx +106 -0
- package/app-template/src/views/basket/basket-item.tsx +16 -13
- package/app-template/src/views/basket/summary.tsx +10 -7
- package/app-template/src/views/product/variant.tsx +38 -37
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @akinon/projectzero
|
|
2
2
|
|
|
3
|
+
## 1.73.0-rc.10
|
|
4
|
+
|
|
5
|
+
## 1.73.0-rc.9
|
|
6
|
+
|
|
7
|
+
## 1.73.0-rc.8
|
|
8
|
+
|
|
9
|
+
## 1.73.0-rc.7
|
|
10
|
+
|
|
11
|
+
## 1.73.0-rc.6
|
|
12
|
+
|
|
13
|
+
## 1.73.0-rc.5
|
|
14
|
+
|
|
15
|
+
## 1.73.0-rc.4
|
|
16
|
+
|
|
17
|
+
## 1.73.0-rc.3
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
|
|
22
|
+
|
|
23
|
+
## 1.73.0-rc.2
|
|
24
|
+
|
|
25
|
+
## 1.73.0-rc.1
|
|
26
|
+
|
|
3
27
|
## 1.73.0-rc.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
|
@@ -1,5 +1,226 @@
|
|
|
1
1
|
# projectzeronext
|
|
2
2
|
|
|
3
|
+
## 1.73.0-rc.10
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 20d6394b: ZERO-3090: Optimize Variant component for better performance
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- @akinon/next@1.73.0-rc.10
|
|
12
|
+
- @akinon/pz-akifast@1.73.0-rc.10
|
|
13
|
+
- @akinon/pz-b2b@1.73.0-rc.10
|
|
14
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.10
|
|
15
|
+
- @akinon/pz-bkm@1.73.0-rc.10
|
|
16
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.10
|
|
17
|
+
- @akinon/pz-click-collect@1.73.0-rc.10
|
|
18
|
+
- @akinon/pz-credit-payment@1.73.0-rc.10
|
|
19
|
+
- @akinon/pz-gpay@1.73.0-rc.10
|
|
20
|
+
- @akinon/pz-masterpass@1.73.0-rc.10
|
|
21
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.10
|
|
22
|
+
- @akinon/pz-otp@1.73.0-rc.10
|
|
23
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.10
|
|
24
|
+
- @akinon/pz-saved-card@1.73.0-rc.10
|
|
25
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.10
|
|
26
|
+
|
|
27
|
+
## 1.73.0-rc.9
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- Updated dependencies [6d6a39d5]
|
|
32
|
+
- @akinon/next@1.73.0-rc.9
|
|
33
|
+
- @akinon/pz-akifast@1.73.0-rc.9
|
|
34
|
+
- @akinon/pz-b2b@1.73.0-rc.9
|
|
35
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.9
|
|
36
|
+
- @akinon/pz-bkm@1.73.0-rc.9
|
|
37
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.9
|
|
38
|
+
- @akinon/pz-click-collect@1.73.0-rc.9
|
|
39
|
+
- @akinon/pz-credit-payment@1.73.0-rc.9
|
|
40
|
+
- @akinon/pz-gpay@1.73.0-rc.9
|
|
41
|
+
- @akinon/pz-masterpass@1.73.0-rc.9
|
|
42
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.9
|
|
43
|
+
- @akinon/pz-otp@1.73.0-rc.9
|
|
44
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.9
|
|
45
|
+
- @akinon/pz-saved-card@1.73.0-rc.9
|
|
46
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.9
|
|
47
|
+
|
|
48
|
+
## 1.73.0-rc.8
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- Updated dependencies [72fd4d67]
|
|
53
|
+
- @akinon/next@1.73.0-rc.8
|
|
54
|
+
- @akinon/pz-akifast@1.73.0-rc.8
|
|
55
|
+
- @akinon/pz-b2b@1.73.0-rc.8
|
|
56
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.8
|
|
57
|
+
- @akinon/pz-bkm@1.73.0-rc.8
|
|
58
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.8
|
|
59
|
+
- @akinon/pz-click-collect@1.73.0-rc.8
|
|
60
|
+
- @akinon/pz-credit-payment@1.73.0-rc.8
|
|
61
|
+
- @akinon/pz-gpay@1.73.0-rc.8
|
|
62
|
+
- @akinon/pz-masterpass@1.73.0-rc.8
|
|
63
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.8
|
|
64
|
+
- @akinon/pz-otp@1.73.0-rc.8
|
|
65
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.8
|
|
66
|
+
- @akinon/pz-saved-card@1.73.0-rc.8
|
|
67
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.8
|
|
68
|
+
|
|
69
|
+
## 1.73.0-rc.7
|
|
70
|
+
|
|
71
|
+
### Patch Changes
|
|
72
|
+
|
|
73
|
+
- Updated dependencies [37239b31]
|
|
74
|
+
- @akinon/next@1.73.0-rc.7
|
|
75
|
+
- @akinon/pz-akifast@1.73.0-rc.7
|
|
76
|
+
- @akinon/pz-b2b@1.73.0-rc.7
|
|
77
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.7
|
|
78
|
+
- @akinon/pz-bkm@1.73.0-rc.7
|
|
79
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.7
|
|
80
|
+
- @akinon/pz-click-collect@1.73.0-rc.7
|
|
81
|
+
- @akinon/pz-credit-payment@1.73.0-rc.7
|
|
82
|
+
- @akinon/pz-gpay@1.73.0-rc.7
|
|
83
|
+
- @akinon/pz-masterpass@1.73.0-rc.7
|
|
84
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.7
|
|
85
|
+
- @akinon/pz-otp@1.73.0-rc.7
|
|
86
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.7
|
|
87
|
+
- @akinon/pz-saved-card@1.73.0-rc.7
|
|
88
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.7
|
|
89
|
+
|
|
90
|
+
## 1.73.0-rc.6
|
|
91
|
+
|
|
92
|
+
### Patch Changes
|
|
93
|
+
|
|
94
|
+
- Updated dependencies [31d5a712]
|
|
95
|
+
- @akinon/next@1.73.0-rc.6
|
|
96
|
+
- @akinon/pz-akifast@1.73.0-rc.6
|
|
97
|
+
- @akinon/pz-b2b@1.73.0-rc.6
|
|
98
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.6
|
|
99
|
+
- @akinon/pz-bkm@1.73.0-rc.6
|
|
100
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.6
|
|
101
|
+
- @akinon/pz-click-collect@1.73.0-rc.6
|
|
102
|
+
- @akinon/pz-credit-payment@1.73.0-rc.6
|
|
103
|
+
- @akinon/pz-gpay@1.73.0-rc.6
|
|
104
|
+
- @akinon/pz-masterpass@1.73.0-rc.6
|
|
105
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.6
|
|
106
|
+
- @akinon/pz-otp@1.73.0-rc.6
|
|
107
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.6
|
|
108
|
+
- @akinon/pz-saved-card@1.73.0-rc.6
|
|
109
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.6
|
|
110
|
+
|
|
111
|
+
## 1.73.0-rc.5
|
|
112
|
+
|
|
113
|
+
### Patch Changes
|
|
114
|
+
|
|
115
|
+
- Updated dependencies [24557b3c]
|
|
116
|
+
- Updated dependencies [178044ed]
|
|
117
|
+
- @akinon/next@1.73.0-rc.5
|
|
118
|
+
- @akinon/pz-akifast@1.73.0-rc.5
|
|
119
|
+
- @akinon/pz-b2b@1.73.0-rc.5
|
|
120
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.5
|
|
121
|
+
- @akinon/pz-bkm@1.73.0-rc.5
|
|
122
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.5
|
|
123
|
+
- @akinon/pz-click-collect@1.73.0-rc.5
|
|
124
|
+
- @akinon/pz-credit-payment@1.73.0-rc.5
|
|
125
|
+
- @akinon/pz-gpay@1.73.0-rc.5
|
|
126
|
+
- @akinon/pz-masterpass@1.73.0-rc.5
|
|
127
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.5
|
|
128
|
+
- @akinon/pz-otp@1.73.0-rc.5
|
|
129
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.5
|
|
130
|
+
- @akinon/pz-saved-card@1.73.0-rc.5
|
|
131
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.5
|
|
132
|
+
|
|
133
|
+
## 1.73.0-rc.4
|
|
134
|
+
|
|
135
|
+
### Patch Changes
|
|
136
|
+
|
|
137
|
+
- Updated dependencies [c594b469]
|
|
138
|
+
- @akinon/pz-saved-card@1.73.0-rc.4
|
|
139
|
+
- @akinon/next@1.73.0-rc.4
|
|
140
|
+
- @akinon/pz-akifast@1.73.0-rc.4
|
|
141
|
+
- @akinon/pz-b2b@1.73.0-rc.4
|
|
142
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.4
|
|
143
|
+
- @akinon/pz-bkm@1.73.0-rc.4
|
|
144
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.4
|
|
145
|
+
- @akinon/pz-click-collect@1.73.0-rc.4
|
|
146
|
+
- @akinon/pz-credit-payment@1.73.0-rc.4
|
|
147
|
+
- @akinon/pz-gpay@1.73.0-rc.4
|
|
148
|
+
- @akinon/pz-masterpass@1.73.0-rc.4
|
|
149
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.4
|
|
150
|
+
- @akinon/pz-otp@1.73.0-rc.4
|
|
151
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.4
|
|
152
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.4
|
|
153
|
+
|
|
154
|
+
## 1.73.0-rc.3
|
|
155
|
+
|
|
156
|
+
### Minor Changes
|
|
157
|
+
|
|
158
|
+
- 7727ae55: ZERO-3073: Refactor basket page to use server-side data fetching and simplify component structure
|
|
159
|
+
- 07b2298e: ZERO-3074: Exclude url schemes to init url without locales
|
|
160
|
+
|
|
161
|
+
### Patch Changes
|
|
162
|
+
|
|
163
|
+
- Updated dependencies [5e3333dc]
|
|
164
|
+
- Updated dependencies [7727ae55]
|
|
165
|
+
- Updated dependencies [07b2298e]
|
|
166
|
+
- @akinon/pz-saved-card@1.73.0-rc.3
|
|
167
|
+
- @akinon/next@1.73.0-rc.3
|
|
168
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.3
|
|
169
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.3
|
|
170
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.3
|
|
171
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.3
|
|
172
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.3
|
|
173
|
+
- @akinon/pz-credit-payment@1.73.0-rc.3
|
|
174
|
+
- @akinon/pz-click-collect@1.73.0-rc.3
|
|
175
|
+
- @akinon/pz-masterpass@1.73.0-rc.3
|
|
176
|
+
- @akinon/pz-akifast@1.73.0-rc.3
|
|
177
|
+
- @akinon/pz-gpay@1.73.0-rc.3
|
|
178
|
+
- @akinon/pz-b2b@1.73.0-rc.3
|
|
179
|
+
- @akinon/pz-bkm@1.73.0-rc.3
|
|
180
|
+
- @akinon/pz-otp@1.73.0-rc.3
|
|
181
|
+
|
|
182
|
+
## 1.73.0-rc.2
|
|
183
|
+
|
|
184
|
+
### Patch Changes
|
|
185
|
+
|
|
186
|
+
- Updated dependencies [eeb20bea]
|
|
187
|
+
- @akinon/next@1.73.0-rc.2
|
|
188
|
+
- @akinon/pz-akifast@1.73.0-rc.2
|
|
189
|
+
- @akinon/pz-b2b@1.73.0-rc.2
|
|
190
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.2
|
|
191
|
+
- @akinon/pz-bkm@1.73.0-rc.2
|
|
192
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.2
|
|
193
|
+
- @akinon/pz-click-collect@1.73.0-rc.2
|
|
194
|
+
- @akinon/pz-credit-payment@1.73.0-rc.2
|
|
195
|
+
- @akinon/pz-gpay@1.73.0-rc.2
|
|
196
|
+
- @akinon/pz-masterpass@1.73.0-rc.2
|
|
197
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.2
|
|
198
|
+
- @akinon/pz-otp@1.73.0-rc.2
|
|
199
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.2
|
|
200
|
+
- @akinon/pz-saved-card@1.73.0-rc.2
|
|
201
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.2
|
|
202
|
+
|
|
203
|
+
## 1.73.0-rc.1
|
|
204
|
+
|
|
205
|
+
### Patch Changes
|
|
206
|
+
|
|
207
|
+
- Updated dependencies [fdd255ee]
|
|
208
|
+
- @akinon/next@1.73.0-rc.1
|
|
209
|
+
- @akinon/pz-akifast@1.73.0-rc.1
|
|
210
|
+
- @akinon/pz-b2b@1.73.0-rc.1
|
|
211
|
+
- @akinon/pz-basket-gift-pack@1.73.0-rc.1
|
|
212
|
+
- @akinon/pz-bkm@1.73.0-rc.1
|
|
213
|
+
- @akinon/pz-checkout-gift-pack@1.73.0-rc.1
|
|
214
|
+
- @akinon/pz-click-collect@1.73.0-rc.1
|
|
215
|
+
- @akinon/pz-credit-payment@1.73.0-rc.1
|
|
216
|
+
- @akinon/pz-gpay@1.73.0-rc.1
|
|
217
|
+
- @akinon/pz-masterpass@1.73.0-rc.1
|
|
218
|
+
- @akinon/pz-one-click-checkout@1.73.0-rc.1
|
|
219
|
+
- @akinon/pz-otp@1.73.0-rc.1
|
|
220
|
+
- @akinon/pz-pay-on-delivery@1.73.0-rc.1
|
|
221
|
+
- @akinon/pz-saved-card@1.73.0-rc.1
|
|
222
|
+
- @akinon/pz-tabby-extension@1.73.0-rc.1
|
|
223
|
+
|
|
3
224
|
## 1.73.0-rc.0
|
|
4
225
|
|
|
5
226
|
### Minor Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "projectzeronext",
|
|
3
|
-
"version": "1.73.0-rc.
|
|
3
|
+
"version": "1.73.0-rc.10",
|
|
4
4
|
"private": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"scripts": {
|
|
@@ -22,21 +22,21 @@
|
|
|
22
22
|
"prestart": "pz-prestart"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@akinon/next": "1.73.0-rc.
|
|
26
|
-
"@akinon/pz-akifast": "1.73.0-rc.
|
|
27
|
-
"@akinon/pz-b2b": "1.73.0-rc.
|
|
28
|
-
"@akinon/pz-basket-gift-pack": "1.73.0-rc.
|
|
29
|
-
"@akinon/pz-bkm": "1.73.0-rc.
|
|
30
|
-
"@akinon/pz-checkout-gift-pack": "1.73.0-rc.
|
|
31
|
-
"@akinon/pz-click-collect": "1.73.0-rc.
|
|
32
|
-
"@akinon/pz-credit-payment": "1.73.0-rc.
|
|
33
|
-
"@akinon/pz-gpay": "1.73.0-rc.
|
|
34
|
-
"@akinon/pz-masterpass": "1.73.0-rc.
|
|
35
|
-
"@akinon/pz-one-click-checkout": "1.73.0-rc.
|
|
36
|
-
"@akinon/pz-otp": "1.73.0-rc.
|
|
37
|
-
"@akinon/pz-pay-on-delivery": "1.73.0-rc.
|
|
38
|
-
"@akinon/pz-saved-card": "1.73.0-rc.
|
|
39
|
-
"@akinon/pz-tabby-extension": "1.73.0-rc.
|
|
25
|
+
"@akinon/next": "1.73.0-rc.10",
|
|
26
|
+
"@akinon/pz-akifast": "1.73.0-rc.10",
|
|
27
|
+
"@akinon/pz-b2b": "1.73.0-rc.10",
|
|
28
|
+
"@akinon/pz-basket-gift-pack": "1.73.0-rc.10",
|
|
29
|
+
"@akinon/pz-bkm": "1.73.0-rc.10",
|
|
30
|
+
"@akinon/pz-checkout-gift-pack": "1.73.0-rc.10",
|
|
31
|
+
"@akinon/pz-click-collect": "1.73.0-rc.10",
|
|
32
|
+
"@akinon/pz-credit-payment": "1.73.0-rc.10",
|
|
33
|
+
"@akinon/pz-gpay": "1.73.0-rc.10",
|
|
34
|
+
"@akinon/pz-masterpass": "1.73.0-rc.10",
|
|
35
|
+
"@akinon/pz-one-click-checkout": "1.73.0-rc.10",
|
|
36
|
+
"@akinon/pz-otp": "1.73.0-rc.10",
|
|
37
|
+
"@akinon/pz-pay-on-delivery": "1.73.0-rc.10",
|
|
38
|
+
"@akinon/pz-saved-card": "1.73.0-rc.10",
|
|
39
|
+
"@akinon/pz-tabby-extension": "1.73.0-rc.10",
|
|
40
40
|
"@hookform/resolvers": "2.9.0",
|
|
41
41
|
"@next/third-parties": "14.1.0",
|
|
42
42
|
"@react-google-maps/api": "2.17.1",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"yup": "0.32.11"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@akinon/eslint-plugin-projectzero": "1.73.0-rc.
|
|
63
|
+
"@akinon/eslint-plugin-projectzero": "1.73.0-rc.10",
|
|
64
64
|
"@semantic-release/changelog": "6.0.2",
|
|
65
65
|
"@semantic-release/exec": "6.0.3",
|
|
66
66
|
"@semantic-release/git": "10.0.1",
|
|
@@ -1,87 +1,14 @@
|
|
|
1
|
-
|
|
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';
|
|
1
|
+
import { BasketContent } from '@theme/views/basket/basket-content';
|
|
2
|
+
import { getBasketData } from '@akinon/next/data/server/basket';
|
|
11
3
|
import settings from '@theme/settings';
|
|
12
4
|
|
|
13
|
-
export default function Page() {
|
|
14
|
-
const {
|
|
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>
|
|
5
|
+
export default async function Page() {
|
|
6
|
+
const { basket } = await getBasketData();
|
|
72
7
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
8
|
+
const multiBasket: boolean =
|
|
9
|
+
typeof settings.plugins?.multiBasket === 'boolean'
|
|
10
|
+
? settings.plugins.multiBasket
|
|
11
|
+
: false;
|
|
77
12
|
|
|
78
|
-
|
|
79
|
-
<Button className="px-10 mt-2" appearance="filled">
|
|
80
|
-
{t('basket.empty.button')}
|
|
81
|
-
</Button>
|
|
82
|
-
</Link>
|
|
83
|
-
</div>
|
|
84
|
-
))}
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
13
|
+
return <BasketContent initialBasket={basket} multiBasket={multiBasket} />;
|
|
87
14
|
}
|
|
@@ -2,26 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
import { useLocalization } from '@akinon/next/hooks';
|
|
4
4
|
import { LocaleUrlStrategy } from '@akinon/next/localization';
|
|
5
|
-
import { urlLocaleMatcherRegex } from '@akinon/next/utils';
|
|
5
|
+
import { urlLocaleMatcherRegex, urlSchemes } from '@akinon/next/utils';
|
|
6
6
|
import NextLink, { LinkProps as NextLinkProps } from 'next/link';
|
|
7
7
|
import { useMemo } from 'react';
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export const Link = ({
|
|
16
|
-
children,
|
|
17
|
-
target,
|
|
18
|
-
className,
|
|
19
|
-
href,
|
|
20
|
-
...rest
|
|
21
|
-
}: LinkProps) => {
|
|
9
|
+
type LinkProps = Omit<
|
|
10
|
+
React.AnchorHTMLAttributes<HTMLAnchorElement>,
|
|
11
|
+
keyof NextLinkProps
|
|
12
|
+
> &
|
|
13
|
+
NextLinkProps;
|
|
14
|
+
|
|
15
|
+
export const Link = ({ children, href, ...rest }: LinkProps) => {
|
|
22
16
|
const { locale, defaultLocaleValue, localeUrlStrategy } = useLocalization();
|
|
23
17
|
const formattedHref = useMemo(() => {
|
|
24
|
-
if (
|
|
18
|
+
if (!href) {
|
|
19
|
+
return '#';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (
|
|
23
|
+
typeof href !== 'string' ||
|
|
24
|
+
urlSchemes.some((scheme) => href.startsWith(scheme))
|
|
25
|
+
) {
|
|
25
26
|
return href;
|
|
26
27
|
}
|
|
27
28
|
|
|
@@ -41,12 +42,7 @@ export const Link = ({
|
|
|
41
42
|
}, [href, defaultLocaleValue, locale, localeUrlStrategy]);
|
|
42
43
|
|
|
43
44
|
return (
|
|
44
|
-
<NextLink
|
|
45
|
-
href={formattedHref}
|
|
46
|
-
target={target}
|
|
47
|
-
className={className}
|
|
48
|
-
{...rest}
|
|
49
|
-
>
|
|
45
|
+
<NextLink href={formattedHref} {...rest}>
|
|
50
46
|
{children}
|
|
51
47
|
</NextLink>
|
|
52
48
|
);
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useLocalization } from '@akinon/next/hooks';
|
|
4
|
+
import { Basket } from '@akinon/next/types';
|
|
5
|
+
import { Button, LoaderSpinner, Link } from '@theme/components';
|
|
6
|
+
import { BasketItem, Summary } from '@theme/views/basket';
|
|
7
|
+
import { ROUTES } from '@theme/routes';
|
|
8
|
+
import PluginModule, { Component } from '@akinon/next/components/plugin-module';
|
|
9
|
+
import { useEffect, useState } from 'react';
|
|
10
|
+
import { pushCartView } from '@theme/utils/gtm';
|
|
11
|
+
|
|
12
|
+
interface BasketContentProps {
|
|
13
|
+
initialBasket: Basket;
|
|
14
|
+
multiBasket: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function BasketContent({
|
|
18
|
+
initialBasket,
|
|
19
|
+
multiBasket
|
|
20
|
+
}: BasketContentProps) {
|
|
21
|
+
const { t } = useLocalization();
|
|
22
|
+
const [basket, setBasket] = useState<Basket>(initialBasket);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (basket) {
|
|
26
|
+
const products = basket.basketitem_set.map((basketItem) => ({
|
|
27
|
+
...basketItem.product
|
|
28
|
+
}));
|
|
29
|
+
pushCartView(products);
|
|
30
|
+
}
|
|
31
|
+
}, [basket]);
|
|
32
|
+
|
|
33
|
+
const handleBasketUpdate = (updatedBasket: Basket) => {
|
|
34
|
+
setBasket(updatedBasket);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
if (!basket) {
|
|
38
|
+
return (
|
|
39
|
+
<div className="flex justify-center w-full">
|
|
40
|
+
<LoaderSpinner />
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div className="max-w-screen-xl p-4 flex flex-col text-primary-800 lg:p-8 xl:flex-row xl:mx-auto">
|
|
47
|
+
{basket.basketitem_set && basket.basketitem_set.length > 0 ? (
|
|
48
|
+
<>
|
|
49
|
+
<div className="flex-1 xl:mr-16">
|
|
50
|
+
<div className="flex items-center justify-between py-2 border-b border-gray-200 lg:py-3">
|
|
51
|
+
<h2 className="text-xl lg:text-2xl font-light">
|
|
52
|
+
{t('basket.my_cart')}
|
|
53
|
+
</h2>
|
|
54
|
+
<Link
|
|
55
|
+
href={ROUTES.HOME}
|
|
56
|
+
className="text-xs hover:text-secondary-500"
|
|
57
|
+
>
|
|
58
|
+
{t('basket.back_to_shopping')}
|
|
59
|
+
</Link>
|
|
60
|
+
</div>
|
|
61
|
+
<ul>
|
|
62
|
+
{multiBasket ? (
|
|
63
|
+
<PluginModule
|
|
64
|
+
component={Component.MultiBasket}
|
|
65
|
+
props={{
|
|
66
|
+
BasketItem,
|
|
67
|
+
onBasketUpdate: handleBasketUpdate
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
) : (
|
|
71
|
+
basket.basketitem_set.map((basketItem, index) => (
|
|
72
|
+
<BasketItem
|
|
73
|
+
key={index}
|
|
74
|
+
basketItem={basketItem}
|
|
75
|
+
onBasketUpdate={handleBasketUpdate}
|
|
76
|
+
/>
|
|
77
|
+
))
|
|
78
|
+
)}
|
|
79
|
+
</ul>
|
|
80
|
+
</div>
|
|
81
|
+
<Summary basket={basket} onBasketUpdate={handleBasketUpdate} />
|
|
82
|
+
</>
|
|
83
|
+
) : (
|
|
84
|
+
<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">
|
|
85
|
+
<h1
|
|
86
|
+
className="w-full text-xl font-light text-secondary text-center sm:text-2xl"
|
|
87
|
+
data-testid="basket-empty"
|
|
88
|
+
>
|
|
89
|
+
{t('basket.empty.title')}
|
|
90
|
+
</h1>
|
|
91
|
+
|
|
92
|
+
<div className="w-full text-sm text-black-800 text-center my-4 mb-2 sm:text-base">
|
|
93
|
+
<p>{t('basket.empty.content_first')}</p>
|
|
94
|
+
<p>{t('basket.empty.content_second')}.</p>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<Link href={ROUTES.HOME} passHref>
|
|
98
|
+
<Button className="px-10 mt-2" appearance="filled">
|
|
99
|
+
{t('basket.empty.button')}
|
|
100
|
+
</Button>
|
|
101
|
+
</Link>
|
|
102
|
+
</div>
|
|
103
|
+
)}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -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 { BasketItem as BasketItemType } from '@akinon/next/types';
|
|
6
|
+
import { Basket, 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,11 +19,12 @@ import { pushRemoveFromCart } from '@theme/utils/gtm';
|
|
|
19
19
|
interface Props {
|
|
20
20
|
basketItem?: BasketItemType;
|
|
21
21
|
namespace?: string;
|
|
22
|
+
onBasketUpdate?: (basket: Basket) => void;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export const BasketItem = (props: Props) => {
|
|
25
26
|
const { t } = useLocalization();
|
|
26
|
-
const { basketItem, namespace } = props;
|
|
27
|
+
const { basketItem, namespace, onBasketUpdate } = props;
|
|
27
28
|
const [updateQuantityMutation] = useUpdateQuantityMutation();
|
|
28
29
|
const dispatch = useAppDispatch();
|
|
29
30
|
const [isRemoveBasketModalOpen, setRemoveBasketModalOpen] = useState(false);
|
|
@@ -49,19 +50,21 @@ export const BasketItem = (props: Props) => {
|
|
|
49
50
|
requestParams.namespace = namespace;
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
|
|
53
|
-
.unwrap()
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
(draftBasket)
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
)
|
|
53
|
+
try {
|
|
54
|
+
const response = await updateQuantityMutation(requestParams).unwrap();
|
|
55
|
+
dispatch(
|
|
56
|
+
basketApi.util.updateQueryData(
|
|
57
|
+
'getBasket',
|
|
58
|
+
undefined,
|
|
59
|
+
(draftBasket) => {
|
|
60
|
+
Object.assign(draftBasket, response.basket);
|
|
61
|
+
}
|
|
63
62
|
)
|
|
64
63
|
);
|
|
64
|
+
onBasketUpdate?.(response.basket);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('Error updating quantity:', error);
|
|
67
|
+
}
|
|
65
68
|
};
|
|
66
69
|
|
|
67
70
|
const deleteProduct = async (productPk?: number) => {
|
|
@@ -18,6 +18,7 @@ import clsx from 'clsx';
|
|
|
18
18
|
|
|
19
19
|
interface Props {
|
|
20
20
|
basket: Basket;
|
|
21
|
+
onBasketUpdate?: (basket: Basket) => void;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
const voucherCodeFormSchema = (t) =>
|
|
@@ -27,7 +28,7 @@ const voucherCodeFormSchema = (t) =>
|
|
|
27
28
|
|
|
28
29
|
export const Summary = (props: Props) => {
|
|
29
30
|
const { t } = useLocalization();
|
|
30
|
-
const { basket } = props;
|
|
31
|
+
const { basket, onBasketUpdate } = props;
|
|
31
32
|
const router = useRouter();
|
|
32
33
|
const {
|
|
33
34
|
register,
|
|
@@ -53,7 +54,7 @@ export const Summary = (props: Props) => {
|
|
|
53
54
|
const removeVoucherCode = () => {
|
|
54
55
|
removeVoucherCodeMutation()
|
|
55
56
|
.unwrap()
|
|
56
|
-
.then((basket) =>
|
|
57
|
+
.then((basket) => {
|
|
57
58
|
dispatch(
|
|
58
59
|
basketApi.util.updateQueryData(
|
|
59
60
|
'getBasket',
|
|
@@ -62,8 +63,9 @@ export const Summary = (props: Props) => {
|
|
|
62
63
|
Object.assign(draftBasket, basket);
|
|
63
64
|
}
|
|
64
65
|
)
|
|
65
|
-
)
|
|
66
|
-
|
|
66
|
+
);
|
|
67
|
+
onBasketUpdate?.(basket);
|
|
68
|
+
})
|
|
67
69
|
.catch((error: Error) => {
|
|
68
70
|
setError('voucherCode', { message: error.data.non_field_errors });
|
|
69
71
|
});
|
|
@@ -74,7 +76,7 @@ export const Summary = (props: Props) => {
|
|
|
74
76
|
voucher_code: data.voucherCode
|
|
75
77
|
})
|
|
76
78
|
.unwrap()
|
|
77
|
-
.then((basket) =>
|
|
79
|
+
.then((basket) => {
|
|
78
80
|
dispatch(
|
|
79
81
|
basketApi.util.updateQueryData(
|
|
80
82
|
'getBasket',
|
|
@@ -83,8 +85,9 @@ export const Summary = (props: Props) => {
|
|
|
83
85
|
Object.assign(draftBasket, basket);
|
|
84
86
|
}
|
|
85
87
|
)
|
|
86
|
-
)
|
|
87
|
-
|
|
88
|
+
);
|
|
89
|
+
onBasketUpdate?.(basket);
|
|
90
|
+
})
|
|
88
91
|
.catch((error: Error) => {
|
|
89
92
|
setError('voucherCode', { message: error.data.non_field_errors });
|
|
90
93
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import React, { useMemo } from 'react';
|
|
3
|
+
import React, { useMemo, useCallback } from 'react';
|
|
4
4
|
import { VariantOption, VariantType } from '@akinon/next/types';
|
|
5
5
|
import { usePathname, useSearchParams } from 'next/navigation';
|
|
6
6
|
import clsx from 'clsx';
|
|
@@ -12,20 +12,23 @@ type VariantProps = {
|
|
|
12
12
|
preventDefaultClick?: boolean;
|
|
13
13
|
} & VariantType;
|
|
14
14
|
|
|
15
|
-
export const Variant = (
|
|
15
|
+
export const Variant = ({
|
|
16
|
+
attribute_key,
|
|
17
|
+
attribute_name,
|
|
18
|
+
options,
|
|
19
|
+
preventDefaultClick,
|
|
20
|
+
onChange,
|
|
21
|
+
className
|
|
22
|
+
}: VariantProps) => {
|
|
16
23
|
const { t } = useLocalization();
|
|
17
|
-
const {
|
|
18
|
-
attribute_key,
|
|
19
|
-
attribute_name,
|
|
20
|
-
options,
|
|
21
|
-
preventDefaultClick,
|
|
22
|
-
onChange
|
|
23
|
-
} = props;
|
|
24
24
|
const router = useRouter();
|
|
25
25
|
const pathname = usePathname();
|
|
26
26
|
const searchParams = useSearchParams();
|
|
27
27
|
// This is a workaround for the fact that we can't use the useSearchParams set method because of this is not implemented in next.js yet. So we have to use the URLSearchParams's set method.
|
|
28
|
-
const params =
|
|
28
|
+
const params = useMemo(
|
|
29
|
+
() => new URLSearchParams(searchParams.toString()),
|
|
30
|
+
[searchParams]
|
|
31
|
+
);
|
|
29
32
|
|
|
30
33
|
const hasSelected = useMemo(
|
|
31
34
|
() => options.some((option) => option.is_selected),
|
|
@@ -37,22 +40,23 @@ export const Variant = (props: VariantProps) => {
|
|
|
37
40
|
[options]
|
|
38
41
|
);
|
|
39
42
|
|
|
40
|
-
const handleClick = (
|
|
41
|
-
|
|
42
|
-
onChange
|
|
43
|
-
|
|
43
|
+
const handleClick = useCallback(
|
|
44
|
+
(option: VariantOption) => {
|
|
45
|
+
if (onChange) {
|
|
46
|
+
onChange(option);
|
|
47
|
+
}
|
|
44
48
|
|
|
45
|
-
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
49
|
+
if (preventDefaultClick) return;
|
|
48
50
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
params.set(attribute_key, option.value);
|
|
52
|
+
router.push(`${pathname}?${params.toString()}`);
|
|
53
|
+
},
|
|
54
|
+
[onChange, preventDefaultClick, params, attribute_key, pathname, router]
|
|
55
|
+
);
|
|
52
56
|
|
|
53
57
|
return (
|
|
54
58
|
<div
|
|
55
|
-
className={clsx('flex flex-col gap-2',
|
|
59
|
+
className={clsx('flex flex-col gap-2', className)}
|
|
56
60
|
data-testid={`product-variant-${attribute_name}`}
|
|
57
61
|
>
|
|
58
62
|
<p className="flex gap-2 text-xs leading-4">
|
|
@@ -66,30 +70,27 @@ export const Variant = (props: VariantProps) => {
|
|
|
66
70
|
className="font-bold"
|
|
67
71
|
data-testid={`product-variant-${attribute_name}-value`}
|
|
68
72
|
>
|
|
69
|
-
{selectedVariant
|
|
73
|
+
{selectedVariant?.value}
|
|
70
74
|
</span>
|
|
71
75
|
)}
|
|
72
76
|
</p>
|
|
73
77
|
<div className="flex gap-3 flex-wrap justify-center">
|
|
74
78
|
{options.map((option, i) => (
|
|
75
79
|
<button
|
|
76
|
-
key={i}
|
|
80
|
+
key={`${i}-${option.value}`}
|
|
77
81
|
className={clsx(
|
|
78
82
|
'h-10 px-4 transition-colors duration-200 text-xs',
|
|
79
|
-
|
|
80
|
-
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground pointer-events-none'
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
!option.is_selectable &&
|
|
91
|
-
option.is_selected &&
|
|
92
|
-
'border border-dashed border-black bg-white text-gray-600 overflow-hidden relative'
|
|
83
|
+
{
|
|
84
|
+
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground pointer-events-none':
|
|
85
|
+
option.is_selected,
|
|
86
|
+
'bg-gray-200 hover:bg-gray-400':
|
|
87
|
+
option.is_selectable && !option.is_selected,
|
|
88
|
+
'border border-gray-300 text-gray-600': !option.is_selectable,
|
|
89
|
+
'cursor-not-allowed':
|
|
90
|
+
!option.is_selectable && !option.is_selectable_without_stock,
|
|
91
|
+
'border border-dashed border-black bg-white text-gray-600 overflow-hidden relative':
|
|
92
|
+
!option.is_selectable && option.is_selected
|
|
93
|
+
}
|
|
93
94
|
)}
|
|
94
95
|
onClick={() => handleClick(option)}
|
|
95
96
|
>
|