0

I have a shopping app, Using Provider I am able to create a list of Cart items. Based on the price and the quantity from each item, a grand total is calculated. I want the user to enter their own quantity.

Here is my CartScreen

  Widget build(BuildContext context) {
    final cart = Provider.of<Cart>(context);
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.red,
        title: Text("Items Purchased"),
      ),
      body: Column(
        children: <Widget>[
          Card(
            margin: EdgeInsets.all(15),
            child: Padding(
              padding: EdgeInsets.all(8.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  Text(
                    'Total',
                    style: TextStyle(
                      fontSize: 20,
                    ),
                  ),
                  Spacer(),
                  Chip(
                    label: Text(
                      'GHC ${cart.totalAmount}',
                      style: TextStyle(
                        color: Colors.white,
                      ),
                    ),
                    backgroundColor: Colors.redAccent,
                  ),
                  FlatButton(
                    onPressed: () {
                      print(cart);
                      // Provider.of<Orders>(context).addOrder(
                      //     cart.items.values.toList(), cart.totalAmount);
                      // cart.clear();
                    },
                    child: Text("CONFIRM"),
                  ),
                ],
              ),
            ),
          ),
          SizedBox(
            height: 10,
          ),
          Expanded(
            child: ListView.builder(
              itemCount: cart.itemCount,
              itemBuilder: (ctx, i) => CartItemWidget(
                  cart.items.values.toList()[i].id,
                  cart.items.keys.toList()[i],
                  cart.items.values.toList()[i].price,


                  TextField(
                    controller: _controllers[i],
                    onChanged: (value) {
                      final x = double.tryParse(value);
                      setState(() {
                        itemTotal = x ?? 0;
                        itemTotal = cart.items.values.toList()[i].price * x;
                        print(itemTotal);
                      });
                    },
                  ),
                  cart.items.values.toList()[i].quantity,
                  cart.items.values.toList()[i].title,
                  cart.items.values.toList()[i].image),
            ),
          ),
        ],
      ),
    );
  }

I think the calculation should be at the CartItemWidget instead.

class CartItemWidget extends StatelessWidget {
  final String id;
  final String productId;
  final double price;
  final Widget quantityField;
  final int quantity;
  final String title;
  final String image;

  CartItemWidget(this.id, this.productId, this.price, this.quantityField,
      this.quantity, this.title, this.image);

  @override
  Widget build(BuildContext context) {
    return Dismissible(
      key: ValueKey(id),
      direction: DismissDirection.endToStart,
      background: Container(
        color: Theme.of(context).errorColor,
        child: Icon(
          Icons.delete,
          color: Colors.white,
          size: 40,
        ),
        alignment: Alignment.centerRight,
        padding: EdgeInsets.only(right: 20),
        margin: EdgeInsets.symmetric(horizontal: 15, vertical: 4),
      ),
      onDismissed: (direction) {
        Provider.of<Cart>(context, listen: false).removeItem(productId);
      },
      child: Card(
        margin: EdgeInsets.symmetric(
          horizontal: 15,
          vertical: 4,
        ),
        child: Padding(
          padding: EdgeInsets.all(8),
          child: ListTile(
            leading: CircleAvatar(
              child: FittedBox(child: Image.asset(image)),
              backgroundColor: Colors.black38,
            ),
            title: Text(title),
            subtitle: Text('Total: GHC ${(price * quantity)}'),
            trailing: Container(width: 70.0, child: TextField()),
            // trailing: Text('$quantity X'),
          ),
        ),
      ),
    );
  }
}

I have a Model class with Provider too.

class CartItem with ChangeNotifier {
  final String id;
  final String title;
  final int quantity;
  final double price;
  final String image;

  CartItem(
      {@required this.id,
      @required this.title,
      @required this.quantity,
      @required this.price,
      this.image});
}

class Cart with ChangeNotifier {
  Map<String, CartItem> _items = {};

  Map<String, CartItem> get items {
    return {..._items};
  }

  int get itemCount {
    return _items.length;
  }

  double get totalAmount {
    double total = 0.0;
    _items.forEach((key, cartItem) {
      total += cartItem.price * cartItem.quantity;
    });
    return total;
  }

  double get totalForEachItem {
    double total = 0.0;
    _items(key, cartItem) {
      total = cartItem.price * cartItem.quantity;
    }
  }

  void addItems(String productId, double price, String title, String image) {
    if (_items.containsKey(productId)) {
      //change quantity
      _items.remove(productId);
      // clear();
    } else {
      _items.putIfAbsent(
        productId,
        () => CartItem(
            id: DateTime.now().toString(),
            title: title,
            price: price,
            quantity: 1,
            image: image),
      );
    }
    notifyListeners();
  }
  
  void removeItem(String productId) {
    _items.remove(productId);
    notifyListeners();
  }

  void getItemTotal(String productId, double price, int quantity) {}

  void clear() {
    _items = {};
    notifyListeners();
  }
}

What I want Currently the product details such as name, price and quantity are passed from the products page. I want the user to enter their own quantity and total will automatically update by multiplying the quantity entered for cartItem[i] by the price at cartItem[i] and add the total for each item for the grandtotal.

What I have done I created a list of controllers so i can get the values at each cartitem. I also used the onChange to get the value to multiply the price and set a total with that.

winfred adrah
  • 428
  • 6
  • 18

1 Answers1

0

Create a void function (use a setter type function set )that sets the quantity of the item. then tie the onSubmitted parameter (or however you're receiving the data) of textField with the setter function of the provider.

Now the setter function sets the new value for the quantity of the product and rebuilds the rest of the widgets.

I may not be able to correctly drop you the code, but you could get some help with my idea.

Happy to help :)

Delwinn
  • 891
  • 4
  • 19