Commit 327d974d authored by Hans Muller's avatar Hans Muller Committed by GitHub

Added shopping cart and sorting to Shrine (#4616)

parent 415324f2
...@@ -15,7 +15,8 @@ import 'shrine_types.dart'; ...@@ -15,7 +15,8 @@ import 'shrine_types.dart';
const double unitSize = kToolBarHeight; const double unitSize = kToolBarHeight;
Map<Product, Order> shoppingCart = <Product, Order>{}; final List<Product> _products = new List<Product>.from(allProducts());
final Map<Product, Order> _shoppingCart = <Product, Order>{};
/// Displays the Vendor's name and avatar. /// Displays the Vendor's name and avatar.
class VendorItem extends StatelessWidget { class VendorItem extends StatelessWidget {
...@@ -63,7 +64,7 @@ abstract class PriceItem extends StatelessWidget { ...@@ -63,7 +64,7 @@ abstract class PriceItem extends StatelessWidget {
Widget buildItem(BuildContext context, TextStyle style, EdgeInsets padding) { Widget buildItem(BuildContext context, TextStyle style, EdgeInsets padding) {
BoxDecoration decoration; BoxDecoration decoration;
if (shoppingCart[product] != null) if (_shoppingCart[product] != null)
decoration = new BoxDecoration(backgroundColor: const Color(0xFFFFE0E0)); decoration = new BoxDecoration(backgroundColor: const Color(0xFFFFE0E0));
return new Container( return new Container(
...@@ -259,18 +260,16 @@ class ShrineHome extends StatefulWidget { ...@@ -259,18 +260,16 @@ class ShrineHome extends StatefulWidget {
} }
class _ShrineHomeState extends State<ShrineHome> { class _ShrineHomeState extends State<ShrineHome> {
final List<Product> _products = allProducts(); static final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>(debugLabel: 'Order page');
void handleCompletedOrder(Order completedOrder) { void handleCompletedOrder(Order completedOrder) {
assert(completedOrder.product != null); assert(completedOrder.product != null);
if (completedOrder.inCart && completedOrder.quantity > 0) if (completedOrder.quantity == 0)
shoppingCart[completedOrder.product] = completedOrder; _shoppingCart.remove(completedOrder.product);
else
shoppingCart[completedOrder.product] = null;
} }
void showOrderPage(Product product) { void showOrderPage(Product product) {
final Order order = shoppingCart[product] ?? new Order(product: product); final Order order = _shoppingCart[product] ?? new Order(product: product);
final Completer<Order> completer = new Completer<Order>(); final Completer<Order> completer = new Completer<Order>();
final Key productKey = new ObjectKey(product); final Key productKey = new ObjectKey(product);
final Set<Key> mostValuableKeys = new HashSet<Key>(); final Set<Key> mostValuableKeys = new HashSet<Key>();
...@@ -282,7 +281,8 @@ class _ShrineHomeState extends State<ShrineHome> { ...@@ -282,7 +281,8 @@ class _ShrineHomeState extends State<ShrineHome> {
builder: (BuildContext context) { builder: (BuildContext context) {
return new OrderPage( return new OrderPage(
order: order, order: order,
products: _products products: _products,
shoppingCart: _shoppingCart
); );
} }
)); ));
...@@ -293,6 +293,9 @@ class _ShrineHomeState extends State<ShrineHome> { ...@@ -293,6 +293,9 @@ class _ShrineHomeState extends State<ShrineHome> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final Product featured = _products.firstWhere((Product product) => product.featureDescription != null); final Product featured = _products.firstWhere((Product product) => product.featureDescription != null);
return new ShrinePage( return new ShrinePage(
scaffoldKey: scaffoldKey,
products: _products,
shoppingCart: _shoppingCart,
body: new ScrollableViewport( body: new ScrollableViewport(
child: new RepaintBoundary( child: new RepaintBoundary(
child: new Column( child: new Column(
......
...@@ -118,13 +118,15 @@ class OrderItem extends StatelessWidget { ...@@ -118,13 +118,15 @@ class OrderItem extends StatelessWidget {
} }
class OrderPage extends StatefulWidget { class OrderPage extends StatefulWidget {
OrderPage({ Key key, this.order, this.products }) : super(key: key) { OrderPage({ Key key, this.order, this.products, this.shoppingCart }) : super(key: key) {
assert(order != null); assert(order != null);
assert(products != null && products.length > 0); assert(products != null && products.length > 0);
assert(shoppingCart != null);
} }
final Order order; final Order order;
final List<Product> products; final List<Product> products;
final Map<Product, Order> shoppingCart;
@override @override
_OrderPageState createState() => new _OrderPageState(); _OrderPageState createState() => new _OrderPageState();
...@@ -134,7 +136,7 @@ class OrderPage extends StatefulWidget { ...@@ -134,7 +136,7 @@ class OrderPage extends StatefulWidget {
/// arranged in two columns. Enables the user to specify a quantity and add an /// arranged in two columns. Enables the user to specify a quantity and add an
/// order to the shopping cart. /// order to the shopping cart.
class _OrderPageState extends State<OrderPage> { class _OrderPageState extends State<OrderPage> {
final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>(debugLabel: 'Order Page'); static final GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey<ScaffoldState>(debugLabel: 'Order page');
Order get currentOrder => ShrineOrderRoute.of(context).order; Order get currentOrder => ShrineOrderRoute.of(context).order;
...@@ -146,6 +148,7 @@ class _OrderPageState extends State<OrderPage> { ...@@ -146,6 +148,7 @@ class _OrderPageState extends State<OrderPage> {
Order newOrder = currentOrder.copyWith(quantity: quantity, inCart: inCart); Order newOrder = currentOrder.copyWith(quantity: quantity, inCart: inCart);
if (currentOrder != newOrder) { if (currentOrder != newOrder) {
setState(() { setState(() {
config.shoppingCart[newOrder.product] = newOrder;
currentOrder = newOrder; currentOrder = newOrder;
}); });
} }
...@@ -159,12 +162,15 @@ class _OrderPageState extends State<OrderPage> { ...@@ -159,12 +162,15 @@ class _OrderPageState extends State<OrderPage> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new ShrinePage( return new ShrinePage(
scaffoldKey: scaffoldKey, scaffoldKey: scaffoldKey,
products: config.products,
shoppingCart: config.shoppingCart,
floatingActionButton: new FloatingActionButton( floatingActionButton: new FloatingActionButton(
onPressed: () { onPressed: () {
updateOrder(inCart: true); updateOrder(inCart: true);
final int n = currentOrder.quantity; final int n = currentOrder.quantity;
final String item = currentOrder.product.name;
showSnackBarMessage( showSnackBarMessage(
'There ${ n == 1 ? "is one item" : "are $n items" } in the shopping cart.' 'There ${ n == 1 ? "is one $item item" : "are $n $item items" } in the shopping cart.'
); );
}, },
backgroundColor: const Color(0xFF16F0F0), backgroundColor: const Color(0xFF16F0F0),
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'shrine_theme.dart'; import 'shrine_theme.dart';
import 'shrine_types.dart';
enum ShrineAction { enum ShrineAction {
sortByPrice, sortByPrice,
...@@ -13,11 +14,23 @@ enum ShrineAction { ...@@ -13,11 +14,23 @@ enum ShrineAction {
} }
class ShrinePage extends StatefulWidget { class ShrinePage extends StatefulWidget {
ShrinePage({ Key key, this.scaffoldKey, this.body, this.floatingActionButton }) : super(key: key); ShrinePage({
Key key,
this.scaffoldKey,
this.body,
this.floatingActionButton,
this.products,
this.shoppingCart
}) : super(key: key) {
assert(body != null);
assert(scaffoldKey != null);
}
final Key scaffoldKey; final GlobalKey<ScaffoldState> scaffoldKey;
final Widget body; final Widget body;
final Widget floatingActionButton; final Widget floatingActionButton;
final List<Product> products;
final Map<Product, Order> shoppingCart;
@override @override
ShrinePageState createState() => new ShrinePageState(); ShrinePageState createState() => new ShrinePageState();
...@@ -37,6 +50,37 @@ class ShrinePageState extends State<ShrinePage> { ...@@ -37,6 +50,37 @@ class ShrinePageState extends State<ShrinePage> {
return false; return false;
} }
void _showShoppingCart() {
showModalBottomSheet/*<Null>*/(context: context, builder: (BuildContext context) {
if (config.shoppingCart.isEmpty) {
return new Padding(
padding: const EdgeInsets.all(24.0),
child: new Text('The shopping cart is empty')
);
}
return new MaterialList(children: config.shoppingCart.values.map((Order order) {
return new ListItem(
title: new Text(order.product.name),
leading: new Text('${order.quantity}'),
subtitle: new Text(order.product.vendor.name)
);
}).toList());
});
}
void _sortByPrice() {
config.products.sort((Product a, Product b) => a.price.compareTo(b.price));
}
void _sortByProduct() {
config.products.sort((Product a, Product b) => a.name.compareTo(b.name));
}
void _emptyCart() {
config.shoppingCart.clear();
config.scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text('Shopping cart is empty')));
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Scaffold( return new Scaffold(
...@@ -59,7 +103,7 @@ class ShrinePageState extends State<ShrinePage> { ...@@ -59,7 +103,7 @@ class ShrinePageState extends State<ShrinePage> {
icon: Icons.shopping_cart, icon: Icons.shopping_cart,
tooltip: 'Shopping cart', tooltip: 'Shopping cart',
onPressed: () { onPressed: () {
// TODO(hansmuller): implement the action. _showShoppingCart();
} }
), ),
new PopupMenuButton<ShrineAction>( new PopupMenuButton<ShrineAction>(
...@@ -80,13 +124,13 @@ class ShrinePageState extends State<ShrinePage> { ...@@ -80,13 +124,13 @@ class ShrinePageState extends State<ShrinePage> {
onSelected: (ShrineAction action) { onSelected: (ShrineAction action) {
switch (action) { switch (action) {
case ShrineAction.sortByPrice: case ShrineAction.sortByPrice:
// TODO(hansmuller): implement the action. setState(_sortByPrice);
break; break;
case ShrineAction.sortByProduct: case ShrineAction.sortByProduct:
// TODO(hansmuller): implement the action. setState(_sortByProduct);
break; break;
case ShrineAction.emptyCart: case ShrineAction.emptyCart:
// TODO(hansmuller): implement the action. setState(_emptyCart);
break; break;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment