Ad

How To Update Firestore Database Value Correctly

I am working to build basic shopping functions in my Flutter app.  I'm new to coding and Flutter.  When the user clicks the PlaceOrderPageContainer (button) to confirm check out the addOrderDetails() method is called which then updates the Firebase database. Everything is updating in Firestore Database correctly other than the Total Amount which is being added as zero regardless of the total amount in the shopping cart. I'm not getting any errors in the console but it's obvious my code isn't written correctly.  Any help will be greatly appreciated.  I can add any additional code if that will be helpful.

    class ShoppingCartPage extends StatefulWidget {
  const ShoppingCartPage({Key? key}) : super(key: key);

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

class _ShoppingCartPageState extends State<ShoppingCartPage> {
  late double totalAmount;

  @override
  void initState() {
    super.initState();
    totalAmount = 0;
    Provider.of<TotalAmountProvider>(
      context,
      listen: false,
    ).display(0);
  }

  @override
  Widget build(BuildContext context) {
    return Consumer2<TotalAmountProvider, CartItemCounterProvider>(
      builder: (context, amountProvider, cartProvider, c) {
        return SafeArea(
          child: Scaffold(
            appBar: const ShoppingCartAppBar(),
            floatingActionButton: FloatingActionButton.extended(
              onPressed: () {
                if (ShoppingApp.sharedPreferences
                        .getStringList(
                          ShoppingApp.userCartList,
                        )
                        ?.length ==
                    1) {
                  Fluttertoast.showToast(msg: ToastString.cartEmpty);
                } else {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => AddressPage(
                        totalAmount: totalAmount,
                      ),
                    ),
                  );
                }
              },
              icon: const Icon(
                Icons.navigate_next,
              ),
              label: Text(
                ButtonString.checkOut.toUpperCase(),
              ),
            ),
            body: CustomScrollView(
              slivers: [
                SliverToBoxAdapter(
                  child:
                      Consumer2<TotalAmountProvider, CartItemCounterProvider>(
                    builder: (context, amountProvider, cartProvider, c) {
                      return Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Center(
                          child: cartProvider.count == 0
                              ? Container()
                              : Text(
                                  'Total Price: \$${amountProvider.totalAmount.toString()}',
                                  style: Theme.of(context).textTheme.headline6,
                                ),
                        ),
                      );
                    },
                  ),
                ),
                StreamBuilder<QuerySnapshot>(
                    stream: ShoppingApp.firestore
                        .collection('items')
                        .where('shortInfo',
                            whereIn: ShoppingApp.sharedPreferences
                                .getStringList(ShoppingApp.userCartList))
                        .snapshots(),
                    builder: (context, AsyncSnapshot snapshot) {
                      return !snapshot.hasData
                          ? const AdaptiveCircularProgressSliver()
                          : snapshot.data.docs.isEmpty
                              ? const EmptyShoppingCartContainer()
                              : SliverList(
                                  delegate: SliverChildBuilderDelegate(
                                    (context, index) {
                                      ItemModel model = ItemModel.fromJson(
                                        snapshot.data.docs[index].data(),
                                      );
                                      if (index == 0) {
                                        totalAmount = 0;
                                        // totalAmount = model.price! + totalAmount;
                                      } else {
                                        totalAmount =
                                            model.price! + totalAmount;
                                      }
                                      if (snapshot.data?.docs.length - 1 ==
                                          index) {
                                        WidgetsBinding.instance!
                                            .addPostFrameCallback((timeStamp) {
                                          Provider.of<TotalAmountProvider>(
                                                  context,
                                                  listen: false)
                                              .display(totalAmount);
                                        });
                                      }
                                      return sourceInfo(
                                        model,
                                        context,
                                        removeCartFunction: () =>
                                            removeItemFromUserCart(
                                          model.shortInfo as String,
                                        ),
                                      );
                                    },
                                    childCount: snapshot.hasData
                                        ? snapshot.data?.docs.length
                                        : 0,
                                  ),
                                );
                    }),
              ],
            ),
          ),
        );
      },
    );
  }

  Future<void> removeItemFromUserCart(
    String shortInfoAsID,
  ) async {
    List<String>? tempCartList = ShoppingApp.sharedPreferences.getStringList(
      ShoppingApp.userCartList,
    );
    tempCartList?.remove(shortInfoAsID);

    await ShoppingApp.firestore
        .collection(ShoppingApp.collectionUser)
        .doc(ShoppingApp.sharedPreferences.getString(
          ShoppingApp.userUID,
        ))
        .update({
      ShoppingApp.userCartList: tempCartList,
    }).then((value) {
      Fluttertoast.showToast(
        msg: ToastString.removeFromCart,
      );
      ShoppingApp.sharedPreferences.setStringList(
        ShoppingApp.userCartList,
        tempCartList as List<String>,
      );

      Provider.of<CartItemCounterProvider>(
        context,
        listen: false,
      ).displayResult();

      totalAmount = 0;
    });
  }
}

class AddressPage extends StatefulWidget {
  const AddressPage({
    Key? key,
    required this.totalAmount,
  }) : super(key: key);

  final double totalAmount;

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

class _AddressPageState extends State<AddressPage> {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: AdaptiveLayoutScaffold(
        appBar: const AddressPageAppBar(),
        floatingActionButton: const AddNewAddressFAB(),
        landscapeBodyWidget: Container(),
        portraitBodyWidget: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.min,
          children: [
            const AddressPageHeadline(
              headlineText: ShoppingPageString.selectAddress,
            ),
            Consumer<AddressChangerProvider>(builder: (
              context,
              address,
              c,
            ) {
              return Flexible(
                child: StreamBuilder<QuerySnapshot>(
                    stream: ShoppingApp.firestore
                        .collection(ShoppingApp.collectionUser)
                        .doc(ShoppingApp.sharedPreferences
                            .getString(ShoppingApp.userUID))
                        .collection(ShoppingApp.subCollectionAddress)
                        .snapshots(),
                    builder: (context, snapshot) {
                      return !snapshot.hasData
                          ? const AdaptiveCircularProgressCenter()
                          : snapshot.data!.docs.isEmpty
                              ? const EmptyShippingAddressContainer()
                              : ListView.builder(
                                  itemCount: snapshot.data?.docs.length,
                                  shrinkWrap: true,
                                  itemBuilder: (context, index) {
                                    return AddressCard(
                                      addressID: snapshot.data?.docs[index].id
                                          as String,
                                      currentIndex: address.count,
                                      model: AddressModel.fromJson(
                                        snapshot.data?.docs[index].data()
                                            as Map<String, dynamic>,
                                      ),
                                      totalAmount: widget.totalAmount,
                                      value: index,
                                    );
                                  },
                                );
                    }),
              );
            }),
          ],
        ),
      ),
    );
  }
}

class AddressCard extends StatefulWidget {

  const AddressCard({
    Key? key,
    required this.addressID,
    required this.currentIndex,
    required this.model,
    required this.totalAmount,
    required this.value,
  }) : super(key: key);

  final String addressID;
  final int currentIndex;
  final AddressModel model;
  final double totalAmount;
  final int value;

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

class _AddressCardState extends State<AddressCard> {
  @override
  Widget build(BuildContext context) {
    return AddressCardContainer(
      onTap: () {
        Provider.of<AddressChangerProvider>(
          context,
          listen: false,
        ).displayResult(widget.value);
      },
      addressCardColumn: AddressCardColumn(
        children: [
          Row(
            children: [
              AddressCardRadioButton(
                groupValue: widget.currentIndex,
                onChanged: (value) {
                  Provider.of<AddressChangerProvider>(
                    context,
                    listen: false,
                  ).displayResult(
                    value as int,
                  );
                },
                value: widget.value,
              ),
              AddressCardContent(
                city: widget.model.city as String,
                fullName: widget.model.name as String,
                phoneNumber: widget.model.phoneNumber as String,
                postalCode: widget.model.postalCode as String,
                state: widget.model.state as String,
                streetAddress: widget.model.streetAddress as String,
              ),
            ],
          ),
          widget.value == Provider.of<AddressChangerProvider>(context).count
              ? ShippingAddressProceedButton(
                  onPressed: () {
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (
                          context,
                        ) =>
                            PlaceOrderPaymentPage(
                          addressID: widget.addressID,
                          totalAmount: widget.totalAmount,
                        ),
                      ),
                    );
                  },
                )
              : Container(),
        ],
      ),
    );
  }
}

class PlaceOrderPaymentPage extends StatefulWidget {
  const PlaceOrderPaymentPage({
    Key? key,
    required this.addressID,
    required this.totalAmount,
  }) : super(key: key);

  final String addressID;
  final double totalAmount;

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

class _PlaceOrderPaymentPageState extends State<PlaceOrderPaymentPage> {
  @override
  Widget build(BuildContext context) {
    return AdaptiveLayoutScaffold(
      appBar: const PlaceOrderPaymentPageAppBar(),
      landscapeBodyWidget: Container(),
      portraitBodyWidget: PlaceOrderPageContainer(
        orderOnPressed: () => addOrderDetails(),
      ),
    );
  }

  void addOrderDetails() {
    final time = DateTime.now().millisecondsSinceEpoch;

    writeOrderDetailsForUser({
      ShoppingApp.addressID: widget.addressID,
      ShoppingApp.totalAmount: widget.totalAmount,
      'orderBy': ShoppingApp.sharedPreferences.getString(
        ShoppingApp.userUID,
      ),
      ShoppingApp.productID: ShoppingApp.sharedPreferences.getStringList(
        ShoppingApp.userCartList,
      ),
      ShoppingApp.paymentDetails: ShoppingPageString.cashOnDelivery,
      ShoppingApp.orderTime: time.toString(),
      ShoppingApp.isSuccess: true,
    });

    writeOrderDetailsForAdmin({
      ShoppingApp.addressID: widget.addressID,
      ShoppingApp.totalAmount: widget.totalAmount,
      'orderBy': ShoppingApp.sharedPreferences.getString(
        ShoppingApp.userUID,
      ),
      ShoppingApp.productID: ShoppingApp.sharedPreferences.getStringList(
        ShoppingApp.userCartList,
      ),
      ShoppingApp.paymentDetails: ShoppingPageString.cashOnDelivery,
      ShoppingApp.orderTime: time.toString(),
      ShoppingApp.isSuccess: true,
    }).whenComplete(() => {
          emptyCartNow(),
        });
  }

  void emptyCartNow() {
    ShoppingApp.sharedPreferences.setStringList(ShoppingApp.userCartList, [
      'garbageValue',
    ]);
    List<String>? tempList = ShoppingApp.sharedPreferences.getStringList(
      ShoppingApp.userCartList,
    );

    FirebaseFirestore.instance
        .collection('users')
        .doc(ShoppingApp.sharedPreferences.getString(
          ShoppingApp.userUID,
        ))
        .update({
      ShoppingApp.userCartList: tempList,
    }).then((value) {
      ShoppingApp.sharedPreferences.setStringList(
        ShoppingApp.userCartList,
        tempList as List<String>,
      );
      Provider.of<CartItemCounterProvider>(
        context,
        listen: false,
      ).displayResult();
    });
    Fluttertoast.showToast(
      msg: ToastString.orderPlacedSuccessfully,
    );
    Navigator.pushReplacement(
      context,
      MaterialPageRoute(
        builder: (context) => const ShoppingPage(),
      ),
    );
  }

  Future<void> writeOrderDetailsForUser(
    Map<String, dynamic> data,
  ) async {
    await ShoppingApp.firestore
        .collection(ShoppingApp.collectionUser)
        .doc(ShoppingApp.sharedPreferences.getString(ShoppingApp.userUID))
        .collection(ShoppingApp.collectionOrders)
        .doc(
          ShoppingApp.sharedPreferences.getString(ShoppingApp.userUID)! +
              data['orderTime'],
        )
        .set(data);
  }

  Future<void> writeOrderDetailsForAdmin(Map<String, dynamic> data) async {
    await ShoppingApp.firestore
        .collection(ShoppingApp.collectionOrders)
        .doc(
          ShoppingApp.sharedPreferences.getString(ShoppingApp.userUID)! +
              data['orderTime'],
        )
        .set(data);
  }
}


class CartItemCounterProvider extends ChangeNotifier {
  final int _counter = (ShoppingApp.sharedPreferences
              .getStringList(
                ShoppingApp.userCartList,
              )
              ?.length ??
          0) -
      1;
  int get count => _counter;

  Future<void> displayResult() async {
    
    int _counter = (ShoppingApp.sharedPreferences
                .getStringList(
                  ShoppingApp.userCartList,
                )
                ?.length ??
            0) -
        1;

    await Future.delayed(
        const Duration(
          milliseconds: 100,
        ), () {
      notifyListeners();
    });
  }
}
Ad

Answer

CartCheckOutFAB is first being instantiated with value 0 always since ShoppingCartPage state is not being changed. You could try to move Consumer2<TotalAmountProvider, CartItemCounterProvider> as parent of AdaptiveLayoutScaffold and instantiate the CartCheckOutFAB with amountProvider.totalAmount

  • If its not working can you provide the CartCheckOutFAB widget class.
Ad
source: stackoverflow.com
Ad