2/28/25, 12:32 AM promo_slider.
dart
lib/features/shop/screens/home/widgets/promo_slider.dart
1 import 'dart:async';
2 import 'package:flutter/material.dart';
3 import 'package:get/get.dart';
4 import 'package:shimmer/shimmer.dart';
5 import 'package:carousel_slider/carousel_slider.dart';
6 import 'package:swadeitt/data/services/cloudinary_service.dart';
7 import
'package:swadeitt/common/widgets/Custom_shapes/containers/circular_container.dart';
8 import 'package:swadeitt/utils/constants/colors.dart';
9 import 'package:swadeitt/utils/constants/sizes.dart';
10
11 class HomePromoSlider extends StatefulWidget {
12 const HomePromoSlider({super.key});
13
14 @override
15 State<HomePromoSlider> createState() => _HomePromoSliderStat
e();
16 }
17
18 class _HomePromoSliderStat
e extends State<HomePromoSlider> {
19 final _controller = Get.put(HomeController());
20 final CloudinaryService _cloudinaryService = CloudinaryService();
21
22 List<String> _banners = [];
23 bool _isLoading = true;
24 Timer? _timer; // Timer for auto-fetch
25
26 @override
27 void initState() {
28 super.initState();
29 _fetchBanners(); // Fetch banners initially
30 _startAutoRefresh(); // Auto-refresh every 10 seconds
31 }
32
33 /// Fetch images from Cloudinary collection
34 Future<void> _fetchBanners() async {
35 try {
36 List<String> images =
37 await _cloudinaryService.fetchImagesFromFolde
r('swadeit/banners');
38 setState(() {
39 _banners = images;
40 _isLoading = false;
41 });
42 } catch (e) {
43 print('Error fetching banners: $e');
44 setState(() {
45 _isLoading = false;
46 });
47 }
48 }
49
50 /// Start auto-refresh every 10 seconds
51 void _startAutoRefresh() {
localhost:33107/cc83cd25-1a3a-4648-8651-3fdb50c65ba6/ 1/3
2/28/25, 12:32 AM promo_slider.dart
52 _timer = Timer.periodic(const Duration(seconds: 10), (timer) {
53 _fetchBanners();
54 });
55 }
56
57 /// Cancel timer when widget is disposed
58 @override
59 void dispose() {
60 _timer?.cancel();
61 super.dispose();
62 }
63
64 @override
65 Widget build(BuildContext context) {
66 return RefreshIndicator(
67 onRefresh: _fetchBanners, // Pull-to-refresh
68 child: _isLoading
69 ? _buildShimmerEffect() // Show shimmer when loading
70 : _banners.isNotEmpty
71 ? Column(
72 children: [
73 CarouselSlider(
74 options: CarouselOptions(
75 viewportFraction: 1,
76 autoPlay: true,
77 autoPlayInterval: const Duration(seconds: 4),
78 onPageChanged: (index, _) =>
79 _controller.updatePageIndicator(index),
80 ),
81 items: _banners.map((url) => _buildImage(url)).toList(),
82 ),
83 const SizedBox(height: TSizes.spaceBtwItems),
84 Obx(
85 () => Row(
86 mainAxisAlignment: MainAxisAlignment.center,
87 children: List.generate(
88 _banners.length,
89 (index) => TCircularContainer(
90 width: 20,
91 height: 4,
92 backgroundColor:
93 _controller.carousalCurrentIndex
.value == index
94 ? TColors.primary
95 : TColors.grey,
96 margins: const EdgeInsets.only(right: 10),
97 ),
98 ),
99 ),
100 ),
101 ],
102 )
103 : const Center(child: Text('No banners available')),
104 );
105 }
localhost:33107/cc83cd25-1a3a-4648-8651-3fdb50c65ba6/ 2/3
2/28/25, 12:32 AM promo_slider.dart
106
107 /// Shimmer Effect while Loading
108 Widget _buildShimmerEffect() {
109 return Padding(
110 padding: const EdgeInsets.symmetric(horizontal: 20),
111 child: Shimmer.fromColors(
112 baseColor: Colors.grey[300]!,
113 highlightColor: Colors.grey[100]!,
114 child: Container(
115 height: 180, // Adjust based on banner size
116 width: double.infinity,
117 decoration: BoxDecoration(
118 color: Colors.white,
119 borderRadius: BorderRadius.circular(10),
120 ),
121 ),
122 ),
123 );
124 }
125
126 /// Image Builder with Shimmer Effect while Loading
127 Widget _buildImage(String url) {
128 return ClipRRect(
129 borderRadius: BorderRadius.circular(10),
130 child: Image.network(
131 url,
132 fit: BoxFit.cover,
133 width: double.infinity,
134 loadingBuilder: (context, child, loadingProgress) {
135 if (loadingProgress == null) return child;
136 return _buildShimmerEffect(); // Show shimmer while image loads
137 },
138 errorBuilder: (context, error, stackTrace) => const Center(
139 child: Text("Error loading image", style: TextStyle(color: Colors.red)),
140 ),
141 ),
142 );
143 }
144 }
145
146 class HomeController extends GetxController {
147 var carousalCurrentIndex= 0.obs;
148
149 void updatePageIndicator(int index) {
150 carousalCurrentIndex
.value = index;
151 }
152 }
153
localhost:33107/cc83cd25-1a3a-4648-8651-3fdb50c65ba6/ 3/3