Product details Flutter, E Com App 15

In any Flutter e-commerce app, the product detail page plays a vital role. For example, we get every detail about the product.

Firstly, it allows users to view the product from every angle, judging the quality. 

Secondly this product detail page displays the price, description of the product adding other features as well.

While building this E Commerce app in Flutter, we try to make things as simple as possible.

For that reason, in this section, we will recapitulate the workflow again. 

On the other hand, we have added two model classes so far. One is the product class and product items. We have used Change Notifier so that child widgets can listen to the changes that happen to the products.

Here is the product class. 

import 'package:flutter/foundation.dart';

class Product with ChangeNotifier {
  final String id;
  final String title;
  final String description;
  final double price;
  final String imageUrl;
  bool isFavorite;

  Product({
    required this.id,
    required this.title,
    required this.description,
    required this.price,
    required this.imageUrl,
    this.isFavorite = false,
  });

  void changeStateOfFavorite() {
    isFavorite = !isFavorite;
    notifyListeners();
  }
}

At the same time, we have added a few products which will work as the backend of our E Commerce app.

import 'package:flutter/material.dart';

import 'product.dart';

class Products with ChangeNotifier {
  final List<Product> _items = [
    Product(
      id: 'p1',
      title: 'Smart Phone',
      description: 'A Smart Phone - get big Discount!',
      price: 29.99,
      imageUrl:
          'https://cdn.pixabay.com/photo/2015/12/13/16/02/ios-1091302_960_720.jpg',
    ),
    Product(
      id: 'p2',
      title: 'Smart TV',
      description: 'A Smart TV.',
      price: 59.99,
      imageUrl:
          'https://cdn.pixabay.com/photo/2015/02/07/20/58/tv-627876_960_720.jpg',
    ),
    Product(
      id: 'p3',
      title: 'Umbrella',
      description: 'Fancy and Beautiful.',
      price: 19.99,
      imageUrl:
          'https://cdn.pixabay.com/photo/2016/11/14/03/19/umbrella-1822478_960_720.jpg',
    ),
    Product(
      id: 'p4',
      title: 'Pants',
      description: 'Fashionable and modern design.',
      price: 99.99,
      imageUrl:
          'https://cdn.pixabay.com/photo/2017/03/24/19/48/jeans-2172032_960_720.jpg',
    ),
    Product(
      id: 'p5',
      title: 'Shirt',
      description: 'Designed with care.',
      price: 47.99,
      imageUrl:
          'https://cdn.pixabay.com/photo/2014/08/05/10/31/waiting-410328_960_720.jpg',
    ),
  ];

  List<Product> get items {
    return [..._items];
  }

  Product findById(String id) {
    return _items.firstWhere((prod) => prod.id == id);
  }

  List<Product> get favoriteItems {
    return _items.where((productItem) => productItem.isFavorite).toList();
  }

  void addProduct() {
    // _items.add(value);
    notifyListeners();
  }
}

After that we have used the multi provider to provide the products to the child widgets.

As a result, these child widgets will listen to any change that happens to the products data. 

This is the workflow regarding the products.

Let’s see the entry point of our E Commerce app.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'models/cart_model.dart';
import 'models/theme.dart';

import 'models/products.dart';
import 'views/cart_page.dart';
import 'views/product_detail_screen.dart';
import 'views/products_overview_screen.dart';

final settings = ValueNotifier(
  ThemeSettings(
    sourceColor: const Color.fromARGB(255, 240, 10, 182),
    themeMode: ThemeMode.system,
  ),
);

/// creating a new branch adding cart
///
///
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (_) => Products(),
        ),
        ChangeNotifierProvider(
          create: (context) => CartModel(),
        )
      ],
      child: DynamicColorBuilder(
        builder: (lightDynamic, darkDynamic) => ThemeProvider(
          lightDynamic: lightDynamic,
          darkDynamic: darkDynamic,
          settings: settings,
          child: const MyApp(),
        ),
      ),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final theme = ThemeProvider.of(context);
    return MaterialApp(
      title: 'E Commerce App',
      debugShowCheckedModeBanner: false,
      theme: theme.light(settings.value.sourceColor),
      home: const ProductsOverviewScreen(),
      routes: {
        ProductDetailScreen.routeName: (ctx) => const ProductDetailScreen(),
        CartScreen.routeName: (ctx) => const CartScreen(),
      },
    );
  }
}

Product detail page

As we see in the above code, we have routes property in the Material App that takes us to the product details screen. 

As an outcome, we can take a look at all the products on one screen.

Flutter Map Adding Cart items first example
Flutter Map Adding Cart items first example

We see all the products on the product overview screen because we have defined those properties in two separate controllers.

We can have a look at the product overview screen, product grid and product items at the respective GitHub repository.

As a result, we can now click any product and view the image, title and price.

But to that, we need to choose each product by its respective product ID. 

The Provider helps us to find the respective ID. 

How?

We have used the “findById” method and passed the respective route name.

We will discuss that part later, in the next discussion.

Before that, let’s see the product details page.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

import '../models/products.dart';

class ProductDetailScreen extends StatelessWidget {
  static const routeName = '/product-detail';

  /// product detail page
  ///
  const ProductDetailScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final productId = ModalRoute.of(context)!.settings.arguments as String;
    final loadedProduct = Provider.of<Products>(
      context,
      listen: false,
    ).findById(productId);
    return Scaffold(
      appBar: AppBar(
        title: Text(loadedProduct.title),
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            SizedBox(
              height: 300,
              width: double.infinity,
              child: Image.network(
                loadedProduct.imageUrl,
                fit: BoxFit.cover,
              ),
            ),
            const SizedBox(height: 10),
            Text(
              '\$${loadedProduct.price}',
              style: const TextStyle(
                color: Colors.grey,
                fontSize: 20,
              ),
            ),
            const SizedBox(
              height: 10,
            ),
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 10),
              width: double.infinity,
              child: Text(
                loadedProduct.description,
                textAlign: TextAlign.center,
                softWrap: true,
              ),
            )
          ],
        ),
      ),
    );
  }
}

Now we can click any product and see the product details.

Let’s see the Smart Phone individually.

Product detail - Smart Phone
Product detail – Smart Phone

After that we can see the Umbrella.

To do that, we need to click the respective image on the products overview page.

Product detail - Umbrella
Product detail – Umbrella

Finding each product by its ID is not simple either.

However, we will try to understand that mechanism in the next section. 

Certainly, the provider plays the most important role here.

For this part you will get the full code in this GitHub repository.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

GitHub repository

Python and Data Science

Twitter

Comments

Leave a Reply