## Learning Objectives

By the end of this chapter, you will be able to:

- Build a complete e-commerce application
- Implement product listing and details screens
- Create a shopping cart with add/remove functionality
- Implement state management for cart operations
- Design a checkout process
- Create a user-friendly product browsing experience

1

## Project Overview

### Project Goal

Build a "ShopMart" e-commerce app that displays products, allows users to browse products, view details, add items to cart, manage cart items, and complete a checkout process.

### Features to Implement

- Product listing with categories
- Product detail view
- Shopping cart with add/remove/update quantities
- Cart total calculation
- Checkout screen
- Order confirmation
- Search functionality

2

## Project Setup

### Step 1: Create Project

    flutter create shopmart
    cd shopmart

### Step 2: Add Dependencies

Update `pubspec.yaml`:

### pubspec.yaml

    name: shopmart
    description: A Flutter e-commerce application
    version: 1.0.0+1

    environment:
      sdk: '>=3.0.0 <4.0.0'

    dependencies:
      flutter:
        sdk: flutter
      provider: ^6.1.1
      cupertino_icons: ^1.0.6

    dev_dependencies:
      flutter_test:
        sdk: flutter
      flutter_lints: ^3.0.0

    flutter:
      uses-material-design: true

### Step 3: Install Dependencies

    flutter pub get

3

## Project Structure

### Suggested Folder Layout

    lib/
      main.dart
      models/
        product.dart
        cart_item.dart
        order.dart
      providers/
        cart_provider.dart
      data/
        products_data.dart
      screens/
        home_screen.dart
        product_detail_screen.dart
        cart_screen.dart
        checkout_screen.dart
        order_confirmation_screen.dart
      widgets/
        product_card.dart
        cart_item_widget.dart
        category_chip.dart
      utils/
        constants.dart

4

## Creating Product Model

### lib/models/product.dart

    class Product {
      final String id;
      final String name;
      final String description;
      final double price;
      final String imageUrl;
      final String category;
      final int stock;
      final double? rating;
      final int? reviewCount;

      Product({
        required this.id,
        required this.name,
        required this.description,
        required this.price,
        required this.imageUrl,
        required this.category,
        required this.stock,
        this.rating,
        this.reviewCount,
      });

      String get formattedPrice => '\$${price.toStringAsFixed(2)}';

      bool get inStock => stock > 0;
    }

5

## Creating Cart Item Model

### lib/models/cart_item.dart

    import 'product.dart';

    class CartItem {
      final Product product;
      int quantity;

      CartItem({
        required this.product,
        this.quantity = 1,
      });

      double get totalPrice => product.price * quantity;

      String get formattedTotalPrice => '\$${totalPrice.toStringAsFixed(2)}';

      CartItem copyWith({
        Product? product,
        int? quantity,
      }) {
        return CartItem(
          product: product ?? this.product,
          quantity: quantity ?? this.quantity,
        );
      }
    }

6

## Creating Order Model

### lib/models/order.dart

    import 'cart_item.dart';

    class Order {
      final String id;
      final List items;
      final double totalAmount;
      final DateTime orderDate;
      final String status;
      final String? shippingAddress;
      final String? paymentMethod;

      Order({
        required this.id,
        required this.items,
        required this.totalAmount,
        required this.orderDate,
        this.status = 'Pending',
        this.shippingAddress,
        this.paymentMethod,
      });

      String get formattedTotalAmount => '\$${totalAmount.toStringAsFixed(2)}';

      int get totalItems => items.fold(0, (sum, item) => sum + item.quantity);
    }

7

## Creating Cart Provider

### lib/providers/cart_provider.dart

    import 'package:flutter/foundation.dart';
    import '../models/product.dart';
    import '../models/cart_item.dart';

    class CartProvider with ChangeNotifier {
      List _items = [];

      List get items => _items;

      int get itemCount => _items.fold(0, (sum, item) => sum + item.quantity);

      double get totalAmount {
        return _items.fold(0.0, (sum, item) => sum + item.totalPrice);
      }

      String get formattedTotalAmount => '\$${totalAmount.toStringAsFixed(2)}';

      bool isInCart(Product product) {
        return _items.any((item) => item.product.id == product.id);
      }

      int getQuantity(Product product) {
        final item = _items.firstWhere(
          (item) => item.product.id == product.id,
          orElse: () => CartItem(product: product, quantity: 0),
        );
        return item.quantity;
      }

      void addItem(Product product) {
        final existingIndex = _items.indexWhere(
          (item) => item.product.id == product.id,
        );

        if (existingIndex >= 0) {
          _items[existingIndex].quantity++;
        } else {
          _items.add(CartItem(product: product, quantity: 1));
        }
        notifyListeners();
      }

      void removeItem(Product product) {
        final existingIndex = _items.indexWhere(
          (item) => item.product.id == product.id,
        );

        if (existingIndex >= 0) {
          if (_items[existingIndex].quantity > 1) {
            _items[existingIndex].quantity--;
          } else {
            _items.removeAt(existingIndex);
          }
          notifyListeners();
        }
      }

      void removeItemCompletely(Product product) {
        _items.removeWhere((item) => item.product.id == product.id);
        notifyListeners();
      }

      void updateQuantity(Product product, int quantity) {
        if (quantity <= 0) {
          removeItemCompletely(product);
          return;
        }

        final existingIndex = _items.indexWhere(
          (item) => item.product.id == product.id,
        );

        if (existingIndex >= 0) {
          _items[existingIndex].quantity = quantity;
        } else {
          _items.add(CartItem(product: product, quantity: quantity));
        }
        notifyListeners();
      }

      void clearCart() {
        _items.clear();
        notifyListeners();
      }
    }

8

## Creating Products Data

### lib/data/products_data.dart

    import '../models/product.dart';

    class ProductsData {
      static List getProducts() {
        return [
          Product(
            id: '1',
            name: 'Wireless Headphones',
            description: 'High-quality wireless headphones with noise cancellation',
            price: 99.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=Headphones',
            category: 'Electronics',
            stock: 50,
            rating: 4.5,
            reviewCount: 120,
          ),
          Product(
            id: '2',
            name: 'Smart Watch',
            description: 'Feature-rich smartwatch with fitness tracking',
            price: 199.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=SmartWatch',
            category: 'Electronics',
            stock: 30,
            rating: 4.7,
            reviewCount: 89,
          ),
          Product(
            id: '3',
            name: 'Running Shoes',
            description: 'Comfortable running shoes for daily workouts',
            price: 79.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=Shoes',
            category: 'Fashion',
            stock: 100,
            rating: 4.3,
            reviewCount: 200,
          ),
          Product(
            id: '4',
            name: 'Laptop Backpack',
            description: 'Durable backpack with laptop compartment',
            price: 49.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=Backpack',
            category: 'Fashion',
            stock: 75,
            rating: 4.6,
            reviewCount: 150,
          ),
          Product(
            id: '5',
            name: 'Coffee Maker',
            description: 'Programmable coffee maker for your morning brew',
            price: 89.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=CoffeeMaker',
            category: 'Home',
            stock: 40,
            rating: 4.4,
            reviewCount: 95,
          ),
          Product(
            id: '6',
            name: 'Desk Lamp',
            description: 'LED desk lamp with adjustable brightness',
            price: 29.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=Lamp',
            category: 'Home',
            stock: 60,
            rating: 4.2,
            reviewCount: 78,
          ),
          Product(
            id: '7',
            name: 'Yoga Mat',
            description: 'Non-slip yoga mat for your fitness routine',
            price: 24.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=YogaMat',
            category: 'Sports',
            stock: 80,
            rating: 4.5,
            reviewCount: 110,
          ),
          Product(
            id: '8',
            name: 'Water Bottle',
            description: 'Stainless steel insulated water bottle',
            price: 19.99,
            imageUrl: 'https://via.placeholder.com/300x300?text=Bottle',
            category: 'Sports',
            stock: 120,
            rating: 4.7,
            reviewCount: 250,
          ),
        ];
      }

      static List getCategories() {
        return ['All', 'Electronics', 'Fashion', 'Home', 'Sports'];
      }
    }

9

## Creating Product Card Widget

### lib/widgets/product_card.dart

    import 'package:flutter/material.dart';
    import '../models/product.dart';

    class ProductCard extends StatelessWidget {
      final Product product;
      final VoidCallback onTap;

      const ProductCard({
        Key? key,
        required this.product,
        required this.onTap,
      }) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return Card(
          margin: EdgeInsets.all(8),
          child: InkWell(
            onTap: onTap,
            borderRadius: BorderRadius.circular(12),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                ClipRRect(
                  borderRadius: BorderRadius.vertical(top: Radius.circular(12)),
                  child: Image.network(
                    product.imageUrl,
                    height: 150,
                    width: double.infinity,
                    fit: BoxFit.cover,
                    errorBuilder: (context, error, stackTrace) {
                      return Container(
                        height: 150,
                        color: Colors.grey[300],
                        child: Icon(Icons.image_not_supported),
                      );
                    },
                  ),
                ),
                Padding(
                  padding: EdgeInsets.all(12),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        product.name,
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                        ),
                        maxLines: 2,
                        overflow: TextOverflow.ellipsis,
                      ),
                      SizedBox(height: 4),
                      Text(
                        product.formattedPrice,
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                          color: Colors.blue,
                        ),
                      ),
                      if (product.rating != null) ...[
                        SizedBox(height: 4),
                        Row(
                          children: [
                            Icon(Icons.star, color: Colors.amber, size: 16),
                            SizedBox(width: 4),
                            Text(
                              '${product.rating}',
                              style: TextStyle(fontSize: 12),
                            ),
                            if (product.reviewCount != null) ...[
                              SizedBox(width: 4),
                              Text(
                                '(${product.reviewCount})',
                                style: TextStyle(fontSize: 12, color: Colors.grey),
                              ),
                            ],
                          ],
                        ),
                      ],
                      SizedBox(height: 4),
                      Text(
                        product.inStock ? 'In Stock' : 'Out of Stock',
                        style: TextStyle(
                          fontSize: 12,
                          color: product.inStock ? Colors.green : Colors.red,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }

10

## Creating Category Chip Widget

### lib/widgets/category_chip.dart

    import 'package:flutter/material.dart';

    class CategoryChip extends StatelessWidget {
      final String category;
      final bool isSelected;
      final VoidCallback onTap;

      const CategoryChip({
        Key? key,
        required this.category,
        required this.isSelected,
        required this.onTap,
      }) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return FilterChip(
          label: Text(category),
          selected: isSelected,
          onSelected: (_) => onTap(),
          selectedColor: Colors.blue[100],
          checkmarkColor: Colors.blue,
          labelStyle: TextStyle(
            color: isSelected ? Colors.blue : Colors.black87,
            fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
          ),
        );
      }
    }

11

## Creating Home Screen

### lib/screens/home_screen.dart

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import '../models/product.dart';
    import '../data/products_data.dart';
    import '../providers/cart_provider.dart';
    import '../widgets/product_card.dart';
    import '../widgets/category_chip.dart';
    import 'product_detail_screen.dart';
    import 'cart_screen.dart';

    class HomeScreen extends StatefulWidget {
      @override
      _HomeScreenState createState() => _HomeScreenState();
    }

    class _HomeScreenState extends State {
      String _selectedCategory = 'All';
      String _searchQuery = '';
      final TextEditingController _searchController = TextEditingController();

      List get _filteredProducts {
        var products = ProductsData.getProducts();

        // Filter by category
        if (_selectedCategory != 'All') {
          products = products.where((p) => p.category == _selectedCategory).toList();
        }

        // Filter by search query
        if (_searchQuery.isNotEmpty) {
          products = products.where((p) {
            return p.name.toLowerCase().contains(_searchQuery.toLowerCase()) ||
                   p.description.toLowerCase().contains(_searchQuery.toLowerCase());
          }).toList();
        }

        return products;
      }

      @override
      void dispose() {
        _searchController.dispose();
        super.dispose();
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('ShopMart'),
            actions: [
              Consumer(
                builder: (context, cart, child) {
                  return Stack(
                    children: [
                      IconButton(
                        icon: Icon(Icons.shopping_cart),
                        onPressed: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(builder: (context) => CartScreen()),
                          );
                        },
                      ),
                      if (cart.itemCount > 0)
                        Positioned(
                          right: 8,
                          top: 8,
                          child: Container(
                            padding: EdgeInsets.all(4),
                            decoration: BoxDecoration(
                              color: Colors.red,
                              shape: BoxShape.circle,
                            ),
                            constraints: BoxConstraints(
                              minWidth: 16,
                              minHeight: 16,
                            ),
                            child: Text(
                              '${cart.itemCount}',
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 10,
                              ),
                              textAlign: TextAlign.center,
                            ),
                          ),
                        ),
                    ],
                  );
                },
              ),
            ],
          ),
          body: Column(
            children: [
              // Search bar
              Padding(
                padding: EdgeInsets.all(16),
                child: TextField(
                  controller: _searchController,
                  decoration: InputDecoration(
                    hintText: 'Search products...',
                    prefixIcon: Icon(Icons.search),
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                  onChanged: (value) {
                    setState(() {
                      _searchQuery = value;
                    });
                  },
                ),
              ),
              // Category chips
              Container(
                height: 50,
                child: ListView(
                  scrollDirection: Axis.horizontal,
                  padding: EdgeInsets.symmetric(horizontal: 16),
                  children: ProductsData.getCategories().map((category) {
                    return Padding(
                      padding: EdgeInsets.only(right: 8),
                      child: CategoryChip(
                        category: category,
                        isSelected: _selectedCategory == category,
                        onTap: () {
                          setState(() {
                            _selectedCategory = category;
                          });
                        },
                      ),
                    );
                  }).toList(),
                ),
              ),
              SizedBox(height: 8),
              // Products grid
              Expanded(
                child: _filteredProducts.isEmpty
                    ? Center(
                        child: Text(
                          'No products found',
                          style: TextStyle(fontSize: 16, color: Colors.grey),
                        ),
                      )
                    : GridView.builder(
                        padding: EdgeInsets.all(8),
                        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                          crossAxisCount: 2,
                          childAspectRatio: 0.75,
                          crossAxisSpacing: 8,
                          mainAxisSpacing: 8,
                        ),
                        itemCount: _filteredProducts.length,
                        itemBuilder: (context, index) {
                          final product = _filteredProducts[index];
                          return ProductCard(
                            product: product,
                            onTap: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                  builder: (context) => ProductDetailScreen(product: product),
                                ),
                              );
                            },
                          );
                        },
                      ),
              ),
            ],
          ),
        );
      }
    }

12

## Creating Product Detail Screen

### lib/screens/product_detail_screen.dart

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import '../models/product.dart';
    import '../providers/cart_provider.dart';

    class ProductDetailScreen extends StatelessWidget {
      final Product product;

      const ProductDetailScreen({Key? key, required this.product}) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(product.name),
          ),
          body: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // Product image
                Container(
                  height: 300,
                  width: double.infinity,
                  child: Image.network(
                    product.imageUrl,
                    fit: BoxFit.cover,
                    errorBuilder: (context, error, stackTrace) {
                      return Container(
                        color: Colors.grey[300],
                        child: Icon(Icons.image_not_supported, size: 64),
                      );
                    },
                  ),
                ),
                Padding(
                  padding: EdgeInsets.all(16),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      // Product name and price
                      Text(
                        product.name,
                        style: TextStyle(
                          fontSize: 24,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      SizedBox(height: 8),
                      Text(
                        product.formattedPrice,
                        style: TextStyle(
                          fontSize: 28,
                          fontWeight: FontWeight.bold,
                          color: Colors.blue,
                        ),
                      ),
                      SizedBox(height: 16),
                      // Rating
                      if (product.rating != null)
                        Row(
                          children: [
                            Icon(Icons.star, color: Colors.amber, size: 20),
                            SizedBox(width: 4),
                            Text(
                              '${product.rating}',
                              style: TextStyle(fontSize: 16),
                            ),
                            if (product.reviewCount != null) ...[
                              SizedBox(width: 4),
                              Text(
                                '(${product.reviewCount} reviews)',
                                style: TextStyle(fontSize: 14, color: Colors.grey),
                              ),
                            ],
                          ],
                        ),
                      SizedBox(height: 16),
                      Divider(),
                      SizedBox(height: 16),
                      // Description
                      Text(
                        'Description',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      SizedBox(height: 8),
                      Text(
                        product.description,
                        style: TextStyle(fontSize: 14),
                      ),
                      SizedBox(height: 16),
                      // Stock status
                      Row(
                        children: [
                          Icon(
                            product.inStock ? Icons.check_circle : Icons.cancel,
                            color: product.inStock ? Colors.green : Colors.red,
                          ),
                          SizedBox(width: 8),
                          Text(
                            product.inStock
                                ? 'In Stock (${product.stock} available)'
                                : 'Out of Stock',
                            style: TextStyle(
                              fontSize: 14,
                              color: product.inStock ? Colors.green : Colors.red,
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 24),
                      // Add to cart button
                      Consumer(
                        builder: (context, cart, child) {
                          final isInCart = cart.isInCart(product);
                          final quantity = cart.getQuantity(product);

                          return Column(
                            children: [
                              if (isInCart) ...[
                                Row(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    IconButton(
                                      icon: Icon(Icons.remove_circle),
                                      onPressed: () => cart.removeItem(product),
                                    ),
                                    Text(
                                      '$quantity',
                                      style: TextStyle(fontSize: 20),
                                    ),
                                    IconButton(
                                      icon: Icon(Icons.add_circle),
                                      onPressed: product.inStock
                                          ? () => cart.addItem(product)
                                          : null,
                                    ),
                                  ],
                                ),
                                SizedBox(height: 8),
                              ],
                              SizedBox(
                                width: double.infinity,
                                height: 50,
                                child: ElevatedButton.icon(
                                  onPressed: product.inStock
                                      ? () {
                                          cart.addItem(product);
                                          ScaffoldMessenger.of(context).showSnackBar(
                                            SnackBar(
                                              content: Text('${product.name} added to cart'),
                                              duration: Duration(seconds: 2),
                                            ),
                                          );
                                        }
                                      : null,
                                  icon: Icon(Icons.shopping_cart),
                                  label: Text(
                                    isInCart ? 'Add More to Cart' : 'Add to Cart',
                                    style: TextStyle(fontSize: 18),
                                  ),
                                  style: ElevatedButton.styleFrom(
                                    shape: RoundedRectangleBorder(
                                      borderRadius: BorderRadius.circular(12),
                                    ),
                                  ),
                                ),
                              ),
                            ],
                          );
                        },
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }

13

## Creating Cart Item Widget

### lib/widgets/cart_item_widget.dart

    import 'package:flutter/material.dart';
    import '../models/cart_item.dart';

    class CartItemWidget extends StatelessWidget {
      final CartItem item;
      final VoidCallback onRemove;
      final VoidCallback onDecrease;
      final VoidCallback onIncrease;

      const CartItemWidget({
        Key? key,
        required this.item,
        required this.onRemove,
        required this.onDecrease,
        required this.onIncrease,
      }) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return Card(
          margin: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
          child: ListTile(
            leading: ClipRRect(
              borderRadius: BorderRadius.circular(8),
              child: Image.network(
                item.product.imageUrl,
                width: 60,
                height: 60,
                fit: BoxFit.cover,
                errorBuilder: (context, error, stackTrace) {
                  return Container(
                    width: 60,
                    height: 60,
                    color: Colors.grey[300],
                    child: Icon(Icons.image_not_supported),
                  );
                },
              ),
            ),
            title: Text(
              item.product.name,
              style: TextStyle(fontWeight: FontWeight.bold),
            ),
            subtitle: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(item.product.formattedPrice),
                SizedBox(height: 4),
                Row(
                  children: [
                    IconButton(
                      icon: Icon(Icons.remove_circle_outline),
                      onPressed: onDecrease,
                      iconSize: 20,
                    ),
                    Text('${item.quantity}'),
                    IconButton(
                      icon: Icon(Icons.add_circle_outline),
                      onPressed: onIncrease,
                      iconSize: 20,
                    ),
                  ],
                ),
              ],
            ),
            trailing: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.end,
              children: [
                Text(
                  item.formattedTotalPrice,
                  style: TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    color: Colors.blue,
                  ),
                ),
                IconButton(
                  icon: Icon(Icons.delete, color: Colors.red),
                  onPressed: onRemove,
                ),
              ],
            ),
          ),
        );
      }
    }

14

## Creating Cart Screen

### lib/screens/cart_screen.dart

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import '../providers/cart_provider.dart';
    import '../widgets/cart_item_widget.dart';
    import 'checkout_screen.dart';

    class CartScreen extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Shopping Cart'),
          ),
          body: Consumer(
            builder: (context, cart, child) {
              if (cart.items.isEmpty) {
                return Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(Icons.shopping_cart_outlined, size: 100, color: Colors.grey),
                      SizedBox(height: 16),
                      Text(
                        'Your cart is empty',
                        style: TextStyle(fontSize: 20, color: Colors.grey),
                      ),
                      SizedBox(height: 8),
                      Text(
                        'Add some products to get started',
                        style: TextStyle(fontSize: 14, color: Colors.grey),
                      ),
                    ],
                  ),
                );
              }

              return Column(
                children: [
                  Expanded(
                    child: ListView.builder(
                      itemCount: cart.items.length,
                      itemBuilder: (context, index) {
                        final item = cart.items[index];
                        return CartItemWidget(
                          item: item,
                          onRemove: () => cart.removeItemCompletely(item.product),
                          onDecrease: () => cart.removeItem(item.product),
                          onIncrease: () => cart.addItem(item.product),
                        );
                      },
                    ),
                  ),
                  // Total and checkout
                  Container(
                    padding: EdgeInsets.all(16),
                    decoration: BoxDecoration(
                      color: Colors.white,
                      boxShadow: [
                        BoxShadow(
                          color: Colors.grey.withOpacity(0.3),
                          spreadRadius: 2,
                          blurRadius: 5,
                          offset: Offset(0, -3),
                        ),
                      ],
                    ),
                    child: Column(
                      children: [
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Text(
                              'Total:',
                              style: TextStyle(
                                fontSize: 20,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            Text(
                              cart.formattedTotalAmount,
                              style: TextStyle(
                                fontSize: 24,
                                fontWeight: FontWeight.bold,
                                color: Colors.blue,
                              ),
                            ),
                          ],
                        ),
                        SizedBox(height: 16),
                        SizedBox(
                          width: double.infinity,
                          height: 50,
                          child: ElevatedButton(
                            onPressed: () {
                              Navigator.push(
                                context,
                                MaterialPageRoute(
                                  builder: (context) => CheckoutScreen(),
                                ),
                              );
                            },
                            child: Text(
                              'Proceed to Checkout',
                              style: TextStyle(fontSize: 18),
                            ),
                            style: ElevatedButton.styleFrom(
                              shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(12),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              );
            },
          ),
        );
      }
    }

15

## Creating Checkout Screen

### lib/screens/checkout_screen.dart

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import '../providers/cart_provider.dart';
    import '../models/order.dart';
    import 'order_confirmation_screen.dart';

    class CheckoutScreen extends StatefulWidget {
      @override
      _CheckoutScreenState createState() => _CheckoutScreenState();
    }

    class _CheckoutScreenState extends State {
      final _formKey = GlobalKey();
      final _nameController = TextEditingController();
      final _emailController = TextEditingController();
      final _addressController = TextEditingController();
      final _phoneController = TextEditingController();
      String _selectedPaymentMethod = 'Credit Card';

      @override
      void dispose() {
        _nameController.dispose();
        _emailController.dispose();
        _addressController.dispose();
        _phoneController.dispose();
        super.dispose();
      }

      void _placeOrder(BuildContext context, CartProvider cart) {
        if (!_formKey.currentState!.validate()) return;

        final order = Order(
          id: DateTime.now().millisecondsSinceEpoch.toString(),
          items: cart.items,
          totalAmount: cart.totalAmount,
          orderDate: DateTime.now(),
          shippingAddress: _addressController.text,
          paymentMethod: _selectedPaymentMethod,
        );

        cart.clearCart();

        Navigator.pushReplacement(
          context,
          MaterialPageRoute(
            builder: (context) => OrderConfirmationScreen(order: order),
          ),
        );
      }

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Checkout'),
          ),
          body: Consumer(
            builder: (context, cart, child) {
              return SingleChildScrollView(
                padding: EdgeInsets.all(16),
                child: Form(
                  key: _formKey,
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      // Shipping Information
                      Text(
                        'Shipping Information',
                        style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      SizedBox(height: 16),
                      TextFormField(
                        controller: _nameController,
                        decoration: InputDecoration(
                          labelText: 'Full Name',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.person),
                        ),
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            return 'Please enter your name';
                          }
                          return null;
                        },
                      ),
                      SizedBox(height: 16),
                      TextFormField(
                        controller: _emailController,
                        decoration: InputDecoration(
                          labelText: 'Email',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.email),
                        ),
                        keyboardType: TextInputType.emailAddress,
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            return 'Please enter your email';
                          }
                          if (!value.contains('@')) {
                            return 'Please enter a valid email';
                          }
                          return null;
                        },
                      ),
                      SizedBox(height: 16),
                      TextFormField(
                        controller: _phoneController,
                        decoration: InputDecoration(
                          labelText: 'Phone Number',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.phone),
                        ),
                        keyboardType: TextInputType.phone,
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            return 'Please enter your phone number';
                          }
                          return null;
                        },
                      ),
                      SizedBox(height: 16),
                      TextFormField(
                        controller: _addressController,
                        decoration: InputDecoration(
                          labelText: 'Shipping Address',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.location_on),
                        ),
                        maxLines: 3,
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            return 'Please enter your address';
                          }
                          return null;
                        },
                      ),
                      SizedBox(height: 32),
                      // Payment Method
                      Text(
                        'Payment Method',
                        style: TextStyle(
                          fontSize: 20,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      SizedBox(height: 16),
                      ...['Credit Card', 'Debit Card', 'PayPal', 'Cash on Delivery']
                          .map((method) {
                        return RadioListTile(
                          title: Text(method),
                          value: method,
                          groupValue: _selectedPaymentMethod,
                          onChanged: (value) {
                            setState(() {
                              _selectedPaymentMethod = value!;
                            });
                          },
                        );
                      }).toList(),
                      SizedBox(height: 32),
                      // Order Summary
                      Card(
                        child: Padding(
                          padding: EdgeInsets.all(16),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                'Order Summary',
                                style: TextStyle(
                                  fontSize: 18,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                              SizedBox(height: 16),
                              Row(
                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                children: [
                                  Text('Items (${cart.itemCount}):'),
                                  Text(cart.formattedTotalAmount),
                                ],
                              ),
                              SizedBox(height: 8),
                              Divider(),
                              SizedBox(height: 8),
                              Row(
                                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                                children: [
                                  Text(
                                    'Total:',
                                    style: TextStyle(
                                      fontSize: 18,
                                      fontWeight: FontWeight.bold,
                                    ),
                                  ),
                                  Text(
                                    cart.formattedTotalAmount,
                                    style: TextStyle(
                                      fontSize: 20,
                                      fontWeight: FontWeight.bold,
                                      color: Colors.blue,
                                    ),
                                  ),
                                ],
                              ),
                            ],
                          ),
                        ),
                      ),
                      SizedBox(height: 24),
                      // Place Order Button
                      SizedBox(
                        width: double.infinity,
                        height: 50,
                        child: ElevatedButton(
                          onPressed: () => _placeOrder(context, cart),
                          child: Text(
                            'Place Order',
                            style: TextStyle(fontSize: 18),
                          ),
                          style: ElevatedButton.styleFrom(
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(12),
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              );
            },
          ),
        );
      }
    }

16

## Creating Order Confirmation Screen

### lib/screens/order_confirmation_screen.dart

    import 'package:flutter/material.dart';
    import '../models/order.dart';
    import 'home_screen.dart';

    class OrderConfirmationScreen extends StatelessWidget {
      final Order order;

      const OrderConfirmationScreen({Key? key, required this.order}) : super(key: key);

      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Order Confirmed'),
            automaticallyImplyLeading: false,
          ),
          body: Center(
            child: Padding(
              padding: EdgeInsets.all(24),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(
                    Icons.check_circle,
                    size: 100,
                    color: Colors.green,
                  ),
                  SizedBox(height: 24),
                  Text(
                    'Order Placed Successfully!',
                    style: TextStyle(
                      fontSize: 24,
                      fontWeight: FontWeight.bold,
                    ),
                    textAlign: TextAlign.center,
                  ),
                  SizedBox(height: 16),
                  Text(
                    'Thank you for your purchase',
                    style: TextStyle(
                      fontSize: 16,
                      color: Colors.grey[600],
                    ),
                    textAlign: TextAlign.center,
                  ),
                  SizedBox(height: 32),
                  Card(
                    child: Padding(
                      padding: EdgeInsets.all(16),
                      child: Column(
                        children: [
                          _buildInfoRow('Order ID', order.id),
                          Divider(),
                          _buildInfoRow('Total Items', '${order.totalItems}'),
                          Divider(),
                          _buildInfoRow('Total Amount', order.formattedTotalAmount),
                          Divider(),
                          _buildInfoRow('Payment Method', order.paymentMethod ?? 'N/A'),
                          Divider(),
                          _buildInfoRow('Status', order.status),
                        ],
                      ),
                    ),
                  ),
                  SizedBox(height: 32),
                  SizedBox(
                    width: double.infinity,
                    height: 50,
                    child: ElevatedButton(
                      onPressed: () {
                        Navigator.pushAndRemoveUntil(
                          context,
                          MaterialPageRoute(builder: (context) => HomeScreen()),
                          (route) => false,
                        );
                      },
                      child: Text(
                        'Continue Shopping',
                        style: TextStyle(fontSize: 18),
                      ),
                      style: ElevatedButton.styleFrom(
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }

      Widget _buildInfoRow(String label, String value) {
        return Padding(
          padding: EdgeInsets.symmetric(vertical: 8),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                label,
                style: TextStyle(fontSize: 14, color: Colors.grey[700]),
              ),
              Text(
                value,
                style: TextStyle(
                  fontSize: 14,
                  fontWeight: FontWeight.bold,
                ),
              ),
            ],
          ),
        );
      }
    }

17

## Updating Main.dart

### lib/main.dart

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'providers/cart_provider.dart';
    import 'screens/home_screen.dart';

    void main() {
      runApp(MyApp());
    }

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return ChangeNotifierProvider(
          create: (_) => CartProvider(),
          child: MaterialApp(
            title: 'ShopMart',
            debugShowCheckedModeBanner: false,
            theme: ThemeData(
              primarySwatch: Colors.blue,
              useMaterial3: true,
            ),
            home: HomeScreen(),
          ),
        );
      }
    }

18

## Project Checklist

### Implementation Checklist

- ✅ Project created with Provider dependency
- ✅ Folder structure organized
- ✅ Product, CartItem, and Order models created
- ✅ CartProvider with state management
- ✅ Products data with sample products
- ✅ Product card widget
- ✅ Category chip widget
- ✅ Home screen with search and category filtering
- ✅ Product detail screen
- ✅ Cart item widget
- ✅ Cart screen with total calculation
- ✅ Checkout screen with form validation
- ✅ Order confirmation screen
- ✅ Main.dart with Provider setup

19

## Enhancement Ideas

### Optional Enhancements

- Add user authentication
- Implement product favorites/wishlist
- Add product reviews and ratings
- Implement order history
- Add product images from actual URLs
- Implement product search with filters
- Add shipping cost calculation
- Implement discount codes and coupons
- Add product recommendations
- Implement push notifications for orders

20

## Exercises

### 1. Complete Implementation

Implement the entire e-commerce app following all the code provided. Test all features including product browsing, cart management, and checkout process.

### 2. Add Wishlist

Create a wishlist feature that allows users to save products for later. Add a heart icon to product cards and create a wishlist screen to view saved products.

### 3. Implement Order History

Create an order history screen that displays all past orders. Store orders locally or integrate with a backend service. Allow users to view order details.