skip to Main Content

I am having some issues in my code.
So I am trying to create a product cart where a user clicks on the + button to increase the quantity of products and clicks on – button to decrease the quantity of products. Also these products are recommended products so they should have a default quantity of 1 product. But when I set the initial quantity to be 1, it does not behave well. When I click on the product once, it does not update but when when I click the second time, it updates it to 2. I tried doing some print statement, and I noticed that the default is still 0 and when it is clicked once, it just update to 1 and the second time is now 2 which now changed on the UI. How do I make it know there is an existing item of 1 quantity so when I increase it, it changes to 2 immediately. Also when I decrease it, it changes to 0 since it is 1 by default.

These are my code
I am using provider for state management

//cart_provider.dart

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

class CartProvider with ChangeNotifier {
  List<Product> cartItems = [];

  void addProduct(Product product) {
    final existingProductIndex =
        cartItems.indexWhere((p) => p.productName == product.productName);
    if (existingProductIndex != -1) {
      cartItems[existingProductIndex].quantity++;
    } else {
      product.quantity = 0;
      cartItems.add(product);
    }
    notifyListeners();
  }

  void updateQuantity(Product product, bool isIncrement) {
    final existingProductIndex =
        cartItems.indexWhere((p) => p.productId == product.productId);
    if (existingProductIndex != -1) {
      if (isIncrement && product.quantity < 99) {
        cartItems[existingProductIndex].quantity++;
        product.isDecrementButtonDisabled = false;
      } else if (!isIncrement) {
        cartItems[existingProductIndex].quantity--;
        if (cartItems[existingProductIndex].quantity == 0) {
          product.isDecrementButtonDisabled = true;
        }
      }
    } else {
      addProduct(product);
    }
    notifyListeners();
  }
}

//product_card.dart (this is where I am displaying the data"

import 'package:flutter/material.dart';
import 'package:greenbii_app/providers/cart_provider.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';

import '../constants/constants.dart';
import '../models/product_model.dart';

class ProductCard extends StatelessWidget {
  final Product product;

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

  @override
  Widget build(BuildContext context) {
    NumberFormat currencyFormat = NumberFormat.currency(
      locale: 'en_NG',
      name: 'naira',
      symbol: '₦',
    );
    return Consumer<CartProvider>(
      builder: (context, cartProvider, child) {
        return Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: [
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    product.productName,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(
                      color: AppColors.textColor,
                      fontSize: 16.0,
                      fontWeight: FontWeight.w700,
                    ),
                  ),
                  Text(
                    product.descriptions,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(
                      color: AppColors.disabledColor,
                      fontSize: 12.0,
                      fontWeight: FontWeight.w500,
                    ),
                  ),
                  const SizedBox(height: 10.0),
                  Text(
                    currencyFormat.format(double.parse(product.amount)),
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(
                      color: AppColors.primaryColor,
                      fontSize: 18.0,
                      fontWeight: FontWeight.w600,
                    ),
                  ),
                ],
              ),
            ),
            Row(
              children: [
                IconButton(
                  onPressed: product.isDecrementButtonDisabled
                      ? null
                      : () => context
                          .read<CartProvider>()
                          .updateQuantity(product, false),
                  icon: const Icon(Icons.remove),
                ),
                const SizedBox(width: 10.0),
                Text(product.quantity.toString()),
                const SizedBox(width: 10.0),
                IconButton(
                  onPressed: () => context
                      .read<CartProvider>()
                      .updateQuantity(product, true),
                  icon: const Icon(Icons.add),
                ),
              ],
            )
          ],
        );
      },
    );
  }
}

//product_model.dart

class Product {
  final int productId;
  final String productName;
  final String descriptions;
  final String amount;
  bool isDecrementButtonDisabled = false;
  int quantity = 1;

  Product({
    required this.productId,
    required this.productName,
    required this.descriptions,
    required this.amount,
  });

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Product &&
          runtimeType == other.runtimeType &&
          productId == other.productId;

  @override
  int get hashCode => productId.hashCode;
}

//loan_application.dart

import 'package:flutter/material.dart';
import 'package:greenbii_app/constants/constants.dart';
import 'package:greenbii_app/providers/cart_provider.dart';
import 'package:greenbii_app/widgets/menu_app_bar.dart';
import 'package:provider/provider.dart';

import '../models/product_model.dart';
import '../navigations/navigate.dart';
import '../widgets/data/product_data.dart';
import '../widgets/product_card.dart';

class LoanApplication extends StatefulWidget {
  const LoanApplication({super.key});

  @override
  State<LoanApplication> createState() => _LoanApplicationState();
}

class _LoanApplicationState extends State<LoanApplication> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const MenuAppBar(
        menuName: 'Loan Application',
        isBack: true,
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                width: double.infinity,
                decoration: BoxDecoration(
                  color: AppColors.successColor,
                  borderRadius: BorderRadius.circular(10),
                ),
                child: const Padding(
                  padding: EdgeInsets.all(16.0),
                  child: Text(
                    'Best rate! The Purchasing Power Index of your business has been applied to your interest rate.',
                    style: TextStyle(
                      color: AppColors.primaryColor,
                    ),
                  ),
                ),
              ),
              const SizedBox(height: 50),
              const Text(
                'Recommended Devices',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w600,
                ),
              ),
              const SizedBox(height: 10),
              Container(
                width: double.infinity,
                padding: const EdgeInsets.symmetric(
                    vertical: 31.0, horizontal: 21.0),
                decoration: BoxDecoration(
                  color: AppColors.whiteColor,
                  borderRadius: BorderRadius.circular(20.0),
                  boxShadow: const [
                    BoxShadow(
                      color: AppColors.shadowColor,
                      spreadRadius: 0.0,
                      blurRadius: 20.0,
                    ),
                  ],
                ),
                child: ListView.separated(
                  itemCount: products.length,
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  itemBuilder: (context, index) {
                    final product = products[index];
                    // final cart = Provider.of<CartProvider>(context);
                    return Consumer<CartProvider>(
                        builder: (context, cartProvider, child) {
                      return ProductCard(
                        key: ValueKey(product.productId),
                        product: product,
                      );
                    });
                  },
                  separatorBuilder: (context, index) => const Divider(
                    height: 30.0,
                  ),
                ),
              ),
              const SizedBox(height: 20),
              const Text(
                'More Devices',
                style: TextStyle(
                  fontSize: 16,
                  fontWeight: FontWeight.w600,
                ),
              ),
              const SizedBox(height: 10),
              Container(
                width: double.infinity,
                padding: const EdgeInsets.symmetric(
                    vertical: 31.0, horizontal: 21.0),
                decoration: BoxDecoration(
                  color: AppColors.whiteColor,
                  borderRadius: BorderRadius.circular(20.0),
                  boxShadow: const [
                    BoxShadow(
                      color: AppColors.shadowColor,
                      spreadRadius: 0.0,
                      blurRadius: 20.0,
                    ),
                  ],
                ),
                child: ListView.separated(
                  itemCount: products.length,
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  itemBuilder: (context, index) {
                    final product = products[index];
                    final cart = Provider.of<CartProvider>(context);
                    return ProductCard(
                      key: ValueKey(product.productId),
                      product: product,
                    );
                  },
                  separatorBuilder: (context, index) => const Divider(
                    height: 30.0,
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 16.0),
        child: GestureDetector(
          onTap: () {
            // navigate(context, const LoanApplication());
          },
          child: Container(
            width: double.infinity,
            padding: const EdgeInsets.all(16),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(20),
              color: AppColors.primaryColor,
            ),
            child: const Text(
              textAlign: TextAlign.center,
              'Apply for Funding',
              style: TextStyle(
                color: Colors.white,
                fontSize: 16,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

//product_data.dart

import 'package:greenbii_app/models/product_model.dart';

final List<Product> products = [
  Product(
    productId: 1,
    productName: 'Mobile Tablet',
    descriptions: '10 inches screen, 4g ram, table or wall fitted.',
    amount: '100000.00',
  ),
  Product(
    productId: 2,
    productName: 'Laptop',
    descriptions: '(500GB HDD, 8GB RAM, Core i5).',
    amount: '250000.00',
  ),
  Product(
    productId: 3,
    productName: '2.5Kva Backup Solar',
    descriptions: '24v hybrid inverter, 2 batteries, 4 380W panels.',
    amount: '300000.00',
  ),
];

Please I will be glad if I get a quick response and detailed explanation as I am just a beginner flutter developer.

Thank you guys. I will really appreciate this.

2

Answers


  1. Chosen as BEST ANSWER

    So I have been able o sort this. I realised that I am not fetching the products into the cart and also not allowing the state management to handle the state.


  2. The problem is that at the very first increment to any product, you’re not actually having that product yet in cartItems. The product is being read directly from the products list, so the first increment only add the product to the cartItems, without incrementing it. Since you said that these products should have the initial quantity to 1, it means that you should populate cartItems with products from the products list at the very beginning. You can solve it by changing the initialization of cartItems like this:

    class CartProvider with ChangeNotifier {
      List<Product> cartItems = [...products];
    
      // ...
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search