Skip to content

Instantly share code, notes, and snippets.

@hanskokx
Created August 22, 2022 21:13
Show Gist options
  • Save hanskokx/9b715219388bed0bfedb16c1dcefcc26 to your computer and use it in GitHub Desktop.
Save hanskokx/9b715219388bed0bfedb16c1dcefcc26 to your computer and use it in GitHub Desktop.
Cubit for app state management example
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() {
runApp(
BlocProvider(
create: (context) => ShoppingCartCubit(),
child: const MyApp(),
),
);
}
const List<Item> inventory = [
Item(name: "Shirt", cost: 12.99),
Item(name: "Shoes", cost: 120.00),
Item(name: "Pants", cost: 63.74),
Item(name: "Hat", cost: 8.23),
];
typedef Cart = List<Item>;
class CartState {
final List<Item> itemsInCart;
CartState(this.itemsInCart);
}
class Inventory extends StatelessWidget {
const Inventory({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
children: [
Text(
'Inventory',
style: Theme.of(context).textTheme.displayMedium,
),
ListView.builder(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
itemCount: inventory.length,
itemBuilder: (BuildContext context, int i) => Card(
child: ListTile(
title: Text(inventory[i].name),
subtitle: Text('\$${inventory[i].cost.toStringAsFixed(2)}'),
trailing: IconButton(
icon: const Icon(Icons.add_shopping_cart),
onPressed: () => context.read<ShoppingCartCubit>().add(
inventory[i],
),
),
),
),
),
],
);
}
}
class Item {
final double cost;
final String name;
const Item({
required this.cost,
required this.name,
});
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
children: const [
Inventory(),
ShoppingCart(),
],
),
),
),
);
}
}
class ShoppingCart extends StatelessWidget {
const ShoppingCart({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocBuilder<ShoppingCartCubit, CartState>(
builder: (BuildContext context, CartState cart) {
final List<Item> uniqueItemsInCart =
context.read<ShoppingCartCubit>().uniqueItemsInCart;
final double totalCost = context.read<ShoppingCartCubit>().totalCost;
return ListView(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
children: [
Text(
'Shopping Cart',
style: Theme.of(context).textTheme.displayMedium,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text('Items in Cart: ${cart.itemsInCart.length}'),
Text('Total Cost: \$${totalCost.toStringAsFixed(2)}'),
OutlinedButton.icon(
label: const Text('Clear cart'),
icon: const Icon(Icons.remove_shopping_cart),
onPressed: () =>
context.read<ShoppingCartCubit>().clearCart(),
),
],
),
ListView.builder(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
itemCount: uniqueItemsInCart.length,
itemBuilder: (context, i) {
return Card(
child: ListTile(
leading: Text(
'${cart.itemsInCart.where((element) => element == uniqueItemsInCart[i]).length} ×'),
title: Text(uniqueItemsInCart[i].name),
subtitle: Text(
'\$${uniqueItemsInCart[i].cost.toStringAsFixed(2)}'),
),
);
},
),
],
);
},
);
}
}
class ShoppingCartCubit extends Cubit<CartState> {
ShoppingCartCubit() : super(CartState([]));
double get totalCost {
double price = 0;
for (Item item in state.itemsInCart) {
price += item.cost;
}
return price;
}
List<Item> get uniqueItemsInCart {
final List<Item> unique = [];
for (Item item in state.itemsInCart) {
if (!unique.contains(item)) {
unique.add(item);
}
}
return unique;
}
void add(Item item) {
final after = state.itemsInCart..add(item);
emit(CartState(after));
}
void clearCart() {
emit(CartState([]));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment