tee3apps-cms-sdk-react 0.0.16 → 0.0.18

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.
@@ -1,617 +1,609 @@
1
- import React from 'react';
2
- import ProductListViewOne from '../Visual-Components/Styles/ProductListViewOne';
3
- import ProductListViewTwo from '../Visual-Components/Styles/ProductListViewTwo';
4
- import { Linodeurl } from '../../const';
5
-
6
- // Utility function to extract price value from different formats
7
- const getPriceValue = (price: any): number => {
8
- if (price === null || price === undefined) return 0;
9
-
10
- // If it's already a number
11
- if (typeof price === 'number') {
12
- return isNaN(price) ? 0 : price;
13
- }
14
-
15
- // If it's an object with $numberDecimal (but not an array)
16
- if (typeof price === 'object' && price !== null && !Array.isArray(price)) {
17
- if (price.$numberDecimal !== undefined && price.$numberDecimal !== null) {
18
- const value = parseFloat(String(price.$numberDecimal));
19
- return isNaN(value) ? 0 : value;
20
- }
21
- }
22
-
23
- // If it's a string, try to parse it
24
- if (typeof price === 'string') {
25
- const value = parseFloat(price);
26
- return isNaN(value) ? 0 : value;
27
- }
28
-
29
- return 0;
30
- };
31
-
32
- // Utility function to get price from pricing array (mrp, costPrice, nlcPrice)
33
- const getPriceFromPricingArray = (pricingArray: any[]): number => {
34
- if (!Array.isArray(pricingArray) || pricingArray.length === 0) return 0;
35
-
36
- // First, try to find the default price with default currency
37
- const defaultPrice = pricingArray.find(
38
- (item: any) => item.isDefault === true && item.isDefaultCurrency === true
39
- );
40
-
41
- if (defaultPrice && defaultPrice.price) {
42
- return getPriceValue(defaultPrice.price);
43
- }
44
-
45
- // Fallback: find any default price
46
- const anyDefault = pricingArray.find((item: any) => item.isDefault === true);
47
- if (anyDefault && anyDefault.price) {
48
- return getPriceValue(anyDefault.price);
49
- }
50
-
51
- // Fallback: use first item
52
- if (pricingArray[0] && pricingArray[0].price) {
53
- return getPriceValue(pricingArray[0].price);
54
- }
55
-
56
- return 0;
57
- };
58
-
59
- // Utility function to get MRP and Selling Price from product pricing object
60
- const getProductPrices = (product: any) => {
61
- // Use pricing object first, fallback to price for backward compatibility
62
- const mrp = product.pricing?.mrp ? getPriceFromPricingArray(product.pricing.mrp) : 0;
63
- const sellingPrice = product.pricing?.nlcPrice
64
- ? getPriceFromPricingArray(product.pricing.nlcPrice)
65
- : product.pricing?.costPrice
66
- ? getPriceFromPricingArray(product.pricing.costPrice)
67
- : 0;
68
-
69
- // Fallback to old price structure if pricing is not available
70
- const fallbackMRP = product.price?.MRP
71
- ? getPriceValue(product.price.MRP)
72
- : 0;
73
- const fallbackSP = product.price?.SP
74
- ? getPriceValue(product.price.SP)
75
- : 0;
76
-
77
- return {
78
- mrp: mrp || fallbackMRP,
79
- sellingPrice: sellingPrice || fallbackSP
80
- };
81
- };
82
-
83
-
84
- interface Product {
85
- _id: string;
86
- code: string;
87
- name: string | { all: string };
88
- image: any;
89
- isActive: boolean;
90
- price?:any;
91
- }
92
-
93
- interface GroupProductStatic {
94
- _id: string;
95
- code: string;
96
- name: string;
97
- }
98
-
99
- interface GroupProductDynamic {
100
- code: string;
101
- name: { all: string };
102
- list: Product[];
103
- isActive: boolean;
104
- }
105
-
106
- interface GroupProductData {
107
- static: GroupProductStatic;
108
- dynamic: GroupProductDynamic;
109
- showItems:Product[]
110
-
111
- }
112
-
113
- interface HeaderTextStyle {
114
- fontSize: number;
115
- fontColor: string;
116
- isBold: boolean;
117
- isItalic: boolean;
118
- isUnderline: boolean;
119
- }
120
-
121
- interface DeviceBooleanProps {
122
- web: boolean;
123
- mobileweb: boolean;
124
- mobileapp: boolean;
125
- tablet: boolean;
126
- }
127
-
128
- interface DeviceLayoutProps {
129
- web: string;
130
- mobileweb: string;
131
- mobileapp: string;
132
- tablet: string;
133
- }
134
-
135
- export interface GroupProductComponentProps {
136
- headerText: { all: string };
137
- type: string;
138
- groupproduct: GroupProductData;
139
- showItems:Product[]
140
- activeStatus: boolean;
141
- headerImage: string;
142
- selectedProducts: Product[];
143
- items: any[];
144
-
145
- cardColor: string;
146
- showProductName: DeviceBooleanProps;
147
- headerTextStyle: HeaderTextStyle;
148
- layout: DeviceLayoutProps;
149
- style: DeviceLayoutProps;
150
-
151
- showHeader: DeviceBooleanProps;
152
- isHorizontalScroll: DeviceBooleanProps;
153
- headerBackground: string;
154
- viewAllLink?: string;
155
- }
156
-
157
- interface GroupProductComponentMainProps {
158
- props: GroupProductComponentProps;
159
- deviceMode?: string;
160
- }
161
-
162
- const GroupProductComponent: React.FC<GroupProductComponentMainProps> = ({
163
- props,
164
- deviceMode = 'web'
165
- }) => {
166
- const getCurrentBooleanProp = (prop: DeviceBooleanProps) => {
167
- switch(deviceMode) {
168
- case 'mobileweb': return prop.mobileweb;
169
- case 'mobileapp': return prop.mobileapp;
170
- case 'tablet': return prop.tablet;
171
- case 'web':
172
- default: return prop.web;
173
- }
174
- };
175
-
176
- const getCurrentLayout = () => {
177
- switch(deviceMode) {
178
- case 'mobileweb': return props.layout.mobileweb;
179
- case 'mobileapp': return props.layout.mobileapp;
180
- case 'tablet': return props.layout.tablet;
181
- case 'web':
182
- default: return props.layout.web;
183
- }
184
- };
185
-
186
- const getCurrentStyle = () => {
187
- switch(deviceMode) {
188
- case 'mobileweb': return props.style.mobileweb;
189
- case 'mobileapp': return props.style.mobileapp;
190
- case 'tablet': return props.style.tablet;
191
- case 'web':
192
- default: return props.style.web;
193
- }
194
- };
195
- const showHeader = getCurrentBooleanProp(props.showHeader);
196
- const showProductName = getCurrentBooleanProp(props.showProductName);
197
- const isHorizontalScroll = getCurrentBooleanProp(props.isHorizontalScroll);
198
- const currentLayout = getCurrentLayout();
199
- const currentstyle=getCurrentStyle();
200
-
201
- const getProducts = () => {
202
- if(props?.groupproduct?.showItems) return props.groupproduct.showItems
203
- return [];
204
- };
205
-
206
- const products = getProducts();
207
-
208
- // Helper function to render product based on style
209
- const renderProduct = (product: Product, key: string) => {
210
- if (currentstyle === 'STYLE1') {
211
- return (
212
- <div key={key}>
213
- <ProductListViewOne props={product} />
214
- </div>
215
- );
216
- } else if (currentstyle === 'STYLE2') {
217
- return (
218
- <div key={key}>
219
- <ProductListViewTwo props={product} />
220
- </div>
221
- );
222
- } else {
223
- // Default style (NONE) - inline JSX
224
- return (
225
- <a href={`/${product.code}`} target={'_blank'} rel="noopener noreferrer" style={{textDecoration:"none"}} key={key}>
226
- <div
227
- className="productImageSlide"
228
- style={{
229
- height: 'auto',
230
- minWidth: deviceMode === 'mobileapp' || deviceMode === 'mobileweb' ? '120px' : '150px',
231
- borderRadius: '8px',
232
- overflow: 'hidden',
233
- border: '1px solid #eee',
234
- backgroundColor: '#fff',
235
- display: 'flex',
236
- flexDirection: 'column',
237
- alignItems: 'center',
238
- justifyContent: 'center',
239
- padding: '12px',
240
- boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
241
- transition: 'transform 0.2s ease',
242
- cursor: 'pointer',
243
- }}
244
- onMouseOver={(e) => {
245
- e.currentTarget.style.transform = 'translateY(-2px)';
246
- e.currentTarget.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
247
- }}
248
- onMouseOut={(e) => {
249
- e.currentTarget.style.transform = 'translateY(0)';
250
- e.currentTarget.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
251
- }}
252
- >
253
- <div
254
- style={{
255
- height: '120px',
256
- width: '100%',
257
- display: 'flex',
258
- alignItems: 'center',
259
- justifyContent: 'center',
260
- marginBottom: '8px',
261
- }}
262
- >
263
- <img
264
- src={`${Linodeurl}${product.image?.url}`}
265
- alt={typeof product.name === 'object' ? product.name.all : product.name}
266
- style={{ width: '100%', height: '100%', objectFit: 'contain' }}
267
- />
268
- </div>
269
-
270
- {showProductName && (
271
- <div
272
- style={{
273
- marginTop: '8px',
274
- textAlign: 'center',
275
- fontSize: '14px',
276
- fontWeight: '500',
277
- color: '#333',
278
- lineHeight: '1.4',
279
- height: '40px',
280
- overflow: 'hidden',
281
- display: '-webkit-box',
282
- WebkitLineClamp: 2,
283
- WebkitBoxOrient: 'vertical',
284
- }}
285
- >
286
- {typeof product.name === 'object' ? product.name.all : product.name}
287
- {(() => {
288
- const prices = getProductPrices(product);
289
- return prices.sellingPrice > 0 ? (
290
- <h1 style={{ fontSize: '16px', fontWeight: '700', color: '#333' }}>
291
- ₹{prices.sellingPrice.toLocaleString("en-IN")}
292
- </h1>
293
- ) : null;
294
- })()}
295
- </div>
296
- )}
297
- </div>
298
- </a>
299
- );
300
- }
301
- };
302
-
303
- // Helper function to render product card (for grid layouts)
304
- const renderProductCard = (product: Product, key: string, imageHeight: string = '120px', fontSize: string = '14px', nameHeight: string = '40px', fontWeight: string = '500') => {
305
- if (currentstyle === 'STYLE1') {
306
- return (
307
- <div key={key}>
308
- <ProductListViewOne props={product} />
309
- </div>
310
- );
311
- } else if (currentstyle === 'STYLE2') {
312
- return (
313
- <div key={key}>
314
- <ProductListViewTwo props={product} />
315
- </div>
316
- );
317
- } else {
318
- // Default style (NONE) - inline JSX
319
- return (
320
- <div
321
- key={key}
322
- className="productImageSlide"
323
- style={{
324
- height: 'auto',
325
- borderRadius: '8px',
326
- overflow: 'hidden',
327
- border: '1px solid #eee',
328
- backgroundColor: '#fff',
329
- display: 'flex',
330
- flexDirection: 'column',
331
- alignItems: 'center',
332
- justifyContent: 'center',
333
- padding: '12px',
334
- boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
335
- transition: 'transform 0.2s ease',
336
- cursor: 'pointer'
337
- }}
338
- onMouseOver={(e) => {
339
- e.currentTarget.style.transform = 'translateY(-2px)';
340
- e.currentTarget.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
341
- }}
342
- onMouseOut={(e) => {
343
- e.currentTarget.style.transform = 'translateY(0)';
344
- e.currentTarget.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
345
- }}
346
- >
347
- <div style={{
348
- height: imageHeight,
349
- width: '100%',
350
- display: 'flex',
351
- alignItems: 'center',
352
- justifyContent: 'center',
353
- marginBottom: '8px'
354
- }}>
355
- <img
356
- src={`${Linodeurl}${product.image?.all?.url || product.image?.url}`}
357
- alt=""
358
- style={{ width: '100%', height: '100%', objectFit: 'contain' }}
359
- />
360
- </div>
361
- {showProductName && <div style={{
362
- textAlign: 'center',
363
- fontSize: fontSize,
364
- fontWeight: fontWeight,
365
- color: '#333',
366
- lineHeight: '1.4',
367
- ...(nameHeight === 'auto' ? {} : {
368
- height: nameHeight,
369
- overflow: 'hidden',
370
- display: '-webkit-box',
371
- WebkitLineClamp: 2,
372
- WebkitBoxOrient: 'vertical'
373
- })
374
- }}>
375
- {typeof product.name === 'object' ? (product.name as { all: string }).all : product.name}
376
- </div>}
377
- </div>
378
- );
379
- }
380
- };
381
-
382
- // Carousel navigation functions
383
- const scrollLeft = () => {
384
- const carousel = document.querySelector('.groupProductCarousel');
385
- if (carousel) {
386
- carousel.scrollBy({ left: -200, behavior: 'smooth' });
387
- }
388
- };
389
-
390
- const scrollRight = () => {
391
- const carousel = document.querySelector('.groupProductCarousel');
392
- if (carousel) {
393
- carousel.scrollBy({ left: 200, behavior: 'smooth' });
394
- }
395
- };
396
-
397
- return (
398
- <div
399
- style={{
400
- border: '1px solid #e1e1e1',
401
- width: '100%',
402
- maxWidth: '100%',
403
- borderRadius: '0px',
404
- minHeight: '100px',
405
- position: 'relative',
406
- overflow: 'hidden',
407
- marginBottom:'20px',
408
- marginTop:'0px'
409
-
410
- }}
411
- className='GroupProductComponent'
412
- >
413
- {showHeader && (
414
- <div
415
- className="groupProductHeader"
416
- style={{
417
- backgroundColor: props.headerBackground,
418
- padding: '12px 16px',
419
- borderRadius: '0px',
420
- marginBottom: '4px',
421
- display: 'flex',
422
- alignItems: 'center',
423
- justifyContent: 'space-between',
424
- flexWrap: 'wrap',
425
- gap: '12px',
426
- }}
427
- >
428
- <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
429
- {props.headerImage && (
430
- <div style={{ width: '32px', height: '32px' }}>
431
- {/* <ImageDisplayComponent
432
- fileUrl={props.headerImage}
433
- preserveAspectRatio={true}
434
- maxWidth="100%"
435
- maxHeight="32px"
436
- /> */}
437
- <img
438
- src={`${Linodeurl}${props.headerImage}`}
439
- style={{ width: '100%', height: '100%', objectFit: 'cover' }}
440
- />
441
- </div>
442
- )}
443
- <p style={{
444
- color: props.headerTextStyle.fontColor,
445
- fontSize: `${props.headerTextStyle.fontSize}px`,
446
- fontWeight: props.headerTextStyle.isBold ? 'bold' : 'normal',
447
- fontStyle: props.headerTextStyle.isItalic ? 'italic' : 'normal',
448
- textDecoration: props.headerTextStyle.isUnderline ? 'underline' : 'none',
449
- margin: 0
450
- }}>
451
- {props.headerText?.all || 'Header text'}
452
- </p>
453
- </div>
454
-
455
- <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
456
-
457
- {props.type=='static' && (
458
- <a
459
- href={`http://localhost:5173/${props.groupproduct.static.code}/s?type=groupproduct`}
460
- target="_blank"
461
- rel="noopener noreferrer"
462
- style={{
463
- color: 'black',
464
- textDecoration: 'none',
465
- fontWeight: '500',
466
- fontSize: '14px',
467
- padding: '6px 12px',
468
- border: 'none',
469
- borderRadius: '4px',
470
- backgroundColor: 'transparent',
471
- cursor: 'pointer'
472
- }}
473
- >
474
- View All
475
- </a>
476
- )}
477
-
478
-
479
-
480
-
481
- {currentLayout === 'NONE' && products.length > 4 && (
482
- <div style={{ display: 'flex', gap: '8px' }}>
483
- <button
484
- onClick={scrollLeft}
485
- style={{
486
- width: '32px',
487
- height: '32px',
488
- borderRadius: '50%',
489
- border: '1px solid #ddd',
490
- backgroundColor: '#fff',
491
- cursor: 'pointer',
492
- display: 'flex',
493
- alignItems: 'center',
494
- justifyContent: 'center',
495
- fontSize: '16px',
496
- fontWeight: 'bold'
497
- }}
498
- onMouseOver={(e) => {
499
- e.currentTarget.style.backgroundColor = '#f8f9fa';
500
- }}
501
- onMouseOut={(e) => {
502
- e.currentTarget.style.backgroundColor = '#fff';
503
- }}
504
- >
505
- &#8249;
506
- </button>
507
- <button
508
- onClick={scrollRight}
509
- style={{
510
- width: '32px',
511
- height: '32px',
512
- borderRadius: '50%',
513
- border: '1px solid #ddd',
514
- backgroundColor: '#fff',
515
- cursor: 'pointer',
516
- display: 'flex',
517
- alignItems: 'center',
518
- justifyContent: 'center',
519
- fontSize: '16px',
520
- fontWeight: 'bold'
521
- }}
522
- onMouseOver={(e) => {
523
- e.currentTarget.style.backgroundColor = '#f8f9fa';
524
- }}
525
- onMouseOut={(e) => {
526
- e.currentTarget.style.backgroundColor = '#fff';
527
- }}
528
- >
529
- &#8250;
530
- </button>
531
- </div>
532
- )}
533
- </div>
534
- </div>
535
- )}
536
-
537
- <div
538
- className="groupProductCarousel"
539
- style={{
540
- display: currentLayout === 'NONE' ? 'flex' : 'block',
541
- overflowX: currentLayout === 'NONE' && isHorizontalScroll ? 'auto' : 'visible',
542
- gap: currentLayout === 'NONE' ? '12px' : '0',
543
- padding: '12px',
544
- scrollBehavior: 'smooth',
545
- backgroundColor: props.cardColor || '#fff',
546
- scrollbarWidth: 'thin',
547
- borderRadius: '8px',
548
- position: 'relative',
549
- scrollbarColor: '#c1c1c1 transparent'
550
- }}
551
- >
552
- {products.length > 0 ? (
553
- currentLayout === 'NONE' ? (
554
- products.slice(0, props.type === 'static' ? 15 : products.length).map((product) =>
555
- renderProduct(product, product._id)
556
- )
557
- ) : currentLayout === 'SMALL' ? (
558
- <div style={{
559
- display: 'grid',
560
- gridTemplateColumns: 'repeat(2, 1fr)',
561
- gap: '16px',
562
- padding: '8px'
563
- }}>
564
- {
565
- products.map((product) =>
566
- renderProductCard(product, product._id, '100px', '12px', '32px')
567
- )}
568
- </div>
569
- ) : currentLayout === 'MEDIUM' ? (
570
- <div style={{
571
- display: 'grid',
572
- gridTemplateColumns: 'repeat(3, 1fr)',
573
- gap: '16px',
574
- padding: '8px'
575
- }}>
576
- {
577
- products.map((product) =>
578
- renderProductCard(product, product._id, '120px', '14px', '40px')
579
- )}
580
- </div>
581
- ) : currentLayout === 'MEDIUM_THREE' ? (
582
- <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '8px' }}>
583
- {products.length > 0 && (
584
- renderProductCard(products[0], products[0]._id, '160px', '16px', 'auto', '600')
585
- )}
586
- {products.length > 1 && (
587
- <div style={{
588
- display: 'grid',
589
- gridTemplateColumns: 'repeat(2,1fr)',
590
- gap: '16px'
591
- }}>
592
- {products.slice(1).map((product) =>
593
- renderProductCard(product, product._id, '100px', '12px', '32px', '500')
594
- )}
595
- </div>
596
- )}
597
- </div>
598
- ) : null
599
- ) : (
600
- <div style={{
601
- textAlign: 'center',
602
- color: '#666',
603
- padding: '40px',
604
- width: '100%',
605
- border: '2px dashed #ddd',
606
- borderRadius: '8px',
607
- backgroundColor: '#f9f9f9'
608
- }}>
609
- <p>No products selected. Use settings to add products.</p>
610
- </div>
611
- )}
612
- </div>
613
- </div>
614
- );
615
- };
616
-
1
+ import React from 'react';
2
+ import ProductListViewOne from '../Visual-Components/Styles/ProductListViewOne';
3
+ import ProductListViewTwo from '../Visual-Components/Styles/ProductListViewTwo';
4
+ import { Linodeurl } from '../../const';
5
+
6
+ // Utility function to extract price value from different formats
7
+ const getPriceValue = (price: any): number => {
8
+ if (price === null || price === undefined) return 0;
9
+
10
+ // If it's already a number
11
+ if (typeof price === 'number') {
12
+ return isNaN(price) ? 0 : price;
13
+ }
14
+
15
+ // If it's an object with $numberDecimal (but not an array)
16
+ if (typeof price === 'object' && price !== null && !Array.isArray(price)) {
17
+ if (price.$numberDecimal !== undefined && price.$numberDecimal !== null) {
18
+ const value = parseFloat(String(price.$numberDecimal));
19
+ return isNaN(value) ? 0 : value;
20
+ }
21
+ }
22
+
23
+ // If it's a string, try to parse it
24
+ if (typeof price === 'string') {
25
+ const value = parseFloat(price);
26
+ return isNaN(value) ? 0 : value;
27
+ }
28
+
29
+ return 0;
30
+ };
31
+
32
+ // Utility function to get price from pricing array (mrp, costPrice, nlcPrice)
33
+ const getPriceFromPricingArray = (pricingArray: any[]): number => {
34
+ if (!Array.isArray(pricingArray) || pricingArray.length === 0) return 0;
35
+
36
+ // First, try to find the default price with default currency
37
+ const defaultPrice = pricingArray.find(
38
+ (item: any) => item.isDefault === true && item.isDefaultCurrency === true
39
+ );
40
+
41
+ if (defaultPrice && defaultPrice.price) {
42
+ return getPriceValue(defaultPrice.price);
43
+ }
44
+
45
+ // Fallback: find any default price
46
+ const anyDefault = pricingArray.find((item: any) => item.isDefault === true);
47
+ if (anyDefault && anyDefault.price) {
48
+ return getPriceValue(anyDefault.price);
49
+ }
50
+
51
+ // Fallback: use first item
52
+ if (pricingArray[0] && pricingArray[0].price) {
53
+ return getPriceValue(pricingArray[0].price);
54
+ }
55
+
56
+ return 0;
57
+ };
58
+
59
+ // Utility function to get MRP and Selling Price from product pricing object
60
+ const getProductPrices = (product: any) => {
61
+ // Use pricing object only
62
+ const mrp = product.pricing?.mrp ? getPriceFromPricingArray(product.pricing.mrp) : 0;
63
+ const sellingPrice = product.pricing?.nlcPrice
64
+ ? getPriceFromPricingArray(product.pricing.nlcPrice)
65
+ : product.pricing?.costPrice
66
+ ? getPriceFromPricingArray(product.pricing.costPrice)
67
+ : 0;
68
+
69
+ return {
70
+ mrp,
71
+ sellingPrice
72
+ };
73
+ };
74
+
75
+
76
+ interface Product {
77
+ _id: string;
78
+ code: string;
79
+ name: string | { all: string };
80
+ image: any;
81
+ isActive: boolean;
82
+ price?:any;
83
+ }
84
+
85
+ interface GroupProductStatic {
86
+ _id: string;
87
+ code: string;
88
+ name: string;
89
+ }
90
+
91
+ interface GroupProductDynamic {
92
+ code: string;
93
+ name: { all: string };
94
+ list: Product[];
95
+ isActive: boolean;
96
+ }
97
+
98
+ interface GroupProductData {
99
+ static: GroupProductStatic;
100
+ dynamic: GroupProductDynamic;
101
+ showItems:Product[]
102
+
103
+ }
104
+
105
+ interface HeaderTextStyle {
106
+ fontSize: number;
107
+ fontColor: string;
108
+ isBold: boolean;
109
+ isItalic: boolean;
110
+ isUnderline: boolean;
111
+ }
112
+
113
+ interface DeviceBooleanProps {
114
+ web: boolean;
115
+ mobileweb: boolean;
116
+ mobileapp: boolean;
117
+ tablet: boolean;
118
+ }
119
+
120
+ interface DeviceLayoutProps {
121
+ web: string;
122
+ mobileweb: string;
123
+ mobileapp: string;
124
+ tablet: string;
125
+ }
126
+
127
+ export interface GroupProductComponentProps {
128
+ headerText: any;
129
+ type: string;
130
+ groupproduct: GroupProductData;
131
+ showItems:Product[]
132
+ activeStatus: boolean;
133
+ headerImage: string;
134
+ selectedProducts: Product[];
135
+ items: any[];
136
+
137
+ cardColor: string;
138
+ showProductName: DeviceBooleanProps;
139
+ headerTextStyle: HeaderTextStyle;
140
+ layout: DeviceLayoutProps;
141
+ style: DeviceLayoutProps;
142
+
143
+ showHeader: DeviceBooleanProps;
144
+ isHorizontalScroll: DeviceBooleanProps;
145
+ headerBackground: string;
146
+ viewAllLink?: string;
147
+ }
148
+
149
+ interface GroupProductComponentMainProps {
150
+ props: GroupProductComponentProps;
151
+ deviceMode?: string;
152
+ }
153
+
154
+ const GroupProductComponent: React.FC<GroupProductComponentMainProps> = ({
155
+ props,
156
+ deviceMode = 'web'
157
+ }) => {
158
+ const getCurrentBooleanProp = (prop: DeviceBooleanProps) => {
159
+ switch(deviceMode) {
160
+ case 'mobileweb': return prop.mobileweb;
161
+ case 'mobileapp': return prop.mobileapp;
162
+ case 'tablet': return prop.tablet;
163
+ case 'web':
164
+ default: return prop.web;
165
+ }
166
+ };
167
+
168
+ const getCurrentLayout = () => {
169
+ switch(deviceMode) {
170
+ case 'mobileweb': return props.layout.mobileweb;
171
+ case 'mobileapp': return props.layout.mobileapp;
172
+ case 'tablet': return props.layout.tablet;
173
+ case 'web':
174
+ default: return props.layout.web;
175
+ }
176
+ };
177
+
178
+ const getCurrentStyle = () => {
179
+ switch(deviceMode) {
180
+ case 'mobileweb': return props.style.mobileweb;
181
+ case 'mobileapp': return props.style.mobileapp;
182
+ case 'tablet': return props.style.tablet;
183
+ case 'web':
184
+ default: return props.style.web;
185
+ }
186
+ };
187
+ const showHeader = getCurrentBooleanProp(props.showHeader);
188
+ const showProductName = getCurrentBooleanProp(props.showProductName);
189
+ const isHorizontalScroll = getCurrentBooleanProp(props.isHorizontalScroll);
190
+ const currentLayout = getCurrentLayout();
191
+ const currentstyle=getCurrentStyle();
192
+
193
+ const getProducts = () => {
194
+ if(props?.groupproduct?.showItems) return props.groupproduct.showItems
195
+ return [];
196
+ };
197
+
198
+ const products = getProducts();
199
+
200
+ // Helper function to render product based on style
201
+ const renderProduct = (product: Product, key: string) => {
202
+ if (currentstyle === 'STYLE1') {
203
+ return (
204
+ <div key={key}>
205
+ <ProductListViewOne props={product} />
206
+ </div>
207
+ );
208
+ } else if (currentstyle === 'STYLE2') {
209
+ return (
210
+ <div key={key}>
211
+ <ProductListViewTwo props={product} />
212
+ </div>
213
+ );
214
+ } else {
215
+ // Default style (NONE) - inline JSX
216
+ return (
217
+ <a href={`/${product.code}`} target={'_blank'} rel="noopener noreferrer" style={{textDecoration:"none"}} key={key}>
218
+ <div
219
+ className="productImageSlide"
220
+ style={{
221
+ height: 'auto',
222
+ minWidth: deviceMode === 'mobileapp' || deviceMode === 'mobileweb' ? '120px' : '150px',
223
+ borderRadius: '8px',
224
+ overflow: 'hidden',
225
+ border: '1px solid #eee',
226
+ backgroundColor: '#fff',
227
+ display: 'flex',
228
+ flexDirection: 'column',
229
+ alignItems: 'center',
230
+ justifyContent: 'center',
231
+ padding: '12px',
232
+ boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
233
+ transition: 'transform 0.2s ease',
234
+ cursor: 'pointer',
235
+ }}
236
+ onMouseOver={(e) => {
237
+ e.currentTarget.style.transform = 'translateY(-2px)';
238
+ e.currentTarget.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
239
+ }}
240
+ onMouseOut={(e) => {
241
+ e.currentTarget.style.transform = 'translateY(0)';
242
+ e.currentTarget.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
243
+ }}
244
+ >
245
+ <div
246
+ style={{
247
+ height: '120px',
248
+ width: '100%',
249
+ display: 'flex',
250
+ alignItems: 'center',
251
+ justifyContent: 'center',
252
+ marginBottom: '8px',
253
+ }}
254
+ >
255
+ <img
256
+ src={`${Linodeurl}${product.image?.url}`}
257
+ alt={typeof product.name === 'object' ? product.name.all : product.name}
258
+ style={{ width: '100%', height: '100%', objectFit: 'contain' }}
259
+ />
260
+ </div>
261
+
262
+ {showProductName && (
263
+ <div
264
+ style={{
265
+ marginTop: '8px',
266
+ textAlign: 'center',
267
+ fontSize: '14px',
268
+ fontWeight: '500',
269
+ color: '#333',
270
+ lineHeight: '1.4',
271
+ height: '40px',
272
+ overflow: 'hidden',
273
+ display: '-webkit-box',
274
+ WebkitLineClamp: 2,
275
+ WebkitBoxOrient: 'vertical',
276
+ }}
277
+ >
278
+ {typeof product.name === 'object' ? product.name.all : product.name}
279
+ {(() => {
280
+ const prices = getProductPrices(product);
281
+ return prices.sellingPrice > 0 ? (
282
+ <h1 style={{ fontSize: '16px', fontWeight: '700', color: '#333' }}>
283
+ {prices.sellingPrice.toLocaleString("en-IN")}
284
+ </h1>
285
+ ) : null;
286
+ })()}
287
+ </div>
288
+ )}
289
+ </div>
290
+ </a>
291
+ );
292
+ }
293
+ };
294
+
295
+ // Helper function to render product card (for grid layouts)
296
+ const renderProductCard = (product: Product, key: string, imageHeight: string = '120px', fontSize: string = '14px', nameHeight: string = '40px', fontWeight: string = '500') => {
297
+ if (currentstyle === 'STYLE1') {
298
+ return (
299
+ <div key={key}>
300
+ <ProductListViewOne props={product} />
301
+ </div>
302
+ );
303
+ } else if (currentstyle === 'STYLE2') {
304
+ return (
305
+ <div key={key}>
306
+ <ProductListViewTwo props={product} />
307
+ </div>
308
+ );
309
+ } else {
310
+ // Default style (NONE) - inline JSX
311
+ return (
312
+ <div
313
+ key={key}
314
+ className="productImageSlide"
315
+ style={{
316
+ height: 'auto',
317
+ borderRadius: '8px',
318
+ overflow: 'hidden',
319
+ border: '1px solid #eee',
320
+ backgroundColor: '#fff',
321
+ display: 'flex',
322
+ flexDirection: 'column',
323
+ alignItems: 'center',
324
+ justifyContent: 'center',
325
+ padding: '12px',
326
+ boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
327
+ transition: 'transform 0.2s ease',
328
+ cursor: 'pointer'
329
+ }}
330
+ onMouseOver={(e) => {
331
+ e.currentTarget.style.transform = 'translateY(-2px)';
332
+ e.currentTarget.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
333
+ }}
334
+ onMouseOut={(e) => {
335
+ e.currentTarget.style.transform = 'translateY(0)';
336
+ e.currentTarget.style.boxShadow = '0 2px 4px rgba(0,0,0,0.1)';
337
+ }}
338
+ >
339
+ <div style={{
340
+ height: imageHeight,
341
+ width: '100%',
342
+ display: 'flex',
343
+ alignItems: 'center',
344
+ justifyContent: 'center',
345
+ marginBottom: '8px'
346
+ }}>
347
+ <img
348
+ src={`${Linodeurl}${product.image?.all?.url || product.image?.url}`}
349
+ alt=""
350
+ style={{ width: '100%', height: '100%', objectFit: 'contain' }}
351
+ />
352
+ </div>
353
+ {showProductName && <div style={{
354
+ textAlign: 'center',
355
+ fontSize: fontSize,
356
+ fontWeight: fontWeight,
357
+ color: '#333',
358
+ lineHeight: '1.4',
359
+ ...(nameHeight === 'auto' ? {} : {
360
+ height: nameHeight,
361
+ overflow: 'hidden',
362
+ display: '-webkit-box',
363
+ WebkitLineClamp: 2,
364
+ WebkitBoxOrient: 'vertical'
365
+ })
366
+ }}>
367
+ {typeof product.name === 'object' ? (product.name as { all: string }).all : product.name}
368
+ </div>}
369
+ </div>
370
+ );
371
+ }
372
+ };
373
+
374
+ // Carousel navigation functions
375
+ const scrollLeft = () => {
376
+ const carousel = document.querySelector('.groupProductCarousel');
377
+ if (carousel) {
378
+ carousel.scrollBy({ left: -200, behavior: 'smooth' });
379
+ }
380
+ };
381
+
382
+ const scrollRight = () => {
383
+ const carousel = document.querySelector('.groupProductCarousel');
384
+ if (carousel) {
385
+ carousel.scrollBy({ left: 200, behavior: 'smooth' });
386
+ }
387
+ };
388
+
389
+ return (
390
+ <div
391
+ style={{
392
+ border: '1px solid #e1e1e1',
393
+ width: '100%',
394
+ maxWidth: '100%',
395
+ borderRadius: '0px',
396
+ minHeight: '100px',
397
+ position: 'relative',
398
+ overflow: 'hidden',
399
+ marginBottom:'20px',
400
+ marginTop:'0px'
401
+
402
+ }}
403
+ className='GroupProductComponent'
404
+ >
405
+ {showHeader && (
406
+ <div
407
+ className="groupProductHeader"
408
+ style={{
409
+ backgroundColor: props.headerBackground,
410
+ padding: '12px 16px',
411
+ borderRadius: '0px',
412
+ marginBottom: '4px',
413
+ display: 'flex',
414
+ alignItems: 'center',
415
+ justifyContent: 'space-between',
416
+ flexWrap: 'wrap',
417
+ gap: '12px',
418
+ }}
419
+ >
420
+ <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
421
+ {props.headerImage && (
422
+ <div style={{ width: '32px', height: '32px' }}>
423
+ {/* <ImageDisplayComponent
424
+ fileUrl={props.headerImage}
425
+ preserveAspectRatio={true}
426
+ maxWidth="100%"
427
+ maxHeight="32px"
428
+ /> */}
429
+ <img
430
+ src={`${Linodeurl}${props.headerImage}`}
431
+ style={{ width: '100%', height: '100%', objectFit: 'cover' }}
432
+ />
433
+ </div>
434
+ )}
435
+ <p style={{
436
+ color: props.headerTextStyle.fontColor,
437
+ fontSize: `${props.headerTextStyle.fontSize}px`,
438
+ fontWeight: props.headerTextStyle.isBold ? 'bold' : 'normal',
439
+ fontStyle: props.headerTextStyle.isItalic ? 'italic' : 'normal',
440
+ textDecoration: props.headerTextStyle.isUnderline ? 'underline' : 'none',
441
+ margin: 0
442
+ }}>
443
+ {props.headerText?.all || props?.headerText}
444
+ </p>
445
+ </div>
446
+
447
+ <div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
448
+
449
+ {/* {props.type=='static' && (
450
+ <a
451
+ href={`http://localhost:5173/${props.groupproduct.static.code}/s?type=groupproduct`}
452
+ target="_blank"
453
+ rel="noopener noreferrer"
454
+ style={{
455
+ color: 'black',
456
+ textDecoration: 'none',
457
+ fontWeight: '500',
458
+ fontSize: '14px',
459
+ padding: '6px 12px',
460
+ border: 'none',
461
+ borderRadius: '4px',
462
+ backgroundColor: 'transparent',
463
+ cursor: 'pointer'
464
+ }}
465
+ >
466
+ View All
467
+ </a>
468
+ )} */}
469
+
470
+
471
+
472
+
473
+ {currentLayout === 'NONE' && products.length > 4 && (
474
+ <div style={{ display: 'flex', gap: '8px' }}>
475
+ <button
476
+ onClick={scrollLeft}
477
+ style={{
478
+ width: '32px',
479
+ height: '32px',
480
+ borderRadius: '50%',
481
+ border: '1px solid #ddd',
482
+ backgroundColor: '#fff',
483
+ cursor: 'pointer',
484
+ display: 'flex',
485
+ alignItems: 'center',
486
+ justifyContent: 'center',
487
+ fontSize: '16px',
488
+ fontWeight: 'bold'
489
+ }}
490
+ onMouseOver={(e) => {
491
+ e.currentTarget.style.backgroundColor = '#f8f9fa';
492
+ }}
493
+ onMouseOut={(e) => {
494
+ e.currentTarget.style.backgroundColor = '#fff';
495
+ }}
496
+ >
497
+ &#8249;
498
+ </button>
499
+ <button
500
+ onClick={scrollRight}
501
+ style={{
502
+ width: '32px',
503
+ height: '32px',
504
+ borderRadius: '50%',
505
+ border: '1px solid #ddd',
506
+ backgroundColor: '#fff',
507
+ cursor: 'pointer',
508
+ display: 'flex',
509
+ alignItems: 'center',
510
+ justifyContent: 'center',
511
+ fontSize: '16px',
512
+ fontWeight: 'bold'
513
+ }}
514
+ onMouseOver={(e) => {
515
+ e.currentTarget.style.backgroundColor = '#f8f9fa';
516
+ }}
517
+ onMouseOut={(e) => {
518
+ e.currentTarget.style.backgroundColor = '#fff';
519
+ }}
520
+ >
521
+ &#8250;
522
+ </button>
523
+ </div>
524
+ )}
525
+ </div>
526
+ </div>
527
+ )}
528
+
529
+ <div
530
+ className="groupProductCarousel"
531
+ style={{
532
+ display: currentLayout === 'NONE' ? 'flex' : 'block',
533
+ overflowX: currentLayout === 'NONE' && isHorizontalScroll ? 'auto' : 'visible',
534
+ gap: currentLayout === 'NONE' ? '12px' : '0',
535
+ padding: '12px',
536
+ scrollBehavior: 'smooth',
537
+ backgroundColor: props.cardColor || '#fff',
538
+ scrollbarWidth: 'thin',
539
+ borderRadius: '8px',
540
+ position: 'relative',
541
+ scrollbarColor: '#c1c1c1 transparent'
542
+ }}
543
+ >
544
+ {products.length > 0 ? (
545
+ currentLayout === 'NONE' ? (
546
+ products.slice(0, props.type === 'static' ? 15 : products.length).map((product) =>
547
+ renderProduct(product, product._id)
548
+ )
549
+ ) : currentLayout === 'SMALL' ? (
550
+ <div style={{
551
+ display: 'grid',
552
+ gridTemplateColumns: 'repeat(2, 1fr)',
553
+ gap: '16px',
554
+ padding: '8px'
555
+ }}>
556
+ {
557
+ products.map((product) =>
558
+ renderProductCard(product, product._id, '100px', '12px', '32px')
559
+ )}
560
+ </div>
561
+ ) : currentLayout === 'MEDIUM' ? (
562
+ <div style={{
563
+ display: 'grid',
564
+ gridTemplateColumns: 'repeat(3, 1fr)',
565
+ gap: '16px',
566
+ padding: '8px'
567
+ }}>
568
+ {
569
+ products.map((product) =>
570
+ renderProductCard(product, product._id, '120px', '14px', '40px')
571
+ )}
572
+ </div>
573
+ ) : currentLayout === 'MEDIUM_THREE' ? (
574
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '8px' }}>
575
+ {products.length > 0 && (
576
+ renderProductCard(products[0], products[0]._id, '160px', '16px', 'auto', '600')
577
+ )}
578
+ {products.length > 1 && (
579
+ <div style={{
580
+ display: 'grid',
581
+ gridTemplateColumns: 'repeat(2,1fr)',
582
+ gap: '16px'
583
+ }}>
584
+ {products.slice(1).map((product) =>
585
+ renderProductCard(product, product._id, '100px', '12px', '32px', '500')
586
+ )}
587
+ </div>
588
+ )}
589
+ </div>
590
+ ) : null
591
+ ) : (
592
+ <div style={{
593
+ textAlign: 'center',
594
+ color: '#666',
595
+ padding: '40px',
596
+ width: '100%',
597
+ border: '2px dashed #ddd',
598
+ borderRadius: '8px',
599
+ backgroundColor: '#f9f9f9'
600
+ }}>
601
+ <p>No products selected. Use settings to add products.</p>
602
+ </div>
603
+ )}
604
+ </div>
605
+ </div>
606
+ );
607
+ };
608
+
617
609
  export default GroupProductComponent;