From d022a0c180fdf808e9cce5f257713db88f16bb67 Mon Sep 17 00:00:00 2001 From: Herwig Birke Date: Thu, 28 Mar 2024 08:28:35 +0100 Subject: [PATCH] backend --- lib/widgets/grocery_list.dart | 82 ++++++++++++++++++++++++++++++++++- lib/widgets/new_item.dart | 30 ++++++++++--- 2 files changed, 104 insertions(+), 8 deletions(-) diff --git a/lib/widgets/grocery_list.dart b/lib/widgets/grocery_list.dart index 5e682bb..68ad7c4 100644 --- a/lib/widgets/grocery_list.dart +++ b/lib/widgets/grocery_list.dart @@ -1,4 +1,8 @@ +import 'dart:convert'; + import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:flutter_shopping_list/data/categories.dart'; import 'package:flutter_shopping_list/models/grocery_item.dart'; import 'package:flutter_shopping_list/widgets/new_item.dart'; @@ -11,7 +15,61 @@ class GroceryList extends StatefulWidget { } class _GroceryListState extends State { - final List _groceryItems = []; + List _groceryItems = []; + var _isLoading = true; + String? _error; + + @override + void initState() { + super.initState(); + _loadItems(); + } + + void _loadItems() async { + final url = Uri.https( + 'flutter-prep-dccfe-default-rtdb.firebaseio.com', 'shopping-list.json'); + + try { + final response = await http.get(url); + + if (response.statusCode >= 400) { + setState(() { + _error = 'Failed to fetch data. Please try again later.'; + }); + } + + if (response.body == 'null') { + setState(() { + _isLoading = false; + }); + return; + } + + final Map listData = json.decode(response.body); + final List loadedItems = []; + for (final item in listData.entries) { + final category = categories.entries + .firstWhere( + (catItem) => catItem.value.title == item.value['category']) + .value; + loadedItems.add(GroceryItem( + id: item.key, + name: item.value['name'], + quantity: item.value['quantity'], + category: category, + )); + } + + setState(() { + _groceryItems = loadedItems; + _isLoading = false; + }); + } catch (error) { + setState(() { + _error = 'Something went wrong. Please try again later.'; + }); + } + } void _addItem() async { final newItem = await Navigator.of(context).push( @@ -29,16 +87,32 @@ class _GroceryListState extends State { }); } - void _removeItem(GroceryItem item) { + void _removeItem(GroceryItem item) async { + final index = _groceryItems.indexOf(item); setState(() { _groceryItems.remove(item); }); + + final url = Uri.https('flutter-prep-dccfe-default-rtdb.firebaseio.com', + 'shopping-list/${item.id}.json'); + + final response = await http.delete(url); + + if (response.statusCode >= 400) { + setState(() { + _groceryItems.insert(index, item); + }); + } } @override Widget build(BuildContext context) { Widget content = const Center(child: Text('No items added yet.')); + if (_isLoading) { + content = const Center(child: CircularProgressIndicator()); + } + if (_groceryItems.isNotEmpty) { content = ListView.builder( itemCount: _groceryItems.length, @@ -62,6 +136,10 @@ class _GroceryListState extends State { ); } + if (_error != null) { + content = Center(child: Text(_error!)); + } + return Scaffold( appBar: AppBar( title: const Text('Your Groceries'), diff --git a/lib/widgets/new_item.dart b/lib/widgets/new_item.dart index 5c3a58e..44f98b4 100644 --- a/lib/widgets/new_item.dart +++ b/lib/widgets/new_item.dart @@ -22,10 +22,14 @@ class _NewItemState extends State { var _enteredName = ''; var _enteredQuantity = 1; var _selectedCategory = categories[Categories.vegetables]!; + var _isSending = false; void _saveItem() async { if (_formKey.currentState!.validate()) { _formKey.currentState!.save(); + setState(() { + _isSending = true; + }); final url = Uri.https('flutter-prep-dccfe-default-rtdb.firebaseio.com', 'shopping-list.json'); final response = await http.post( @@ -40,14 +44,20 @@ class _NewItemState extends State { ), ); - print(response.body); - print(response.statusCode); + final Map resData = json.decode(response.body); if (!context.mounted) { return; } - Navigator.of(context).pop(); + Navigator.of(context).pop( + GroceryItem( + id: resData['name'], + name: _enteredName, + quantity: _enteredQuantity, + category: _selectedCategory, + ), + ); } } @@ -144,14 +154,22 @@ class _NewItemState extends State { mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( - onPressed: () { + onPressed: _isSending + ? null + : () { _formKey.currentState!.reset(); }, child: const Text('Reset'), ), ElevatedButton( - onPressed: _saveItem, - child: const Text('Add Item'), + onPressed: _isSending ? null : _saveItem, + child: _isSending + ? SizedBox( + height: 16, + width: 16, + child: const CircularProgressIndicator(), + ) + : const Text('Add Item'), ), ], ),