tee3apps-cms-sdk-react 0.0.1

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.
Files changed (43) hide show
  1. package/.env +11 -0
  2. package/README.md +255 -0
  3. package/dist/index.d.ts +5 -0
  4. package/dist/index.js +13 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +13 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +33 -0
  9. package/rollup.config.js +43 -0
  10. package/src/Components/BoxRenderer.tsx +108 -0
  11. package/src/Components/ComponentRenderer.tsx +29 -0
  12. package/src/Components/ImageComponent.tsx +68 -0
  13. package/src/Components/RowComponent.tsx +66 -0
  14. package/src/Components/TextComponent.tsx +47 -0
  15. package/src/ErrorBoundary.tsx +35 -0
  16. package/src/Page.tsx +124 -0
  17. package/src/PageComponents/BoxComponent.tsx +397 -0
  18. package/src/PageComponents/RowComponent.tsx +113 -0
  19. package/src/PageComponents/Visual-Components/CarouselComponent.tsx +366 -0
  20. package/src/PageComponents/Visual-Components/GroupBrandComponent.tsx +391 -0
  21. package/src/PageComponents/Visual-Components/GroupCategoryComponent.tsx +425 -0
  22. package/src/PageComponents/Visual-Components/GroupImageList.tsx +669 -0
  23. package/src/PageComponents/Visual-Components/GroupProductComponent.tsx +671 -0
  24. package/src/PageComponents/Visual-Components/GroupVideoList.tsx +590 -0
  25. package/src/PageComponents/Visual-Components/ImageComponent.tsx +163 -0
  26. package/src/PageComponents/Visual-Components/LinkComponent.tsx +68 -0
  27. package/src/PageComponents/Visual-Components/LottieComponent.tsx +213 -0
  28. package/src/PageComponents/Visual-Components/NavigationComponent.tsx +178 -0
  29. package/src/PageComponents/Visual-Components/Styles/ProductListViewOne.tsx +102 -0
  30. package/src/PageComponents/Visual-Components/Styles/ProductListViewTwo.tsx +104 -0
  31. package/src/PageComponents/Visual-Components/Styles/product-list-view-one.css +166 -0
  32. package/src/PageComponents/Visual-Components/Styles/product-list-view-two.css +182 -0
  33. package/src/PageComponents/Visual-Components/TabComponent.tsx +1169 -0
  34. package/src/PageComponents/Visual-Components/TextComponent.tsx +114 -0
  35. package/src/PageComponents/Visual-Components/VideoComponent.tsx +191 -0
  36. package/src/PageComponents/Visual-Components/tab.css +697 -0
  37. package/src/common.interface.ts +216 -0
  38. package/src/const.ts +6 -0
  39. package/src/env.d.ts +15 -0
  40. package/src/index.css +82 -0
  41. package/src/index.ts +2 -0
  42. package/src/types.ts +234 -0
  43. package/tsconfig.json +20 -0
@@ -0,0 +1,590 @@
1
+ import React, { useState } from 'react';
2
+ import { Linodeurl } from '../../const';
3
+
4
+ interface VideoItem {
5
+ id: number;
6
+ attr: {
7
+ playerType: 'Video' | 'Youtube' | 'Vimeo' | 'Dailymotion';
8
+ controls?: boolean;
9
+ loop?: boolean;
10
+ alt?: string;
11
+ url: string;
12
+ autoplay?: boolean;
13
+ muted?: boolean;
14
+ };
15
+ title: string;
16
+ subTitle: string;
17
+ }
18
+
19
+ interface GroupVideoStatic {
20
+ _id: string;
21
+ name: string;
22
+ code: string;
23
+ }
24
+
25
+ interface GroupVideoDynamic {
26
+ code: string;
27
+ name: { all: string };
28
+ list: VideoItem[];
29
+ isActive?: boolean;
30
+ }
31
+
32
+ interface GroupVideoData {
33
+ static: GroupVideoStatic;
34
+ dynamic: GroupVideoDynamic;
35
+ groupvideodata: VideoItem[];
36
+ groupimagedata: any[];
37
+ }
38
+
39
+ interface HeaderTextStyle {
40
+ fontSize: number;
41
+ fontColor: string;
42
+ isBold: boolean;
43
+ isItalic: boolean;
44
+ isUnderline: boolean;
45
+ }
46
+
47
+ interface DeviceBooleanProps {
48
+ web: boolean;
49
+ mobileweb: boolean;
50
+ mobileapp: boolean;
51
+ tablet: boolean;
52
+ }
53
+
54
+ interface DeviceLayoutProps {
55
+ web: string;
56
+ mobileweb: string;
57
+ mobileapp: string;
58
+ tablet: string;
59
+ }
60
+
61
+ export interface GroupVideoListProps {
62
+ nameData: string;
63
+ type: string;
64
+ groupvideo: GroupVideoData;
65
+ headerText: string;
66
+ activeStatus: boolean;
67
+ headerImage: string;
68
+ headerTextStyle: HeaderTextStyle;
69
+ layout: DeviceLayoutProps;
70
+ showHeader: DeviceBooleanProps;
71
+ isHorizontalScroll: DeviceBooleanProps;
72
+ headerBackground: string;
73
+ carouselBackground: string;
74
+ cardcolor: string;
75
+ showSubtitle?: boolean;
76
+ showTitle?: boolean;
77
+ titleStyle?: {
78
+ fontSize: number;
79
+ fontColor: string;
80
+ isBold: boolean;
81
+ isItalic: boolean;
82
+ isUnderline: boolean;
83
+ };
84
+ subtitleStyle?: {
85
+ fontSize: number;
86
+ fontColor: string;
87
+ isBold: boolean;
88
+ isItalic: boolean;
89
+ isUnderline: boolean;
90
+ };
91
+ }
92
+
93
+ interface GroupVideoListMainProps {
94
+ props: GroupVideoListProps;
95
+ deviceMode?: string;
96
+ boxHeight?: string;
97
+ }
98
+
99
+ // Helper functions for extracting video IDs
100
+ const extractYouTubeId = (url: string): string | null => {
101
+ try {
102
+ const parsed = new URL(url);
103
+ if (parsed.hostname.includes('youtu.be')) {
104
+ return parsed.pathname.replace('/', '') || null;
105
+ }
106
+ if (parsed.hostname.includes('youtube.com')) {
107
+ if (parsed.pathname.startsWith('/watch')) {
108
+ return parsed.searchParams.get('v');
109
+ }
110
+ if (parsed.pathname.startsWith('/embed/')) {
111
+ return parsed.pathname.split('/embed/')[1] || null;
112
+ }
113
+ }
114
+ } catch {}
115
+ return null;
116
+ };
117
+
118
+ const extractVimeoId = (url: string): string | null => {
119
+ try {
120
+ const parsed = new URL(url);
121
+ if (parsed.hostname.includes('vimeo.com')) {
122
+ const parts = parsed.pathname.split('/').filter(Boolean);
123
+ if (parts[0] === 'video') return parts[1] || null;
124
+ return parts[0] || null;
125
+ }
126
+ if (parsed.hostname.includes('player.vimeo.com')) {
127
+ const parts = parsed.pathname.split('/').filter(Boolean);
128
+ return parts[1] || null;
129
+ }
130
+ } catch {}
131
+ return null;
132
+ };
133
+
134
+ const extractDailymotionId = (url: string): string | null => {
135
+ try {
136
+ const parsed = new URL(url);
137
+ if (parsed.hostname.includes('dailymotion.com')) {
138
+ const parts = parsed.pathname.split('/').filter(Boolean);
139
+ if (parts[0] === 'video') return parts[1] || null;
140
+ }
141
+ if (parsed.hostname.includes('dai.ly')) {
142
+ return parsed.pathname.replace('/', '') || null;
143
+ }
144
+ } catch {}
145
+ return null;
146
+ };
147
+
148
+ // Video Component
149
+ interface VideoComponentProps {
150
+ videoData: {
151
+ url: string;
152
+ type: 'Youtube' | 'Vimeo' | 'Dailymotion' | 'Video';
153
+ controls?: boolean;
154
+ loop?: boolean;
155
+ alt?: string;
156
+ autoplay?: boolean;
157
+ muted?: boolean;
158
+ };
159
+ borderRadius?: number;
160
+ height?: string;
161
+ }
162
+
163
+ const VideoComponent: React.FC<VideoComponentProps> = ({
164
+ videoData,
165
+ borderRadius = 6,
166
+ height = '100%'
167
+ }) => {
168
+ const renderPlayer = () => {
169
+ const commonStyle: React.CSSProperties = {
170
+ width: '100%',
171
+ height: '100%',
172
+ border: 0,
173
+ borderRadius: `${borderRadius}px`,
174
+ };
175
+
176
+ if (videoData.type === 'Youtube') {
177
+ const id = extractYouTubeId(videoData.url);
178
+ const src = id ? `https://www.youtube.com/embed/${id}` : videoData.url;
179
+ return (
180
+ <iframe
181
+ title={videoData.alt || 'YouTube video'}
182
+ src={src}
183
+ allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
184
+ allowFullScreen
185
+ style={commonStyle}
186
+ />
187
+ );
188
+ }
189
+
190
+ if (videoData.type === 'Vimeo') {
191
+ const id = extractVimeoId(videoData.url);
192
+ const src = id ? `https://player.vimeo.com/video/${id}` : videoData.url;
193
+ return (
194
+ <iframe
195
+ title={videoData.alt || 'Vimeo video'}
196
+ src={src}
197
+ allow="autoplay; fullscreen; picture-in-picture"
198
+ allowFullScreen
199
+ style={commonStyle}
200
+ />
201
+ );
202
+ }
203
+
204
+ if (videoData.type === 'Dailymotion') {
205
+ const id = extractDailymotionId(videoData.url);
206
+ const src = id ? `https://www.dailymotion.com/embed/video/${id}` : videoData.url;
207
+ return (
208
+ <iframe
209
+ title={videoData.alt || 'Dailymotion video'}
210
+ src={src}
211
+ allow="autoplay; fullscreen; picture-in-picture"
212
+ allowFullScreen
213
+ style={commonStyle}
214
+ />
215
+ );
216
+ }
217
+
218
+ // Default: normal video
219
+ return (
220
+ <video
221
+ autoPlay={videoData.autoplay !== false}
222
+ muted={videoData.muted !== false}
223
+ playsInline
224
+ controls={videoData.controls !== false}
225
+ loop={videoData.loop === true}
226
+ style={{ width: '100%', height: '100%', borderRadius: `${borderRadius}px` }}
227
+ >
228
+ <source src={`${Linodeurl}${videoData.url}`} />
229
+ Your browser does not support the video tag.
230
+ </video>
231
+ );
232
+ };
233
+
234
+ return (
235
+ <div
236
+ style={{
237
+ borderRadius: `${borderRadius}px`,
238
+ height: height,
239
+ overflow: 'hidden'
240
+ }}
241
+ >
242
+ {renderPlayer()}
243
+ </div>
244
+ );
245
+ };
246
+
247
+ // Main GroupVideoList Component
248
+ const GroupVideoList: React.FC<GroupVideoListMainProps> = ({ props, deviceMode = 'web', boxHeight }) => {
249
+ const getCurrentBooleanProp = (prop?: DeviceBooleanProps) => {
250
+ if (!prop) return false;
251
+ switch (deviceMode) {
252
+ case 'mobileweb': return !!prop.mobileweb;
253
+ case 'mobileapp': return !!prop.mobileapp;
254
+ case 'tablet': return !!prop.tablet;
255
+ case 'web':
256
+ default: return !!prop.web;
257
+ }
258
+ };
259
+
260
+ const getCurrentLayout = () => {
261
+ if (!props.layout) return 'NONE';
262
+ switch (deviceMode) {
263
+ case 'mobileweb': return props.layout.mobileweb || 'NONE';
264
+ case 'mobileapp': return props.layout.mobileapp || 'NONE';
265
+ case 'tablet': return props.layout.tablet || 'NONE';
266
+ case 'web':
267
+ default: return props.layout.web || 'NONE';
268
+ }
269
+ };
270
+
271
+ const showHeader = getCurrentBooleanProp(props.showHeader);
272
+ const isHorizontalScroll = getCurrentBooleanProp(props.isHorizontalScroll);
273
+ const currentLayout = getCurrentLayout();
274
+
275
+ const getVideos = (): VideoItem[] => {
276
+ if (props.type === 'dynamic') {
277
+ if (props.groupvideo?.dynamic?.list?.length) return props.groupvideo.dynamic.list;
278
+ }
279
+ if (props.groupvideo?.groupvideodata?.length) return props.groupvideo.groupvideodata;
280
+ return [];
281
+ };
282
+
283
+ const videos = getVideos();
284
+
285
+ // Carousel navigation buttons (layout NONE)
286
+ const scrollLeft = () => {
287
+ const scrollableContainer = document.querySelector('.scrollable-container');
288
+ if (scrollableContainer) {
289
+ (scrollableContainer as HTMLElement).scrollBy({ left: -200, behavior: 'smooth' });
290
+ }
291
+ };
292
+
293
+ const scrollRight = () => {
294
+ const scrollableContainer = document.querySelector('.scrollable-container');
295
+ if (scrollableContainer) {
296
+ (scrollableContainer as HTMLElement).scrollBy({ left: 200, behavior: 'smooth' });
297
+ }
298
+ };
299
+
300
+ const VideoCard = ({ item, large = false }: { item: VideoItem; large?: boolean }) => {
301
+ const [isHovered, setIsHovered] = useState(false);
302
+
303
+ return (
304
+ <div
305
+ className="videoCard"
306
+ style={{
307
+ height: 'auto',
308
+ borderRadius: '8px',
309
+ overflow: 'hidden',
310
+ border: '1px solid #eee',
311
+ backgroundColor: props.cardcolor || '#fff',
312
+ display: 'flex',
313
+ flexDirection: 'column',
314
+ padding: large ? '16px' : '12px',
315
+ boxShadow: isHovered ? '0 4px 8px rgba(0,0,0,0.15)' : '0 2px 4px rgba(0,0,0,0.1)',
316
+ transition: 'all 0.2s ease',
317
+ cursor: 'pointer',
318
+ transform: isHovered ? 'translateY(-2px)' : 'translateY(0px)',
319
+ flex: 1
320
+ }}
321
+ onMouseOver={() => setIsHovered(true)}
322
+ onMouseOut={() => setIsHovered(false)}
323
+ >
324
+ <div style={{ width: '100%', marginBottom: large ? '12px' : '8px' }}>
325
+ <VideoComponent
326
+ videoData={{
327
+ url: item.attr.url,
328
+ type: item.attr.playerType,
329
+ controls: item.attr.controls,
330
+ loop: item.attr.loop,
331
+ alt: item.attr.alt,
332
+ autoplay: item.attr.autoplay !== false,
333
+ muted: item.attr.muted !== false
334
+ }}
335
+ borderRadius={6}
336
+ height={`${parseInt(boxHeight || '280') - 160}px`}
337
+ />
338
+ </div>
339
+ {(props?.showTitle !== false) && item.title && (
340
+ <div style={{
341
+ textAlign: 'center',
342
+ fontSize: props.titleStyle ? `${props.titleStyle.fontSize}px` : (large ? '16px' : '14px'),
343
+ fontWeight: props.titleStyle?.isBold ? 'bold' : (large ? 600 : 500),
344
+ color: props.titleStyle?.fontColor || '#333',
345
+ fontStyle: props.titleStyle?.isItalic ? 'italic' : 'normal',
346
+ textDecoration: props.titleStyle?.isUnderline ? 'underline' : 'none',
347
+ lineHeight: '1.4',
348
+ marginBottom: '4px'
349
+ }}>
350
+ {item.title}
351
+ </div>
352
+ )}
353
+ {(props?.showSubtitle !== false) && item.subTitle && (
354
+ <div style={{
355
+ textAlign: 'center',
356
+ fontSize: props.subtitleStyle ? `${props.subtitleStyle.fontSize}px` : (large ? '14px' : '12px'),
357
+ fontWeight: props.subtitleStyle?.isBold ? 'bold' : 400,
358
+ color: props.subtitleStyle?.fontColor || '#666',
359
+ fontStyle: props.subtitleStyle?.isItalic ? 'italic' : 'normal',
360
+ textDecoration: props.subtitleStyle?.isUnderline ? 'underline' : 'none',
361
+ lineHeight: '1.3'
362
+ }}>
363
+ {item.subTitle}
364
+ </div>
365
+ )}
366
+ </div>
367
+ );
368
+ };
369
+
370
+ return (
371
+ <div
372
+ style={{
373
+ border: '1px solid #e1e1e1',
374
+ width: '100%',
375
+ maxWidth: '100%',
376
+ borderRadius: '0px',
377
+ height: boxHeight || 'auto',
378
+ minHeight: boxHeight ? boxHeight : '100px',
379
+ position: 'relative',
380
+ overflow: 'hidden',
381
+ marginBottom: '20px',
382
+ marginTop: '0px',
383
+ display: 'flex',
384
+ flexDirection: 'column'
385
+ }}
386
+ className='GroupVideoListComponent'
387
+ >
388
+ {showHeader && (
389
+ <div
390
+ className="groupVideoHeader"
391
+ style={{
392
+ backgroundColor: props.headerBackground,
393
+ padding: '12px 16px',
394
+ borderRadius: '0px',
395
+ marginBottom: '4px',
396
+ display: 'flex',
397
+ alignItems: 'center',
398
+ justifyContent: 'space-between',
399
+ flexWrap: 'wrap',
400
+ gap: '12px',
401
+ }}
402
+ >
403
+ <p style={{
404
+ color: props.headerTextStyle.fontColor,
405
+ fontSize: `${props.headerTextStyle.fontSize}px`,
406
+ fontWeight: props.headerTextStyle.isBold ? 'bold' : 'normal',
407
+ fontStyle: props.headerTextStyle.isItalic ? 'italic' : 'normal',
408
+ textDecoration: props.headerTextStyle.isUnderline ? 'underline' : 'none',
409
+ margin: 0
410
+ }}>
411
+ {props.headerText || 'Video List'}
412
+ </p>
413
+
414
+ {currentLayout === 'NONE' && videos.length > 2 && (
415
+ <div style={{ display: 'flex', gap: '8px' }}>
416
+ <button
417
+ onClick={scrollLeft}
418
+ style={{
419
+ width: '32px',
420
+ height: '32px',
421
+ borderRadius: '50%',
422
+ border: '1px solid #ddd',
423
+ backgroundColor: '#fff',
424
+ cursor: 'pointer',
425
+ display: 'flex',
426
+ alignItems: 'center',
427
+ justifyContent: 'center',
428
+ fontSize: '16px',
429
+ fontWeight: 'bold'
430
+ }}
431
+ onMouseOver={(e) => { e.currentTarget.style.backgroundColor = '#f8f9fa'; }}
432
+ onMouseOut={(e) => { e.currentTarget.style.backgroundColor = '#fff'; }}
433
+ >
434
+
435
+ </button>
436
+ <button
437
+ onClick={scrollRight}
438
+ style={{
439
+ width: '32px',
440
+ height: '32px',
441
+ borderRadius: '50%',
442
+ border: '1px solid #ddd',
443
+ backgroundColor: '#fff',
444
+ cursor: 'pointer',
445
+ display: 'flex',
446
+ alignItems: 'center',
447
+ justifyContent: 'center',
448
+ fontSize: '16px',
449
+ fontWeight: 'bold'
450
+ }}
451
+ onMouseOver={(e) => { e.currentTarget.style.backgroundColor = '#f8f9fa'; }}
452
+ onMouseOut={(e) => { e.currentTarget.style.backgroundColor = '#fff'; }}
453
+ >
454
+
455
+ </button>
456
+ </div>
457
+ )}
458
+ </div>
459
+ )}
460
+
461
+ <div
462
+ style={{
463
+ display: currentLayout === 'NONE' ? 'flex' : 'block',
464
+ overflowX: currentLayout === 'NONE' ? (isHorizontalScroll ? 'auto' : 'hidden') : 'visible',
465
+ gap: currentLayout === 'NONE' ? '12px' : '0',
466
+ padding: '12px',
467
+ scrollBehavior: 'smooth',
468
+ backgroundColor: props.carouselBackground || '#fff',
469
+ scrollbarWidth: 'thin',
470
+ borderRadius: '8px',
471
+ position: 'relative',
472
+ scrollbarColor: '#c1c1c1 transparent',
473
+ flex: 1,
474
+ overflow: 'hidden'
475
+ }}
476
+ className="groupVideoCarousel"
477
+ >
478
+ {/* Navigation buttons - positioned like carousel */}
479
+ {!showHeader && currentLayout === 'NONE' && videos.length > 2 && (
480
+ <>
481
+ <button
482
+ onClick={scrollLeft}
483
+ style={{
484
+ position: 'absolute',
485
+ left: '10px',
486
+ top: '50%',
487
+ transform: 'translateY(-50%)',
488
+ background: 'rgba(0,0,0,0.5)',
489
+ color: 'white',
490
+ border: 'none',
491
+ borderRadius: '50%',
492
+ width: '40px',
493
+ height: '40px',
494
+ cursor: 'pointer',
495
+ display: 'flex',
496
+ alignItems: 'center',
497
+ justifyContent: 'center',
498
+ fontSize: '18px',
499
+ zIndex: 10,
500
+ transition: 'all 0.2s ease'
501
+ }}
502
+ onMouseOver={(e) => {
503
+ e.currentTarget.style.background = 'rgba(0,0,0,0.7)';
504
+ e.currentTarget.style.transform = 'translateY(-50%) scale(1.1)';
505
+ }}
506
+ onMouseOut={(e) => {
507
+ e.currentTarget.style.background = 'rgba(0,0,0,0.5)';
508
+ e.currentTarget.style.transform = 'translateY(-50%) scale(1)';
509
+ }}
510
+ >
511
+
512
+ </button>
513
+ <button
514
+ onClick={scrollRight}
515
+ style={{
516
+ position: 'absolute',
517
+ right: '10px',
518
+ top: '50%',
519
+ transform: 'translateY(-50%)',
520
+ background: 'rgba(0,0,0,0.5)',
521
+ color: 'white',
522
+ border: 'none',
523
+ borderRadius: '50%',
524
+ width: '40px',
525
+ height: '40px',
526
+ cursor: 'pointer',
527
+ display: 'flex',
528
+ alignItems: 'center',
529
+ justifyContent: 'center',
530
+ fontSize: '18px',
531
+ zIndex: 10,
532
+ transition: 'all 0.2s ease'
533
+ }}
534
+ onMouseOver={(e) => {
535
+ e.currentTarget.style.background = 'rgba(0,0,0,0.7)';
536
+ e.currentTarget.style.transform = 'translateY(-50%) scale(1.1)';
537
+ }}
538
+ onMouseOut={(e) => {
539
+ e.currentTarget.style.background = 'rgba(0,0,0,0.5)';
540
+ e.currentTarget.style.transform = 'translateY(-50%) scale(1)';
541
+ }}
542
+ >
543
+
544
+ </button>
545
+ </>
546
+ )}
547
+ {videos.length > 0 ? (
548
+ currentLayout === 'NONE' ? (
549
+ videos.map((video) => (
550
+ <div key={video.id} style={{ minWidth: '200px',height: 'auto' }}>
551
+ <VideoCard item={video} />
552
+ </div>
553
+ ))
554
+ ) : currentLayout === 'SMALL' ? (
555
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px', padding: '8px' }}>
556
+ {videos.map((video) => (
557
+ <VideoCard key={video.id} item={video} />
558
+ ))}
559
+ </div>
560
+ ) : currentLayout === 'MEDIUM' ? (
561
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '16px', padding: '8px' }}>
562
+ {videos.map((video) => (
563
+ <VideoCard key={video.id} item={video} />
564
+ ))}
565
+ </div>
566
+ ) : currentLayout === 'MEDIUM_THREE' ? (
567
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '8px' }}>
568
+ {videos.length > 0 && (
569
+ <VideoCard item={videos[0]} large />
570
+ )}
571
+ {videos.length > 1 && (
572
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '16px' }}>
573
+ {videos.slice(1).map((video) => (
574
+ <VideoCard key={video.id} item={video} />
575
+ ))}
576
+ </div>
577
+ )}
578
+ </div>
579
+ ) : null
580
+ ) : (
581
+ <div style={{ textAlign: 'center', color: '#666', padding: '40px', width: '100%', border: '2px dashed #ddd', borderRadius: '8px', backgroundColor: '#f9f9f9' }}>
582
+ <p>No videos available.</p>
583
+ </div>
584
+ )}
585
+ </div>
586
+ </div>
587
+ );
588
+ };
589
+
590
+ export default GroupVideoList;