Created
June 13, 2025 13:25
-
-
Save hectorAguero/fff608870f54f9d6aa4dc5803a3ef4f0 to your computer and use it in GitHub Desktop.
Bloc with ShoppingCart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/material.dart'; | |
import 'package:flutter_bloc/flutter_bloc.dart'; | |
void main() { | |
runApp(const MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
const MyApp({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Shopping Cart App', | |
theme: ThemeData(primarySwatch: Colors.blue), | |
home: const ShoppingCartPage(), | |
); | |
} | |
} | |
class ShoppingCartPage extends StatelessWidget { | |
const ShoppingCartPage({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar(title: const Text('Shopping Cart')), | |
body: BlocProvider( | |
create: (context) => ShoppingCartCubit(), | |
child: const ShoppingCartView(), | |
), | |
); | |
} | |
} | |
class ShoppingCartView extends StatelessWidget { | |
const ShoppingCartView({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return BlocBuilder<ShoppingCartCubit, ShoppingCartState>( | |
builder: (context, state) { | |
if (state is ShoppingCartInitial) { | |
return const Center(child: CircularProgressIndicator()); | |
} else if (state is ShoppingCartLoaded) { | |
return ListView.builder( | |
itemCount: state.items.length, | |
itemBuilder: (context, index) { | |
final item = state.items[index]; | |
return BlocProvider( | |
// Provide unique keys to BLoCs | |
//key: Key(item.id.toString()), | |
create: (context) => CartItemCubit(item), | |
child: CartItemWidget(item: item), | |
); | |
}, | |
); | |
} else if (state is ShoppingCartError) { | |
return Center(child: Text('Error: ${state.message}')); | |
} else { | |
return const Center(child: Text('Unknown state')); | |
} | |
}, | |
); | |
} | |
} | |
class CartItemWidget extends StatelessWidget { | |
const CartItemWidget({super.key, required this.item}); | |
final CartItem item; | |
@override | |
Widget build(BuildContext context) { | |
return BlocBuilder<CartItemCubit, CartItemState>( | |
builder: (context, state) { | |
return Card( | |
margin: const EdgeInsets.all(8.0), | |
child: Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: Row( | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: [ | |
Text(item.name), | |
Row( | |
children: [ | |
IconButton( | |
icon: const Icon(Icons.remove), | |
onPressed: state.quantity > 0 | |
? () => context.read<CartItemCubit>().decrement() | |
: null, | |
), | |
Text('${state.quantity}'), | |
IconButton( | |
icon: const Icon(Icons.add), | |
onPressed: () => | |
context.read<CartItemCubit>().increment(), | |
), | |
], | |
), | |
], | |
), | |
), | |
); | |
}, | |
); | |
} | |
} | |
// Data Model | |
class CartItem { | |
final int id; | |
final String name; | |
CartItem({required this.id, required this.name}); | |
} | |
// Cart Item Cubit | |
sealed class CartItemState { | |
final int quantity; | |
CartItemState({required this.quantity}); | |
} | |
class CartItemInitial extends CartItemState { | |
CartItemInitial({required super.quantity}); | |
} | |
class CartItemUpdated extends CartItemState { | |
CartItemUpdated({required super.quantity}); | |
} | |
class CartItemCubit extends Cubit<CartItemState> { | |
final CartItem item; | |
CartItemCubit(this.item) : super(CartItemInitial(quantity: 0)); | |
void increment() { | |
emit(CartItemUpdated(quantity: state.quantity + 1)); | |
} | |
void decrement() { | |
if (state.quantity > 0) { | |
emit(CartItemUpdated(quantity: state.quantity - 1)); | |
} | |
} | |
} | |
// Shopping Cart Cubit | |
sealed class ShoppingCartState {} | |
class ShoppingCartInitial extends ShoppingCartState {} | |
class ShoppingCartLoaded extends ShoppingCartState { | |
final List<CartItem> items; | |
ShoppingCartLoaded({required this.items}); | |
} | |
class ShoppingCartError extends ShoppingCartState { | |
final String message; | |
ShoppingCartError({required this.message}); | |
} | |
class ShoppingCartCubit extends Cubit<ShoppingCartState> { | |
ShoppingCartCubit() : super(ShoppingCartInitial()) { | |
loadItems(); | |
} | |
Future<void> loadItems() async { | |
try { | |
// Simulate loading items from a data source | |
await Future.delayed(const Duration(seconds: 1)); | |
final items = [ | |
CartItem(id: 1, name: 'Apple'), | |
CartItem(id: 2, name: 'Banana'), | |
CartItem(id: 3, name: 'Orange'), | |
]; | |
emit(ShoppingCartLoaded(items: items)); | |
} catch (e) { | |
emit(ShoppingCartError(message: 'Failed to load items')); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment