aboutsummaryrefslogtreecommitdiff
path: root/lib/views/shoplist_view.dart
diff options
context:
space:
mode:
Diffstat (limited to 'lib/views/shoplist_view.dart')
-rw-r--r--lib/views/shoplist_view.dart167
1 files changed, 167 insertions, 0 deletions
diff --git a/lib/views/shoplist_view.dart b/lib/views/shoplist_view.dart
new file mode 100644
index 0000000..a9caed8
--- /dev/null
+++ b/lib/views/shoplist_view.dart
@@ -0,0 +1,167 @@
+import 'dart:convert';
+
+import 'package:flutter/material.dart';
+
+import 'package:kulinar_app/constants.dart';
+import 'package:kulinar_app/widgets/error_widgets.dart';
+import 'package:kulinar_app/widgets/toastbar_widget.dart';
+import 'package:kulinar_app/widgets/custom_drawer_widget.dart';
+import 'package:kulinar_app/models/data/shoplist_data_class.dart';
+
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+class ShoplistView extends StatefulWidget {
+ const ShoplistView({Key? key}) : super(key: key);
+
+ @override
+ _ShoplistView createState() => _ShoplistView();
+}
+
+class _ShoplistView extends State<ShoplistView> {
+ final FocusNode _focusNode = FocusNode();
+ final TextEditingController _controller = TextEditingController();
+ final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
+ final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
+ PersistentBottomSheetController? _bottomSheetController;
+ bool _open = false;
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ key: _scaffoldKey,
+ appBar: AppBar(title: Text(AppLocalizations.of(context)!.category7)),
+ drawer: CustomDrawer(initalIndex: 4),
+ floatingActionButton: _buildFloatingActionButton(),
+ body: _buildAnimatedList(),
+ );
+ }
+
+ Widget _buildFloatingActionButton() {
+ return FloatingActionButton(
+ child: Icon(_open ? Icons.remove_rounded : Icons.add_rounded, color: cIconColor),
+ onPressed: () {
+ if (_open) {
+ _closeInput();
+ } else {
+ _bottomSheetController = _scaffoldKey.currentState!.showBottomSheet((context) => _buildBottomSheetInput());
+ _open = !_open;
+
+ setState(() {});
+ }
+ },
+ );
+ }
+
+ // TODO: FIXME: Sometimes exception "cant call insertItem of null" is thrown when first item is added or last is removed
+ Widget _buildAnimatedList() {
+ if (ShoplistData.shoplist.length == 0) return NoContentError();
+
+ return AnimatedList(
+ key: _listKey,
+ initialItemCount: ShoplistData.shoplist.length,
+ itemBuilder: (BuildContext context, int index, Animation<double> animation) {
+ return SlideTransition(
+ position: animation.drive(Tween(begin: Offset(1.0, 0.0), end: Offset(0.0, 0.0))),
+ child: Dismissible(
+ key: Key(_getUniqueKeyString(ShoplistData.shoplist[index])),
+ background: _buildDimissibleBackground(true),
+ secondaryBackground: _buildDimissibleBackground(false),
+ child: ListTile(
+ title: Text(ShoplistData.shoplist[index]),
+ ),
+ onDismissed: (_) {
+ String _content = AppLocalizations.of(context)!.removed;
+ String _actionLabel = AppLocalizations.of(context)!.undo;
+
+ _removeItem(index);
+ ToastBar.showToastBar(context, _content, actionLabel: _actionLabel, actionCallback: () => _addItem(ShoplistData.removed.removeLast()));
+ },
+ ),
+ );
+ },
+ );
+ }
+
+ Widget _buildDimissibleBackground(bool left) {
+ return Container(
+ color: cPrimaryColor,
+ /*
+ child: Row(
+ mainAxisAlignment: left ? MainAxisAlignment.start : MainAxisAlignment.end,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Icon(
+ Icons.delete_rounded,
+ color: cIconColor,
+ ),
+ ),
+ ],
+ ),
+ */
+ );
+ }
+
+ Widget _buildBottomSheetInput() {
+ _focusNode.requestFocus();
+
+ return WillPopScope(
+ child: Container(
+ height: 75.0,
+ color: cPrimaryColor,
+ child: Padding(
+ padding: const EdgeInsets.all(15.0),
+ child: TextFormField(
+ controller: _controller,
+ style: cRecipeTextStyle.copyWith(color: cIconColor),
+ cursorColor: cIconColor,
+ focusNode: _focusNode,
+ textInputAction: TextInputAction.done,
+ onEditingComplete: () {
+ String _text = _controller.text.trim();
+
+ _closeInput();
+ _controller.clear();
+
+ if (_text != "") _addItem(_text);
+ },
+ ),
+ ),
+ ),
+ onWillPop: () async {
+ return false;
+ },
+ );
+ }
+
+ String _getUniqueKeyString(String item) {
+ return base64Encode(utf8.encode(item));
+ }
+
+ void _removeItem(int index) {
+ _listKey.currentState!.removeItem(index, (_, __) => Container());
+ ShoplistData.removed.add(ShoplistData.shoplist.removeAt(index));
+
+ ShoplistData.save();
+
+ setState(() {});
+ }
+
+ void _addItem(String string) {
+ ShoplistData.shoplist.add(string);
+ if (ShoplistData.shoplist.length > 1) _listKey.currentState!.insertItem(ShoplistData.shoplist.indexOf(string));
+
+ ShoplistData.save();
+
+ setState(() {});
+ }
+
+ void _closeInput() {
+ _bottomSheetController!.close();
+ _focusNode.unfocus();
+
+ _open = !_open;
+
+ setState(() {});
+ }
+}