0

I am Developing Cart Page for e com application. backend is firebase real time database. In cart Page Price Details is calculating when the page load. But when user change the quantity of cart item, It is going to update the cart. But the problem is Cant Calculate the Price Details On this time. When I reopen the page, Price Details is Calculating According to new Cart Quantity. But How can I can do that without re opening the Page

Cart page

1.This is my cart_page.dart file

  //this cart is show when user select my cart From the navigation drawer
import 'package:flutter/material.dart';
import 'package:buy_app_flutter/main.dart';
import 'package:buy_app_flutter/pages/notification_page.dart';
import 'package:buy_app_flutter/pages/search_page.dart';
import 'package:buy_app_flutter/componets/cart_products.dart';

import 'BuyNowDeliveryDetailsPage.dart';
import 'HomePage.dart';

class CartPage extends StatefulWidget {
  @override
  _CartPageState createState() => _CartPageState();
}

class _CartPageState extends State<CartPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(

      drawer: new DrawerCodeOnly(),

      appBar: new AppBar(
        elevation: 0.1,
        backgroundColor: Colors.orangeAccent,
        title: Text("My Cart"),
        actions:<Widget> [
          new IconButton(icon: Icon(Icons.search,color: Colors.white,), onPressed: (){
            showSearch(context: context, delegate: DataSearch());
          } ),

          new IconButton(icon: Icon(Icons.notifications,color: Colors.white,), onPressed: (){
            Navigator.push(context, MaterialPageRoute(builder: (context) => new NotificationPage() ));
          } ),

        ],
      ),

      body:new Cart_products(),

      bottomNavigationBar:new Container(
        color: Colors.white,
        child: Row(
          children:<Widget> [
            Expanded(child: ListTile(
              title: new Text("Total:"),
              subtitle:new Text("Rs 00.00") ,
            )),

            Expanded(
                child: new MaterialButton(onPressed: (){
                  Navigator.push(context, MaterialPageRoute(builder: (context) => new BuyNowDeliveryDetailsActivity() ));
                },
                  child: new Text("Check Out"),
                  color: Colors.orangeAccent,
                )
            )

          ],
        ),
      ) ,
    );
  }
}

2.This is cart_procucts.dart file

import 'package:buy_app_flutter/DBModels/CartModel.dart';
import 'package:buy_app_flutter/DBModels/ProductModel.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';

class Cart_products extends StatefulWidget {
  @override
  _Cart_productsState createState() => _Cart_productsState();
}

class _Cart_productsState extends State<Cart_products> {

  //firebase database reference to cart===============================
  final Cartref= FirebaseDatabase.instance.reference().child("UserData").child(FirebaseAuth.instance.currentUser.uid).child("Cart");

  List<CartModel> Products_on_the_cart=List();
  ///=============================================firebase end
  bool _progressController=true;

  //variables to cal total
  int TotalItemPrice=0;
  int SavedAmount=0;
  int DeliveryPrice=0;
  int TotalAmount=0;

  @override
  initState(){
    _getCartList();  //call function to get cart from firebase
    super.initState();
  }

  ///display the cart Items one by one===============================
  @override
  Widget build(BuildContext context) {

    if(_progressController==true) //reading database
        {
      return Center(child: new CircularProgressIndicator());
    }
    else{  //db read end=========
          if(Products_on_the_cart.isNotEmpty)
            {
              _calTotalPrice();
              //===============================================if not empty the cart

              return Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  ListView.separated(
                    itemBuilder: (context, index){
                        return Single_cart_product(
                        cart_product_key: Products_on_the_cart[index].productKey,
                        cart_product_name: Products_on_the_cart[index].ProductTitle,
                        cart_prod_picture: Products_on_the_cart[index].Img,
                        cart_prod_price: Products_on_the_cart[index].Price,
                        cart_prod_cutted_price: Products_on_the_cart[index].CuttedPrice,
                        cart_prod_qty: Products_on_the_cart[index].qty,
                        cart_product_status: Products_on_the_cart[index].Status,

                        );
              },
                    //end of item builder
                    separatorBuilder:(context,index){
                      return Row();
                    },
                    itemCount: Products_on_the_cart.length,
                    shrinkWrap: true,

                  ),

                  Divider(),

                  Padding(
                    padding: const EdgeInsets.only(left: 8.0),
                    child: Text("PRICE DETAILS",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.grey),),
                  ),

                  Divider(),

                  ///start of items total price row===========================
                  Padding(
                    padding: const EdgeInsets.only(left: 8.0,right: 8.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text("price (${Products_on_the_cart.length} items)",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.black),),

                        Text("Rs ${TotalItemPrice}/-",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.black),),
                      ],
                    ),
                  ),
                  ///end of items total price row============================

                  ///start of delivery price row==================================
                  Padding(
                    padding: const EdgeInsets.only(left: 8.0,top: 8.0,right: 8.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text("Delivery",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.black),),

                        Text("Rs ${DeliveryPrice}/-",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.green),),
                      ],
                    ),
                  ),
                  ///end of delivery price row============================

                  Divider(),

                  ///Start of total amount row==================================
                  Padding(
                    padding: const EdgeInsets.only(left: 8.0,right: 8.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text("Total Amount",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.black),),

                        Text("Rs ${TotalAmount}/-",style: TextStyle(fontWeight: FontWeight.bold,color: Colors.black),),
                      ],
                    ),
                  ),
                  ///end of total amount row===========================================

                  Divider(),

                  Padding(
                    padding: const EdgeInsets.only(left: 8.0,right: 8.0),
                    child: Text("You saved Rs ${SavedAmount}/- on this order",style: TextStyle(fontWeight: FontWeight.normal,color: Colors.green),),
                  ),

                ],
              );

              //end of if not empty the cart===========================================
            }
          else
            {
              return Center(child: Text("Your cart is empty !"));
            }
    }


  }

  ///end of displaying cart items one by one====================================

  _getCartList()
  async {

    //get cart data from firebase==========

    try{
      await Cartref.once().then((DataSnapshot snapshot) {
        var data = snapshot.value;

        if(data==null)  //if the no cart items found hide progress
            {
          setState(() {
            _progressController=false;
          });
        }

        Products_on_the_cart.clear();

        data.forEach((key,value)
        async {
          CartModel model = new CartModel(

            date: value["date"],
            time: value["time"],
            productKey: value["productKey"],
            qty: value["qty"],

          );

          //use  Pref(product ref) to get details from products record

          try{

            //Product details ref and list
            final Pref= FirebaseDatabase.instance.reference().child("Product");

            List<ProductModel> product =List();

            //====================================
            await Pref.child(model.productKey).once().then((DataSnapshot snap) {

              // print('Product : ${snap.value}');
              model.ProductTitle=snap.value["ProductTitle"];
              model.Img=snap.value["img1"];
              model.Price=snap.value["Price"];
              model.DPrice=snap.value["DPrice"];
              model.CuttedPrice=snap.value["CuttedPrice"];
              model.Status=snap.value["Status"];

            });

          }
          catch(e)
          {
            print("Error In try block for get data from real time db ");
            print(e);
          }
          finally
              {
                setState(() {
                  _progressController=false;
                });
              }

          //========================================================end of get product details

          setState(() {
            Products_on_the_cart.add(model);
          });

        }
        );

      });
    }
    catch(e)
    {
      print(e);
    }

    // end of get cart data from firebase
  }

  ///function for calculate total price
  _calTotalPrice(){

     TotalItemPrice=0;
     DeliveryPrice=0;
     TotalAmount=0;
     SavedAmount=0;

    Products_on_the_cart.forEach((item){

      //set total item price===========
         TotalItemPrice=TotalItemPrice+int.parse(item.Price)*int.parse(item.qty);

         //set delivery price==========
         if (item.DPrice=="FREE")
         {
           //nothing
         }
         else
         {

           if (int.parse(item.DPrice)>DeliveryPrice)
           {
             DeliveryPrice=int.parse(item.DPrice);
           }
         }

         //set Total amount=======
        TotalAmount=TotalItemPrice+DeliveryPrice;

         //set saved amount
         SavedAmount=SavedAmount + (int.parse(item.CuttedPrice)-int.parse(item.Price))*int.parse(item.qty);
         
    });
  }
  /// end of calculate total price function

}


///from here design the cart item display ==========================================
class Single_cart_product extends StatefulWidget {

  final cart_product_key;
  final cart_product_name;
  final cart_prod_picture;
  final cart_prod_price;
  final cart_prod_cutted_price;
  String cart_prod_qty;
  final cart_product_status;

  Single_cart_product({
    this.cart_product_key,
    this.cart_product_name,
    this.cart_prod_picture,
    this.cart_prod_price,
    this.cart_prod_cutted_price,
    this.cart_prod_qty,
    this.cart_product_status,
});

  @override
  _Single_cart_productState createState() => _Single_cart_productState();
}

class _Single_cart_productState extends State<Single_cart_product> {
  ///==========================start of Cart Item Display Design==================================================================
  @override
  Widget build(BuildContext context) {

    var cartQty=int.parse(widget.cart_prod_qty);

    return Card(
      child: Column(
        children: [
          ListTile(
            ///===============START LEADING SECTION ===============================
            leading: FadeInImage.assetNetwork(
              placeholder: 'assets/close_box.png',
              image:widget.cart_prod_picture,
              height: 80.0,
              width: 80.0,
              fit: BoxFit.contain,
            ),
            ///=======END OF LEADING SECTION=======================================

            /// =========== TITLE SECTION =========================================
            title: new Text(widget.cart_product_name),
            ///====END OF TITLE SECTION============================================

            ///========== SUBTITLE SECTION ==================================
            subtitle: new Column(
              children:<Widget> [
                //Row inside the column
                new Row(
                  children: <Widget> [

                    // =============this section is for the Product price =====
                    new Container(
                      alignment: Alignment.topLeft,
                      child: new Text("\Rs.${widget.cart_prod_price}",
                        style: TextStyle(
                            fontSize:16.0,
                            fontWeight: FontWeight.bold,
                            color: Colors.black
                        ),
                      ),
                    ),

                    SizedBox(width: 4,),
                    //==========this section is for the cutted price of the product=========
                    Padding(
                      padding: const EdgeInsets.all(5.0),
                      child: new Text("\Rs.${widget.cart_prod_cutted_price}",
                        style: TextStyle(
                            fontSize:16.0,
                            fontWeight: FontWeight.normal,
                            decoration: TextDecoration.lineThrough,
                            color: Colors.grey
                        ),
                      ),
                    ),
                    //end of cutted price of the product


                  ],
                ),




              ],
            ),

            ///=====END OF SUBTITLE SECTION============================================

            ///======START OF TRAILING SECTION==========================================

            trailing:
            Column(

              children:
              <Widget>[

                Expanded(child: new IconButton(
                    padding: const EdgeInsets.all(0.0),
                    icon: Icon(Icons.arrow_drop_up), onPressed: (){
                      cartQty++;
                      print(cartQty);
                      _updateCartQty(widget.cart_product_key,cartQty.toString()); //call to update cart qty

                      setState(() {
                        widget.cart_prod_qty=cartQty.toString();
                      });


                })),
                Padding(
                  padding: const EdgeInsets.all(0.0),
                  child: new Text(cartQty.toString()),
                ),
                Expanded(child: new IconButton(
                    padding: const EdgeInsets.all(0.0),
                    icon: Icon(Icons.arrow_drop_down), onPressed: (){
                      if(cartQty>1)
                        {
                          cartQty--;
                          print(cartQty);
                          _updateCartQty(widget.cart_product_key,cartQty.toString()); //call to update cart qty

                          setState(() {
                            widget.cart_prod_qty=cartQty.toString();
                          });
                        }

                })),


              ],
            ),


          ///==END OF TRAILING======================================================================

          ),

          //REMOVE BTN AND STATUS
          Row(
            children: [
              new IconButton(
                  icon: Icon(Icons.delete),
                  color:Colors.red ,
                  onPressed: (){}),

              Padding(
                padding: const EdgeInsets.all(4.0),
                child: new Text(widget.cart_product_status,style: TextStyle(color: Colors.orangeAccent)),
              ),
            ],
          )

          //END OF REMOVE BTN SND STATUS


        ],
      ),



    );
  }

  ///==========================end of Cart Item Display Design==================================================================

  /// function for update cart qty
  _updateCartQty(String Pkey,String Qty){

    try {
      final Cartref = FirebaseDatabase.instance.reference()
          .child("UserData")
          .child(FirebaseAuth.instance.currentUser.uid)
          .child("Cart");

        Cartref.child(Pkey).child("qty").set(Qty);
    }
    catch(Ex)
    {
      Fluttertoast.showToast(
          msg: Ex.message,
          toastLength: Toast.LENGTH_SHORT,
          gravity: ToastGravity.BOTTOM,
          timeInSecForIosWeb: 1,
          backgroundColor: Colors.red,
          textColor: Colors.white,
          fontSize: 16.0);
    }

  }
}

3.After that I need to view the calculated total amount in Bottom of the cart page

view total amount like this

  • https://stackoverflow.com/questions/67312142/flutter-how-to-change-the-body-widget-of-parent-while-passing-a-value-from-c/67313509#67313509 – MobIT May 14 '21 at 18:29

1 Answers1

1

Updating product quantity value in Cart_products class:

You need to create a variable final ValueChanged<int> onProdQty; in Single_cart_product class and then where the quantity value changes use the callback like this widget.onProdQty?.call(here Pass the new quantity value). Also one last step is that in class Cart_products where you are calling Single_cart_product() add this in argument onProdQty: (value) => setState(() { Products_on_the_cart[index].qty = value; }),. By doing this whenever the callback is called the setstate would run in Cart_products class and wherever Products_on_the_cart[index].qty is used it would get updated.

Updating product quantity value in CartPage class:

Note: I'm not sure if these steps would work corectly as I have limited information about your project. But you will surely learn how to pass data around using callbacks:

  • Follow steps of Updating product quantity value in Cart_products class and then continue.
  • Add final ValueChanged<int> onProdQty; in Cart_products class and then change Single_cart_product() argument in class Cart_products like this:
Single_cart_product(onProdQty: (value) => setState((){
    Products_on_the_cart[index].qty = value; 

    widget.onProdQty?.call(value); //add this

}),)
  • Then add List<CartModel> Products_on_the_cart=List(); in the _CartPageState class in cart_page.dart and at last in the body: Cart_products() make these changes:
Cart_products(onProdQty: (value) => setState((){
    Products_on_the_cart[index].qty = value; 
}),)
  • Now use Products_on_the_cart[index].qty in bottomNavigationBar.

Please let me know if you have any further queries.

Deepanshu
  • 890
  • 5
  • 18
  • 1
    Thank You very much. it is working. ! cloud you please give me an advice for sent the Total amount to bottomNavigationBar in cart_page.dart – Sampath Dissanayake May 15 '21 at 07:40
  • I'm glad that it worked for you. As for advice, I would soon share a simple project in the answer which would help you become more familiar with callbacks. But as of now, I have updated the answer for `bottomNavigationBar`. Unfortunately, I can't guarantee that it would work as I have limited information about your project. But I'm sure that it would give you the idea. – Deepanshu May 15 '21 at 10:40