tee3apps-cms-sdk-react 0.0.15 → 0.0.17
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 +616 -534
- package/src/PageComponents/Visual-Components/Styles/ProductListViewOne.tsx +162 -101
- package/src/PageComponents/Visual-Components/Styles/ProductListViewTwo.tsx +164 -103
- package/src/PageComponents/Visual-Components/TabComponent.tsx +132 -48
|
@@ -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>;
|
|
@@ -818,7 +895,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
818
895
|
// Handle both DYNAMIC and STATIC types
|
|
819
896
|
const videos = tab.tabContentGroupVideo.type === 'DYNAMIC'
|
|
820
897
|
? tab.tabContentGroupVideo.dynamicVideos
|
|
821
|
-
: tab.tabContentGroupVideo.showItems;
|
|
898
|
+
: (tab.tabContentGroupVideo.staticVideos || tab.tabContentGroupVideo.showItems);
|
|
822
899
|
|
|
823
900
|
if (!videos || videos.length === 0) {
|
|
824
901
|
return <div>No videos available</div>;
|
|
@@ -1162,8 +1239,15 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1162
1239
|
break;
|
|
1163
1240
|
|
|
1164
1241
|
case 'GROUPPRODUCT':
|
|
1165
|
-
if (tab.tabContentGroupProduct
|
|
1166
|
-
|
|
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
|
+
}
|
|
1167
1251
|
|
|
1168
1252
|
// 1x1 layout: Carousel view
|
|
1169
1253
|
if (layout === '1x1') {
|
|
@@ -1508,7 +1592,7 @@ const TabComponent: React.FC<TabComponentMainProps> = ({ props, deviceMode = 'we
|
|
|
1508
1592
|
return null;
|
|
1509
1593
|
};
|
|
1510
1594
|
|
|
1511
|
-
const tabs = props.tabs
|
|
1595
|
+
const tabs = props.tabs || [];
|
|
1512
1596
|
|
|
1513
1597
|
return (
|
|
1514
1598
|
<div style={{
|