@akinon/pz-similar-products 1.92.0-snapshot-ZERO-3457-20250627111231 → 1.92.0-snapshot-ZERO-3457-20250627121541
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 -1
- package/README.md +5 -2
- package/package.json +1 -1
- package/src/types/index.ts +2 -0
- package/src/views/filters.tsx +664 -646
- package/src/views/image-search.tsx +98 -86
package/src/views/filters.tsx
CHANGED
|
@@ -167,742 +167,760 @@ export function SimilarProductsFilterSidebar({
|
|
|
167
167
|
);
|
|
168
168
|
|
|
169
169
|
return (
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const mobileHeaderClassName = twMerge(
|
|
190
|
-
'flex justify-between mb-6 md:hidden',
|
|
191
|
-
settings?.customStyles?.filterSidebarMobileHeader
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
return (
|
|
195
|
-
<>
|
|
196
|
-
<div className={mobileHeaderClassName}>
|
|
197
|
-
<h3
|
|
198
|
-
className={twMerge(
|
|
199
|
-
'text-2xl font-bold',
|
|
200
|
-
settings?.customStyles?.filterSidebarMobileTitle
|
|
201
|
-
)}
|
|
202
|
-
>
|
|
203
|
-
{t('common.product.filters')}
|
|
204
|
-
</h3>
|
|
205
|
-
<Button
|
|
206
|
-
appearance="ghost"
|
|
207
|
-
size="sm"
|
|
208
|
-
onClick={() => setIsFilterMenuOpen(false)}
|
|
209
|
-
className={twMerge(
|
|
210
|
-
'hover:bg-gray-200 rounded-full p-0 w-6 h-6',
|
|
211
|
-
settings?.customStyles?.filterSidebarMobileCloseButton
|
|
212
|
-
)}
|
|
213
|
-
>
|
|
214
|
-
<Icon name="close" size={16} />
|
|
215
|
-
</Button>
|
|
216
|
-
</div>
|
|
217
|
-
<div
|
|
218
|
-
className={twMerge(
|
|
219
|
-
'flex justify-between items-center mb-6 md:hidden',
|
|
220
|
-
settings?.customStyles?.filterSidebarMobileCounter
|
|
221
|
-
)}
|
|
222
|
-
>
|
|
223
|
-
<span
|
|
224
|
-
className={twMerge(
|
|
225
|
-
'text-sm',
|
|
226
|
-
settings?.customStyles?.filterSidebarMobileCounterText
|
|
227
|
-
)}
|
|
228
|
-
>
|
|
229
|
-
{searchResults?.pagination?.total_count || 0} items
|
|
230
|
-
</span>
|
|
231
|
-
</div>
|
|
232
|
-
</>
|
|
233
|
-
);
|
|
234
|
-
})()}
|
|
235
|
-
|
|
236
|
-
{(() => {
|
|
237
|
-
if (
|
|
238
|
-
settings?.customRenderers?.render?.filterSidebar?.renderImageSection
|
|
239
|
-
) {
|
|
240
|
-
return settings.customRenderers.render.filterSidebar.renderImageSection(
|
|
241
|
-
{
|
|
242
|
-
currentImageUrl,
|
|
243
|
-
isCropping,
|
|
244
|
-
onToggleCrop: handleToggleCropMode,
|
|
245
|
-
onFileUpload: handleFileChangeWithCropReset,
|
|
246
|
-
onResetToOriginal: handleResetToOriginal,
|
|
247
|
-
fileError,
|
|
248
|
-
isLoading
|
|
249
|
-
}
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const imageSectionClassName = twMerge(
|
|
254
|
-
'relative mb-2 md:mb-6 mt-4',
|
|
255
|
-
settings?.customStyles?.imageSection
|
|
256
|
-
);
|
|
257
|
-
|
|
258
|
-
const imageContainerClassName = twMerge(
|
|
259
|
-
'relative bg-white overflow-hidden flex items-center justify-center transition-all duration-300 ease-in-out',
|
|
260
|
-
isCropping ? 'border-2 border-dashed border-gray-300' : '',
|
|
261
|
-
settings?.customStyles?.imageContainer
|
|
262
|
-
);
|
|
263
|
-
|
|
264
|
-
const cropButtonClassName = twMerge(
|
|
265
|
-
`absolute z-10 bottom-3 left-3 p-2 rounded-full bg-white shadow-md w-10 h-10 ${
|
|
266
|
-
isCropping ? 'text-red-500' : 'text-gray-700'
|
|
267
|
-
} ${isLoading ? 'opacity-50 cursor-not-allowed' : ''}`,
|
|
268
|
-
settings?.customStyles?.cropButton
|
|
269
|
-
);
|
|
270
|
-
|
|
271
|
-
const renderCropButton = () => {
|
|
272
|
-
if (!settings?.enableCropping || settings.enableCropping === false)
|
|
273
|
-
return null;
|
|
274
|
-
|
|
170
|
+
<>
|
|
171
|
+
{isFilterMenuOpen && (
|
|
172
|
+
<div
|
|
173
|
+
className={twMerge(
|
|
174
|
+
'fixed inset-0 bg-black bg-opacity-50 z-40 md:hidden',
|
|
175
|
+
settings?.customStyles?.filterSidebarMobileOverlay
|
|
176
|
+
)}
|
|
177
|
+
onClick={() => setIsFilterMenuOpen(false)}
|
|
178
|
+
/>
|
|
179
|
+
)}
|
|
180
|
+
|
|
181
|
+
<div
|
|
182
|
+
className={sidebarClassName}
|
|
183
|
+
style={{
|
|
184
|
+
maxHeight: 'calc(100vh - 120px)'
|
|
185
|
+
}}
|
|
186
|
+
>
|
|
187
|
+
{(() => {
|
|
275
188
|
if (
|
|
276
|
-
settings?.customRenderers?.render?.filterSidebar?.
|
|
189
|
+
settings?.customRenderers?.render?.filterSidebar?.renderMobileHeader
|
|
277
190
|
) {
|
|
278
|
-
return settings.customRenderers.render.filterSidebar.
|
|
191
|
+
return settings.customRenderers.render.filterSidebar.renderMobileHeader(
|
|
279
192
|
{
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
193
|
+
title: t('common.product.filters'),
|
|
194
|
+
itemCount: searchResults?.pagination?.total_count || 0,
|
|
195
|
+
onClose: () => setIsFilterMenuOpen(false)
|
|
283
196
|
}
|
|
284
197
|
);
|
|
285
198
|
}
|
|
286
199
|
|
|
200
|
+
const mobileHeaderClassName = twMerge(
|
|
201
|
+
'flex justify-between mb-6 md:hidden',
|
|
202
|
+
settings?.customStyles?.filterSidebarMobileHeader
|
|
203
|
+
);
|
|
204
|
+
|
|
287
205
|
return (
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
{isLoading ? (
|
|
296
|
-
<LoaderSpinner className="w-5 h-5" />
|
|
297
|
-
) : isCropping ? (
|
|
298
|
-
<svg
|
|
299
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
300
|
-
width="20"
|
|
301
|
-
height="20"
|
|
302
|
-
viewBox="0 0 24 24"
|
|
303
|
-
fill="none"
|
|
304
|
-
stroke="currentColor"
|
|
305
|
-
strokeWidth="2"
|
|
306
|
-
strokeLinecap="round"
|
|
307
|
-
strokeLinejoin="round"
|
|
206
|
+
<>
|
|
207
|
+
<div className={mobileHeaderClassName}>
|
|
208
|
+
<h3
|
|
209
|
+
className={twMerge(
|
|
210
|
+
'text-2xl font-bold',
|
|
211
|
+
settings?.customStyles?.filterSidebarMobileTitle
|
|
212
|
+
)}
|
|
308
213
|
>
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
stroke="currentColor"
|
|
320
|
-
strokeWidth="2"
|
|
321
|
-
strokeLinecap="round"
|
|
322
|
-
strokeLinejoin="round"
|
|
214
|
+
{t('common.product.filters')}
|
|
215
|
+
</h3>
|
|
216
|
+
<Button
|
|
217
|
+
appearance="ghost"
|
|
218
|
+
size="sm"
|
|
219
|
+
onClick={() => setIsFilterMenuOpen(false)}
|
|
220
|
+
className={twMerge(
|
|
221
|
+
'hover:bg-gray-200 rounded-full p-0 w-6 h-6',
|
|
222
|
+
settings?.customStyles?.filterSidebarMobileCloseButton
|
|
223
|
+
)}
|
|
323
224
|
>
|
|
324
|
-
<
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
225
|
+
<Icon name="close" size={16} />
|
|
226
|
+
</Button>
|
|
227
|
+
</div>
|
|
228
|
+
<div
|
|
229
|
+
className={twMerge(
|
|
230
|
+
'flex justify-between items-center mb-6 md:hidden',
|
|
231
|
+
settings?.customStyles?.filterSidebarMobileCounter
|
|
232
|
+
)}
|
|
233
|
+
>
|
|
234
|
+
<span
|
|
235
|
+
className={twMerge(
|
|
236
|
+
'text-sm',
|
|
237
|
+
settings?.customStyles?.filterSidebarMobileCounterText
|
|
238
|
+
)}
|
|
239
|
+
>
|
|
240
|
+
{searchResults?.pagination?.total_count || 0} items
|
|
241
|
+
</span>
|
|
242
|
+
</div>
|
|
243
|
+
</>
|
|
329
244
|
);
|
|
330
|
-
}
|
|
245
|
+
})()}
|
|
331
246
|
|
|
332
|
-
|
|
333
|
-
if (!settings?.enableCropping || settings.enableCropping === false)
|
|
334
|
-
return null;
|
|
247
|
+
{(() => {
|
|
335
248
|
if (
|
|
336
|
-
|
|
337
|
-
!completedCrop ||
|
|
338
|
-
completedCrop.width <= 10 ||
|
|
339
|
-
completedCrop.height <= 10
|
|
340
|
-
)
|
|
341
|
-
return null;
|
|
342
|
-
|
|
343
|
-
if (
|
|
344
|
-
settings?.customRenderers?.render?.filterSidebar?.renderTickButton
|
|
249
|
+
settings?.customRenderers?.render?.filterSidebar?.renderImageSection
|
|
345
250
|
) {
|
|
346
|
-
return settings.customRenderers.render.filterSidebar.
|
|
251
|
+
return settings.customRenderers.render.filterSidebar.renderImageSection(
|
|
347
252
|
{
|
|
348
|
-
|
|
349
|
-
|
|
253
|
+
currentImageUrl,
|
|
254
|
+
isCropping,
|
|
255
|
+
onToggleCrop: handleToggleCropMode,
|
|
256
|
+
onFileUpload: handleFileChangeWithCropReset,
|
|
257
|
+
onResetToOriginal: handleResetToOriginal,
|
|
258
|
+
fileError,
|
|
259
|
+
isLoading
|
|
350
260
|
}
|
|
351
261
|
);
|
|
352
262
|
}
|
|
353
263
|
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
}`,
|
|
358
|
-
settings?.customStyles?.tickButton
|
|
264
|
+
const imageSectionClassName = twMerge(
|
|
265
|
+
'relative mb-2 md:mb-6 mt-4',
|
|
266
|
+
settings?.customStyles?.imageSection
|
|
359
267
|
);
|
|
360
268
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
onClick={() => {
|
|
366
|
-
if (!isLoading) {
|
|
367
|
-
handleSafeProcessCrop(completedCrop);
|
|
368
|
-
}
|
|
369
|
-
}}
|
|
370
|
-
disabled={isLoading}
|
|
371
|
-
className={tickButtonClassName}
|
|
372
|
-
>
|
|
373
|
-
{isLoading ? (
|
|
374
|
-
<LoaderSpinner className="w-5 h-5" />
|
|
375
|
-
) : (
|
|
376
|
-
<svg
|
|
377
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
378
|
-
width="20"
|
|
379
|
-
height="20"
|
|
380
|
-
viewBox="0 0 24 24"
|
|
381
|
-
fill="none"
|
|
382
|
-
stroke="currentColor"
|
|
383
|
-
strokeWidth="2"
|
|
384
|
-
strokeLinecap="round"
|
|
385
|
-
strokeLinejoin="round"
|
|
386
|
-
>
|
|
387
|
-
<polyline points="20,6 9,17 4,12"></polyline>
|
|
388
|
-
</svg>
|
|
389
|
-
)}
|
|
390
|
-
</Button>
|
|
269
|
+
const imageContainerClassName = twMerge(
|
|
270
|
+
'relative bg-white overflow-hidden flex items-center justify-center transition-all duration-300 ease-in-out',
|
|
271
|
+
isCropping ? 'border-2 border-dashed border-gray-300' : '',
|
|
272
|
+
settings?.customStyles?.imageContainer
|
|
391
273
|
);
|
|
392
|
-
};
|
|
393
274
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
275
|
+
const cropButtonClassName = twMerge(
|
|
276
|
+
`absolute z-10 bottom-3 left-3 p-2 rounded-full bg-white shadow-md w-10 h-10 ${
|
|
277
|
+
isCropping ? 'text-red-500' : 'text-gray-700'
|
|
278
|
+
} ${isLoading ? 'opacity-50 cursor-not-allowed' : ''}`,
|
|
279
|
+
settings?.customStyles?.cropButton
|
|
280
|
+
);
|
|
399
281
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
282
|
+
const renderCropButton = () => {
|
|
283
|
+
if (!settings?.enableCropping || settings.enableCropping === false)
|
|
284
|
+
return null;
|
|
285
|
+
|
|
286
|
+
if (
|
|
287
|
+
settings?.customRenderers?.render?.filterSidebar?.renderCropButton
|
|
288
|
+
) {
|
|
289
|
+
return settings.customRenderers.render.filterSidebar.renderCropButton(
|
|
290
|
+
{
|
|
291
|
+
isCropping,
|
|
292
|
+
onClick: handleToggleCropMode,
|
|
293
|
+
disabled: isLoading
|
|
412
294
|
}
|
|
295
|
+
);
|
|
296
|
+
}
|
|
413
297
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
298
|
+
return (
|
|
299
|
+
<Button
|
|
300
|
+
appearance="ghost"
|
|
301
|
+
size="sm"
|
|
302
|
+
onClick={handleToggleCropMode}
|
|
303
|
+
disabled={isLoading}
|
|
304
|
+
className={cropButtonClassName}
|
|
305
|
+
>
|
|
306
|
+
{isLoading ? (
|
|
307
|
+
<LoaderSpinner className="w-5 h-5" />
|
|
308
|
+
) : isCropping ? (
|
|
309
|
+
<svg
|
|
310
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
311
|
+
width="20"
|
|
312
|
+
height="20"
|
|
313
|
+
viewBox="0 0 24 24"
|
|
314
|
+
fill="none"
|
|
315
|
+
stroke="currentColor"
|
|
316
|
+
strokeWidth="2"
|
|
317
|
+
strokeLinecap="round"
|
|
318
|
+
strokeLinejoin="round"
|
|
319
|
+
>
|
|
320
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
321
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
322
|
+
</svg>
|
|
323
|
+
) : (
|
|
324
|
+
<svg
|
|
325
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
326
|
+
width="20"
|
|
327
|
+
height="20"
|
|
328
|
+
viewBox="0 0 24 24"
|
|
329
|
+
fill="none"
|
|
330
|
+
stroke="currentColor"
|
|
331
|
+
strokeWidth="2"
|
|
332
|
+
strokeLinecap="round"
|
|
333
|
+
strokeLinejoin="round"
|
|
334
|
+
>
|
|
335
|
+
<path d="M6 2v14a2 2 0 0 0 2 2h14"></path>
|
|
336
|
+
<path d="M18 22V8a2 2 0 0 0-2-2H2"></path>
|
|
337
|
+
</svg>
|
|
338
|
+
)}
|
|
339
|
+
</Button>
|
|
340
|
+
);
|
|
341
|
+
};
|
|
418
342
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}}
|
|
432
|
-
onComplete={handleCropComplete}
|
|
433
|
-
onDragStart={() => {}}
|
|
434
|
-
onDragEnd={() => {}}
|
|
435
|
-
ruleOfThirds={false}
|
|
436
|
-
aspect={settings?.cropAspectRatio}
|
|
437
|
-
className="slider-crop"
|
|
438
|
-
disabled={isLoading}
|
|
439
|
-
keepSelection={true}
|
|
440
|
-
>
|
|
441
|
-
<img
|
|
442
|
-
ref={imageRef}
|
|
443
|
-
src={currentImageUrl || ''}
|
|
444
|
-
alt={product?.name || 'Product image'}
|
|
445
|
-
className="max-w-full max-h-[200px] md:max-h-[280px]"
|
|
446
|
-
style={{ transform: `scale(1) rotate(0deg)` }}
|
|
447
|
-
/>
|
|
448
|
-
</ReactCrop>
|
|
449
|
-
) : (
|
|
450
|
-
<div className="relative w-full h-full flex items-center justify-center">
|
|
451
|
-
<img
|
|
452
|
-
ref={imageRef}
|
|
453
|
-
src={currentImageUrl || ''}
|
|
454
|
-
alt={product?.name || 'Product image'}
|
|
455
|
-
className="max-w-full max-h-[200px] md:max-h-[280px] object-contain"
|
|
456
|
-
/>
|
|
457
|
-
{!isCropping && completedCrop && (
|
|
458
|
-
<div className="hidden md:block absolute inset-0 bg-black bg-opacity-50 transition-opacity duration-300 ease-in-out">
|
|
459
|
-
<div
|
|
460
|
-
className="absolute transition-all duration-300 ease-in-out"
|
|
461
|
-
style={{
|
|
462
|
-
width: `${completedCrop.width}px`,
|
|
463
|
-
height: `${completedCrop.height}px`,
|
|
464
|
-
left: `${completedCrop.x}px`,
|
|
465
|
-
top: `${completedCrop.y}px`,
|
|
466
|
-
boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.5)',
|
|
467
|
-
border: '2px solid white'
|
|
468
|
-
}}
|
|
469
|
-
></div>
|
|
470
|
-
</div>
|
|
471
|
-
)}
|
|
472
|
-
</div>
|
|
473
|
-
)}
|
|
474
|
-
</div>
|
|
475
|
-
);
|
|
476
|
-
})()}
|
|
477
|
-
</div>
|
|
343
|
+
const renderTickButton = () => {
|
|
344
|
+
if (!settings?.enableCropping || settings.enableCropping === false)
|
|
345
|
+
return null;
|
|
346
|
+
if (
|
|
347
|
+
!isCropping ||
|
|
348
|
+
!completedCrop ||
|
|
349
|
+
completedCrop.width <= 10 ||
|
|
350
|
+
completedCrop.height <= 10
|
|
351
|
+
)
|
|
352
|
+
return null;
|
|
478
353
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
type="file"
|
|
490
|
-
accept="image/*"
|
|
491
|
-
ref={fileInputRef}
|
|
492
|
-
onChange={handleFileChangeWithCropReset}
|
|
493
|
-
className="hidden"
|
|
494
|
-
/>
|
|
495
|
-
{(() => {
|
|
496
|
-
if (
|
|
497
|
-
settings?.customRenderers?.render?.filterSidebar
|
|
498
|
-
?.renderUploadButton
|
|
499
|
-
) {
|
|
500
|
-
return settings.customRenderers.render.filterSidebar.renderUploadButton(
|
|
501
|
-
{
|
|
502
|
-
onClick: handleNewImageClick,
|
|
503
|
-
disabled: isLoading
|
|
504
|
-
}
|
|
505
|
-
);
|
|
506
|
-
}
|
|
354
|
+
if (
|
|
355
|
+
settings?.customRenderers?.render?.filterSidebar?.renderTickButton
|
|
356
|
+
) {
|
|
357
|
+
return settings.customRenderers.render.filterSidebar.renderTickButton(
|
|
358
|
+
{
|
|
359
|
+
onClick: () => handleSafeProcessCrop(completedCrop),
|
|
360
|
+
disabled: isLoading
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
}
|
|
507
364
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
365
|
+
const tickButtonClassName = twMerge(
|
|
366
|
+
`absolute z-10 bottom-3 right-3 p-2 rounded-full bg-white shadow-md w-10 h-10 text-green-600 ${
|
|
367
|
+
isLoading ? 'opacity-50 cursor-not-allowed' : ''
|
|
368
|
+
}`,
|
|
369
|
+
settings?.customStyles?.tickButton
|
|
370
|
+
);
|
|
514
371
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
372
|
+
return (
|
|
373
|
+
<Button
|
|
374
|
+
appearance="ghost"
|
|
375
|
+
size="sm"
|
|
376
|
+
onClick={() => {
|
|
377
|
+
if (!isLoading) {
|
|
378
|
+
handleSafeProcessCrop(completedCrop);
|
|
379
|
+
}
|
|
380
|
+
}}
|
|
381
|
+
disabled={isLoading}
|
|
382
|
+
className={tickButtonClassName}
|
|
383
|
+
>
|
|
384
|
+
{isLoading ? (
|
|
385
|
+
<LoaderSpinner className="w-5 h-5" />
|
|
386
|
+
) : (
|
|
387
|
+
<svg
|
|
388
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
389
|
+
width="20"
|
|
390
|
+
height="20"
|
|
391
|
+
viewBox="0 0 24 24"
|
|
392
|
+
fill="none"
|
|
393
|
+
stroke="currentColor"
|
|
394
|
+
strokeWidth="2"
|
|
395
|
+
strokeLinecap="round"
|
|
396
|
+
strokeLinejoin="round"
|
|
397
|
+
>
|
|
398
|
+
<polyline points="20,6 9,17 4,12"></polyline>
|
|
399
|
+
</svg>
|
|
543
400
|
)}
|
|
401
|
+
</Button>
|
|
402
|
+
);
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
return (
|
|
406
|
+
<div className={imageSectionClassName}>
|
|
407
|
+
<div className={imageContainerClassName}>
|
|
408
|
+
{renderCropButton()}
|
|
409
|
+
{renderTickButton()}
|
|
544
410
|
|
|
545
411
|
{(() => {
|
|
546
412
|
if (
|
|
547
413
|
settings?.customRenderers?.render?.filterSidebar
|
|
548
|
-
?.
|
|
414
|
+
?.renderImageContainer
|
|
549
415
|
) {
|
|
550
|
-
return settings.customRenderers.render.filterSidebar.
|
|
416
|
+
return settings.customRenderers.render.filterSidebar.renderImageContainer(
|
|
551
417
|
{
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
showResetButton && (hasUploadedImage || completedCrop)
|
|
418
|
+
imageUrl: currentImageUrl || '',
|
|
419
|
+
productName: product?.name || 'Product image',
|
|
420
|
+
isCropping
|
|
556
421
|
}
|
|
557
422
|
);
|
|
558
423
|
}
|
|
559
424
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
const resetButtonClassName = twMerge(
|
|
564
|
-
`flex items-center gap-2 text-xs md:text-sm justify-center bg-blue-100 hover:bg-blue-200 border-blue-200 text-blue-600 ${
|
|
565
|
-
isLoading ? 'opacity-50 cursor-not-allowed' : ''
|
|
566
|
-
}`,
|
|
567
|
-
settings?.customStyles?.resetButton
|
|
425
|
+
const imageWrapperClassName = twMerge(
|
|
426
|
+
'w-full h-full flex items-center justify-center',
|
|
427
|
+
settings?.customStyles?.imageWrapper
|
|
568
428
|
);
|
|
569
429
|
|
|
570
430
|
return (
|
|
571
|
-
<
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
431
|
+
<div className={imageWrapperClassName}>
|
|
432
|
+
{isCropping ? (
|
|
433
|
+
<ReactCrop
|
|
434
|
+
crop={crop}
|
|
435
|
+
onChange={(newCrop) => {
|
|
436
|
+
if (!isLoading) {
|
|
437
|
+
setCrop(newCrop);
|
|
438
|
+
if (newCrop?.width > 10 && newCrop?.height > 10) {
|
|
439
|
+
setCompletedCrop(newCrop);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}}
|
|
443
|
+
onComplete={handleCropComplete}
|
|
444
|
+
onDragStart={() => {}}
|
|
445
|
+
onDragEnd={() => {}}
|
|
446
|
+
ruleOfThirds={false}
|
|
447
|
+
aspect={settings?.cropAspectRatio}
|
|
448
|
+
className="slider-crop"
|
|
449
|
+
disabled={isLoading}
|
|
450
|
+
keepSelection={true}
|
|
451
|
+
>
|
|
452
|
+
<img
|
|
453
|
+
ref={imageRef}
|
|
454
|
+
src={currentImageUrl || ''}
|
|
455
|
+
alt={product?.name || 'Product image'}
|
|
456
|
+
className="max-w-full max-h-[200px] md:max-h-[280px]"
|
|
457
|
+
style={{ transform: `scale(1) rotate(0deg)` }}
|
|
458
|
+
/>
|
|
459
|
+
</ReactCrop>
|
|
460
|
+
) : (
|
|
461
|
+
<div className="relative w-full h-full flex items-center justify-center">
|
|
462
|
+
<img
|
|
463
|
+
ref={imageRef}
|
|
464
|
+
src={currentImageUrl || ''}
|
|
465
|
+
alt={product?.name || 'Product image'}
|
|
466
|
+
className="max-w-full max-h-[200px] md:max-h-[280px] object-contain"
|
|
467
|
+
/>
|
|
468
|
+
{!isCropping && completedCrop && (
|
|
469
|
+
<div className="hidden md:block absolute inset-0 bg-black bg-opacity-50 transition-opacity duration-300 ease-in-out">
|
|
470
|
+
<div
|
|
471
|
+
className="absolute transition-all duration-300 ease-in-out"
|
|
472
|
+
style={{
|
|
473
|
+
width: `${completedCrop.width}px`,
|
|
474
|
+
height: `${completedCrop.height}px`,
|
|
475
|
+
left: `${completedCrop.x}px`,
|
|
476
|
+
top: `${completedCrop.y}px`,
|
|
477
|
+
boxShadow: '0 0 0 9999px rgba(0, 0, 0, 0.5)',
|
|
478
|
+
border: '2px solid white'
|
|
479
|
+
}}
|
|
480
|
+
></div>
|
|
481
|
+
</div>
|
|
482
|
+
)}
|
|
483
|
+
</div>
|
|
484
|
+
)}
|
|
485
|
+
</div>
|
|
597
486
|
);
|
|
598
487
|
})()}
|
|
599
488
|
</div>
|
|
600
|
-
)}
|
|
601
489
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
490
|
+
{!isCropping && (
|
|
491
|
+
<div
|
|
492
|
+
className={twMerge(
|
|
493
|
+
'flex flex-col md:flex-row justify-center mt-3 gap-2',
|
|
494
|
+
settings?.customStyles?.cropControls
|
|
495
|
+
)}
|
|
496
|
+
>
|
|
497
|
+
{settings?.enableFileUpload !== false && (
|
|
498
|
+
<>
|
|
499
|
+
<input
|
|
500
|
+
type="file"
|
|
501
|
+
accept="image/*"
|
|
502
|
+
ref={fileInputRef}
|
|
503
|
+
onChange={handleFileChangeWithCropReset}
|
|
504
|
+
className="hidden"
|
|
505
|
+
/>
|
|
506
|
+
{(() => {
|
|
507
|
+
if (
|
|
508
|
+
settings?.customRenderers?.render?.filterSidebar
|
|
509
|
+
?.renderUploadButton
|
|
510
|
+
) {
|
|
511
|
+
return settings.customRenderers.render.filterSidebar.renderUploadButton(
|
|
512
|
+
{
|
|
513
|
+
onClick: handleNewImageClick,
|
|
514
|
+
disabled: isLoading
|
|
515
|
+
}
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const uploadButtonClassName = twMerge(
|
|
520
|
+
`flex items-center gap-2 text-xs md:text-sm justify-center bg-gray-100 hover:bg-gray-200 border-gray-200 ${
|
|
521
|
+
isLoading ? 'opacity-50 cursor-not-allowed' : ''
|
|
522
|
+
}`,
|
|
523
|
+
settings?.customStyles?.uploadButton
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
return (
|
|
527
|
+
<Button
|
|
528
|
+
appearance="outlined"
|
|
529
|
+
size="sm"
|
|
530
|
+
onClick={handleNewImageClick}
|
|
531
|
+
disabled={isLoading}
|
|
532
|
+
className={uploadButtonClassName}
|
|
533
|
+
>
|
|
534
|
+
<svg
|
|
535
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
536
|
+
width="20"
|
|
537
|
+
height="20"
|
|
538
|
+
viewBox="0 0 24 24"
|
|
539
|
+
fill="none"
|
|
540
|
+
stroke="currentColor"
|
|
541
|
+
strokeWidth="2"
|
|
542
|
+
strokeLinecap="round"
|
|
543
|
+
strokeLinejoin="round"
|
|
544
|
+
className="text-gray-500"
|
|
545
|
+
>
|
|
546
|
+
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path>
|
|
547
|
+
<circle cx="12" cy="13" r="4"></circle>
|
|
548
|
+
</svg>
|
|
549
|
+
{t('common.product.new_image')}
|
|
550
|
+
</Button>
|
|
551
|
+
);
|
|
552
|
+
})()}
|
|
553
|
+
</>
|
|
554
|
+
)}
|
|
555
|
+
|
|
556
|
+
{(() => {
|
|
557
|
+
if (
|
|
558
|
+
settings?.customRenderers?.render?.filterSidebar
|
|
559
|
+
?.renderResetButton
|
|
560
|
+
) {
|
|
561
|
+
return settings.customRenderers.render.filterSidebar.renderResetButton(
|
|
562
|
+
{
|
|
563
|
+
onClick: handleResetToOriginal,
|
|
564
|
+
disabled: isLoading,
|
|
565
|
+
showButton:
|
|
566
|
+
showResetButton &&
|
|
567
|
+
(hasUploadedImage || completedCrop)
|
|
568
|
+
}
|
|
569
|
+
);
|
|
612
570
|
}
|
|
613
|
-
);
|
|
614
|
-
}
|
|
615
571
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
572
|
+
if (
|
|
573
|
+
!showResetButton ||
|
|
574
|
+
(!hasUploadedImage && !completedCrop)
|
|
575
|
+
)
|
|
576
|
+
return null;
|
|
620
577
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
);
|
|
628
|
-
})()}
|
|
629
|
-
</div>
|
|
630
|
-
);
|
|
631
|
-
})()}
|
|
632
|
-
|
|
633
|
-
{/* Filters */}
|
|
634
|
-
<div className="space-y-2 md:space-y-4">
|
|
635
|
-
{searchResults?.facets
|
|
636
|
-
?.filter((facet) => facet.key !== 'category_ids')
|
|
637
|
-
?.map((facet) => {
|
|
638
|
-
if (
|
|
639
|
-
settings?.customRenderers?.render?.filterSidebar
|
|
640
|
-
?.renderFilterGroup
|
|
641
|
-
) {
|
|
642
|
-
return settings.customRenderers.render.filterSidebar.renderFilterGroup(
|
|
643
|
-
{
|
|
644
|
-
facet,
|
|
645
|
-
onFacetChange: handleFacetChange,
|
|
646
|
-
isLoading
|
|
647
|
-
}
|
|
648
|
-
);
|
|
649
|
-
}
|
|
578
|
+
const resetButtonClassName = twMerge(
|
|
579
|
+
`flex items-center gap-2 text-xs md:text-sm justify-center bg-blue-100 hover:bg-blue-200 border-blue-200 text-blue-600 ${
|
|
580
|
+
isLoading ? 'opacity-50 cursor-not-allowed' : ''
|
|
581
|
+
}`,
|
|
582
|
+
settings?.customStyles?.resetButton
|
|
583
|
+
);
|
|
650
584
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
585
|
+
return (
|
|
586
|
+
<Button
|
|
587
|
+
appearance="outlined"
|
|
588
|
+
size="sm"
|
|
589
|
+
onClick={handleResetToOriginal}
|
|
590
|
+
disabled={isLoading}
|
|
591
|
+
className={resetButtonClassName}
|
|
592
|
+
>
|
|
593
|
+
<svg
|
|
594
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
595
|
+
width="20"
|
|
596
|
+
height="20"
|
|
597
|
+
viewBox="0 0 24 24"
|
|
598
|
+
fill="none"
|
|
599
|
+
stroke="currentColor"
|
|
600
|
+
strokeWidth="2"
|
|
601
|
+
strokeLinecap="round"
|
|
602
|
+
strokeLinejoin="round"
|
|
603
|
+
className="text-blue-600"
|
|
604
|
+
>
|
|
605
|
+
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
|
|
606
|
+
<path d="M21 3v5h-5"></path>
|
|
607
|
+
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path>
|
|
608
|
+
<path d="M3 21v-5h5"></path>
|
|
609
|
+
</svg>
|
|
610
|
+
{t('common.product.reset_to_original')}
|
|
611
|
+
</Button>
|
|
612
|
+
);
|
|
613
|
+
})()}
|
|
614
|
+
</div>
|
|
615
|
+
)}
|
|
656
616
|
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
617
|
+
{fileError &&
|
|
618
|
+
!isCropping &&
|
|
619
|
+
(() => {
|
|
620
|
+
if (
|
|
621
|
+
settings?.customRenderers?.render?.filterSidebar
|
|
622
|
+
?.renderErrorMessage
|
|
623
|
+
) {
|
|
624
|
+
return settings.customRenderers.render.filterSidebar.renderErrorMessage(
|
|
625
|
+
{
|
|
626
|
+
error: fileError
|
|
627
|
+
}
|
|
628
|
+
);
|
|
629
|
+
}
|
|
664
630
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
631
|
+
const errorClassName = twMerge(
|
|
632
|
+
'mt-2 px-3 py-2 bg-red-50 border border-red-100 rounded-md',
|
|
633
|
+
settings?.customStyles?.errorMessage
|
|
634
|
+
);
|
|
669
635
|
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
636
|
+
return (
|
|
637
|
+
<div className={errorClassName}>
|
|
638
|
+
<p className="text-xs text-red-600 font-medium">
|
|
639
|
+
{fileError}
|
|
640
|
+
</p>
|
|
641
|
+
</div>
|
|
642
|
+
);
|
|
643
|
+
})()}
|
|
644
|
+
</div>
|
|
645
|
+
);
|
|
646
|
+
})()}
|
|
677
647
|
|
|
678
|
-
|
|
648
|
+
{/* Filters */}
|
|
649
|
+
<div className="space-y-2 md:space-y-4">
|
|
650
|
+
{searchResults?.facets
|
|
651
|
+
?.filter((facet) => facet.key !== 'category_ids')
|
|
652
|
+
?.map((facet) => {
|
|
679
653
|
if (
|
|
680
654
|
settings?.customRenderers?.render?.filterSidebar
|
|
681
|
-
?.
|
|
655
|
+
?.renderFilterGroup
|
|
682
656
|
) {
|
|
683
|
-
return settings.customRenderers.render.filterSidebar.
|
|
657
|
+
return settings.customRenderers.render.filterSidebar.renderFilterGroup(
|
|
684
658
|
{
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
659
|
+
facet,
|
|
660
|
+
onFacetChange: handleFacetChange,
|
|
661
|
+
isLoading
|
|
688
662
|
}
|
|
689
663
|
);
|
|
690
664
|
}
|
|
691
|
-
return null;
|
|
692
|
-
};
|
|
693
665
|
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
isLoading,
|
|
705
|
-
isSelected: choice.is_selected
|
|
706
|
-
}
|
|
666
|
+
const Component = getComponentByWidgetType(
|
|
667
|
+
facet.widget_type,
|
|
668
|
+
facet.key
|
|
669
|
+
);
|
|
670
|
+
const choices = facet.data.choices || [];
|
|
671
|
+
|
|
672
|
+
if (!Component) {
|
|
673
|
+
console.warn(
|
|
674
|
+
'Component not found for widget type:',
|
|
675
|
+
facet.widget_type
|
|
707
676
|
);
|
|
677
|
+
return null;
|
|
708
678
|
}
|
|
709
679
|
|
|
710
|
-
const
|
|
711
|
-
'filter-
|
|
712
|
-
settings?.customStyles?.
|
|
680
|
+
const filterGroupClassName = twMerge(
|
|
681
|
+
'filter-group',
|
|
682
|
+
settings?.customStyles?.filterGroup
|
|
713
683
|
);
|
|
714
684
|
|
|
715
|
-
const
|
|
716
|
-
'
|
|
717
|
-
|
|
685
|
+
const filterGroupContentClassName = twMerge(
|
|
686
|
+
clsx('flex gap-4', {
|
|
687
|
+
'flex-wrap flex-row': facet.key === sizeKey,
|
|
688
|
+
'flex-col': facet.key !== sizeKey
|
|
689
|
+
}),
|
|
690
|
+
settings?.customStyles?.filterGroupContent
|
|
718
691
|
);
|
|
719
692
|
|
|
720
|
-
const
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
693
|
+
const renderFilterGroupTitle = () => {
|
|
694
|
+
if (
|
|
695
|
+
settings?.customRenderers?.render?.filterSidebar
|
|
696
|
+
?.renderFilterGroupTitle
|
|
697
|
+
) {
|
|
698
|
+
return settings.customRenderers.render.filterSidebar.renderFilterGroupTitle(
|
|
699
|
+
{
|
|
700
|
+
title: facet.name,
|
|
701
|
+
isCollapsed: choices.some((choice) => choice.is_selected),
|
|
702
|
+
onToggle: () => {}
|
|
703
|
+
}
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
return null;
|
|
707
|
+
};
|
|
724
708
|
|
|
725
|
-
const
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
709
|
+
const renderFilterItem = (choice: any, index: number) => {
|
|
710
|
+
if (
|
|
711
|
+
settings?.customRenderers?.render?.filterSidebar
|
|
712
|
+
?.renderFilterItem
|
|
713
|
+
) {
|
|
714
|
+
return settings.customRenderers.render.filterSidebar.renderFilterItem(
|
|
715
|
+
{
|
|
716
|
+
choice,
|
|
717
|
+
facetKey: facet.key,
|
|
718
|
+
onFacetChange: handleFacetChange,
|
|
719
|
+
isLoading,
|
|
720
|
+
isSelected: choice.is_selected
|
|
721
|
+
}
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
const filterItemClassName = twMerge(
|
|
726
|
+
'filter-item',
|
|
727
|
+
settings?.customStyles?.filterItem
|
|
728
|
+
);
|
|
729
|
+
|
|
730
|
+
const filterItemInputClassName = twMerge(
|
|
731
|
+
'filter-item-input',
|
|
732
|
+
settings?.customStyles?.filterItemInput
|
|
733
|
+
);
|
|
734
|
+
|
|
735
|
+
const filterItemLabelClassName = twMerge(
|
|
736
|
+
'filter-item-label',
|
|
737
|
+
settings?.customStyles?.filterItemLabel
|
|
738
|
+
);
|
|
739
|
+
|
|
740
|
+
const filterItemCountClassName = twMerge(
|
|
741
|
+
'filter-item-count',
|
|
742
|
+
settings?.customStyles?.filterItemCount
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
return (
|
|
746
|
+
<div key={choice.value} className={filterItemClassName}>
|
|
747
|
+
<Component
|
|
748
|
+
key={choice.label}
|
|
749
|
+
value={choice.value}
|
|
750
|
+
label={choice.label}
|
|
751
|
+
name={facet.key}
|
|
752
|
+
onChange={() => {
|
|
753
|
+
if (!isLoading) {
|
|
754
|
+
handleFacetChange(facet.key, choice.value);
|
|
755
|
+
}
|
|
756
|
+
}}
|
|
757
|
+
onClick={() => {
|
|
758
|
+
if (!isLoading && facet.key === sizeKey) {
|
|
759
|
+
handleFacetChange(facet.key, choice.value);
|
|
760
|
+
}
|
|
761
|
+
}}
|
|
762
|
+
checked={choice.is_selected}
|
|
763
|
+
data-testid={`${choice.label.trim()}`}
|
|
764
|
+
disabled={isLoading}
|
|
765
|
+
className={filterItemInputClassName}
|
|
766
|
+
>
|
|
767
|
+
<span className={filterItemLabelClassName}>
|
|
768
|
+
{choice.label}
|
|
769
|
+
</span>{' '}
|
|
770
|
+
(
|
|
771
|
+
<span
|
|
772
|
+
data-testid={`filter-count-${facet.name.toLowerCase()}-${index}`}
|
|
773
|
+
className={filterItemCountClassName}
|
|
774
|
+
>
|
|
775
|
+
{choice.quantity}
|
|
776
|
+
</span>
|
|
777
|
+
)
|
|
778
|
+
</Component>
|
|
779
|
+
</div>
|
|
780
|
+
);
|
|
781
|
+
};
|
|
729
782
|
|
|
730
783
|
return (
|
|
731
|
-
<div key={
|
|
732
|
-
<
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
name={facet.key}
|
|
737
|
-
onChange={() => {
|
|
738
|
-
if (!isLoading) {
|
|
739
|
-
handleFacetChange(facet.key, choice.value);
|
|
740
|
-
}
|
|
741
|
-
}}
|
|
742
|
-
onClick={() => {
|
|
743
|
-
if (!isLoading && facet.key === sizeKey) {
|
|
744
|
-
handleFacetChange(facet.key, choice.value);
|
|
745
|
-
}
|
|
746
|
-
}}
|
|
747
|
-
checked={choice.is_selected}
|
|
748
|
-
data-testid={`${choice.label.trim()}`}
|
|
749
|
-
disabled={isLoading}
|
|
750
|
-
className={filterItemInputClassName}
|
|
784
|
+
<div key={facet.key} className={filterGroupClassName}>
|
|
785
|
+
<Accordion
|
|
786
|
+
title={renderFilterGroupTitle() || facet.name}
|
|
787
|
+
isCollapse={choices.some((choice) => choice.is_selected)}
|
|
788
|
+
dataTestId={`filter-${facet.name}`}
|
|
751
789
|
>
|
|
752
|
-
<
|
|
753
|
-
{
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
{choice.quantity}
|
|
761
|
-
</span>
|
|
762
|
-
)
|
|
763
|
-
</Component>
|
|
790
|
+
<div className={filterGroupContentClassName}>
|
|
791
|
+
{choices
|
|
792
|
+
.slice(0, 10)
|
|
793
|
+
.map((choice, index) =>
|
|
794
|
+
renderFilterItem(choice, index)
|
|
795
|
+
)}
|
|
796
|
+
</div>
|
|
797
|
+
</Accordion>
|
|
764
798
|
</div>
|
|
765
799
|
);
|
|
766
|
-
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
<div className={filterGroupContentClassName}>
|
|
776
|
-
{choices
|
|
777
|
-
.slice(0, 10)
|
|
778
|
-
.map((choice, index) => renderFilterItem(choice, index))}
|
|
779
|
-
</div>
|
|
780
|
-
</Accordion>
|
|
781
|
-
</div>
|
|
800
|
+
})}
|
|
801
|
+
</div>
|
|
802
|
+
|
|
803
|
+
{/* Mobile Active Filters and Clear Button */}
|
|
804
|
+
{(() => {
|
|
805
|
+
const hasActiveFilters = searchResults?.facets
|
|
806
|
+
?.filter((facet) => facet.key !== 'category_ids')
|
|
807
|
+
?.some((facet) =>
|
|
808
|
+
facet.data.choices?.some((choice) => choice.is_selected)
|
|
782
809
|
);
|
|
783
|
-
})}
|
|
784
|
-
</div>
|
|
785
810
|
|
|
786
|
-
|
|
787
|
-
{(() => {
|
|
788
|
-
const hasActiveFilters = searchResults?.facets
|
|
789
|
-
?.filter((facet) => facet.key !== 'category_ids')
|
|
790
|
-
?.some((facet) =>
|
|
791
|
-
facet.data.choices?.some((choice) => choice.is_selected)
|
|
792
|
-
);
|
|
811
|
+
if (!hasActiveFilters) return null;
|
|
793
812
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
.flatMap(
|
|
799
|
-
(facet) =>
|
|
800
|
-
facet.data.choices
|
|
801
|
-
?.filter((choice) => choice.is_selected)
|
|
802
|
-
.map((choice) => ({
|
|
803
|
-
key: facet.key,
|
|
804
|
-
value: choice.value.toString(),
|
|
805
|
-
label: choice.label
|
|
806
|
-
})) || []
|
|
807
|
-
);
|
|
808
|
-
|
|
809
|
-
const handleClearAll = () => {
|
|
810
|
-
if (!isLoading) {
|
|
811
|
-
const facetsToRemove = [];
|
|
812
|
-
searchResults?.facets
|
|
813
|
-
?.filter((facet) => facet.key !== 'category_ids')
|
|
814
|
-
?.forEach((facet) => {
|
|
813
|
+
const activeFilters = searchResults.facets
|
|
814
|
+
.filter((facet) => facet.key !== 'category_ids')
|
|
815
|
+
.flatMap(
|
|
816
|
+
(facet) =>
|
|
815
817
|
facet.data.choices
|
|
816
818
|
?.filter((choice) => choice.is_selected)
|
|
817
|
-
.
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
819
|
+
.map((choice) => ({
|
|
820
|
+
key: facet.key,
|
|
821
|
+
value: choice.value.toString(),
|
|
822
|
+
label: choice.label
|
|
823
|
+
})) || []
|
|
824
|
+
);
|
|
825
|
+
|
|
826
|
+
const handleClearAll = () => {
|
|
827
|
+
if (!isLoading) {
|
|
828
|
+
const facetsToRemove = [];
|
|
829
|
+
searchResults?.facets
|
|
830
|
+
?.filter((facet) => facet.key !== 'category_ids')
|
|
831
|
+
?.forEach((facet) => {
|
|
832
|
+
facet.data.choices
|
|
833
|
+
?.filter((choice) => choice.is_selected)
|
|
834
|
+
.forEach((choice) => {
|
|
835
|
+
facetsToRemove.push({
|
|
836
|
+
facetKey: facet.key,
|
|
837
|
+
choiceValue: choice.value
|
|
838
|
+
});
|
|
821
839
|
});
|
|
822
|
-
|
|
840
|
+
});
|
|
841
|
+
|
|
842
|
+
facetsToRemove.forEach(({ facetKey, choiceValue }) => {
|
|
843
|
+
removeFacetFilter(facetKey, choiceValue);
|
|
823
844
|
});
|
|
845
|
+
}
|
|
846
|
+
};
|
|
824
847
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
848
|
+
if (
|
|
849
|
+
settings?.customRenderers?.render?.filterSidebar
|
|
850
|
+
?.renderMobileActiveFilters
|
|
851
|
+
) {
|
|
852
|
+
return (
|
|
853
|
+
<div className="md:hidden mt-6">
|
|
854
|
+
{settings.customRenderers.render.filterSidebar.renderMobileActiveFilters(
|
|
855
|
+
{
|
|
856
|
+
filters: activeFilters,
|
|
857
|
+
onRemove: handleFacetChange,
|
|
858
|
+
onClearAll: handleClearAll,
|
|
859
|
+
isLoading
|
|
860
|
+
}
|
|
861
|
+
)}
|
|
862
|
+
</div>
|
|
863
|
+
);
|
|
828
864
|
}
|
|
829
|
-
};
|
|
830
865
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
?.
|
|
834
|
-
) {
|
|
835
|
-
return (
|
|
836
|
-
<div className="md:hidden mt-6">
|
|
837
|
-
{settings.customRenderers.render.filterSidebar.renderMobileActiveFilters(
|
|
838
|
-
{
|
|
839
|
-
filters: activeFilters,
|
|
840
|
-
onRemove: handleFacetChange,
|
|
841
|
-
onClearAll: handleClearAll,
|
|
842
|
-
isLoading
|
|
843
|
-
}
|
|
844
|
-
)}
|
|
845
|
-
</div>
|
|
866
|
+
const mobileActiveFiltersClassName = twMerge(
|
|
867
|
+
'md:hidden mt-6',
|
|
868
|
+
settings?.customStyles?.mobileActiveFilters
|
|
846
869
|
);
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
</h4>
|
|
870
|
-
<div className="flex flex-wrap gap-2">
|
|
871
|
-
{activeFilters.map((filter) => (
|
|
872
|
-
<div
|
|
873
|
-
key={`${filter.key}-${filter.value}`}
|
|
874
|
-
className={mobileActiveFilterTagClassName}
|
|
875
|
-
>
|
|
876
|
-
<span>{filter.label}</span>
|
|
877
|
-
<Button
|
|
878
|
-
appearance="ghost"
|
|
879
|
-
size="sm"
|
|
880
|
-
onClick={() => {
|
|
881
|
-
if (!isLoading) {
|
|
882
|
-
handleFacetChange(filter.key, filter.value);
|
|
883
|
-
}
|
|
884
|
-
}}
|
|
885
|
-
disabled={isLoading}
|
|
886
|
-
className="hover:bg-gray-200 rounded-full p-0 w-5 h-5 disabled:opacity-50 disabled:cursor-not-allowed ml-1"
|
|
870
|
+
|
|
871
|
+
const mobileActiveFilterTagClassName = twMerge(
|
|
872
|
+
'flex items-center gap-1 px-2 py-1 bg-gray-100 rounded-full text-xs',
|
|
873
|
+
settings?.customStyles?.mobileActiveFilterTag
|
|
874
|
+
);
|
|
875
|
+
|
|
876
|
+
const mobileClearAllButtonClassName = twMerge(
|
|
877
|
+
'w-full',
|
|
878
|
+
settings?.customStyles?.mobileClearAllButton
|
|
879
|
+
);
|
|
880
|
+
|
|
881
|
+
return (
|
|
882
|
+
<div className={mobileActiveFiltersClassName}>
|
|
883
|
+
<div className="mb-4">
|
|
884
|
+
<h4 className="text-sm font-medium mb-2">
|
|
885
|
+
{t('common.product.active_filters')}
|
|
886
|
+
</h4>
|
|
887
|
+
<div className="flex flex-wrap gap-2">
|
|
888
|
+
{activeFilters.map((filter) => (
|
|
889
|
+
<div
|
|
890
|
+
key={`${filter.key}-${filter.value}`}
|
|
891
|
+
className={mobileActiveFilterTagClassName}
|
|
887
892
|
>
|
|
888
|
-
<
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
893
|
+
<span>{filter.label}</span>
|
|
894
|
+
<Button
|
|
895
|
+
appearance="ghost"
|
|
896
|
+
size="sm"
|
|
897
|
+
onClick={() => {
|
|
898
|
+
if (!isLoading) {
|
|
899
|
+
handleFacetChange(filter.key, filter.value);
|
|
900
|
+
}
|
|
901
|
+
}}
|
|
902
|
+
disabled={isLoading}
|
|
903
|
+
className="hover:bg-gray-200 rounded-full p-0 w-5 h-5 disabled:opacity-50 disabled:cursor-not-allowed ml-1"
|
|
904
|
+
>
|
|
905
|
+
<Icon name="close" size={10} />
|
|
906
|
+
</Button>
|
|
907
|
+
</div>
|
|
908
|
+
))}
|
|
909
|
+
</div>
|
|
892
910
|
</div>
|
|
893
|
-
</div>
|
|
894
911
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
912
|
+
<Button
|
|
913
|
+
appearance="outlined"
|
|
914
|
+
className={mobileClearAllButtonClassName}
|
|
915
|
+
onClick={handleClearAll}
|
|
916
|
+
disabled={isLoading}
|
|
917
|
+
>
|
|
918
|
+
{t('common.product.clear_all_filters')}
|
|
919
|
+
</Button>
|
|
920
|
+
</div>
|
|
921
|
+
);
|
|
922
|
+
})()}
|
|
923
|
+
</div>
|
|
924
|
+
</>
|
|
907
925
|
);
|
|
908
926
|
}
|