import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:carousel_slider/carousel_slider.dart'; import '../../../common/theme/theme.dart'; import '../../components/image/image.dart'; import '../../router/app_router.gr.dart'; // Models (simplified) class DrawEvent { final String id; final String name; final String description; final int entryPoints; final String icon; final String imageUrl; final Color primaryColor; final String prize; final String prizeValue; final DateTime drawDate; final int totalParticipants; final int hadiah; final String status; // 'active', 'ended' final int minSpending; DrawEvent({ required this.id, required this.name, required this.description, required this.entryPoints, required this.icon, required this.imageUrl, required this.primaryColor, required this.prize, required this.prizeValue, required this.drawDate, required this.totalParticipants, required this.hadiah, required this.status, required this.minSpending, }); bool get isActive => status == 'active'; } class UserEntry { final String drawId; final DateTime entryDate; UserEntry({required this.drawId, required this.entryDate}); } class CarouselBanner { final String id; final String imageUrl; final String title; final String subtitle; final Color backgroundColor; CarouselBanner({ required this.id, required this.imageUrl, required this.title, required this.subtitle, required this.backgroundColor, }); } @RoutePage() class DrawPage extends StatefulWidget { const DrawPage({super.key}); @override State createState() => _DrawPageState(); } class _DrawPageState extends State { final TextEditingController _dateFilterController = TextEditingController(); final CarouselSliderController _carouselController = CarouselSliderController(); final ScrollController _scrollController = ScrollController(); int _currentBannerIndex = 0; DateTime? _selectedFilterDate; bool _isCollapsed = false; final List userEntries = [ UserEntry( drawId: "1", entryDate: DateTime.now().subtract(Duration(hours: 3)), ), ]; final List banners = [ CarouselBanner( id: "1", imageUrl: "https://images.unsplash.com/photo-1610375461246-83df859d849d?w=800&h=400&fit=crop&crop=center", title: "Gebyar Undian Emas", subtitle: "Menangkan hadiah emas 3 gram!", backgroundColor: Color(0xFFFF6B6B), ), CarouselBanner( id: "2", imageUrl: "https://images.unsplash.com/photo-1592750475338-74b7b21085ab?w=800&h=400&fit=crop&crop=center", title: "Undian iPhone 15 Pro", subtitle: "Smartphone premium menanti Anda!", backgroundColor: Color(0xFF4ECDC4), ), CarouselBanner( id: "3", imageUrl: "https://images.unsplash.com/photo-1593640408182-31c70c8268f5?w=800&h=400&fit=crop&crop=center", title: "Undian Laptop Gaming", subtitle: "Laptop gaming terbaru untuk gamers!", backgroundColor: Color(0xFF45B7D1), ), CarouselBanner( id: "4", imageUrl: "https://images.unsplash.com/photo-1549298916-b41d501d3772?w=800&h=400&fit=crop&crop=center", title: "Undian Sneakers Limited", subtitle: "Sepatu branded edition terbatas!", backgroundColor: Color(0xFF96CEB4), ), CarouselBanner( id: "5", imageUrl: "https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=800&h=400&fit=crop&crop=center", title: "Undian Camera DSLR", subtitle: "Kamera profesional untuk fotografer!", backgroundColor: Color(0xFFFECEA8), ), CarouselBanner( id: "6", imageUrl: "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=800&h=400&fit=crop&crop=center", title: "Undian Gaming Console", subtitle: "PlayStation 5 siap dimainkan!", backgroundColor: Color(0xFFFF9AA2), ), CarouselBanner( id: "7", imageUrl: "https://images.unsplash.com/photo-1512499617640-c74ae3a79d37?w=800&h=400&fit=crop&crop=center", title: "Undian Motor Sport", subtitle: "Motor sport impian Anda!", backgroundColor: Color(0xFFB5EAD7), ), CarouselBanner( id: "8", imageUrl: "https://images.unsplash.com/photo-1484704849700-f032a568e944?w=800&h=400&fit=crop&crop=center", title: "Undian Home Theater", subtitle: "Sistem audio premium untuk rumah!", backgroundColor: Color(0xFFC7CEDB), ), CarouselBanner( id: "9", imageUrl: "https://images.unsplash.com/photo-1434493789847-2f02dc6ca35d?w=800&h=400&fit=crop&crop=center", title: "Undian Luxury Watch", subtitle: "Jam tangan mewah Swiss Made!", backgroundColor: Color(0xFFFFB7B2), ), CarouselBanner( id: "10", imageUrl: "https://images.unsplash.com/photo-1558618666-fbd1c326d4a4?w=800&h=400&fit=crop&crop=center", title: "Undian Travel Voucher", subtitle: "Liburan gratis ke destinasi impian!", backgroundColor: Color(0xFFE2F0CB), ), ]; final List drawEvents = [ DrawEvent( id: "1", name: "Emas 3 Gram", description: "Gebyar Undian Enaklo\nMenangkan hadiah emas batangan", entryPoints: 0, icon: "👑", imageUrl: "https://images.unsplash.com/photo-1610375461246-83df859d849d?w=400&h=200&fit=crop&crop=center", primaryColor: AppColor.primary, prize: "Emas 3 Gram", prizeValue: "Rp 2.500.000", drawDate: DateTime.now().add(Duration(hours: 1, minutes: 20)), totalParticipants: 245, hadiah: 2, status: 'active', minSpending: 50000, ), DrawEvent( id: "2", name: "iPhone 15 Pro", description: "Undian Smartphone Premium\nDapatkan iPhone terbaru", entryPoints: 0, icon: "📱", imageUrl: "https://images.unsplash.com/photo-1592750475338-74b7b21085ab?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFF007AFF), prize: "iPhone 15 Pro", prizeValue: "Rp 18.000.000", drawDate: DateTime.now().add(Duration(days: 2)), totalParticipants: 1456, hadiah: 1, status: 'active', minSpending: 100000, ), DrawEvent( id: "3", name: "Laptop Gaming", description: "Undian Laptop Gaming ROG\nPerforma tinggi untuk gaming", entryPoints: 0, icon: "💻", imageUrl: "https://images.unsplash.com/photo-1593640408182-31c70c8268f5?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFFFF4444), prize: "ROG Strix G15", prizeValue: "Rp 15.000.000", drawDate: DateTime.now().add(Duration(days: 5)), totalParticipants: 892, hadiah: 1, status: 'active', minSpending: 75000, ), DrawEvent( id: "4", name: "Sneakers Limited", description: "Undian Sepatu Nike Air Jordan\nEdition terbatas collectors", entryPoints: 0, icon: "👟", imageUrl: "https://images.unsplash.com/photo-1549298916-b41d501d3772?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFF32CD32), prize: "Nike Air Jordan", prizeValue: "Rp 3.500.000", drawDate: DateTime.now().add(Duration(days: 3)), totalParticipants: 567, hadiah: 3, status: 'active', minSpending: 30000, ), DrawEvent( id: "5", name: "Camera DSLR", description: "Undian Kamera Canon EOS\nKamera profesional untuk fotografer", entryPoints: 0, icon: "📷", imageUrl: "https://images.unsplash.com/photo-1571019613454-1cb2f99b2d8b?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFF8B4513), prize: "Canon EOS R5", prizeValue: "Rp 25.000.000", drawDate: DateTime.now().add(Duration(days: 7)), totalParticipants: 334, hadiah: 1, status: 'active', minSpending: 150000, ), DrawEvent( id: "6", name: "PlayStation 5", description: "Undian Gaming Console\nPS5 bundle dengan 3 games", entryPoints: 0, icon: "🎮", imageUrl: "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFF0070D1), prize: "PlayStation 5", prizeValue: "Rp 8.500.000", drawDate: DateTime.now().add(Duration(days: 4)), totalParticipants: 1789, hadiah: 2, status: 'active', minSpending: 60000, ), DrawEvent( id: "7", name: "Motor Yamaha R15", description: "Undian Motor Sport\nYamaha R15 V4 warna special edition", entryPoints: 0, icon: "🏍️", imageUrl: "https://images.unsplash.com/photo-1512499617640-c74ae3a79d37?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFFDC143C), prize: "Yamaha R15 V4", prizeValue: "Rp 35.000.000", drawDate: DateTime.now().add(Duration(days: 10)), totalParticipants: 456, hadiah: 1, status: 'active', minSpending: 200000, ), DrawEvent( id: "8", name: "Home Theater", description: "Undian Sound System\nSony Home Theater 7.1 surround", entryPoints: 0, icon: "🔊", imageUrl: "https://images.unsplash.com/photo-1484704849700-f032a568e944?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFF4B0082), prize: "Sony HT-A7000", prizeValue: "Rp 12.000.000", drawDate: DateTime.now().add(Duration(days: 6)), totalParticipants: 298, hadiah: 1, status: 'active', minSpending: 80000, ), DrawEvent( id: "9", name: "Luxury Watch", description: "Undian Jam Tangan Mewah\nRolex Submariner Swiss Made", entryPoints: 0, icon: "⌚", imageUrl: "https://images.unsplash.com/photo-1434493789847-2f02dc6ca35d?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFFB8860B), prize: "Rolex Submariner", prizeValue: "Rp 150.000.000", drawDate: DateTime.now().add(Duration(days: 14)), totalParticipants: 123, hadiah: 1, status: 'active', minSpending: 500000, ), DrawEvent( id: "10", name: "Travel Voucher Bali", description: "Undian Liburan Gratis\nPaket tour Bali 4D3N all inclusive", entryPoints: 0, icon: "✈️", imageUrl: "https://images.unsplash.com/photo-1558618666-fbd1c326d4a4?w=400&h=200&fit=crop&crop=center", primaryColor: Color(0xFF20B2AA), prize: "Bali Tour Package", prizeValue: "Rp 10.000.000", drawDate: DateTime.now().subtract(Duration(days: 2)), totalParticipants: 2156, hadiah: 5, status: 'ended', minSpending: 40000, ), ]; @override void initState() { super.initState(); _scrollController.addListener(_onScroll); } @override void dispose() { _dateFilterController.dispose(); _scrollController.dispose(); super.dispose(); } void _onScroll() { final bool isCollapsed = _scrollController.hasClients && _scrollController.offset > (280 - kToolbarHeight); if (_isCollapsed != isCollapsed) { setState(() { _isCollapsed = isCollapsed; }); } } List get filteredDraws { List filtered = drawEvents; if (_selectedFilterDate != null) { filtered = filtered.where((draw) { return draw.drawDate.year == _selectedFilterDate!.year && draw.drawDate.month == _selectedFilterDate!.month && draw.drawDate.day == _selectedFilterDate!.day; }).toList(); } return filtered; } String _getTimeRemaining(DateTime targetDate) { final now = DateTime.now(); final difference = targetDate.difference(now); if (difference.isNegative) return "Berakhir"; if (difference.inHours > 0) { return "${difference.inHours}h ${difference.inMinutes % 60}m"; } else if (difference.inMinutes > 0) { return "${difference.inMinutes}m"; } else { return "Sekarang!"; } } Future _selectDate() async { final DateTime? picked = await showDatePicker( context: context, initialDate: _selectedFilterDate ?? DateTime.now(), firstDate: DateTime.now().subtract(Duration(days: 365)), lastDate: DateTime.now().add(Duration(days: 365)), ); if (picked != null) { setState(() { _selectedFilterDate = picked; _dateFilterController.text = "${picked.day}/${picked.month}/${picked.year}"; }); } } void _clearDateFilter() { setState(() { _selectedFilterDate = null; _dateFilterController.clear(); }); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppColor.background, body: CustomScrollView( controller: _scrollController, slivers: [ // SliverAppBar with Carousel Background SliverAppBar( expandedHeight: 280, floating: false, pinned: true, backgroundColor: AppColor.surface, leading: Container( margin: EdgeInsets.all(8), decoration: BoxDecoration( color: Colors.black.withOpacity(0.3), borderRadius: BorderRadius.circular(20), ), child: IconButton( icon: Icon(Icons.arrow_back, color: Colors.white), onPressed: () => Navigator.of(context).pop(), ), ), flexibleSpace: FlexibleSpaceBar( title: AnimatedOpacity( opacity: _isCollapsed ? 1.0 : 0.0, duration: Duration(milliseconds: 200), child: Text( "Undian", style: AppStyle.lg.copyWith( fontWeight: FontWeight.w600, color: AppColor.textPrimary, ), ), ), titlePadding: EdgeInsets.only(left: 72, bottom: 16), collapseMode: CollapseMode.parallax, background: Stack( children: [ // Carousel Slider Positioned.fill( child: CarouselSlider.builder( carouselController: _carouselController, itemCount: banners.length, options: CarouselOptions( height: double.infinity, viewportFraction: 1.0, autoPlay: true, autoPlayInterval: Duration(seconds: 4), autoPlayAnimationDuration: Duration(milliseconds: 800), onPageChanged: (index, reason) { setState(() => _currentBannerIndex = index); }, ), itemBuilder: (context, index, realIndex) { final banner = banners[index]; return GestureDetector( onTap: () { context.router.push(DrawDetailRoute()); }, child: AppNetworkImage(url: banner.imageUrl), ); }, ), ), // Page indicators Positioned( bottom: 20, left: 0, right: 0, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: banners.asMap().entries.map((entry) { return GestureDetector( onTap: () => _carouselController.animateToPage(entry.key), child: Container( width: _currentBannerIndex == entry.key ? 24 : 8, height: 8, margin: EdgeInsets.symmetric(horizontal: 4), decoration: BoxDecoration( borderRadius: BorderRadius.circular(4), color: _currentBannerIndex == entry.key ? Colors.white : Colors.white.withOpacity(0.4), ), ), ); }).toList(), ), ), ], ), ), ), // Date Filter SliverToBoxAdapter( child: Container( margin: EdgeInsets.all(16), child: TextFormField( controller: _dateFilterController, readOnly: true, onTap: _selectDate, decoration: InputDecoration( hintText: "Filter berdasarkan tanggal", hintStyle: AppStyle.md.copyWith( color: AppColor.textSecondary, ), prefixIcon: Icon( Icons.calendar_today, color: AppColor.textSecondary, ), suffixIcon: _selectedFilterDate != null ? IconButton( icon: Icon( Icons.clear, color: AppColor.textSecondary, ), onPressed: _clearDateFilter, ) : null, border: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: AppColor.border), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: AppColor.border), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: AppColor.primary, width: 2), ), filled: true, fillColor: AppColor.surface, contentPadding: EdgeInsets.symmetric( horizontal: 16, vertical: 14, ), ), style: AppStyle.md.copyWith(color: AppColor.textPrimary), ), ), ), // Draw List Header SliverToBoxAdapter( child: Padding( padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: Text( "Daftar Undian (${filteredDraws.length})", style: AppStyle.lg.copyWith( fontWeight: FontWeight.w600, color: AppColor.textPrimary, ), ), ), ), // Draw List SliverList( delegate: SliverChildBuilderDelegate((context, index) { final draw = filteredDraws[index]; return Container( margin: EdgeInsets.symmetric(horizontal: 16, vertical: 4), child: _buildSimpleDrawCard(draw), ); }, childCount: filteredDraws.length), ), // Bottom padding SliverToBoxAdapter(child: SizedBox(height: 100)), ], ), ); } Widget _buildSimpleDrawCard(DrawEvent draw) { final timeRemaining = _getTimeRemaining(draw.drawDate); return GestureDetector( onTap: () => context.router.push(DrawDetailRoute()), child: Container( margin: EdgeInsets.only(bottom: 8), padding: EdgeInsets.all(16), decoration: BoxDecoration( gradient: LinearGradient( colors: [draw.primaryColor, draw.primaryColor.withOpacity(0.8)], begin: Alignment.topLeft, end: Alignment.bottomRight, ), borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: AppColor.black.withOpacity(0.08), blurRadius: 8, offset: Offset(0, 2), ), ], ), child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Name Text( draw.name, style: AppStyle.lg.copyWith( fontWeight: FontWeight.w600, color: AppColor.textWhite, ), ), SizedBox(height: 6), // Description Text( draw.description, style: AppStyle.sm.copyWith( color: AppColor.textWhite.withOpacity(0.9), ), maxLines: 2, overflow: TextOverflow.ellipsis, ), SizedBox(height: 8), // Date and participants Row( children: [ Icon( Icons.access_time, size: 16, color: AppColor.textWhite.withOpacity(0.8), ), SizedBox(width: 4), Text( draw.isActive ? "Berakhir: $timeRemaining" : "Selesai", style: AppStyle.xs.copyWith( color: AppColor.textWhite.withOpacity(0.8), fontWeight: FontWeight.w500, ), ), SizedBox(width: 16), Icon( Icons.people, size: 16, color: AppColor.textWhite.withOpacity(0.8), ), SizedBox(width: 4), Text( "${draw.totalParticipants}", style: AppStyle.xs.copyWith( color: AppColor.textWhite.withOpacity(0.8), fontWeight: FontWeight.w500, ), ), ], ), ], ), ), // Prize info Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ Text(draw.icon, style: TextStyle(fontSize: 28)), SizedBox(height: 4), Text( draw.prize, style: AppStyle.sm.copyWith( fontWeight: FontWeight.bold, color: AppColor.textWhite, ), ), Text( draw.prizeValue, style: AppStyle.xs.copyWith( color: AppColor.textWhite.withOpacity(0.8), fontWeight: FontWeight.w500, ), ), ], ), ], ), ), ); } }