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 {
|
onRefresh: () async {
|
||||||
await provider.readQuotes();
|
await provider.readQuotes();
|
||||||
},
|
},
|
||||||
child: _bodyBuilder(provider),
|
child: _bodyBuilder(context, provider),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _bodyBuilder(QuoteProvider provider) {
|
Widget _bodyBuilder(BuildContext context, QuoteProvider provider) {
|
||||||
if (provider.loading) {
|
if (provider.loading) {
|
||||||
return Center(child: CircularProgressIndicator());
|
return Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
@@ -30,61 +30,79 @@ class ListPage extends StatelessWidget {
|
|||||||
return Center(child: Text(provider.error!));
|
return Center(child: Text(provider.error!));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final quoteCount = provider.quotes.length;
|
||||||
|
|
||||||
return
|
return
|
||||||
ListView.builder(
|
Column(
|
||||||
padding: EdgeInsets.all(Constants.edgeInset),
|
children: [
|
||||||
itemCount: provider.quotes.length,
|
Center(
|
||||||
itemBuilder: (context, index) {
|
child: Padding(
|
||||||
final quote = provider.quotes[index];
|
padding: const EdgeInsets.all(Constants.edgeInset),
|
||||||
|
child: Text(
|
||||||
return
|
'${Strings.allQuotesCount} – $quoteCount',
|
||||||
ListTile(
|
style: TextStyle(fontSize: 18),
|
||||||
contentPadding: EdgeInsets.only(
|
),
|
||||||
bottom: Constants.edgeInset,
|
),
|
||||||
left: Constants.edgeInset,
|
),
|
||||||
right: Constants.edgeInset,
|
filterBar(context, provider),
|
||||||
),
|
Expanded(
|
||||||
title: Text(quote.body),
|
child: ListView.builder(
|
||||||
subtitle: Text("– ${quote.author}"),
|
padding: EdgeInsets.all(Constants.edgeInset),
|
||||||
trailing: PopupMenuButton<String>(
|
itemCount: provider.quotes.length,
|
||||||
icon: const Icon(Icons.more_vert),
|
itemBuilder: (context, index) {
|
||||||
|
final quote = provider.quotes[index];
|
||||||
onSelected: (value) {
|
|
||||||
if (value == 'update') {
|
return
|
||||||
// open a dialog window that allows for mods
|
ListTile(
|
||||||
_showUpdateDialog(context, provider, quote);
|
contentPadding: EdgeInsets.only(
|
||||||
} else if (value == 'delete') {
|
bottom: Constants.edgeInset,
|
||||||
// open a confirmation dialog window for deletion
|
left: Constants.edgeInset,
|
||||||
_showDeleteDialog(context, provider, quote);
|
right: Constants.edgeInset,
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
itemBuilder: (context) => [
|
|
||||||
const PopupMenuItem(
|
|
||||||
value: 'update',
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Icon(Icons.edit),
|
|
||||||
SizedBox(width: 10),
|
|
||||||
Text(Strings.updateQuote),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
title: Text(quote.body),
|
||||||
|
subtitle: Text("– ${quote.author}"),
|
||||||
const PopupMenuItem(
|
trailing: PopupMenuButton<String>(
|
||||||
value: 'delete',
|
icon: const Icon(Icons.more_vert),
|
||||||
child: Row(
|
|
||||||
children: [
|
onSelected: (value) {
|
||||||
Icon(Icons.delete),
|
if (value == 'update') {
|
||||||
SizedBox(width: 10),
|
// open a dialog window that allows for mods
|
||||||
Text(Strings.deleteQuote),
|
_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();
|
final QuoteRepository repo = QuoteRepository();
|
||||||
|
|
||||||
|
var filterController = TextEditingController(text: '');
|
||||||
|
|
||||||
|
void clearFilterController() {
|
||||||
|
filterController.text = '';
|
||||||
|
}
|
||||||
|
|
||||||
QuoteProvider() {
|
QuoteProvider() {
|
||||||
readQuotes(); // auto-load on creation
|
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 author = "Autor";
|
||||||
|
|
||||||
static const String noUndo = "Tuto akci nelze odčinit.";
|
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