Flutter backend local, E Commerce app – 2

We’ve discussed how to use Flutter backend before. There are several options. Using a local file is certainly one of them. 

In this e-commerce app, we’re going to use local files as well. As a result, what we’re displaying as products on the home page, are objects that we’ve instantiated locally.

As the first step, we have created a few products in our model folder as we’re following the model-view-controller approach.

However, we cannot go on creating like this. Right? 

Therefore we need to evolve another process to add the products. 

Not only that, we will also add other features, such as sign-in method, a dynamic backend where the administrator can only add, or modify products.

At present, we have a product class where we have declared the properties.

class Product {
  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,
  });
}

Now we can add as many items as we want.

However, we have limited ourselves to five products at present.

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);
  }

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

As we notice, we have used mixins to extend our class to ChangeNotifier. 

The reason is simple.

We want to notify the listeners.

At present, we want to concentrate on displaying the products only. 

As a result, we have a view as follows.

import 'package:flutter/material.dart';

import '../controllers/products_grid.dart';

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('E-Commerce App'),
      ),
      body: const ProductsGrid(),
    );
  }
}

Now we need to decide how to control this display. As a result, in our “controllers” folder, we have two controllers of the app. 

One of the controllers will get the products according to their IDs. 

And the other controller will display them on a Grid. 

Flutter backend data and class constructor

We will use the GridView builder constructor to get all the products first.

Let’s see the code first.

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

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

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

  @override
  Widget build(BuildContext context) {
    final productsData = Provider.of<Products>(context);
    final products = productsData.items;
    return GridView.builder(
      padding: const EdgeInsets.all(10.0),
      itemCount: products.length,
      itemBuilder: (ctx, i) => ProductItem(
        products[i].id,
        products[i].title,
        products[i].imageUrl,
      ),
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        childAspectRatio: 3 / 2,
        crossAxisSpacing: 10,
        mainAxisSpacing: 10,
      ),
    );
  }
}

Through Provider we have passed the Products class where we have instantiated the product items. As a result, in the above code we can easily pass the products list using the index. 

GridView builder constructor has made our life easier, as it passes the same context that Provider uses and it also passes the index of the products.

Since we have passed data through the class constructor, we can easily grab each item now. 

Not only that, we can control the Material You color across the app. 

Managing the Flutter backend and controlling the color
Managing the Flutter backend and controlling the color

Let’s take a look at the code. 

import 'package:flutter/material.dart';

import '../views/product_detail_screen.dart';

class ProductItem extends StatelessWidget {
  final String id;
  final String title;
  final String imageUrl;

  const ProductItem(
    this.id,
    this.title,
    this.imageUrl,
  );

  @override
  Widget build(BuildContext context) {
    return ClipRRect(
      borderRadius: BorderRadius.circular(10),
      child: GridTile(
        footer: GridTileBar(
          backgroundColor: Colors.yellow.shade900,
          leading: IconButton(
            icon: const Icon(Icons.favorite),
            color: Theme.of(context).colorScheme.onSecondary,
            onPressed: () {},
          ),
          title: Text(
            title,
            textAlign: TextAlign.center,
          ),
          trailing: IconButton(
            icon: Icon(
              Icons.shopping_cart,
              color: Theme.of(context).colorScheme.onPrimary,
            ),
            onPressed: () {},
            color: Theme.of(context).colorScheme.secondary,
          ),
        ),
        child: GestureDetector(
          onTap: () {
            Navigator.of(context).pushNamed(
              ProductDetailScreen.routeName,
              arguments: id,
            );
          },
          child: Image.network(
            imageUrl,
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

We have got every product item property. Therefore, we can use the ID to navigate to the detail page. 

That’ll be our next challenge. 

We’ll discuss that topic in the next section.

Stay tuned.

What Next?

Books at Leanpub

Books in Apress

My books at Amazon

Courses at Educative

GitHub repository

Python and Data Science

Twitter

Comments

3 responses to “Flutter backend local, E Commerce app – 2”

  1. […] It’s necessary because we will pass arguments again from any part of the app to another part of th… […]

  2. […] For that reason we don’t want to miss any step. We’ve been explaining every small point that might be useful to understand the concepts. […]

  3. […] However, before that we would like to explain it. Why do we need this particular method in the E Commerce app?  […]

Leave a Reply