@o2vend/theme-cli 1.0.36 → 1.0.38
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/README.md +4 -0
- package/lib/lib/dev-server.js +344 -48
- package/lib/lib/liquid-engine.js +3 -1
- package/lib/lib/mock-data.js +473 -119
- package/lib/lib/widget-service.js +12 -4
- package/package.json +2 -2
- package/test-theme/assets/async-sections.js +32 -24
- package/test-theme/assets/cart-drawer.js +20 -22
- package/test-theme/assets/cart-manager.js +1 -15
- package/test-theme/assets/checkout-price-handler.js +12 -11
- package/test-theme/assets/checkout.css +1415 -0
- package/test-theme/assets/checkout.js +3174 -0
- package/test-theme/assets/components.css +178 -29
- package/test-theme/assets/delivery-zone.js +1 -1
- package/test-theme/assets/product-detail.css +1050 -0
- package/test-theme/assets/product-detail.js +2940 -0
- package/test-theme/assets/theme.css +95 -120
- package/test-theme/assets/theme.js +781 -186
- package/test-theme/layout/theme.liquid +91 -17
- package/test-theme/sections/content.liquid +64 -57
- package/test-theme/sections/footer-fallback.liquid +57 -7
- package/test-theme/sections/footer.liquid +63 -12
- package/test-theme/sections/header-fallback.liquid +41 -41
- package/test-theme/sections/header.liquid +41 -51
- package/test-theme/sections/hero-fallback.liquid +1 -1
- package/test-theme/sections/hero.liquid +159 -136
- package/test-theme/snippets/account-sidebar.liquid +121 -29
- package/test-theme/snippets/add-to-cart-modal.liquid +258 -206
- package/test-theme/snippets/breadcrumbs.liquid +98 -11
- package/test-theme/snippets/cart-drawer.liquid +93 -0
- package/test-theme/snippets/delivery-zone-city-selector.liquid +101 -15
- package/test-theme/snippets/delivery-zone-modal.liquid +529 -84
- package/test-theme/snippets/delivery-zone-search.liquid +104 -18
- package/test-theme/snippets/login-modal.liquid +269 -82
- package/test-theme/snippets/mega-menu.liquid +130 -43
- package/test-theme/snippets/news-thumbnail.liquid +120 -28
- package/test-theme/snippets/pagination.liquid +1 -1
- package/test-theme/snippets/price.liquid +100 -9
- package/test-theme/snippets/product-card-related.liquid +22 -4
- package/test-theme/snippets/product-card-simple.liquid +521 -25
- package/test-theme/snippets/product-card.liquid +145 -232
- package/test-theme/snippets/rating.liquid +100 -9
- package/test-theme/snippets/skeleton-collection-grid.liquid +94 -8
- package/test-theme/snippets/skeleton-product-card.liquid +102 -16
- package/test-theme/snippets/skeleton-product-grid.liquid +87 -1
- package/test-theme/snippets/social-sharing.liquid +133 -32
- package/test-theme/templates/account/dashboard.liquid +30 -0
- package/test-theme/templates/account/loyalty-redemption.liquid +29 -28
- package/test-theme/templates/account/loyalty.liquid +45 -43
- package/test-theme/templates/account/order-detail.liquid +15 -8
- package/test-theme/templates/account/orders.liquid +189 -35
- package/test-theme/templates/account/profile.liquid +509 -114
- package/test-theme/templates/account/register.liquid +18 -8
- package/test-theme/templates/account/return-orders.liquid +31 -30
- package/test-theme/templates/account/store-credit.liquid +27 -26
- package/test-theme/templates/account/subscriptions.liquid +22 -5
- package/test-theme/templates/account/wishlist.liquid +88 -19
- package/test-theme/templates/address-book.liquid +166 -69
- package/test-theme/templates/categories.liquid +90 -30
- package/test-theme/templates/checkout.liquid +137 -3834
- package/test-theme/templates/error.liquid +23 -21
- package/test-theme/templates/index.liquid +29 -0
- package/test-theme/templates/login.liquid +33 -6
- package/test-theme/templates/order-confirmation.liquid +67 -9
- package/test-theme/templates/page.liquid +418 -206
- package/test-theme/templates/product-detail.liquid +124 -3878
- package/test-theme/templates/products.liquid +155 -30
- package/test-theme/templates/search.liquid +739 -225
- package/test-theme/widgets/brand-carousel.liquid +102 -82
- package/test-theme/widgets/brand.liquid +78 -50
- package/test-theme/widgets/carousel.liquid +253 -121
- package/test-theme/widgets/category-list-carousel.liquid +32 -8
- package/test-theme/widgets/category-list.liquid +21 -6
- package/test-theme/widgets/category.liquid +104 -37
- package/test-theme/widgets/discount-time.liquid +326 -119
- package/test-theme/widgets/footer-menu.liquid +115 -23
- package/test-theme/widgets/footer.liquid +118 -5
- package/test-theme/widgets/gallery.liquid +29 -5
- package/test-theme/widgets/header-menu.liquid +25 -13
- package/test-theme/widgets/header.liquid +64 -26
- package/test-theme/widgets/html.liquid +29 -6
- package/test-theme/widgets/news.liquid +6 -0
- package/test-theme/widgets/product-canvas.liquid +20 -12
- package/test-theme/widgets/product-carousel.liquid +118 -56
- package/test-theme/widgets/shared/product-grid.liquid +12 -0
- package/test-theme/widgets/single-product.liquid +688 -250
- package/test-theme/widgets/spacebar-carousel.liquid +39 -10
- package/test-theme/widgets/spacebar.liquid +77 -6
- package/test-theme/widgets/splash.liquid +40 -30
- package/test-theme/widgets/testimonial-carousel.liquid +111 -67
|
@@ -1,41 +1,537 @@
|
|
|
1
1
|
{% comment %}
|
|
2
|
-
|
|
2
|
+
Enhanced Modern Product Card
|
|
3
|
+
{% endcomment %}
|
|
4
|
+
{% assign call_for_pricing_raw = product.showCallForPricing | default: product.ShowCallForPricing | default: product.isCallForPricing | default: product.IsCallForPricing | default: false %}
|
|
5
|
+
{% assign show_call_for_pricing = false %}
|
|
6
|
+
{% if call_for_pricing_raw == true or call_for_pricing_raw == 'true' or call_for_pricing_raw == 1 or call_for_pricing_raw == '1' %}
|
|
7
|
+
{% assign show_call_for_pricing = true %}
|
|
8
|
+
{% endif %}
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
|
|
12
|
+
.product-info .product-title {
|
|
13
|
+
font-size: var(--text-1xl);
|
|
14
|
+
font-weight: 700;
|
|
15
|
+
color: var(--color-gray-900);
|
|
16
|
+
line-height: 1.2;
|
|
17
|
+
letter-spacing: -0.025em;
|
|
18
|
+
}
|
|
19
|
+
.product-card {
|
|
20
|
+
background: var(--color-background, #fff);
|
|
21
|
+
border-radius: 10px
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
24
|
+
max-width: 100%;
|
|
25
|
+
text-align: center;
|
|
26
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
border: 1px solid var(--color-border-light, rgba(0,0,0,0.06));
|
|
30
|
+
position: relative;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.product-card::before {
|
|
34
|
+
content: '';
|
|
35
|
+
position: absolute;
|
|
36
|
+
top: 0;
|
|
37
|
+
left: 0;
|
|
38
|
+
right: 0;
|
|
39
|
+
bottom: 0;
|
|
40
|
+
background: linear-gradient(135deg, transparent 0%, rgba(0,0,0,0.02) 100%);
|
|
41
|
+
opacity: 0;
|
|
42
|
+
transition: opacity 0.3s ease;
|
|
43
|
+
pointer-events: none;
|
|
44
|
+
z-index: 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.product-card:hover {
|
|
48
|
+
transform: translateY(-6px);
|
|
49
|
+
border-color: var(--color-primary, rgba(0,0,0,0.15));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.product-card:hover::before {
|
|
53
|
+
opacity: 1;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.product-link {
|
|
57
|
+
color: inherit;
|
|
58
|
+
text-decoration: none;
|
|
59
|
+
display: block;
|
|
60
|
+
flex: 1;
|
|
61
|
+
position: relative;
|
|
62
|
+
z-index: 2;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.product-image {
|
|
66
|
+
width: 100%;
|
|
67
|
+
height: 0;
|
|
68
|
+
padding-bottom: 100%; /* 1:1 aspect ratio */
|
|
69
|
+
background: linear-gradient(135deg, var(--color-card-bg, #f8f9fa) 0%, var(--color-border-light, #f0f1f3) 100%);
|
|
70
|
+
display: block;
|
|
71
|
+
position: relative;
|
|
72
|
+
overflow: hidden;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.product-image::after {
|
|
76
|
+
content: '';
|
|
77
|
+
position: absolute;
|
|
78
|
+
top: 0;
|
|
79
|
+
left: 0;
|
|
80
|
+
right: 0;
|
|
81
|
+
bottom: 0;
|
|
82
|
+
background: linear-gradient(to bottom, transparent 60%, rgba(0,0,0,0.03) 100%);
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.product-image img {
|
|
87
|
+
position: absolute;
|
|
88
|
+
top: 0;
|
|
89
|
+
left: 0;
|
|
90
|
+
width: 100%;
|
|
91
|
+
height: 100%;
|
|
92
|
+
object-fit: cover;
|
|
93
|
+
transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.product-card:hover .product-image img {
|
|
97
|
+
transform: scale(1.08);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.product-info {
|
|
101
|
+
padding: clamp(12px, 2vw, 16px);
|
|
102
|
+
background: var(--color-background, #fff);
|
|
103
|
+
position: relative;
|
|
104
|
+
z-index: 2;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.product-title {
|
|
108
|
+
font-size: clamp(0.8125rem, 1.5vw, 0.875rem);
|
|
109
|
+
font-weight: 600;
|
|
110
|
+
color: var(--color-text, #1a1a1a);
|
|
111
|
+
margin: 0 0 6px 0;
|
|
112
|
+
line-height: 1.4;
|
|
113
|
+
height: 2.8em;
|
|
114
|
+
overflow: hidden;
|
|
115
|
+
display: -webkit-box;
|
|
116
|
+
-webkit-line-clamp: 2;
|
|
117
|
+
-webkit-box-orient: vertical;
|
|
118
|
+
text-overflow: ellipsis;
|
|
119
|
+
letter-spacing: -0.01em;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.product-description {
|
|
123
|
+
font-size: clamp(0.6875rem, 1.2vw, 0.75rem);
|
|
124
|
+
color: var(--color-text-light, #666);
|
|
125
|
+
margin: 0 0 8px 0;
|
|
126
|
+
line-height: 1.5;
|
|
127
|
+
height: 3em;
|
|
128
|
+
overflow: hidden;
|
|
129
|
+
display: -webkit-box;
|
|
130
|
+
-webkit-line-clamp: 2;
|
|
131
|
+
-webkit-box-orient: vertical;
|
|
132
|
+
text-overflow: ellipsis;
|
|
133
|
+
letter-spacing: 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.product-price {
|
|
137
|
+
font-size: clamp(0.9375rem, 1.8vw, 1.0625rem);
|
|
138
|
+
font-weight: 700;
|
|
139
|
+
color: var(--color-primary, #000);
|
|
140
|
+
margin-bottom: clamp(10px, 2vw, 14px);
|
|
141
|
+
letter-spacing: -0.02em;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.btn-add {
|
|
145
|
+
background: var(--color-primary, #000);
|
|
146
|
+
color: var(--color-background, #fff);
|
|
147
|
+
border: none;
|
|
148
|
+
border-radius: clamp(6px, 1vw, 8px);
|
|
149
|
+
padding: clamp(10px, 2vw, 12px) clamp(14px, 2.5vw, 18px);
|
|
150
|
+
font-size: clamp(0.75rem, 1.4vw, 0.8125rem);
|
|
151
|
+
font-weight: 600;
|
|
152
|
+
cursor: pointer;
|
|
153
|
+
width: calc(100% - clamp(16px, 3vw, 24px));
|
|
154
|
+
margin: 0 clamp(8px, 1.5vw, 12px) clamp(12px, 2vw, 16px);
|
|
155
|
+
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
156
|
+
text-transform: uppercase;
|
|
157
|
+
letter-spacing: 0.05em;
|
|
158
|
+
position: relative;
|
|
159
|
+
z-index: 3;
|
|
160
|
+
overflow: hidden;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.btn-add::before {
|
|
164
|
+
content: '';
|
|
165
|
+
position: absolute;
|
|
166
|
+
top: 50%;
|
|
167
|
+
left: 50%;
|
|
168
|
+
width: 0;
|
|
169
|
+
height: 0;
|
|
170
|
+
border-radius: 50%;
|
|
171
|
+
background: rgba(255, 255, 255, 0.2);
|
|
172
|
+
transform: translate(-50%, -50%);
|
|
173
|
+
transition: width 0.6s ease, height 0.6s ease;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.btn-add:hover::before {
|
|
177
|
+
width: 300px;
|
|
178
|
+
height: 300px;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.btn-add:hover {
|
|
182
|
+
background: var(--color-primary-hover, #222);
|
|
183
|
+
transform: translateY(-2px);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.btn-add:active {
|
|
187
|
+
transform: translateY(0);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Grid responsiveness */
|
|
191
|
+
@media (min-width: 1200px) {
|
|
192
|
+
.product-card {
|
|
193
|
+
max-width: 280px;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@media (min-width: 768px) and (max-width: 1199px) {
|
|
198
|
+
.product-card {
|
|
199
|
+
max-width: 240px;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@media (min-width: 481px) and (max-width: 767px) {
|
|
204
|
+
.product-card {
|
|
205
|
+
max-width: 220px;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.product-image {
|
|
209
|
+
padding-bottom: 85%;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@media (max-width: 480px) {
|
|
214
|
+
.product-card {
|
|
215
|
+
max-width: 100%;
|
|
216
|
+
border-radius: 12px;
|
|
217
|
+
}
|
|
3
218
|
|
|
4
|
-
|
|
5
|
-
|
|
219
|
+
.product-image {
|
|
220
|
+
padding-bottom: 90%;
|
|
221
|
+
}
|
|
6
222
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
223
|
+
.product-title {
|
|
224
|
+
font-size: 0.8125rem;
|
|
225
|
+
height: 2.6em;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.product-description {
|
|
229
|
+
font-size: 0.6875rem;
|
|
230
|
+
height: 2.8em;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.product-price {
|
|
234
|
+
font-size: 0.9375rem;
|
|
235
|
+
margin-bottom: 10px;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.btn-add {
|
|
239
|
+
font-size: 0.75rem;
|
|
240
|
+
padding: 10px 14px;
|
|
241
|
+
letter-spacing: 0.03em;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
@media (max-width: 360px) {
|
|
246
|
+
.product-card {
|
|
247
|
+
border-radius: 10px;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.product-info {
|
|
251
|
+
padding: 10px;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
.product-title {
|
|
255
|
+
font-size: 0.75rem;
|
|
256
|
+
margin-bottom: 4px;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.product-description {
|
|
260
|
+
font-size: 0.625rem;
|
|
261
|
+
margin-bottom: 6px;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.product-price {
|
|
265
|
+
font-size: 0.875rem;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.btn-add {
|
|
269
|
+
font-size: 0.6875rem;
|
|
270
|
+
padding: 8px 12px;
|
|
271
|
+
width: calc(100% - 16px);
|
|
272
|
+
margin: 0 8px 10px;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* Loading state */
|
|
277
|
+
.product-card.loading {
|
|
278
|
+
pointer-events: none;
|
|
279
|
+
opacity: 0.6;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.product-card.loading .btn-add {
|
|
283
|
+
position: relative;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.product-card.loading .btn-add::after {
|
|
287
|
+
content: '';
|
|
288
|
+
position: absolute;
|
|
289
|
+
top: 50%;
|
|
290
|
+
left: 50%;
|
|
291
|
+
width: 14px;
|
|
292
|
+
height: 14px;
|
|
293
|
+
margin: -7px 0 0 -7px;
|
|
294
|
+
border: 2px solid rgba(255,255,255,0.3);
|
|
295
|
+
border-top-color: #fff;
|
|
296
|
+
border-radius: 50%;
|
|
297
|
+
animation: spin 0.6s linear infinite;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@keyframes spin {
|
|
301
|
+
to { transform: rotate(360deg); }
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* Accessibility */
|
|
305
|
+
.btn-add:focus-visible {
|
|
306
|
+
outline: 2px solid var(--color-primary, #000);
|
|
307
|
+
outline-offset: 2px;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.product-link:focus-visible {
|
|
311
|
+
outline: 2px solid var(--color-primary, #000);
|
|
312
|
+
outline-offset: 2px;
|
|
313
|
+
border-radius: clamp(12px, 1.5vw, 16px);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* Dark mode support */
|
|
317
|
+
@media (prefers-color-scheme: dark) {
|
|
318
|
+
.product-card {
|
|
319
|
+
background: var(--color-background, #1a1a1a);
|
|
320
|
+
border-color: var(--color-border-light, rgba(255,255,255,0.08));
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
.product-title {
|
|
324
|
+
color: var(--color-text, #f5f5f5);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.product-description {
|
|
328
|
+
color: var(--color-text-light, #a0a0a0);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.product-image {
|
|
332
|
+
background: linear-gradient(135deg, var(--color-card-bg, #2a2a2a) 0%, var(--color-border-light, #333) 100%);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* Print styles */
|
|
337
|
+
@media print {
|
|
338
|
+
.product-card {
|
|
339
|
+
break-inside: avoid;
|
|
340
|
+
border: 1px solid #ddd;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.btn-add {
|
|
344
|
+
display: none;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.product-card:hover {
|
|
348
|
+
transform: none;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
</style>
|
|
10
352
|
|
|
11
353
|
<div class="product-card">
|
|
12
354
|
<a href="/{{ product.slug }}" class="product-link">
|
|
13
355
|
<div class="product-image">
|
|
14
|
-
{%
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
356
|
+
{% assign product_image_alt = product.name | default: "Product Image" %}
|
|
357
|
+
{% if product.thumbnailImage1 and product.thumbnailImage1.url %}
|
|
358
|
+
{% assign product_image = product.thumbnailImage1.url %}
|
|
359
|
+
{% assign product_image_alt = product.thumbnailImage1.altText | default: product_image_alt %}
|
|
360
|
+
{% elsif product.ThumbnailImage1 and product.ThumbnailImage1.Url %}
|
|
361
|
+
{% assign product_image = product.ThumbnailImage1.Url %}
|
|
362
|
+
{% assign product_image_alt = product.ThumbnailImage1.AltText | default: product_image_alt %}
|
|
363
|
+
{% elsif product.images and product.images.size > 0 %}
|
|
364
|
+
{% assign first_image = product.images | first %}
|
|
365
|
+
{% if first_image.url %}
|
|
366
|
+
{% assign product_image = first_image.url %}
|
|
367
|
+
{% assign product_image_alt = first_image.altText | default: product_image_alt %}
|
|
368
|
+
{% elsif first_image.Url %}
|
|
369
|
+
{% assign product_image = first_image.Url %}
|
|
370
|
+
{% assign product_image_alt = first_image.AltText | default: product_image_alt %}
|
|
371
|
+
{% endif %}
|
|
372
|
+
{% elsif product.thumbnailImage and product.thumbnailImage.url %}
|
|
373
|
+
{% assign product_image = product.thumbnailImage.url %}
|
|
374
|
+
{% assign product_image_alt = product.thumbnailImage.altText | default: product_image_alt %}
|
|
375
|
+
{% elsif product.ThumbnailImage and product.ThumbnailImage.Url %}
|
|
376
|
+
{% assign product_image = product.ThumbnailImage.Url %}
|
|
377
|
+
{% assign product_image_alt = product.ThumbnailImage.AltText | default: product_image_alt %}
|
|
378
|
+
{% elsif product.imageUrl %}
|
|
379
|
+
{% assign product_image = product.imageUrl %}
|
|
380
|
+
{% elsif product.ImageUrl %}
|
|
381
|
+
{% assign product_image = product.ImageUrl %}
|
|
382
|
+
{% endif %}
|
|
383
|
+
|
|
384
|
+
{% if product_image %}
|
|
385
|
+
<img src="{{ product_image }}" alt="{{ product_image_alt }}" loading="lazy">
|
|
18
386
|
{% else %}
|
|
19
|
-
<img src="/assets/placeholder-product.jpg"
|
|
20
|
-
alt="{{ product.title }}"
|
|
21
|
-
loading="lazy">
|
|
387
|
+
<img src="/assets/placeholder-product.jpg" alt="{{ product_image_alt }}" loading="lazy">
|
|
22
388
|
{% endif %}
|
|
23
389
|
</div>
|
|
390
|
+
|
|
24
391
|
<div class="product-info">
|
|
25
|
-
<h3 class="product-title">{{ product.title }}</h3>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
392
|
+
<h3 class="product-title">{{ product.name | default: product.title | default: "Product Name" }}</h3>
|
|
393
|
+
<div class="product-price" data-price="{{ product.prices.price | default: product.price | default: 0 }}" data-show-call-for-pricing="{% if show_call_for_pricing %}true{% else %}false{% endif %}">
|
|
394
|
+
{% if show_call_for_pricing %}
|
|
395
|
+
Call for pricing
|
|
396
|
+
{% elsif product.prices and product.prices.priceString %}
|
|
397
|
+
{{ product.prices.priceString }}
|
|
398
|
+
{% elsif product.prices and product.prices.price %}
|
|
399
|
+
{{ product.prices.price | money }}
|
|
400
|
+
{% elsif product.price %}
|
|
401
|
+
{{ product.price | money }}
|
|
402
|
+
{% else %}
|
|
403
|
+
Price not available
|
|
404
|
+
{% endif %}
|
|
30
405
|
</div>
|
|
31
406
|
</div>
|
|
32
407
|
</a>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
</div>
|
|
408
|
+
|
|
409
|
+
<button class="btn-add add-to-cart-button"
|
|
410
|
+
data-product-id="{{ product.productId | default: product.id | default: '' }}"
|
|
411
|
+
data-variant-id="{{ product.variants[0].id | default: '' }}">
|
|
412
|
+
Add to Cart
|
|
413
|
+
</button>
|
|
40
414
|
</div>
|
|
41
415
|
|
|
416
|
+
<script>
|
|
417
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
418
|
+
// Format prices using Theme.formatMoneyProductCard (reads shop currency symbol) when available
|
|
419
|
+
document.querySelectorAll('.product-price[data-price]').forEach((el) => {
|
|
420
|
+
try {
|
|
421
|
+
var showCallForPricing = el.getAttribute('data-show-call-for-pricing');
|
|
422
|
+
if (showCallForPricing === 'true' || showCallForPricing === '1') {
|
|
423
|
+
el.textContent = 'Call for pricing';
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
var priceRaw = el.getAttribute('data-price');
|
|
427
|
+
if (!priceRaw) return;
|
|
428
|
+
var num = parseFloat(priceRaw);
|
|
429
|
+
if (isNaN(num)) return;
|
|
430
|
+
if (window.Theme && typeof window.Theme.formatMoneyProductCard === 'function') {
|
|
431
|
+
el.textContent = window.Theme.formatMoneyProductCard(num);
|
|
432
|
+
} else if (window.__SHOP_CURRENCY_SYMBOL__) {
|
|
433
|
+
el.textContent = window.__SHOP_CURRENCY_SYMBOL__ + num.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
434
|
+
}
|
|
435
|
+
} catch (e) {
|
|
436
|
+
// ignore formatting errors and leave server-rendered value
|
|
437
|
+
console.warn('[product-card-simple] price format error', e);
|
|
438
|
+
}
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
document.querySelectorAll('.btn-add.add-to-cart-button').forEach((btn) => {
|
|
442
|
+
if (btn.dataset.simpleBound === '1') return;
|
|
443
|
+
btn.dataset.simpleBound = '1';
|
|
444
|
+
|
|
445
|
+
btn.addEventListener('click', async (e) => {
|
|
446
|
+
e.preventDefault();
|
|
447
|
+
const productId = btn.getAttribute('data-product-id') || '';
|
|
448
|
+
const variantId = btn.getAttribute('data-variant-id') || '';
|
|
449
|
+
const idToUse = variantId || productId;
|
|
450
|
+
if (!idToUse) return;
|
|
451
|
+
|
|
452
|
+
const originalText = btn.textContent.trim();
|
|
453
|
+
btn.disabled = true;
|
|
454
|
+
btn.textContent = 'Adding...';
|
|
455
|
+
|
|
456
|
+
try {
|
|
457
|
+
// Prefer central Theme.addToCart when available (keeps behavior consistent)
|
|
458
|
+
if (window.Theme && typeof window.Theme.addToCart === 'function') {
|
|
459
|
+
await window.Theme.addToCart(idToUse, 1);
|
|
460
|
+
} else {
|
|
461
|
+
// Fallback: direct API call (keeps behavior similar to product-card)
|
|
462
|
+
const response = await fetch('/webstoreapi/carts/add', {
|
|
463
|
+
method: 'POST',
|
|
464
|
+
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
|
|
465
|
+
body: JSON.stringify({ productId: idToUse, quantity: 1 })
|
|
466
|
+
});
|
|
467
|
+
const data = await response.json();
|
|
468
|
+
|
|
469
|
+
if (!data.success) {
|
|
470
|
+
// If backend indicates authentication is required, open login instead of showing a generic error
|
|
471
|
+
if (data.requiresAuth) {
|
|
472
|
+
if (window.Theme && typeof window.Theme.openLoginModal === 'function') {
|
|
473
|
+
window.Theme.openLoginModal();
|
|
474
|
+
} else if (window.CartManager && typeof window.CartManager.openLoginModal === 'function') {
|
|
475
|
+
window.CartManager.openLoginModal();
|
|
476
|
+
} else {
|
|
477
|
+
const loginTrigger = document.querySelector('[data-login-modal-trigger]');
|
|
478
|
+
if (loginTrigger) loginTrigger.click();
|
|
479
|
+
}
|
|
480
|
+
// Reset button state and exit gracefully
|
|
481
|
+
btn.textContent = originalText;
|
|
482
|
+
btn.disabled = false;
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
throw new Error(data.error || data.message || 'Failed to add product to cart');
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// Try to update badge via CartManager
|
|
490
|
+
if (window.CartManager && typeof window.CartManager.getCartCount === 'function') {
|
|
491
|
+
const cartCount = await window.CartManager.getCartCount(true);
|
|
492
|
+
if (window.CartManager.dispatchCartUpdated) {
|
|
493
|
+
window.CartManager.dispatchCartUpdated({ itemCount: cartCount, cart: data.data });
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// If we used Theme.addToCart above, it is responsible for notifications; only show success toast when using the fallback API path
|
|
499
|
+
if (!(window.Theme && typeof window.Theme.addToCart === 'function')) {
|
|
500
|
+
if (window.Theme && typeof window.Theme.showNotification === 'function') {
|
|
501
|
+
window.Theme.showNotification('Product added to cart!', 'success');
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
btn.textContent = '✓ Added';
|
|
506
|
+
setTimeout(() => {
|
|
507
|
+
btn.textContent = originalText;
|
|
508
|
+
btn.disabled = false;
|
|
509
|
+
}, 2000);
|
|
510
|
+
} catch (err) {
|
|
511
|
+
console.error('product-card-simple addToCart failed', err);
|
|
512
|
+
|
|
513
|
+
// If this is an authentication-related error, open login popup and do not show a generic error toast
|
|
514
|
+
if (err && err.message && (
|
|
515
|
+
err.message.includes('Authentication required') ||
|
|
516
|
+
err.message.includes('Please sign in') ||
|
|
517
|
+
err.message.toLowerCase().includes('unauthorized')
|
|
518
|
+
)) {
|
|
519
|
+
if (window.Theme && typeof window.Theme.openLoginModal === 'function') {
|
|
520
|
+
window.Theme.openLoginModal();
|
|
521
|
+
} else if (window.CartManager && typeof window.CartManager.openLoginModal === 'function') {
|
|
522
|
+
window.CartManager.openLoginModal();
|
|
523
|
+
} else {
|
|
524
|
+
const loginTrigger = document.querySelector('[data-login-modal-trigger]');
|
|
525
|
+
if (loginTrigger) loginTrigger.click();
|
|
526
|
+
}
|
|
527
|
+
} else if (window.Theme && typeof window.Theme.showNotification === 'function') {
|
|
528
|
+
window.Theme.showNotification('Failed to add product to cart. Please sign in or try again.', 'error');
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
btn.textContent = originalText;
|
|
532
|
+
btn.disabled = false;
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
});
|
|
537
|
+
</script>
|