Created
July 20, 2025 11:18
-
-
Save mihalycsaba/acd411b511512473e3711aa30f2125b8 to your computer and use it in GitHub Desktop.
shopping list with callbacks
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'; | |
typedef CartChangedCallback = void Function(Product product); | |
typedef CartDeleteCallback = void Function(Product product); | |
void main() { | |
runApp(const MaterialApp( | |
title: 'Shopping App', | |
home: ShoppingList(), | |
)); | |
} | |
class Product { | |
Product({required this.inCart, required this.name}); | |
final String name; | |
bool inCart; | |
} | |
class ShoppingListItem extends StatelessWidget { | |
ShoppingListItem( | |
{required this.product, required this.onCartChanged, this.onCartDelete}) | |
: super(key: ObjectKey(product)); | |
final Product product; | |
final CartChangedCallback onCartChanged; | |
final CartDeleteCallback? onCartDelete; | |
Color _getColor(BuildContext context) { | |
return product.inCart // | |
? Colors.black54 | |
: Theme.of(context).primaryColor; | |
} | |
TextStyle? _getTextStyle(BuildContext context) { | |
if (!product.inCart) return null; | |
return const TextStyle( | |
color: Colors.black54, | |
decoration: TextDecoration.lineThrough, | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return ListTile( | |
onLongPress: () { | |
onCartDelete!(product); | |
}, | |
onTap: () { | |
onCartChanged(product); | |
}, | |
leading: CircleAvatar( | |
backgroundColor: _getColor(context), | |
child: Text(product.name[0]), | |
), | |
title: Text(product.name, style: _getTextStyle(context)), | |
); | |
} | |
} | |
class ShoppingList extends StatefulWidget { | |
const ShoppingList({super.key}); | |
@override | |
_ShoppingListState createState() => _ShoppingListState(); | |
} | |
class _ShoppingListState extends State<ShoppingList> { | |
List<Product> products = List<Product>.empty(growable: true); | |
final TextEditingController _textFieldController = TextEditingController(); | |
late String valueText; | |
void _handleCartChanged(Product product) async { | |
setState(() { | |
if (!product.inCart) { | |
product.inCart = true; | |
} else { | |
product.inCart = false; | |
} | |
}); | |
} | |
void _handleCartDelete(Product product) { | |
showDialog( | |
context: context, | |
builder: (context) { | |
return AlertDialog( | |
title: const Text('Attention'), | |
content: const Text('Do you want to delete the item?'), | |
actions: <Widget>[ | |
TextButton( | |
style: TextButton.styleFrom( | |
foregroundColor: Colors.red, | |
), | |
child: const Text('CANCEL'), | |
onPressed: () { | |
setState(() { | |
Navigator.pop(context); | |
}); | |
}, | |
), | |
TextButton( | |
child: const Text('YES'), | |
onPressed: () async { | |
products.removeWhere((item) => item.name == product.name); | |
setState(() { | |
Navigator.pop(context); | |
}); | |
}, | |
), | |
]); | |
}); | |
} | |
void _addProduct(BuildContext context) async { | |
return showDialog( | |
context: context, | |
builder: (context) { | |
return AlertDialog( | |
title: const Text('Item'), | |
content: TextField( | |
onChanged: (value) { | |
setState(() { | |
valueText = value; | |
}); | |
}, | |
controller: _textFieldController, | |
decoration: const InputDecoration(hintText: "Add"), | |
), | |
actions: <Widget>[ | |
TextButton( | |
style: TextButton.styleFrom( | |
foregroundColor: Colors.red, | |
), | |
child: const Text('CANCEL'), | |
onPressed: () { | |
setState(() { | |
_textFieldController.clear(); | |
Navigator.pop(context); | |
}); | |
}, | |
), | |
TextButton( | |
child: const Text('OK'), | |
onPressed: () async { | |
products.add(Product(inCart: true, name: valueText)); | |
_handleCartChanged(products.last); | |
setState(() { | |
_textFieldController.clear(); | |
Navigator.pop(context); | |
}); | |
}, | |
), | |
], | |
); | |
}); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text('Shopping List'), | |
), | |
body: ListView.builder( | |
itemCount: products.length, | |
itemBuilder: (context, index) { | |
return ShoppingListItem( | |
product: products[index], | |
onCartChanged: _handleCartChanged, | |
onCartDelete: _handleCartDelete, | |
); | |
}), | |
floatingActionButton: FloatingActionButton( | |
onPressed: () => _addProduct(context), | |
tooltip: 'Add', | |
child: const Icon(Icons.add), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment