import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../providers/cart_provider.dart'; import '../providers/cart_total_provider.dart'; import '../../../../shared/widgets/price_display.dart'; /// Bottom bar showing cart total and checkout button class CartBottomBar extends ConsumerWidget { const CartBottomBar({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final cartAsync = ref.watch(cartProvider); final totalData = ref.watch(cartTotalProvider); final theme = Theme.of(context); final itemCount = cartAsync.value?.length ?? 0; final hasItems = itemCount > 0; return AnimatedContainer( duration: const Duration(milliseconds: 300), height: hasItems ? 80 : 0, child: hasItems ? Container( decoration: BoxDecoration( color: theme.colorScheme.primaryContainer, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, -2), ), ], ), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), child: Row( children: [ // Cart icon with badge Stack( clipBehavior: Clip.none, children: [ Icon( Icons.shopping_cart, size: 32, color: theme.colorScheme.onPrimaryContainer, ), Positioned( right: -8, top: -8, child: Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: theme.colorScheme.error, shape: BoxShape.circle, ), constraints: const BoxConstraints( minWidth: 20, minHeight: 20, ), child: Center( child: Text( '$itemCount', style: theme.textTheme.labelSmall?.copyWith( color: theme.colorScheme.onError, fontWeight: FontWeight.bold, ), ), ), ), ), ], ), const SizedBox(width: 16), // Total info Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '$itemCount item${itemCount == 1 ? '' : 's'}', style: theme.textTheme.bodySmall?.copyWith( color: theme.colorScheme.onPrimaryContainer, ), ), const SizedBox(height: 2), PriceDisplay( price: totalData.total, style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.onPrimaryContainer, ), ), ], ), ), // View Cart button OutlinedButton( onPressed: () { _showCartBottomSheet(context, ref); }, style: OutlinedButton.styleFrom( foregroundColor: theme.colorScheme.onPrimaryContainer, side: BorderSide( color: theme.colorScheme.onPrimaryContainer, ), ), child: const Text('View Cart'), ), const SizedBox(width: 8), // Checkout button FilledButton.icon( onPressed: () { // TODO: Navigate to checkout ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Checkout coming soon!'), ), ); }, icon: const Icon(Icons.payment), label: const Text('Checkout'), style: FilledButton.styleFrom( backgroundColor: theme.colorScheme.primary, foregroundColor: theme.colorScheme.onPrimary, padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 12, ), ), ), ], ), ) : const SizedBox.shrink(), ); } void _showCartBottomSheet(BuildContext context, WidgetRef ref) { showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) => DraggableScrollableSheet( initialChildSize: 0.7, minChildSize: 0.5, maxChildSize: 0.95, expand: false, builder: (context, scrollController) { return CartBottomSheet(scrollController: scrollController); }, ), ); } } /// Cart bottom sheet content class CartBottomSheet extends ConsumerWidget { final ScrollController scrollController; const CartBottomSheet({ super.key, required this.scrollController, }); @override Widget build(BuildContext context, WidgetRef ref) { final cartAsync = ref.watch(cartProvider); final totalData = ref.watch(cartTotalProvider); final theme = Theme.of(context); return Container( decoration: BoxDecoration( color: theme.colorScheme.surface, borderRadius: const BorderRadius.vertical(top: Radius.circular(20)), ), child: Column( children: [ // Handle bar Container( margin: const EdgeInsets.symmetric(vertical: 12), width: 40, height: 4, decoration: BoxDecoration( color: theme.colorScheme.onSurfaceVariant.withOpacity(0.4), borderRadius: BorderRadius.circular(2), ), ), // Header Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Shopping Cart', style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, ), ), if (cartAsync.value?.isNotEmpty ?? false) TextButton.icon( onPressed: () { ref.read(cartProvider.notifier).clearCart(); }, icon: const Icon(Icons.delete_sweep), label: const Text('Clear'), ), ], ), ), const Divider(), // Cart items Expanded( child: cartAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (error, stack) => Center(child: Text('Error: $error')), data: (items) { if (items.isEmpty) { return const Center( child: Text('Cart is empty'), ); } return ListView.separated( controller: scrollController, padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: items.length, separatorBuilder: (context, index) => const Divider(), itemBuilder: (context, index) { final item = items[index]; return ListTile( contentPadding: EdgeInsets.zero, title: Text(item.productName), subtitle: PriceDisplay( price: item.price, style: theme.textTheme.bodyMedium, ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ // Quantity controls IconButton( icon: const Icon(Icons.remove_circle_outline), onPressed: item.quantity > 1 ? () => ref .read(cartProvider.notifier) .updateQuantity( item.productId, item.quantity - 1, ) : null, iconSize: 20, ), Text( '${item.quantity}', style: theme.textTheme.titleMedium, ), IconButton( icon: const Icon(Icons.add_circle_outline), onPressed: () => ref .read(cartProvider.notifier) .updateQuantity( item.productId, item.quantity + 1, ), iconSize: 20, ), // Remove button IconButton( icon: const Icon(Icons.delete_outline), onPressed: () => ref .read(cartProvider.notifier) .removeItem(item.productId), color: theme.colorScheme.error, iconSize: 20, ), ], ), ); }, ); }, ), ), // Summary Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: theme.colorScheme.surfaceContainerHighest, border: Border( top: BorderSide(color: theme.dividerColor), ), ), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text('Subtotal:', style: theme.textTheme.bodyLarge), PriceDisplay( price: totalData.subtotal, style: theme.textTheme.bodyLarge, ), ], ), if (totalData.tax > 0) ...[ const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Tax (${(totalData.taxRate * 100).toStringAsFixed(0)}%):', style: theme.textTheme.bodyLarge, ), PriceDisplay( price: totalData.tax, style: theme.textTheme.bodyLarge, ), ], ), ], const Divider(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Total:', style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, ), ), PriceDisplay( price: totalData.total, style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, color: theme.colorScheme.primary, ), ), ], ), ], ), ), ], ), ); } }