tee3apps-cms-sdk-react 0.0.14 → 0.0.16
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/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/PageComponents/Visual-Components/GroupProductComponent.tsx +86 -4
- package/src/PageComponents/Visual-Components/Styles/ProductListViewOne.tsx +69 -8
- package/src/PageComponents/Visual-Components/Styles/ProductListViewTwo.tsx +70 -9
- package/src/PageComponents/Visual-Components/TabComponent.tsx +261 -67
|
@@ -49,7 +49,19 @@ interface TabContentGroup {
|
|
|
49
49
|
dynamicImages?: any[];
|
|
50
50
|
dynamicVideos?: any[];
|
|
51
51
|
dynamicProducts?: any[];
|
|
52
|
+
staticImages?: any[];
|
|
53
|
+
staticVideos?: any[];
|
|
54
|
+
staticProducts?: any[];
|
|
52
55
|
showItems?: Product[];
|
|
56
|
+
dynamic?: {
|
|
57
|
+
conditions: any[];
|
|
58
|
+
query: string;
|
|
59
|
+
list: any[];
|
|
60
|
+
pagination: number;
|
|
61
|
+
};
|
|
62
|
+
dynamicQueries?: {
|
|
63
|
+
selectedVariants: any[];
|
|
64
|
+
};
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
interface TabMode {
|
|
@@ -97,10 +109,6 @@ interface HeaderStyle {
|
|
|
97
109
|
activeColorText: string;
|
|
98
110
|
}
|
|
99
111
|
|
|
100
|
-
interface TabsData {
|
|
101
|
-
all: TabItem[];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
112
|
export interface TabComponentProps {
|
|
105
113
|
name: string;
|
|
106
114
|
code: string;
|
|
@@ -109,7 +117,7 @@ export interface TabComponentProps {
|
|
|
109
117
|
showTitle: boolean;
|
|
110
118
|
title: TitleStyle;
|
|
111
119
|
header: HeaderStyle;
|
|
112
|
-
tabs:
|
|
120
|
+
tabs: TabItem[];
|
|
113
121
|
}
|
|
114
122
|
|
|
115
123
|
interface TabComponentMainProps {
|
|
@@ -157,27 +165,51 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
157
165
|
const getImageUrl = (url: string) => {
|
|
158
166
|
if (!url) return '';
|
|
159
167
|
if (url.startsWith('http://') || url.startsWith('https://')) return url;
|
|
160
|
-
|
|
168
|
+
// Ensure URL has leading slash if Linodeurl doesn't end with one
|
|
169
|
+
const cleanUrl = url.startsWith('/') ? url : `/${url}`;
|
|
170
|
+
const baseUrl = Linodeurl.endsWith('/') ? Linodeurl.slice(0, -1) : Linodeurl;
|
|
171
|
+
return `${baseUrl}${cleanUrl}`;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Helper function to extract numeric value from price in any format
|
|
175
|
+
const getPriceValue = (price: any): number => {
|
|
176
|
+
console.error(price,"price-----")
|
|
177
|
+
if (price === null || price === undefined) return 0;
|
|
178
|
+
|
|
179
|
+
// If it's already a number
|
|
180
|
+
if (typeof price === 'number') {
|
|
181
|
+
return isNaN(price) ? 0 : price;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// If it's an object with $numberDecimal (but not an array)
|
|
185
|
+
if (typeof price === 'object' && price !== null && !Array.isArray(price)) {
|
|
186
|
+
if (price.$numberDecimal !== undefined && price.$numberDecimal !== null) {
|
|
187
|
+
const value = parseFloat(String(price.$numberDecimal));
|
|
188
|
+
return isNaN(value) ? 0 : value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// If it's a string, try to parse it
|
|
193
|
+
if (typeof price === 'string') {
|
|
194
|
+
const value = parseFloat(price);
|
|
195
|
+
return isNaN(value) ? 0 : value;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return 0;
|
|
161
199
|
};
|
|
162
200
|
|
|
163
201
|
// Inline Product Card Component
|
|
164
202
|
const ProductCard: React.FC<{ product: any; layout?: string }> = ({ product, layout = '1x1' }) => {
|
|
165
203
|
const formatPrice = (price: any) => {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
currency: 'INR',
|
|
170
|
-
minimumFractionDigits: 0,
|
|
171
|
-
maximumFractionDigits: 0
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
return price;
|
|
204
|
+
const priceValue = getPriceValue(price);
|
|
205
|
+
if (priceValue === 0 && !price) return '0';
|
|
206
|
+
return priceValue
|
|
175
207
|
};
|
|
176
208
|
|
|
177
209
|
const calculateOffer = (mrp: any, sp: any) => {
|
|
178
|
-
const mrpValue =
|
|
179
|
-
const spValue =
|
|
180
|
-
if (mrpValue > spValue) {
|
|
210
|
+
const mrpValue = getPriceValue(mrp);
|
|
211
|
+
const spValue = getPriceValue(sp);
|
|
212
|
+
if (mrpValue > spValue && mrpValue > 0) {
|
|
181
213
|
const discount = ((mrpValue - spValue) / mrpValue) * 100;
|
|
182
214
|
return Math.round(discount);
|
|
183
215
|
}
|
|
@@ -204,22 +236,39 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
204
236
|
return variant.valueId?.name?.all || variant.valueId?.name || '';
|
|
205
237
|
};
|
|
206
238
|
|
|
207
|
-
|
|
208
|
-
const
|
|
239
|
+
// Use pricing object first, fallback to price for backward compatibility
|
|
240
|
+
const mrp = product.pricing?.mrp ;
|
|
241
|
+
console.error(mrp,product,"mrp-----")
|
|
242
|
+
const sp = product.pricing?.costPrice;
|
|
243
|
+
console.error(sp,"sp-----")
|
|
209
244
|
const offer = calculateOffer(mrp, sp);
|
|
210
245
|
|
|
211
246
|
const cardMode = layout === '1x1' ? 'carousel-mode' : layout === '2x1' ? 'layout-2x1' : 'grid-mode';
|
|
212
247
|
const productSlug = product.code;
|
|
213
248
|
const productLink = `/${productSlug}`;
|
|
214
249
|
|
|
250
|
+
// Get product image URL - try multiple possible locations
|
|
251
|
+
const getProductImageUrl = () => {
|
|
252
|
+
return product.image?.all?.url ||
|
|
253
|
+
product.image?.url ||
|
|
254
|
+
product.model?.image?.url ||
|
|
255
|
+
product.model?.image?.all?.url ||
|
|
256
|
+
'';
|
|
257
|
+
};
|
|
258
|
+
|
|
215
259
|
const cardContent = (
|
|
216
260
|
<>
|
|
217
261
|
{/* Product Image */}
|
|
218
262
|
<div className="product-image-container">
|
|
219
263
|
<img
|
|
220
|
-
src={getImageUrl(
|
|
221
|
-
alt={product.name?.all || product.name?.displayName}
|
|
264
|
+
src={getImageUrl(getProductImageUrl())}
|
|
265
|
+
alt={product.name?.all || product.name?.displayName || 'Product image'}
|
|
222
266
|
className="product-image"
|
|
267
|
+
onError={(e) => {
|
|
268
|
+
// Fallback if image fails to load
|
|
269
|
+
const target = e.target as HTMLImageElement;
|
|
270
|
+
target.style.display = 'none';
|
|
271
|
+
}}
|
|
223
272
|
/>
|
|
224
273
|
</div>
|
|
225
274
|
|
|
@@ -266,10 +315,10 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
266
315
|
<div className="product-pricing">
|
|
267
316
|
<div className="price-row">
|
|
268
317
|
<span className="current-price">{formatPrice(sp)}</span>
|
|
269
|
-
{mrp && sp &&
|
|
318
|
+
{mrp && sp && offer > 0 && (
|
|
270
319
|
<>
|
|
271
320
|
<span className="original-price">{formatPrice(mrp)}</span>
|
|
272
|
-
|
|
321
|
+
<span className="offer-badge">{offer}% OFF</span>
|
|
273
322
|
</>
|
|
274
323
|
)}
|
|
275
324
|
</div>
|
|
@@ -432,28 +481,56 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
432
481
|
|
|
433
482
|
switch (tab.tabContentType) {
|
|
434
483
|
case 'IMAGE':
|
|
435
|
-
if (tab.tabContentImage) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
484
|
+
if (tab.tabContentImage && tab.tabContentImage.image) {
|
|
485
|
+
const imageUrl = tab.tabContentImage.image.url;
|
|
486
|
+
const imageAlt = tab.tabContentImage.image.alt || 'Image';
|
|
487
|
+
const fullImageUrl = getImageUrl(imageUrl);
|
|
488
|
+
const linkUrl = buildLinkForSlide(tab.tabContentImage);
|
|
489
|
+
const linkTarget = tab.tabContentImage.link_type === 'EXTERNALLINK'
|
|
490
|
+
? tab.tabContentImage.external_link?.target || '_blank'
|
|
491
|
+
: '_blank';
|
|
492
|
+
|
|
493
|
+
// Debug: Log image URL construction
|
|
494
|
+
if (!fullImageUrl) {
|
|
495
|
+
console.warn('Image URL is empty. Original URL:', imageUrl);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
const imageElement = (
|
|
499
|
+
<div style={contentStyle}>
|
|
500
|
+
<div className="media-box" style={{ width: '100%', height: '100%', overflow: 'hidden' }}>
|
|
501
|
+
<img
|
|
502
|
+
src={fullImageUrl}
|
|
503
|
+
alt={imageAlt}
|
|
504
|
+
className="media-content"
|
|
505
|
+
style={{
|
|
506
|
+
width: '100%',
|
|
507
|
+
height: '100%',
|
|
508
|
+
objectFit: 'cover',
|
|
509
|
+
display: 'block'
|
|
510
|
+
}}
|
|
511
|
+
onError={(e) => {
|
|
512
|
+
const target = e.target as HTMLImageElement;
|
|
513
|
+
console.error('Image failed to load. URL:', fullImageUrl, 'Original:', imageUrl);
|
|
514
|
+
target.style.display = 'none';
|
|
515
|
+
}}
|
|
516
|
+
/>
|
|
454
517
|
</div>
|
|
518
|
+
</div>
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
if (linkUrl) {
|
|
522
|
+
return (
|
|
523
|
+
<a
|
|
524
|
+
href={linkUrl}
|
|
525
|
+
target={linkTarget}
|
|
526
|
+
style={{ textDecoration: 'none', color: 'inherit', display: 'contents' }}
|
|
527
|
+
>
|
|
528
|
+
{imageElement}
|
|
455
529
|
</a>
|
|
456
530
|
);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return imageElement;
|
|
457
534
|
}
|
|
458
535
|
break;
|
|
459
536
|
case 'VIDEO':
|
|
@@ -478,7 +555,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
478
555
|
// Handle both DYNAMIC and STATIC types
|
|
479
556
|
const images = tab.tabContentGroupImage.type === 'DYNAMIC'
|
|
480
557
|
? tab.tabContentGroupImage.dynamicImages
|
|
481
|
-
: tab.tabContentGroupImage.showItems;
|
|
558
|
+
: (tab.tabContentGroupImage.staticImages || tab.tabContentGroupImage.showItems);
|
|
482
559
|
|
|
483
560
|
if (!images || images.length === 0) {
|
|
484
561
|
return <div>No images available</div>;
|
|
@@ -642,6 +719,19 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
642
719
|
const displayImages = displayIndices.map(idx => images[idx]);
|
|
643
720
|
const needsCarousel = images.length > itemsPerView;
|
|
644
721
|
|
|
722
|
+
// Navigation handlers specific to this layout
|
|
723
|
+
const handleNextImage = () => {
|
|
724
|
+
if (carouselIndex < maxCarouselIndex) {
|
|
725
|
+
setCarouselIndex((prev) => Math.min(prev + 1, maxCarouselIndex));
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
const handlePrevImage = () => {
|
|
730
|
+
if (carouselIndex > 0) {
|
|
731
|
+
setCarouselIndex((prev) => Math.max(prev - 1, 0));
|
|
732
|
+
}
|
|
733
|
+
};
|
|
734
|
+
|
|
645
735
|
// Create dynamic content style for GROUPIMAGE
|
|
646
736
|
const groupImageContentStyle = {
|
|
647
737
|
display: 'grid',
|
|
@@ -653,7 +743,17 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
653
743
|
};
|
|
654
744
|
|
|
655
745
|
return (
|
|
656
|
-
<div
|
|
746
|
+
<div
|
|
747
|
+
style={{
|
|
748
|
+
position: 'relative',
|
|
749
|
+
width: '100%',
|
|
750
|
+
height: 'auto',
|
|
751
|
+
overflow: 'hidden',
|
|
752
|
+
display: 'flex',
|
|
753
|
+
alignItems: 'center',
|
|
754
|
+
justifyContent: 'center',
|
|
755
|
+
}}
|
|
756
|
+
>
|
|
657
757
|
<div style={groupImageContentStyle} className='media-box'>
|
|
658
758
|
{displayImages.map((image, displayIndex) => {
|
|
659
759
|
const originalIndex = displayIndices[displayIndex];
|
|
@@ -702,7 +802,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
702
802
|
<>
|
|
703
803
|
{/* Previous Button */}
|
|
704
804
|
<button
|
|
705
|
-
onClick={
|
|
805
|
+
onClick={handlePrevImage}
|
|
706
806
|
disabled={carouselIndex === 0}
|
|
707
807
|
style={{
|
|
708
808
|
position: 'absolute',
|
|
@@ -729,7 +829,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
729
829
|
|
|
730
830
|
{/* Next Button */}
|
|
731
831
|
<button
|
|
732
|
-
onClick={
|
|
832
|
+
onClick={handleNextImage}
|
|
733
833
|
disabled={carouselIndex >= maxCarouselIndex}
|
|
734
834
|
style={{
|
|
735
835
|
position: 'absolute',
|
|
@@ -795,7 +895,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
795
895
|
// Handle both DYNAMIC and STATIC types
|
|
796
896
|
const videos = tab.tabContentGroupVideo.type === 'DYNAMIC'
|
|
797
897
|
? tab.tabContentGroupVideo.dynamicVideos
|
|
798
|
-
: tab.tabContentGroupVideo.showItems;
|
|
898
|
+
: (tab.tabContentGroupVideo.staticVideos || tab.tabContentGroupVideo.showItems);
|
|
799
899
|
|
|
800
900
|
if (!videos || videos.length === 0) {
|
|
801
901
|
return <div>No videos available</div>;
|
|
@@ -964,6 +1064,19 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
964
1064
|
const displayVideos = displayIndices.map(idx => videos[idx]);
|
|
965
1065
|
const needsCarousel = videos.length > itemsPerView;
|
|
966
1066
|
|
|
1067
|
+
// Navigation handlers specific to this layout
|
|
1068
|
+
const handleNextVideo = () => {
|
|
1069
|
+
if (carouselIndex < maxCarouselIndex) {
|
|
1070
|
+
setCarouselIndex((prev) => Math.min(prev + 1, maxCarouselIndex));
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
|
|
1074
|
+
const handlePrevVideo = () => {
|
|
1075
|
+
if (carouselIndex > 0) {
|
|
1076
|
+
setCarouselIndex((prev) => Math.max(prev - 1, 0));
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
|
|
967
1080
|
// Create dynamic content style for GROUPVIDEO
|
|
968
1081
|
const groupVideoContentStyle = {
|
|
969
1082
|
display: 'grid',
|
|
@@ -975,7 +1088,17 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
975
1088
|
};
|
|
976
1089
|
|
|
977
1090
|
return (
|
|
978
|
-
<div
|
|
1091
|
+
<div
|
|
1092
|
+
style={{
|
|
1093
|
+
position: 'relative',
|
|
1094
|
+
width: '100%',
|
|
1095
|
+
height: 'auto',
|
|
1096
|
+
overflow: 'hidden',
|
|
1097
|
+
display: 'flex',
|
|
1098
|
+
alignItems: 'center',
|
|
1099
|
+
justifyContent: 'center',
|
|
1100
|
+
}}
|
|
1101
|
+
>
|
|
979
1102
|
<div style={groupVideoContentStyle} className='media-box'>
|
|
980
1103
|
{displayVideos.map((video, displayIndex) => {
|
|
981
1104
|
const originalIndex = displayIndices[displayIndex];
|
|
@@ -1027,7 +1150,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1027
1150
|
<>
|
|
1028
1151
|
{/* Previous Button */}
|
|
1029
1152
|
<button
|
|
1030
|
-
onClick={
|
|
1153
|
+
onClick={handlePrevVideo}
|
|
1031
1154
|
disabled={carouselIndex === 0}
|
|
1032
1155
|
style={{
|
|
1033
1156
|
position: 'absolute',
|
|
@@ -1054,7 +1177,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1054
1177
|
|
|
1055
1178
|
{/* Next Button */}
|
|
1056
1179
|
<button
|
|
1057
|
-
onClick={
|
|
1180
|
+
onClick={handleNextVideo}
|
|
1058
1181
|
disabled={carouselIndex >= maxCarouselIndex}
|
|
1059
1182
|
style={{
|
|
1060
1183
|
position: 'absolute',
|
|
@@ -1116,8 +1239,15 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1116
1239
|
break;
|
|
1117
1240
|
|
|
1118
1241
|
case 'GROUPPRODUCT':
|
|
1119
|
-
if (tab.tabContentGroupProduct
|
|
1120
|
-
|
|
1242
|
+
if (tab.tabContentGroupProduct) {
|
|
1243
|
+
// Handle both DYNAMIC and STATIC types
|
|
1244
|
+
const products = tab.tabContentGroupProduct.type === 'DYNAMIC'
|
|
1245
|
+
? tab.tabContentGroupProduct.dynamicProducts
|
|
1246
|
+
: ( tab.tabContentGroupProduct.showItems || []);
|
|
1247
|
+
|
|
1248
|
+
if (!products || products.length === 0) {
|
|
1249
|
+
return <div>No products available</div>;
|
|
1250
|
+
}
|
|
1121
1251
|
|
|
1122
1252
|
// 1x1 layout: Carousel view
|
|
1123
1253
|
if (layout === '1x1') {
|
|
@@ -1254,6 +1384,40 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1254
1384
|
const displayProducts = displayIndices.map(idx => products[idx]);
|
|
1255
1385
|
const needsCarousel = products.length > itemsPerView;
|
|
1256
1386
|
|
|
1387
|
+
// Debug logging
|
|
1388
|
+
console.log('GROUPPRODUCT Grid Layout:', {
|
|
1389
|
+
layout,
|
|
1390
|
+
totalProducts: products.length,
|
|
1391
|
+
itemsPerView,
|
|
1392
|
+
carouselIndex,
|
|
1393
|
+
maxCarouselIndex,
|
|
1394
|
+
displayIndices,
|
|
1395
|
+
needsCarousel
|
|
1396
|
+
});
|
|
1397
|
+
|
|
1398
|
+
// Navigation handlers specific to this layout
|
|
1399
|
+
const handleNextProduct = () => {
|
|
1400
|
+
console.log('Next clicked, current:', carouselIndex, 'max:', maxCarouselIndex);
|
|
1401
|
+
if (carouselIndex < maxCarouselIndex) {
|
|
1402
|
+
setCarouselIndex((prev) => {
|
|
1403
|
+
const next = Math.min(prev + 1, maxCarouselIndex);
|
|
1404
|
+
console.log('Setting carousel index to:', next);
|
|
1405
|
+
return next;
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1408
|
+
};
|
|
1409
|
+
|
|
1410
|
+
const handlePrevProduct = () => {
|
|
1411
|
+
console.log('Prev clicked, current:', carouselIndex);
|
|
1412
|
+
if (carouselIndex > 0) {
|
|
1413
|
+
setCarouselIndex((prev) => {
|
|
1414
|
+
const next = Math.max(prev - 1, 0);
|
|
1415
|
+
console.log('Setting carousel index to:', next);
|
|
1416
|
+
return next;
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
};
|
|
1420
|
+
|
|
1257
1421
|
// Create dynamic content style for GROUPPRODUCT
|
|
1258
1422
|
const groupProductContentStyle = {
|
|
1259
1423
|
display: 'grid',
|
|
@@ -1267,7 +1431,17 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1267
1431
|
};
|
|
1268
1432
|
|
|
1269
1433
|
return (
|
|
1270
|
-
<div
|
|
1434
|
+
<div
|
|
1435
|
+
style={{
|
|
1436
|
+
position: 'relative',
|
|
1437
|
+
width: '100%',
|
|
1438
|
+
height: 'auto',
|
|
1439
|
+
overflow: 'hidden',
|
|
1440
|
+
display: 'flex',
|
|
1441
|
+
alignItems: 'center',
|
|
1442
|
+
justifyContent: 'center',
|
|
1443
|
+
}}
|
|
1444
|
+
>
|
|
1271
1445
|
<div style={groupProductContentStyle}>
|
|
1272
1446
|
{displayProducts.map((product, displayIndex) => {
|
|
1273
1447
|
const originalIndex = displayIndices[displayIndex];
|
|
@@ -1294,14 +1468,18 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1294
1468
|
<>
|
|
1295
1469
|
{/* Previous Button */}
|
|
1296
1470
|
<button
|
|
1297
|
-
onClick={
|
|
1471
|
+
onClick={(e) => {
|
|
1472
|
+
e.preventDefault();
|
|
1473
|
+
e.stopPropagation();
|
|
1474
|
+
handlePrevProduct();
|
|
1475
|
+
}}
|
|
1298
1476
|
disabled={carouselIndex === 0}
|
|
1299
1477
|
style={{
|
|
1300
1478
|
position: 'absolute',
|
|
1301
1479
|
left: '10px',
|
|
1302
1480
|
top: '50%',
|
|
1303
1481
|
transform: 'translateY(-50%)',
|
|
1304
|
-
background: 'rgba(0,0,0,0.
|
|
1482
|
+
background: carouselIndex === 0 ? 'rgba(0,0,0,0.3)' : 'rgba(0,0,0,0.7)',
|
|
1305
1483
|
color: 'white',
|
|
1306
1484
|
border: 'none',
|
|
1307
1485
|
borderRadius: '50%',
|
|
@@ -1312,8 +1490,11 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1312
1490
|
display: 'flex',
|
|
1313
1491
|
alignItems: 'center',
|
|
1314
1492
|
justifyContent: 'center',
|
|
1315
|
-
fontSize: '
|
|
1316
|
-
|
|
1493
|
+
fontSize: '24px',
|
|
1494
|
+
fontWeight: 'bold',
|
|
1495
|
+
zIndex: 100,
|
|
1496
|
+
pointerEvents: 'auto',
|
|
1497
|
+
transition: 'all 0.3s ease',
|
|
1317
1498
|
}}
|
|
1318
1499
|
>
|
|
1319
1500
|
‹
|
|
@@ -1321,14 +1502,18 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1321
1502
|
|
|
1322
1503
|
{/* Next Button */}
|
|
1323
1504
|
<button
|
|
1324
|
-
onClick={
|
|
1505
|
+
onClick={(e) => {
|
|
1506
|
+
e.preventDefault();
|
|
1507
|
+
e.stopPropagation();
|
|
1508
|
+
handleNextProduct();
|
|
1509
|
+
}}
|
|
1325
1510
|
disabled={carouselIndex >= maxCarouselIndex}
|
|
1326
1511
|
style={{
|
|
1327
1512
|
position: 'absolute',
|
|
1328
1513
|
right: '10px',
|
|
1329
1514
|
top: '50%',
|
|
1330
1515
|
transform: 'translateY(-50%)',
|
|
1331
|
-
background: 'rgba(0,0,0,0.
|
|
1516
|
+
background: carouselIndex >= maxCarouselIndex ? 'rgba(0,0,0,0.3)' : 'rgba(0,0,0,0.7)',
|
|
1332
1517
|
color: 'white',
|
|
1333
1518
|
border: 'none',
|
|
1334
1519
|
borderRadius: '50%',
|
|
@@ -1339,8 +1524,11 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1339
1524
|
display: 'flex',
|
|
1340
1525
|
alignItems: 'center',
|
|
1341
1526
|
justifyContent: 'center',
|
|
1342
|
-
fontSize: '
|
|
1343
|
-
|
|
1527
|
+
fontSize: '24px',
|
|
1528
|
+
fontWeight: 'bold',
|
|
1529
|
+
zIndex: 100,
|
|
1530
|
+
pointerEvents: 'auto',
|
|
1531
|
+
transition: 'all 0.3s ease',
|
|
1344
1532
|
}}
|
|
1345
1533
|
>
|
|
1346
1534
|
›
|
|
@@ -1355,21 +1543,27 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1355
1543
|
transform: 'translateX(-50%)',
|
|
1356
1544
|
display: 'flex',
|
|
1357
1545
|
gap: '8px',
|
|
1358
|
-
zIndex:
|
|
1546
|
+
zIndex: 100,
|
|
1547
|
+
pointerEvents: 'auto',
|
|
1359
1548
|
}}
|
|
1360
1549
|
>
|
|
1361
1550
|
{Array.from({ length: maxCarouselIndex + 1 }, (_, index) => (
|
|
1362
1551
|
<button
|
|
1363
1552
|
key={index}
|
|
1364
|
-
onClick={() =>
|
|
1553
|
+
onClick={(e) => {
|
|
1554
|
+
e.preventDefault();
|
|
1555
|
+
e.stopPropagation();
|
|
1556
|
+
goToCarouselItem(index);
|
|
1557
|
+
}}
|
|
1365
1558
|
style={{
|
|
1366
1559
|
width: index === carouselIndex ? '12px' : '8px',
|
|
1367
1560
|
height: index === carouselIndex ? '12px' : '8px',
|
|
1368
1561
|
borderRadius: '50%',
|
|
1369
|
-
border: '
|
|
1370
|
-
background: index === carouselIndex ? 'white' : 'rgba(255,255,255,0.
|
|
1562
|
+
border: '2px solid white',
|
|
1563
|
+
background: index === carouselIndex ? 'white' : 'rgba(255,255,255,0.6)',
|
|
1371
1564
|
cursor: 'pointer',
|
|
1372
1565
|
transition: 'all 0.3s ease',
|
|
1566
|
+
pointerEvents: 'auto',
|
|
1373
1567
|
}}
|
|
1374
1568
|
/>
|
|
1375
1569
|
))}
|
|
@@ -1398,7 +1592,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1398
1592
|
return null;
|
|
1399
1593
|
};
|
|
1400
1594
|
|
|
1401
|
-
const tabs = props.tabs
|
|
1595
|
+
const tabs = props.tabs || [];
|
|
1402
1596
|
|
|
1403
1597
|
return (
|
|
1404
1598
|
<div style={{
|