import 'package:flutter/material.dart'; import 'services/cart_service.dart'; class CheckoutPage extends StatefulWidget { const CheckoutPage({super.key}); @override State createState() => _CheckoutPageState(); } class _CheckoutPageState extends State { final CartService _cartService = CartService(); final _formKey = GlobalKey(); bool _isLoading = false; // To store mock final total from cart page late double _finalTotal; @override void initState() { super.initState(); // Calculate final total once when page loads _finalTotal = _cartService.totalPrice + (_cartService.totalPrice * 0.07) + // Mock tax (_cartService.totalPrice > 50 ? 0 : 5.00); // Mock shipping // If cart is empty when navigating here, redirect. WidgetsBinding.instance.addPostFrameCallback((_) { if (_cartService.items.isEmpty && mounted) { Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Your cart is empty. Cannot proceed to checkout.')), ); } }); } void _placeOrder() async { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); setState(() => _isLoading = true); await Future.delayed(const Duration(seconds: 2)); // Simulate network call final orderTotal = _finalTotal; // Use the calculated final total _cartService.clearCart(); setState(() => _isLoading = false); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Mock order placed successfully for \$${orderTotal.toStringAsFixed(2)}!'), duration: const Duration(seconds: 3), backgroundColor: Theme.of(context).colorScheme.primary, // Or a specific success color ), ); Navigator.pushNamedAndRemoveUntil(context, '/home', (route) => false); } } } @override Widget build(BuildContext context) { final theme = Theme.of(context); final cartItems = _cartService.items; // This check is a fallback, initState handles initial redirection if (cartItems.isEmpty && !_isLoading) { return const Scaffold(body: Center(child: CircularProgressIndicator())); } return Scaffold( appBar: AppBar( title: const Text('Checkout'), centerTitle: true, ), body: SingleChildScrollView( padding: const EdgeInsets.all(16.0), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text('Order Summary', style: theme.textTheme.headlineSmall), const SizedBox(height: 8), Card( child: Padding( padding: const EdgeInsets.all(12.0), child: Column( children: [ ...cartItems.map((item) => ListTile( leading: Image.network(item.product.imageUrl, width: 40, height: 40, fit: BoxFit.cover, errorBuilder: (c,o,s) => const Icon(Icons.image)), title: Text('${item.product.name} (x${item.quantity})', style: theme.textTheme.bodyMedium), trailing: Text('\$${item.subtotal.toStringAsFixed(2)}', style: theme.textTheme.bodyMedium), )), const Divider(height: 20, thickness: 0.5), ListTile( title: Text('Subtotal', style: theme.textTheme.titleSmall), trailing: Text('\$${_cartService.totalPrice.toStringAsFixed(2)}', style: theme.textTheme.titleSmall), ), ListTile( title: Text('Est. Tax (7%)', style: theme.textTheme.titleSmall), trailing: Text('\$${(_cartService.totalPrice * 0.07).toStringAsFixed(2)}', style: theme.textTheme.titleSmall), ), ListTile( title: Text('Shipping', style: theme.textTheme.titleSmall), trailing: Text(_cartService.totalPrice > 50 ? 'FREE' : '\$5.00', style: theme.textTheme.titleSmall), ), const Divider(height: 20, thickness: 1), ListTile( title: Text('Total Amount', style: theme.textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold)), trailing: Text('\$${_finalTotal.toStringAsFixed(2)}', style: theme.textTheme.titleLarge?.copyWith(color: theme.colorScheme.primary, fontWeight: FontWeight.bold)), ), ], ), ), ), const SizedBox(height: 24), Text('Shipping Information (Mock)', style: theme.textTheme.headlineSmall), const SizedBox(height: 12), _buildTextField(label: 'Full Name', icon: Icons.person_outline, validator: (val) => val!.isEmpty ? 'Enter full name' : null), const SizedBox(height: 12), _buildTextField(label: 'Address Line 1', icon: Icons.home_outlined, validator: (val) => val!.isEmpty ? 'Enter address' : null), const SizedBox(height: 12), _buildTextField(label: 'City', icon: Icons.location_city_outlined, validator: (val) => val!.isEmpty ? 'Enter city' : null), const SizedBox(height: 12), _buildTextField(label: 'Postal Code', icon: Icons.markunread_mailbox_outlined, keyboardType: TextInputType.number, validator: (val) => val!.isEmpty ? 'Enter postal code' : null), const SizedBox(height: 24), Text('Payment Details (Mock)', style: theme.textTheme.headlineSmall), const SizedBox(height: 12), _buildTextField(label: 'Card Number', icon: Icons.credit_card_outlined, keyboardType: TextInputType.number, validator: (val) => val!.isEmpty ? 'Enter card number' : null), const SizedBox(height: 12), Row( children: [ Expanded(child: _buildTextField(label: 'Expiry Date (MM/YY)', icon: Icons.calendar_today_outlined, keyboardType: TextInputType.datetime, validator: (val) => val!.isEmpty ? 'Enter expiry' : null)), const SizedBox(width: 12), Expanded(child: _buildTextField(label: 'CVV', icon: Icons.lock_outline, keyboardType: TextInputType.number, validator: (val) => val!.isEmpty ? 'Enter CVV' : null)), ], ), const SizedBox(height: 32), _isLoading ? const Center(child: CircularProgressIndicator()) : ElevatedButton( onPressed: _placeOrder, child: const Text('Place Mock Order'), ), const SizedBox(height: 16), ], ), ), ), ); } Widget _buildTextField({required String label, required IconData icon, TextInputType? keyboardType, required FormFieldValidator validator}) { return TextFormField( decoration: InputDecoration( labelText: label, prefixIcon: Icon(icon), ), keyboardType: keyboardType, validator: validator, autovalidateMode: AutovalidateMode.onUserInteraction, ); } }