added prototype of the filter bar + all quotes count
This commit is contained in:
+131
-54
@@ -17,11 +17,11 @@ class ListPage extends StatelessWidget {
|
||||
onRefresh: () async {
|
||||
await provider.readQuotes();
|
||||
},
|
||||
child: _bodyBuilder(provider),
|
||||
child: _bodyBuilder(context, provider),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _bodyBuilder(QuoteProvider provider) {
|
||||
Widget _bodyBuilder(BuildContext context, QuoteProvider provider) {
|
||||
if (provider.loading) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
}
|
||||
@@ -30,61 +30,79 @@ class ListPage extends StatelessWidget {
|
||||
return Center(child: Text(provider.error!));
|
||||
}
|
||||
|
||||
final quoteCount = provider.quotes.length;
|
||||
|
||||
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<String>(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
|
||||
onSelected: (value) {
|
||||
if (value == 'update') {
|
||||
// open a dialog window that allows for mods
|
||||
_showUpdateDialog(context, provider, quote);
|
||||
} else if (value == 'delete') {
|
||||
// open a confirmation dialog window for deletion
|
||||
_showDeleteDialog(context, provider, quote);
|
||||
}
|
||||
},
|
||||
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'update',
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.edit),
|
||||
SizedBox(width: 10),
|
||||
Text(Strings.updateQuote),
|
||||
],
|
||||
Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(Constants.edgeInset),
|
||||
child: Text(
|
||||
'${Strings.allQuotesCount} – $quoteCount',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
),
|
||||
),
|
||||
filterBar(context, provider),
|
||||
Expanded(
|
||||
child: 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,
|
||||
),
|
||||
),
|
||||
|
||||
const PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.delete),
|
||||
SizedBox(width: 10),
|
||||
Text(Strings.deleteQuote),
|
||||
title: Text(quote.body),
|
||||
subtitle: Text("– ${quote.author}"),
|
||||
trailing: PopupMenuButton<String>(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
|
||||
onSelected: (value) {
|
||||
if (value == 'update') {
|
||||
// open a dialog window that allows for mods
|
||||
_showUpdateDialog(context, provider, quote);
|
||||
} else if (value == 'delete') {
|
||||
// open a confirmation dialog window for deletion
|
||||
_showDeleteDialog(context, provider, quote);
|
||||
}
|
||||
},
|
||||
|
||||
itemBuilder: (context) => [
|
||||
const PopupMenuItem(
|
||||
value: 'update',
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.edit),
|
||||
SizedBox(width: 10),
|
||||
Text(Strings.updateQuote),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.delete),
|
||||
SizedBox(width: 10),
|
||||
Text(Strings.deleteQuote),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -191,4 +209,63 @@ class ListPage extends StatelessWidget {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget filterBar(BuildContext context, QuoteProvider provider) {
|
||||
int filterBy = 0; // 0 = by author, 1 = by quote
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(Constants.edgeInset),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: provider.filterController,
|
||||
decoration: InputDecoration(
|
||||
label: Text(Strings.filterQuery),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(Icons.cancel),
|
||||
onPressed: provider.clearFilterController
|
||||
)
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.search),
|
||||
onPressed: () {
|
||||
// TODO: filtering
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: Icon(Icons.more_horiz),
|
||||
onPressed: () {
|
||||
_showOptionsBottomSheet(context, provider);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showOptionsBottomSheet(BuildContext context, QuoteProvider provider) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return SizedBox(
|
||||
height: 300,
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.all(Constants.edgeInset),
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(Strings.filterBy),
|
||||
trailing: Icon(Icons.filter_alt),
|
||||
),
|
||||
ListTile(
|
||||
title: Text(Strings.exportSelectedQuotes),
|
||||
trailing: Icon(Icons.import_export),
|
||||
),
|
||||
],
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,12 @@ class QuoteProvider extends ChangeNotifier {
|
||||
|
||||
final QuoteRepository repo = QuoteRepository();
|
||||
|
||||
var filterController = TextEditingController(text: '');
|
||||
|
||||
void clearFilterController() {
|
||||
filterController.text = '';
|
||||
}
|
||||
|
||||
QuoteProvider() {
|
||||
readQuotes(); // auto-load on creation
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
// talks to the DB itself
|
||||
// TODO: mock for now!
|
||||
|
||||
import 'package:frontend/model/quote.dart';
|
||||
|
||||
class QuoteRepository {
|
||||
//final String _dbBaseUrl = 'https://hlaskovnik-reimagined-latest.onrender.com';
|
||||
|
||||
Future<List<Quote>> getQuotes() async {
|
||||
return [
|
||||
Quote(id: 1, author: 'Adam', body: 'kratom je vule bozi'),
|
||||
Quote(id: 2, author: 'Vojta', body: 'kalach s kecupem'),
|
||||
Quote(id: 3, author: 'Anton', body: 'have you ever noticed how long cows are'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -20,4 +20,8 @@ class Strings {
|
||||
static const String author = "Autor";
|
||||
|
||||
static const String noUndo = "Tuto akci nelze odčinit.";
|
||||
static const String filterQuery = "Filtrovací požadavek";
|
||||
static const String allQuotesCount = "Celkový počet hlášek";
|
||||
static const String filterBy = "Filtrovat podle";
|
||||
static const String exportSelectedQuotes = "Exportovat vybrané hlášky";
|
||||
}
|
||||
Reference in New Issue
Block a user