From 67008188b91efa7318214d6e41f21253c29d2778 Mon Sep 17 00:00:00 2001 From: Odweta Date: Mon, 23 Mar 2026 09:59:42 +0100 Subject: [PATCH] add author selection menu --- frontend/lib/main.dart | 2 +- frontend/lib/main_scaffold.dart | 2 +- frontend/lib/pages/add.dart | 37 +++++++++++++++++-- frontend/lib/pages/list.dart | 43 ++++++++++++++++++++++- frontend/lib/provider/quote_provider.dart | 24 ++++++++++++- 5 files changed, 101 insertions(+), 7 deletions(-) diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 5fda8f9..39a0d06 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; -import 'strings.dart'; +import 'values/strings.dart'; import 'main_scaffold.dart'; // providers diff --git a/frontend/lib/main_scaffold.dart b/frontend/lib/main_scaffold.dart index 2bfa2da..2e64928 100644 --- a/frontend/lib/main_scaffold.dart +++ b/frontend/lib/main_scaffold.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'strings.dart'; +import 'values/strings.dart'; class MainScaffold extends StatelessWidget { final Widget child; diff --git a/frontend/lib/pages/add.dart b/frontend/lib/pages/add.dart index 0cb2411..fb8be0e 100644 --- a/frontend/lib/pages/add.dart +++ b/frontend/lib/pages/add.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:frontend/provider/quote_provider.dart'; import 'package:frontend/model/quote.dart'; +import 'package:provider/provider.dart'; + import 'package:frontend/values/strings.dart'; import 'package:frontend/values/constants.dart'; @@ -12,7 +14,7 @@ class AddPage extends StatelessWidget { Widget build(BuildContext context) { final bodyController = TextEditingController(text: ''); final authorController = TextEditingController(text: ''); - final provider = QuoteProvider(); + final provider = Provider.of(context); return Card( margin: const EdgeInsets.all(Constants.edgeInset), child: Padding( @@ -40,11 +42,40 @@ class AddPage extends StatelessWidget { ), const SizedBox(height: 8), - TextField( controller: authorController, - decoration: const InputDecoration( + decoration: InputDecoration( labelText: Strings.author, + suffixIcon: IconButton( + icon: Icon(Icons.arrow_drop_down), + onPressed: () { + showModalBottomSheet( + context: context, + builder: (context) { + var authors = provider.authors.toList()..sort(); + + return SizedBox( + height: 300, + child: ListView.builder( + padding: const EdgeInsets.all(Constants.edgeInset), + itemCount: authors.length, + itemBuilder: (context, index) { + final author = authors[index]; + + return ListTile( + title: Text(author), + onTap: () { + authorController.text = author; + Navigator.pop(context); + }, + ); + }, + ), + ); + }, + ); + }, + ), ), ), diff --git a/frontend/lib/pages/list.dart b/frontend/lib/pages/list.dart index ef59e22..bb40a71 100644 --- a/frontend/lib/pages/list.dart +++ b/frontend/lib/pages/list.dart @@ -2,9 +2,11 @@ import 'package:flutter/material.dart'; import 'package:frontend/provider/quote_provider.dart'; import 'package:frontend/model/quote.dart'; -import 'package:frontend/strings.dart'; +import 'package:frontend/values/strings.dart'; import 'package:provider/provider.dart'; +import 'package:frontend/values/constants.dart'; + class ListPage extends StatelessWidget { const ListPage({super.key}); @@ -30,12 +32,18 @@ class ListPage extends StatelessWidget { return ListView.builder( + padding: EdgeInsets.all(Constants.edgeInset), itemCount: provider.quotes.length, itemBuilder: (context, index) { final quote = provider.quotes[index]; return ListTile( + contentPadding: EdgeInsets.only( + bottom: Constants.edgeInset, + left: Constants.edgeInset, + right: Constants.edgeInset, + ), title: Text(quote.body), subtitle: Text("– ${quote.author}"), trailing: PopupMenuButton( @@ -97,6 +105,39 @@ class ListPage extends StatelessWidget { ), TextField( controller: authorController, + decoration: InputDecoration( + label: Text(Strings.author), + suffixIcon: IconButton( + icon: Icon(Icons.arrow_drop_down), + onPressed: () { + showModalBottomSheet( + context: context, + builder: (context) { + var authors = provider.authors.toList()..sort(); + + return SizedBox( + height: 300, + child: ListView.builder( + padding: const EdgeInsets.all(Constants.edgeInset), + itemCount: authors.length, + itemBuilder: (context, index) { + final author = authors[index]; + + return ListTile( + title: Text(author), + onTap: () { + authorController.text = author; + Navigator.pop(context); + }, + ); + }, + ), + ); + }, + ); + }, + ), + ), ), ], ), diff --git a/frontend/lib/provider/quote_provider.dart b/frontend/lib/provider/quote_provider.dart index 342844d..ff9ba55 100644 --- a/frontend/lib/provider/quote_provider.dart +++ b/frontend/lib/provider/quote_provider.dart @@ -7,10 +7,12 @@ import 'package:frontend/repository/quote_repository.dart'; class QuoteProvider extends ChangeNotifier { List _quotes = []; + Set _authors = {}; bool _loading = false; String? _error; List get quotes => _quotes; + Set get authors => _authors; bool get loading => _loading; String? get error => _error; @@ -20,6 +22,13 @@ class QuoteProvider extends ChangeNotifier { readQuotes(); // auto-load on creation } + void populateAuthors() { + _authors = {}; + for (var i = 0; i < quotes.length; i++) { + _authors.add(quotes[i].author); + } + } + Future readQuotes() async { _loading = true; _error = null; @@ -31,6 +40,8 @@ class QuoteProvider extends ChangeNotifier { _error = e.toString(); } + populateAuthors(); + _loading = false; notifyListeners(); } @@ -38,6 +49,7 @@ class QuoteProvider extends ChangeNotifier { Future createQuote(Quote quote) async { final newQuote = await repo.createQuote(quote); _quotes.add(newQuote); + populateAuthors(); notifyListeners(); } @@ -50,11 +62,20 @@ class QuoteProvider extends ChangeNotifier { final index = _quotes.indexWhere((q) => q.id == quote.id); if (index != -1) { + final oldAuthor = _quotes[index].author; final newList = List.from(_quotes); newList[index] = updated; _quotes = newList; + Map authorMap = {}; + for (final q in quotes) { + authorMap[q.author] = (authorMap[q.author] ?? 0) + 1; + } + if (authorMap[oldAuthor] == 1) { + _authors.remove(oldAuthor); + } + _authors.add(updated.author); } - } finally { + } finally { _loading = false; notifyListeners(); } @@ -64,6 +85,7 @@ class QuoteProvider extends ChangeNotifier { await repo.deleteQuote(quote); _quotes.removeWhere((q) => q.id == quote.id); + populateAuthors(); notifyListeners(); } } \ No newline at end of file