import 'package:flutter/material.dart'; import '../services/odoo_service.dart'; import '../theme/app_theme.dart'; import '../widgets/carousel_widget.dart'; import '../widgets/promo_card_widget.dart'; import '../widgets/subscription_list_widget.dart'; /// Home tab — shows loyalty card, subscriptions, carousel, and promo highlights. /// Notification polling and AppBar are handled by MainShell. class LoyaltyDashboard extends StatefulWidget { final int partnerId; const LoyaltyDashboard({super.key, required this.partnerId}); @override State createState() => _LoyaltyDashboardState(); } class _LoyaltyDashboardState extends State { List _loyaltyCards = []; List _subscriptions = []; List _carouselSlides = []; List _promos = []; bool _isLoading = true; @override void initState() { super.initState(); _fetchAll(); } Future _fetchAll() async { setState(() => _isLoading = true); try { final results = await Future.wait([ OdooService().getLoyaltyCards(widget.partnerId), OdooService().getSubscriptionCards(widget.partnerId), OdooService().getCmsContent(), ]); final rawCards = results[0] as List; final rawSubs = results[1] as List; final cms = results[2] as Map; final List cards = []; final List subs = [...rawSubs]; for (var card in rawCards) { final progName = (card['program_id']?[1] as String? ?? '').toLowerCase(); final isSub = progName.contains('subscription') || card['subscription_start_date'] != null || card['subscription_end_date'] != null; if (isSub) { final code = card['code']; if (!subs.any((s) => s['code'] == code)) { subs.add(card); } } else { cards.add(card); } } if (mounted) { setState(() { _loyaltyCards = cards; _subscriptions = subs; _carouselSlides = (cms['carousel'] as List?) ?? []; _promos = (cms['promos'] as List?) ?? []; _isLoading = false; }); } } catch (e) { if (mounted) { setState(() => _isLoading = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error loading data: $e')), ); } } } @override Widget build(BuildContext context) { if (_isLoading) { return const Center(child: CircularProgressIndicator()); } return RefreshIndicator( onRefresh: _fetchAll, child: ListView( children: [ // ── Loyalty Card ───────────────────────────────────────────── if (_loyaltyCards.isEmpty) Padding( padding: const EdgeInsets.fromLTRB(24, 32, 24, 0), child: Text( 'No active loyalty card yet.', style: Theme.of(context).textTheme.titleLarge, textAlign: TextAlign.center, ), ) else ..._loyaltyCards.map((card) => _LoyaltyCardTile(card: card)), // ── Subscriptions ───────────────────────────────────────────── if (_subscriptions.isNotEmpty) SubscriptionListWidget(subscriptions: _subscriptions), const SizedBox(height: 20), // ── Carousel ────────────────────────────────────────────────── if (_carouselSlides.isNotEmpty) ...[ CarouselWidget(slides: _carouselSlides), const SizedBox(height: 24), ], // ── Promo Highlights ───────────────────────────────────────── if (_promos.isNotEmpty) ...[ PromoCardRow(promos: _promos), const SizedBox(height: 24), ], ], ), ); } } class _LoyaltyCardTile extends StatelessWidget { final dynamic card; const _LoyaltyCardTile({required this.card}); @override Widget build(BuildContext context) { final programName = (card['program_id']?[1] as String? ?? '').toLowerCase(); String tier = 'Member'; if (programName.contains('silver')) tier = 'Silver Member'; if (programName.contains('gold')) tier = 'Gold Member'; if (programName.contains('platinum')) tier = 'Platinum Member'; return Container( margin: const EdgeInsets.fromLTRB(16, 16, 16, 0), padding: const EdgeInsets.all(24), decoration: const BoxDecoration( color: AppTheme.surfaceContainerHighest, borderRadius: BorderRadius.zero, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Text( '${card['program_id']?[1] ?? 'Loyalty Program'}', style: Theme.of(context).textTheme.titleLarge, softWrap: true, ), ), const SizedBox(width: 12), Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: const BoxDecoration( color: AppTheme.secondaryContainer, borderRadius: BorderRadius.zero, ), child: Text( tier, style: Theme.of(context).textTheme.labelLarge?.copyWith( color: AppTheme.onSecondaryContainer, fontWeight: FontWeight.bold, ), ), ), ], ), const SizedBox(height: 20), Text('Membership Code', style: Theme.of(context).textTheme.bodyMedium), const SizedBox(height: 4), Text('${card['code'] ?? 'N/A'}', style: Theme.of(context).textTheme.titleMedium), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.end, children: [ Text('Available Points', style: Theme.of(context).textTheme.bodyMedium), Text( '${card['points'] ?? 0}', style: Theme.of(context).textTheme.displayMedium?.copyWith( color: AppTheme.primary, ), ), ], ), ], ), ); } }