From a0549069704a49fb7b841ce37cac926ae1f40fa8 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Sun, 26 Feb 2023 23:24:23 +0100 Subject: [PATCH 01/30] Add relapse model and database --- lib/models/relapse.dart | 27 +++++++++++++++++++++++++++ lib/services/database_service.dart | 15 +++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 lib/models/relapse.dart diff --git a/lib/models/relapse.dart b/lib/models/relapse.dart new file mode 100644 index 0000000..78eeb12 --- /dev/null +++ b/lib/models/relapse.dart @@ -0,0 +1,27 @@ +import 'package:smoke_cess_app/interface/db_record.dart'; + +class Relapse implements DatabaseRecord { + final String _comment; + final DateTime _date; + + Relapse(this._comment, this._date); + + @override + factory Relapse.fromDatabase(Map map) { + DateTime date = DateTime.parse(map['date']); + return Relapse(map['comment'], date); + } + + @override + String toCSV() { + return "${_date.toIso8601String()}, {_wokeUpAt.minute}, $_comment"; + } + + @override + Map toMap() { + return { + 'comment': _comment, + 'date': _date.toIso8601String(), + }; + } +} diff --git a/lib/services/database_service.dart b/lib/services/database_service.dart index 8dc8788..030a5af 100644 --- a/lib/services/database_service.dart +++ b/lib/services/database_service.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:path/path.dart'; import 'package:smoke_cess_app/models/mood.dart'; +import 'package:smoke_cess_app/models/relapse.dart'; import 'package:sqflite/sqflite.dart'; // ignore: depend_on_referenced_packages import 'package:path_provider/path_provider.dart'; @@ -53,6 +54,15 @@ class DatabaseService { return sleepList; } + Future> getRelapseRecords() async { + Database db = await instance.database; + var relapseRecords = await db.query('relapse'); + List relapseList = relapseRecords.isNotEmpty + ? relapseRecords.map((e) => Relapse.fromDatabase(e)).toList() + : []; + return relapseList; + } + Future addMood(Mood mood) async { Database db = await instance.database; return await db.insert('mood', mood.toMap()); @@ -62,6 +72,11 @@ class DatabaseService { Database db = await instance.database; return await db.insert('sleep', sleep.toMap()); } + + Future addRelapse(Relapse relapse) async { + Database db = await instance.database; + return await db.insert('relapse', relapse.toMap()); + } } String _createMoodTable = ''' From 0b57c14e05365544a294dcab9cbf9128b7022f59 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Sun, 26 Feb 2023 23:29:47 +0100 Subject: [PATCH 02/30] Add relapse db part2 --- lib/mock/db_mock.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/mock/db_mock.dart b/lib/mock/db_mock.dart index a06f003..e7c60c3 100644 --- a/lib/mock/db_mock.dart +++ b/lib/mock/db_mock.dart @@ -1,5 +1,6 @@ import 'package:smoke_cess_app/interface/db_record.dart'; import 'package:smoke_cess_app/models/mood.dart'; +import 'package:smoke_cess_app/models/relapse.dart'; import 'package:smoke_cess_app/models/sleep.dart'; import 'package:smoke_cess_app/services/database_service.dart'; import 'package:sqflite_common/sqlite_api.dart'; @@ -13,6 +14,7 @@ class DatabaseMock implements DatabaseService { final List _moodRecords = []; final List _sleepRecords = []; + final List _relapseRecords = []; final List _workoutRecords = []; @override @@ -27,6 +29,12 @@ class DatabaseMock implements DatabaseService { return Future.value(1); } + @override + Future addRelapse(Relapse relapse) { + _relapseRecords.add(relapse); + return Future.value(1); + } + @override // TODO: implement database Future get database => DatabaseService.instance.database; @@ -40,4 +48,9 @@ class DatabaseMock implements DatabaseService { Future> getSleepRecords() { return Future.value(_sleepRecords); } + + @override + Future> getRelapseRecords() { + return Future.value(_relapseRecords); + } } From a574e7f718f2fd94e064664b47d744898fa6abbb Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Sun, 26 Feb 2023 23:30:00 +0100 Subject: [PATCH 03/30] Add relapse form --- lib/pages/relapse_page.dart | 9 ++++++++- lib/widgets/relapse_form.dart | 31 +++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 lib/widgets/relapse_form.dart diff --git a/lib/pages/relapse_page.dart b/lib/pages/relapse_page.dart index 7710e10..75e007d 100644 --- a/lib/pages/relapse_page.dart +++ b/lib/pages/relapse_page.dart @@ -1,10 +1,17 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:smoke_cess_app/widgets/relapse_form.dart'; +import '../providers/input_provider.dart'; class RelapsePage extends StatelessWidget { const RelapsePage({super.key}); @override Widget build(BuildContext context) { - return const Center(child: Text('Hier werden Rückfälle dokumentiert')); + return Center( + child: ChangeNotifierProvider( + create: (context) => InputProvider(), + child: const RelapseForm(), + )); } } diff --git a/lib/widgets/relapse_form.dart b/lib/widgets/relapse_form.dart new file mode 100644 index 0000000..825e303 --- /dev/null +++ b/lib/widgets/relapse_form.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:smoke_cess_app/widgets/text_formfield.dart'; + +import '../providers/input_provider.dart'; +import 'elevated_card.dart'; + +class RelapseForm extends StatelessWidget { + const RelapseForm({super.key}); + + @override + Widget build(BuildContext context) { + var inputModel = context.watch(); + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const ElevatedCard( + title: 'Beschreibe deinen Rückfall', + child: MyTextFormField('Beschreibe deinen Rückfall'), + ), + const SizedBox( + height: 80, + ), + ElevatedButton( + onPressed: () {}, + child: const Text('Speichern'), + ) + ], + ); + } +} From a2ed17fd5cb3babf9bf01a01c04c443612550fe9 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 02:27:42 +0100 Subject: [PATCH 04/30] Added SettingsProvider around MyApp --- lib/main.dart | 9 ++++++- lib/pages/main_page.dart | 2 ++ lib/pages/scanner_page.dart | 14 ++++++++++- lib/providers/settings_provider.dart | 35 ++++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 lib/providers/settings_provider.dart diff --git a/lib/main.dart b/lib/main.dart index 2c2245d..a1cf5ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:smoke_cess_app/pages/main_page.dart'; import 'package:smoke_cess_app/services/notification_service.dart'; import 'package:timezone/data/latest.dart' as tz; import 'globals.dart' as globals; +import 'providers/settings_provider.dart'; void main() { // to ensure all the widgets are initialized. @@ -21,6 +23,11 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return const MaterialApp(title: _title, home: MyHomePage()); + return MaterialApp( + title: _title, + home: ChangeNotifierProvider( + create: (context) => SettingsProvider(), + child: const MyHomePage(), + )); } } diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 2af4f13..739f0d1 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; import 'package:smoke_cess_app/pages/mood_page.dart'; import 'package:smoke_cess_app/pages/relapse_page.dart'; import 'package:smoke_cess_app/pages/scanner_page.dart'; import 'package:smoke_cess_app/pages/sleep_page.dart'; import 'package:smoke_cess_app/pages/interval_page.dart'; +import 'package:smoke_cess_app/providers/settings_provider.dart'; import 'package:smoke_cess_app/services/settings_service.dart'; import 'package:smoke_cess_app/widgets/missing_config_popup.dart'; diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index 7159694..82485f8 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:provider/provider.dart'; import 'package:smoke_cess_app/models/mood.dart'; +import 'package:smoke_cess_app/models/relapse.dart'; import 'package:smoke_cess_app/models/settings.dart'; import 'package:smoke_cess_app/services/database_service.dart'; import 'package:smoke_cess_app/services/json_service.dart'; @@ -8,6 +10,7 @@ import 'package:smoke_cess_app/services/settings_service.dart'; import 'package:smoke_cess_app/services/notification_service.dart'; import '../models/sleep.dart'; +import '../providers/settings_provider.dart'; import '../widgets/missing_config_popup.dart'; import '../globals.dart' as globals; @@ -23,6 +26,7 @@ class ScannerPageState extends State { @override Widget build(BuildContext context) { + var settings = context.watch(); return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, @@ -72,7 +76,10 @@ class ScannerPageState extends State { textStyle: const TextStyle(fontSize: 20)), onPressed: () { loadSettingsFromLocalJSON(); - NotificationService().setAllNotifications(); + Future.delayed(Duration(milliseconds: 100), () { + settings.initSettings(); + NotificationService().setAllNotifications(); + }); }, child: const Text('Read JSON'), ), @@ -84,12 +91,17 @@ class ScannerPageState extends State { List moods = await globals.databaseService.getMoodRecords(); List sleeps = await globals.databaseService.getSleepRecords(); + List relapses = + await globals.databaseService.getRelapseRecords(); for (Mood mood in moods) { print(mood.toCSV()); } for (Sleep sleep in sleeps) { print(sleep.toCSV()); } + for (Relapse relapse in relapses) { + print(relapse.toCSV()); + } }, child: const Text('Export'), ) diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart new file mode 100644 index 0000000..71efb11 --- /dev/null +++ b/lib/providers/settings_provider.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/services/settings_service.dart'; + +import '../models/settings.dart'; + +class SettingsProvider extends ChangeNotifier { + Settings? _settings; + + Settings? get settings => _settings; + + SettingsProvider() { + initSettings(); + } + + void initSettings() async { + int? group = await getGroup(); + List? relapseCategories = await getRelapseCategories(); + int? moodHours = await getMoodQueryHours(); + int? moodMinutes = await getMoodQueryMinutes(); + List? moodDays = await getMoodQueryDaysCategories(); + int? sleepHours = await getSleepQueryHours(); + int? sleepMinutes = await getSleepQueryMinutes(); + List? sleepDays = await getSleepQueryDaysCategories(); + int? chessHours = await getChessHours(); + int? chessMinutes = await getChessMinutes(); + + _settings = Settings( + group ?? 0, + relapseCategories, + QueryConfig(moodHours ?? 0, moodMinutes ?? 0, moodDays), + QueryConfig(sleepHours ?? 0, sleepMinutes ?? 0, sleepDays), + TimeConfig(chessHours ?? 0, chessMinutes ?? 0)); + notifyListeners(); + } +} From 63fdda819544f0cdf5f03f8514d5f1ae1dcee6f4 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 02:28:26 +0100 Subject: [PATCH 05/30] Added DropDown for Relapse --- lib/models/relapse.dart | 7 ++++--- lib/providers/input_provider.dart | 15 +++++++++++++++ lib/widgets/drop_down.dart | 30 ++++++++++++++++++++++++++++++ lib/widgets/relapse_form.dart | 7 ++++++- 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 lib/widgets/drop_down.dart diff --git a/lib/models/relapse.dart b/lib/models/relapse.dart index 78eeb12..2e65f51 100644 --- a/lib/models/relapse.dart +++ b/lib/models/relapse.dart @@ -1,20 +1,21 @@ import 'package:smoke_cess_app/interface/db_record.dart'; class Relapse implements DatabaseRecord { + final String _category; final String _comment; final DateTime _date; - Relapse(this._comment, this._date); + Relapse(this._category, this._comment, this._date); @override factory Relapse.fromDatabase(Map map) { DateTime date = DateTime.parse(map['date']); - return Relapse(map['comment'], date); + return Relapse(map['_category'], map['comment'], date); } @override String toCSV() { - return "${_date.toIso8601String()}, {_wokeUpAt.minute}, $_comment"; + return "${_date.toIso8601String()}, $_category, $_comment"; } @override diff --git a/lib/providers/input_provider.dart b/lib/providers/input_provider.dart index 881ce2c..5fec37c 100644 --- a/lib/providers/input_provider.dart +++ b/lib/providers/input_provider.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/models/mood.dart'; +import 'package:smoke_cess_app/models/relapse.dart'; import 'package:smoke_cess_app/models/sleep.dart'; import '../globals.dart' as globals; @@ -10,15 +11,22 @@ class InputProvider extends ChangeNotifier { 'wokeUpAt': const TimeOfDay(hour: 8, minute: 0), 'sleptAt': const TimeOfDay(hour: 22, minute: 0), }; + String _relapseCategory = ''; double get sliderValue => _sliderValue; TextEditingController get textController => _textController; + String get relapseCategory => _relapseCategory; set sliderValue(double newValue) { _sliderValue = newValue; notifyListeners(); } + set relapseCategory(String newValue) { + _relapseCategory = newValue; + notifyListeners(); + } + TimeOfDay getTimeEntry(String key) { return _times[key] ?? const TimeOfDay(hour: 12, minute: 0); } @@ -43,6 +51,13 @@ class InputProvider extends ChangeNotifier { _resetFields(); } + void saveRelapse() { + Relapse relapse = + Relapse(_relapseCategory, _textController.text, DateTime.now()); + globals.databaseService.addRelapse(relapse); + _resetFields(); + } + void saveSleep(String wokeUpKey, String sleptKey) { Sleep sleep = Sleep(_sliderValue.toInt(), _textController.text, DateTime.now(), getTimeEntry(sleptKey), getTimeEntry(wokeUpKey)); diff --git a/lib/widgets/drop_down.dart b/lib/widgets/drop_down.dart new file mode 100644 index 0000000..2df8b07 --- /dev/null +++ b/lib/widgets/drop_down.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../providers/input_provider.dart'; +import '../providers/settings_provider.dart'; + +class DropDown extends StatelessWidget { + const DropDown({super.key}); + + @override + Widget build(BuildContext context) { + var inputModel = context.watch(); + var settings = context.watch(); + return DropdownButtonFormField( + value: settings.settings?.relapseCategories?[0] ?? '', + icon: const Icon(Icons.arrow_downward), + elevation: 16, + style: const TextStyle(color: Colors.deepPurple), + onChanged: (String? value) { + inputModel.relapseCategory = value ?? ''; + }, + items: settings.settings?.relapseCategories + ?.map>((String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }).toList(), + ); + } +} diff --git a/lib/widgets/relapse_form.dart b/lib/widgets/relapse_form.dart index 825e303..b80fcba 100644 --- a/lib/widgets/relapse_form.dart +++ b/lib/widgets/relapse_form.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:smoke_cess_app/widgets/drop_down.dart'; import 'package:smoke_cess_app/widgets/text_formfield.dart'; import '../providers/input_provider.dart'; @@ -14,6 +15,10 @@ class RelapseForm extends StatelessWidget { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ + const ElevatedCard( + title: 'Rückfallkategorie', + child: DropDown(), + ), const ElevatedCard( title: 'Beschreibe deinen Rückfall', child: MyTextFormField('Beschreibe deinen Rückfall'), @@ -22,7 +27,7 @@ class RelapseForm extends StatelessWidget { height: 80, ), ElevatedButton( - onPressed: () {}, + onPressed: () => inputModel.saveRelapse(), child: const Text('Speichern'), ) ], From cbf384f9e9851aa5e7907136aae9fc22a1aa7c17 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 02:35:17 +0100 Subject: [PATCH 06/30] Refactoring: DropDown more modular --- lib/widgets/drop_down.dart | 10 ++++------ lib/widgets/relapse_form.dart | 6 ++++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/widgets/drop_down.dart b/lib/widgets/drop_down.dart index 2df8b07..ae4dec9 100644 --- a/lib/widgets/drop_down.dart +++ b/lib/widgets/drop_down.dart @@ -1,25 +1,23 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '../providers/input_provider.dart'; -import '../providers/settings_provider.dart'; class DropDown extends StatelessWidget { - const DropDown({super.key}); + final List _items; + const DropDown(this._items, {super.key}); @override Widget build(BuildContext context) { var inputModel = context.watch(); - var settings = context.watch(); return DropdownButtonFormField( - value: settings.settings?.relapseCategories?[0] ?? '', + value: _items[0], icon: const Icon(Icons.arrow_downward), elevation: 16, style: const TextStyle(color: Colors.deepPurple), onChanged: (String? value) { inputModel.relapseCategory = value ?? ''; }, - items: settings.settings?.relapseCategories - ?.map>((String value) { + items: _items.map>((String value) { return DropdownMenuItem( value: value, child: Text(value), diff --git a/lib/widgets/relapse_form.dart b/lib/widgets/relapse_form.dart index b80fcba..cc53a53 100644 --- a/lib/widgets/relapse_form.dart +++ b/lib/widgets/relapse_form.dart @@ -4,6 +4,7 @@ import 'package:smoke_cess_app/widgets/drop_down.dart'; import 'package:smoke_cess_app/widgets/text_formfield.dart'; import '../providers/input_provider.dart'; +import '../providers/settings_provider.dart'; import 'elevated_card.dart'; class RelapseForm extends StatelessWidget { @@ -12,12 +13,13 @@ class RelapseForm extends StatelessWidget { @override Widget build(BuildContext context) { var inputModel = context.watch(); + var settings = context.watch(); return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const ElevatedCard( + ElevatedCard( title: 'Rückfallkategorie', - child: DropDown(), + child: DropDown(settings.settings?.relapseCategories ?? []), ), const ElevatedCard( title: 'Beschreibe deinen Rückfall', From ba558adecbe398b7989da9c3b97923308307efaa Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:07:46 +0100 Subject: [PATCH 07/30] Check for empty list --- lib/widgets/drop_down.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/drop_down.dart b/lib/widgets/drop_down.dart index ae4dec9..845c42c 100644 --- a/lib/widgets/drop_down.dart +++ b/lib/widgets/drop_down.dart @@ -10,7 +10,7 @@ class DropDown extends StatelessWidget { Widget build(BuildContext context) { var inputModel = context.watch(); return DropdownButtonFormField( - value: _items[0], + value: _items.isEmpty ? null : _items[0], icon: const Icon(Icons.arrow_downward), elevation: 16, style: const TextStyle(color: Colors.deepPurple), From b1c6288b2b296401174bc360731a7bf3a9248138 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:08:38 +0100 Subject: [PATCH 08/30] Add initilized field for Settingsprovider --- lib/providers/settings_provider.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 71efb11..d7a2e0f 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -5,8 +5,10 @@ import '../models/settings.dart'; class SettingsProvider extends ChangeNotifier { Settings? _settings; + bool _initialized = false; Settings? get settings => _settings; + bool get initialized => _initialized; SettingsProvider() { initSettings(); @@ -30,6 +32,7 @@ class SettingsProvider extends ChangeNotifier { QueryConfig(moodHours ?? 0, moodMinutes ?? 0, moodDays), QueryConfig(sleepHours ?? 0, sleepMinutes ?? 0, sleepDays), TimeConfig(chessHours ?? 0, chessMinutes ?? 0)); + _initialized = group != 0 ? true : false; notifyListeners(); } } From 28e46d1806a978ea27ab6b4cb80d841e17cf47ee Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:19:56 +0100 Subject: [PATCH 09/30] Settingsfields nullable --- lib/models/settings.dart | 14 +++++++------- lib/providers/settings_provider.dart | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 0e7cf30..7dea33f 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -1,10 +1,10 @@ import 'package:smoke_cess_app/services/json_service.dart'; class Settings { - final int group; + final int? group; final List? relapseCategories; - final QueryConfig moodQuery; - final QueryConfig sleepQuery; + final QueryConfig? moodQuery; + final QueryConfig? sleepQuery; final TimeConfig? chessTime; Settings(this.group, this.relapseCategories, this.moodQuery, this.sleepQuery, @@ -21,8 +21,8 @@ class Settings { } class QueryConfig { - final int hours; - final int minutes; + final int? hours; + final int? minutes; final List? days; QueryConfig(this.hours, this.minutes, this.days); @@ -34,8 +34,8 @@ class QueryConfig { } class TimeConfig { - final int hours; - final int minutes; + final int? hours; + final int? minutes; TimeConfig(this.hours, this.minutes); diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index d7a2e0f..5283808 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -27,12 +27,12 @@ class SettingsProvider extends ChangeNotifier { int? chessMinutes = await getChessMinutes(); _settings = Settings( - group ?? 0, + group, relapseCategories, - QueryConfig(moodHours ?? 0, moodMinutes ?? 0, moodDays), - QueryConfig(sleepHours ?? 0, sleepMinutes ?? 0, sleepDays), - TimeConfig(chessHours ?? 0, chessMinutes ?? 0)); - _initialized = group != 0 ? true : false; + QueryConfig(moodHours, moodMinutes, moodDays), + QueryConfig(sleepHours, sleepMinutes, sleepDays), + TimeConfig(chessHours, chessMinutes)); + _initialized = group != null ? true : false; notifyListeners(); } } From d46dd3ff7b31637f7bfb45df3059c460ac4f884e Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:21:57 +0100 Subject: [PATCH 10/30] Make Settingsfields nullable part 2 --- lib/services/settings_service.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index 52028bd..c046cd2 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -52,16 +52,16 @@ Future loadSettingsFromLocalJSON() async { } void saveSettings(Settings settings) { - _setIntSetting('group', settings.group); + _setIntSetting('group', settings.group!); _setStringListSetting('relapse_categories', settings.relapseCategories!); - _setStringListSetting('mood_query_days', settings.moodQuery.days!); - _setIntSetting('mood_query_hours', settings.moodQuery.hours); - _setIntSetting('mood_query_minutes', settings.moodQuery.minutes); - _setStringListSetting('sleep_query_days', settings.sleepQuery.days!); - _setIntSetting('sleep_query_hours', settings.sleepQuery.hours); - _setIntSetting('sleep_query_minutes', settings.sleepQuery.minutes); + _setStringListSetting('mood_query_days', settings.moodQuery!.days!); + _setIntSetting('mood_query_hours', settings.moodQuery!.hours!); + _setIntSetting('mood_query_minutes', settings.moodQuery!.minutes!); + _setStringListSetting('sleep_query_days', settings.sleepQuery!.days!); + _setIntSetting('sleep_query_hours', settings.sleepQuery!.hours!); + _setIntSetting('sleep_query_minutes', settings.sleepQuery!.minutes!); if (settings.chessTime != null) { - _setIntSetting('chess_hours', settings.chessTime!.hours); - _setIntSetting('chess_minutes', settings.chessTime!.minutes); + _setIntSetting('chess_hours', settings.chessTime!.hours!); + _setIntSetting('chess_minutes', settings.chessTime!.minutes!); } } From 21470da038398f4184aeaa90d632f4654f02024b Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:27:45 +0100 Subject: [PATCH 11/30] outsource loadsettings to settings_service --- lib/providers/settings_provider.dart | 20 ++------------------ lib/services/settings_service.dart | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/lib/providers/settings_provider.dart b/lib/providers/settings_provider.dart index 5283808..f51c5e1 100644 --- a/lib/providers/settings_provider.dart +++ b/lib/providers/settings_provider.dart @@ -15,24 +15,8 @@ class SettingsProvider extends ChangeNotifier { } void initSettings() async { - int? group = await getGroup(); - List? relapseCategories = await getRelapseCategories(); - int? moodHours = await getMoodQueryHours(); - int? moodMinutes = await getMoodQueryMinutes(); - List? moodDays = await getMoodQueryDaysCategories(); - int? sleepHours = await getSleepQueryHours(); - int? sleepMinutes = await getSleepQueryMinutes(); - List? sleepDays = await getSleepQueryDaysCategories(); - int? chessHours = await getChessHours(); - int? chessMinutes = await getChessMinutes(); - - _settings = Settings( - group, - relapseCategories, - QueryConfig(moodHours, moodMinutes, moodDays), - QueryConfig(sleepHours, sleepMinutes, sleepDays), - TimeConfig(chessHours, chessMinutes)); - _initialized = group != null ? true : false; + _settings = await loadSettings(); + _initialized = _settings != null ? true : false; notifyListeners(); } } diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index c046cd2..d72c245 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -65,3 +65,23 @@ void saveSettings(Settings settings) { _setIntSetting('chess_minutes', settings.chessTime!.minutes!); } } + +Future loadSettings() async { + int? group = await getGroup(); + List? relapseCategories = await getRelapseCategories(); + int? moodHours = await getMoodQueryHours(); + int? moodMinutes = await getMoodQueryMinutes(); + List? moodDays = await getMoodQueryDaysCategories(); + int? sleepHours = await getSleepQueryHours(); + int? sleepMinutes = await getSleepQueryMinutes(); + List? sleepDays = await getSleepQueryDaysCategories(); + int? chessHours = await getChessHours(); + int? chessMinutes = await getChessMinutes(); + + return Settings( + group, + relapseCategories, + QueryConfig(moodHours, moodMinutes, moodDays), + QueryConfig(sleepHours, sleepMinutes, sleepDays), + TimeConfig(chessHours, chessMinutes)); +} From 9c4a5e0fbb69921a967f92037a4891642ce5b2ab Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:39:42 +0100 Subject: [PATCH 12/30] return null if settings cant be correctly loaded --- lib/models/settings.dart | 2 +- lib/services/settings_service.dart | 17 ++++++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/models/settings.dart b/lib/models/settings.dart index 7dea33f..83fad43 100644 --- a/lib/models/settings.dart +++ b/lib/models/settings.dart @@ -1,7 +1,7 @@ import 'package:smoke_cess_app/services/json_service.dart'; class Settings { - final int? group; + final int group; final List? relapseCategories; final QueryConfig? moodQuery; final QueryConfig? sleepQuery; diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index d72c245..13de7f6 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -66,7 +66,7 @@ void saveSettings(Settings settings) { } } -Future loadSettings() async { +Future loadSettings() async { int? group = await getGroup(); List? relapseCategories = await getRelapseCategories(); int? moodHours = await getMoodQueryHours(); @@ -78,10 +78,13 @@ Future loadSettings() async { int? chessHours = await getChessHours(); int? chessMinutes = await getChessMinutes(); - return Settings( - group, - relapseCategories, - QueryConfig(moodHours, moodMinutes, moodDays), - QueryConfig(sleepHours, sleepMinutes, sleepDays), - TimeConfig(chessHours, chessMinutes)); + if (group != null) { + return Settings( + group, + relapseCategories, + QueryConfig(moodHours, moodMinutes, moodDays), + QueryConfig(sleepHours, sleepMinutes, sleepDays), + TimeConfig(chessHours, chessMinutes)); + } + return null; } From 395749618b47da83d7e0f20e482a96e57fda5fbf Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:40:24 +0100 Subject: [PATCH 13/30] quickfix --- lib/services/settings_service.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/settings_service.dart b/lib/services/settings_service.dart index 13de7f6..8c7e7a7 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -52,7 +52,7 @@ Future loadSettingsFromLocalJSON() async { } void saveSettings(Settings settings) { - _setIntSetting('group', settings.group!); + _setIntSetting('group', settings.group); _setStringListSetting('relapse_categories', settings.relapseCategories!); _setStringListSetting('mood_query_days', settings.moodQuery!.days!); _setIntSetting('mood_query_hours', settings.moodQuery!.hours!); From 95915e759bd008638c54942f9e6875eba604a2a2 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 11:57:55 +0100 Subject: [PATCH 14/30] Start Refactoring mainpage using Settingsprovider --- lib/pages/main_page.dart | 13 +++++++------ lib/widgets/relapse_form.dart | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 739f0d1..2e6a9f8 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -18,7 +18,7 @@ class MyHomePage extends StatefulWidget { class MyHomePageState extends State { int _selectedIndex = 4; - int? _gruppe; + bool _isConfigured = false; final List _titles = [ 'Stimmung', @@ -35,11 +35,9 @@ class MyHomePageState extends State { ScannerPage(), ]; - Future _onItemTapped(int index) async { - _gruppe = await getGroup(); - bool isConfigured = _gruppe != null; + void _onItemTapped(int index) { setState(() { - isConfigured + _isConfigured ? _selectedIndex = index : showDialog( context: context, @@ -54,10 +52,13 @@ class MyHomePageState extends State { @override Widget build(BuildContext context) { + var settingsModel = context.watch(); + var group = settingsModel.settings?.group; + _isConfigured = settingsModel.initialized; return Scaffold( appBar: AppBar( title: Text( - '${_titles[_selectedIndex]} ${_gruppe != null ? "Gruppe $_gruppe" : ""}')), + '${_titles[_selectedIndex]} ${_isConfigured ? "Gruppe $group" : ""}')), body: _widgetOptions.elementAt(_selectedIndex), bottomNavigationBar: NavigationBar( onDestinationSelected: _onItemTapped, diff --git a/lib/widgets/relapse_form.dart b/lib/widgets/relapse_form.dart index cc53a53..a00ab31 100644 --- a/lib/widgets/relapse_form.dart +++ b/lib/widgets/relapse_form.dart @@ -13,13 +13,13 @@ class RelapseForm extends StatelessWidget { @override Widget build(BuildContext context) { var inputModel = context.watch(); - var settings = context.watch(); + var settingsModel = context.watch(); return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedCard( title: 'Rückfallkategorie', - child: DropDown(settings.settings?.relapseCategories ?? []), + child: DropDown(settingsModel.settings?.relapseCategories ?? []), ), const ElevatedCard( title: 'Beschreibe deinen Rückfall', From 01d62a291c7929846b0fea08bddadf4e264e7ae6 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 14:57:56 +0100 Subject: [PATCH 15/30] refactoring mainpage --- lib/pages/main_page.dart | 59 +++++++----------------------------- lib/pages/pages_service.dart | 32 +++++++++++++++++++ 2 files changed, 43 insertions(+), 48 deletions(-) create mode 100644 lib/pages/pages_service.dart diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 2e6a9f8..5a2af86 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -1,12 +1,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:smoke_cess_app/pages/mood_page.dart'; -import 'package:smoke_cess_app/pages/relapse_page.dart'; -import 'package:smoke_cess_app/pages/scanner_page.dart'; -import 'package:smoke_cess_app/pages/sleep_page.dart'; -import 'package:smoke_cess_app/pages/interval_page.dart'; +import 'package:smoke_cess_app/pages/pages_service.dart'; import 'package:smoke_cess_app/providers/settings_provider.dart'; -import 'package:smoke_cess_app/services/settings_service.dart'; import 'package:smoke_cess_app/widgets/missing_config_popup.dart'; class MyHomePage extends StatefulWidget { @@ -20,21 +15,6 @@ class MyHomePageState extends State { int _selectedIndex = 4; bool _isConfigured = false; - final List _titles = [ - 'Stimmung', - 'Schlaf', - 'Timer', - 'Rückfall', - 'Scanner' - ]; - static const List _widgetOptions = [ - MoodPage(), - SleepPage(), - IntervalTimerPage(), - RelapsePage(), - ScannerPage(), - ]; - void _onItemTapped(int index) { setState(() { _isConfigured @@ -58,34 +38,17 @@ class MyHomePageState extends State { return Scaffold( appBar: AppBar( title: Text( - '${_titles[_selectedIndex]} ${_isConfigured ? "Gruppe $group" : ""}')), - body: _widgetOptions.elementAt(_selectedIndex), + '${pages.keys.elementAt(_selectedIndex)} ${_isConfigured ? "Gruppe $group" : ""}')), + body: pages.values.elementAt(_selectedIndex)['page'], bottomNavigationBar: NavigationBar( - onDestinationSelected: _onItemTapped, - selectedIndex: _selectedIndex, - destinations: const [ - NavigationDestination( - icon: Icon(Icons.mood_outlined, color: Colors.black), - label: 'Stimmung'), - NavigationDestination( - icon: Icon(Icons.bedtime_outlined, color: Colors.black), - label: 'Schlaf'), - NavigationDestination( - icon: Icon( - Icons.timer_outlined, - color: Colors.black, - ), - label: 'Timer'), - NavigationDestination( - icon: Icon(Icons.smoke_free_outlined, color: Colors.black), - label: 'Rückfall'), - NavigationDestination( - icon: Icon(Icons.camera_alt_outlined, color: Colors.black), - label: 'Settings'), - ], - - //onTap: _onItemTapped, - ), + onDestinationSelected: _onItemTapped, + selectedIndex: _selectedIndex, + destinations: pages.keys.map((key) { + return NavigationDestination( + icon: pages[key]!['icon'] ?? + const Icon(Icons.disabled_by_default), + label: key); + }).toList()), ); } } diff --git a/lib/pages/pages_service.dart b/lib/pages/pages_service.dart new file mode 100644 index 0000000..e530550 --- /dev/null +++ b/lib/pages/pages_service.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'interval_page.dart'; +import 'mood_page.dart'; +import 'relapse_page.dart'; +import 'scanner_page.dart'; +import 'sleep_page.dart'; + +const pages = { + 'Stimmung': { + 'page': MoodPage(), + 'icon': Icon(Icons.mood_outlined, color: Colors.black) + }, + 'Schlaf': { + 'page': SleepPage(), + 'icon': Icon(Icons.bedtime_outlined, color: Colors.black) + }, + 'Timer': { + 'page': IntervalTimerPage(), + 'icon': Icon(Icons.smoke_free_outlined, color: Colors.black) + }, + 'Rückfall': { + 'page': RelapsePage(), + 'icon': Icon( + Icons.timer_outlined, + color: Colors.black, + ) + }, + 'Scanner': { + 'page': ScannerPage(), + 'icon': Icon(Icons.camera_alt_outlined, color: Colors.black) + }, +}; From 7a402e464cfab04be24f5f8ff223b648a81950ac Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 15:19:03 +0100 Subject: [PATCH 16/30] quickfix relapse model --- lib/models/relapse.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/models/relapse.dart b/lib/models/relapse.dart index 2e65f51..0271d31 100644 --- a/lib/models/relapse.dart +++ b/lib/models/relapse.dart @@ -10,7 +10,7 @@ class Relapse implements DatabaseRecord { @override factory Relapse.fromDatabase(Map map) { DateTime date = DateTime.parse(map['date']); - return Relapse(map['_category'], map['comment'], date); + return Relapse(map['category'], map['comment'], date); } @override @@ -21,6 +21,7 @@ class Relapse implements DatabaseRecord { @override Map toMap() { return { + 'category': _category, 'comment': _comment, 'date': _date.toIso8601String(), }; From d4018826719b2ec8cd040470ed772854bec4f3d6 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 17:00:28 +0100 Subject: [PATCH 17/30] Refactoring ScannerPage --- lib/pages/scanner_page.dart | 100 +++++++++--------------------------- lib/widgets/scanner.dart | 82 +++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 75 deletions(-) create mode 100644 lib/widgets/scanner.dart diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index 82485f8..7e9df8f 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,108 +1,58 @@ import 'package:flutter/material.dart'; -import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:provider/provider.dart'; import 'package:smoke_cess_app/models/mood.dart'; import 'package:smoke_cess_app/models/relapse.dart'; -import 'package:smoke_cess_app/models/settings.dart'; -import 'package:smoke_cess_app/services/database_service.dart'; -import 'package:smoke_cess_app/services/json_service.dart'; import 'package:smoke_cess_app/services/settings_service.dart'; import 'package:smoke_cess_app/services/notification_service.dart'; - +import 'package:smoke_cess_app/widgets/scanner.dart'; import '../models/sleep.dart'; import '../providers/settings_provider.dart'; -import '../widgets/missing_config_popup.dart'; import '../globals.dart' as globals; -class ScannerPage extends StatefulWidget { +class ScannerPage extends StatelessWidget { const ScannerPage({super.key}); - @override - State createState() => ScannerPageState(); -} + void export() async { + List moods = await globals.databaseService.getMoodRecords(); + List sleeps = await globals.databaseService.getSleepRecords(); + List relapses = await globals.databaseService.getRelapseRecords(); + for (Mood mood in moods) { + print(mood.toCSV()); + } + for (Sleep sleep in sleeps) { + print(sleep.toCSV()); + } + for (Relapse relapse in relapses) { + print(relapse.toCSV()); + } + } -class ScannerPageState extends State { - bool scanning = false; + void loadJSON(BuildContext context) async { + var settingsModel = context.read(); + await loadSettingsFromLocalJSON(); + settingsModel.initSettings(); + NotificationService().setAllNotifications(); + } @override Widget build(BuildContext context) { - var settings = context.watch(); return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - scanning - ? Expanded( - child: MobileScanner( - fit: BoxFit.contain, - controller: MobileScannerController( - detectionTimeoutMs: 2000, - ), - onDetect: (capture) { - //TODO Errorhandling!! - final List barcodes = capture.barcodes; - for (final barcode in barcodes) { - if (barcode.rawValue != null) { - String qrText = barcode.rawValue!; - Map json = stringToJSON(qrText); - Settings settings = Settings.fromJson(json); - saveSettings(settings); - setState(() { - scanning = false; - showDialog( - context: context, - builder: (BuildContext context) { - return MissingConfigPopup( - title: 'Konfiguration erfolgreich', - text: 'Du gehörst zu Gruppe ${settings.group}', - ); - }); - }); - } - } - }, - )) - : ElevatedButton( - style: ElevatedButton.styleFrom( - textStyle: const TextStyle(fontSize: 20)), - onPressed: () { - setState(() => scanning = true); - }, - child: const Text('Scan QR Code'), - ), + const MyScanner(), const SizedBox(height: 30), ElevatedButton( style: ElevatedButton.styleFrom( textStyle: const TextStyle(fontSize: 20)), - onPressed: () { - loadSettingsFromLocalJSON(); - Future.delayed(Duration(milliseconds: 100), () { - settings.initSettings(); - NotificationService().setAllNotifications(); - }); - }, + onPressed: () => loadJSON(context), child: const Text('Read JSON'), ), const SizedBox(height: 30), ElevatedButton( style: ElevatedButton.styleFrom( textStyle: const TextStyle(fontSize: 20)), - onPressed: () async { - List moods = await globals.databaseService.getMoodRecords(); - List sleeps = - await globals.databaseService.getSleepRecords(); - List relapses = - await globals.databaseService.getRelapseRecords(); - for (Mood mood in moods) { - print(mood.toCSV()); - } - for (Sleep sleep in sleeps) { - print(sleep.toCSV()); - } - for (Relapse relapse in relapses) { - print(relapse.toCSV()); - } - }, + onPressed: export, child: const Text('Export'), ) ], diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart new file mode 100644 index 0000000..f8e22d1 --- /dev/null +++ b/lib/widgets/scanner.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:smoke_cess_app/models/settings.dart'; +import 'package:smoke_cess_app/services/json_service.dart'; +import 'package:smoke_cess_app/services/settings_service.dart'; +import '../widgets/missing_config_popup.dart'; + +class MyScanner extends StatefulWidget { + const MyScanner({super.key}); + + @override + State createState() => MyScannerState(); +} + +class MyScannerState extends State { + bool scanning = false; + + void handleError(String error) { + setState(() { + scanning = false; + showDialog( + context: context, + builder: (BuildContext context) { + return MissingConfigPopup( + title: 'Scanfehler', + text: + 'Beim Scanen gab es folgende Meldung: $error. Bitte erneut versuchen', + ); + }); + }); + } + + void handleSucces(String group) { + setState(() { + scanning = false; + showDialog( + context: context, + builder: (BuildContext context) { + return MissingConfigPopup( + title: 'Konfiguration erfolgreich', + text: 'Du gehörst zu Gruppe $group', + ); + }); + }); + } + + void onDetect(capture) { + try { + final List barcodes = capture.barcodes; + for (final barcode in barcodes) { + if (barcode.rawValue != null) { + String qrText = barcode.rawValue!; + Map json = stringToJSON(qrText); + Settings settings = Settings.fromJson(json); + saveSettings(settings); + } + } + } catch (e) { + handleError(e.toString()); + } + } + + @override + Widget build(BuildContext context) { + return scanning + ? Expanded( + child: MobileScanner( + fit: BoxFit.contain, + controller: MobileScannerController( + detectionTimeoutMs: 2000, + ), + onDetect: onDetect)) + : ElevatedButton( + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20)), + onPressed: () { + setState(() => scanning = true); + }, + child: const Text('Scan QR Code'), + ); + } +} From 3909bfd66cfc53ea2d4ffcdaeab38b486065bbe1 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 17:01:44 +0100 Subject: [PATCH 18/30] forgot to add handlesuccess --- lib/widgets/scanner.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index f8e22d1..76ec40a 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -30,7 +30,7 @@ class MyScannerState extends State { }); } - void handleSucces(String group) { + void handleSucces(int group) { setState(() { scanning = false; showDialog( @@ -53,6 +53,7 @@ class MyScannerState extends State { Map json = stringToJSON(qrText); Settings settings = Settings.fromJson(json); saveSettings(settings); + handleSucces(settings.group); } } } catch (e) { From 074ebb1871d2ed0306542567eeb9570f9fc99002 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 17:09:58 +0100 Subject: [PATCH 19/30] finally instead of catch to secure if nothing is found an message is deplayed --- lib/widgets/scanner.dart | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index 76ec40a..b1aff7d 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -15,22 +15,26 @@ class MyScanner extends StatefulWidget { class MyScannerState extends State { bool scanning = false; - void handleError(String error) { + void handleError() { setState(() { scanning = false; showDialog( context: context, builder: (BuildContext context) { - return MissingConfigPopup( + return const MissingConfigPopup( title: 'Scanfehler', text: - 'Beim Scanen gab es folgende Meldung: $error. Bitte erneut versuchen', + 'Beim Scanen gab es wohl einen Fehler. Bitte erneut versuchen', ); }); }); } - void handleSucces(int group) { + void handleSucces(String? rawValue) { + String qrText = rawValue!; + Map json = stringToJSON(qrText); + Settings settings = Settings.fromJson(json); + saveSettings(settings); setState(() { scanning = false; showDialog( @@ -38,7 +42,7 @@ class MyScannerState extends State { builder: (BuildContext context) { return MissingConfigPopup( title: 'Konfiguration erfolgreich', - text: 'Du gehörst zu Gruppe $group', + text: 'Du gehörst zu Gruppe ${settings.group}', ); }); }); @@ -49,15 +53,11 @@ class MyScannerState extends State { final List barcodes = capture.barcodes; for (final barcode in barcodes) { if (barcode.rawValue != null) { - String qrText = barcode.rawValue!; - Map json = stringToJSON(qrText); - Settings settings = Settings.fromJson(json); - saveSettings(settings); - handleSucces(settings.group); + handleSucces(barcode.rawValue); } } - } catch (e) { - handleError(e.toString()); + } finally { + handleError(); } } From b96604103d4855c4c305d0d7c27067f45a48daca Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 17:15:34 +0100 Subject: [PATCH 20/30] Added initating Settings from QR-Code --- lib/widgets/scanner.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index b1aff7d..a97e14d 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -1,8 +1,11 @@ import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:provider/provider.dart'; import 'package:smoke_cess_app/models/settings.dart'; import 'package:smoke_cess_app/services/json_service.dart'; import 'package:smoke_cess_app/services/settings_service.dart'; +import '../providers/settings_provider.dart'; +import '../services/notification_service.dart'; import '../widgets/missing_config_popup.dart'; class MyScanner extends StatefulWidget { @@ -35,6 +38,9 @@ class MyScannerState extends State { Map json = stringToJSON(qrText); Settings settings = Settings.fromJson(json); saveSettings(settings); + var settingsModel = context.read(); + settingsModel.initSettings(); + NotificationService().setAllNotifications(); setState(() { scanning = false; showDialog( From 6a6b44a5557f5870ee13632dca422dd16a24a960 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 17:27:01 +0100 Subject: [PATCH 21/30] Moved pageservice to service folder --- lib/pages/main_page.dart | 2 +- lib/{pages => services}/pages_service.dart | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) rename lib/{pages => services}/pages_service.dart (77%) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 5a2af86..48897d0 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:smoke_cess_app/pages/pages_service.dart'; +import 'package:smoke_cess_app/services/pages_service.dart'; import 'package:smoke_cess_app/providers/settings_provider.dart'; import 'package:smoke_cess_app/widgets/missing_config_popup.dart'; diff --git a/lib/pages/pages_service.dart b/lib/services/pages_service.dart similarity index 77% rename from lib/pages/pages_service.dart rename to lib/services/pages_service.dart index e530550..c3b1bd8 100644 --- a/lib/pages/pages_service.dart +++ b/lib/services/pages_service.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; -import 'interval_page.dart'; -import 'mood_page.dart'; -import 'relapse_page.dart'; -import 'scanner_page.dart'; -import 'sleep_page.dart'; +import '../pages/interval_page.dart'; +import '../pages/mood_page.dart'; +import '../pages/relapse_page.dart'; +import '../pages/scanner_page.dart'; +import '../pages/sleep_page.dart'; const pages = { 'Stimmung': { From 2c96f711b64e4b15a3caeded35a8a1c24d2c9f85 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 19:29:22 +0100 Subject: [PATCH 22/30] Add SingleChildScrollView --- lib/pages/main_page.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 5a2af86..65024a9 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -39,7 +39,8 @@ class MyHomePageState extends State { appBar: AppBar( title: Text( '${pages.keys.elementAt(_selectedIndex)} ${_isConfigured ? "Gruppe $group" : ""}')), - body: pages.values.elementAt(_selectedIndex)['page'], + body: SingleChildScrollView( + child: pages.values.elementAt(_selectedIndex)['page']), bottomNavigationBar: NavigationBar( onDestinationSelected: _onItemTapped, selectedIndex: _selectedIndex, From d18d48493259c78533ed002dffeb0eb5e2908eb1 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 19:34:11 +0100 Subject: [PATCH 23/30] Center every page --- lib/pages/main_page.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index 65024a9..f373582 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -39,8 +39,9 @@ class MyHomePageState extends State { appBar: AppBar( title: Text( '${pages.keys.elementAt(_selectedIndex)} ${_isConfigured ? "Gruppe $group" : ""}')), - body: SingleChildScrollView( - child: pages.values.elementAt(_selectedIndex)['page']), + body: Center( + child: SingleChildScrollView( + child: pages.values.elementAt(_selectedIndex)['page'])), bottomNavigationBar: NavigationBar( onDestinationSelected: _onItemTapped, selectedIndex: _selectedIndex, From 5b411ef6bf02f7a4deb1a6abf0c480c6baa8cf12 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 20:02:15 +0100 Subject: [PATCH 24/30] Add AwesomeDialog --- lib/pages/main_page.dart | 14 ++++++-------- lib/providers/input_provider.dart | 4 ++-- lib/widgets/mood_form.dart | 5 ++--- lib/widgets/submit_form_button.dart | 22 +++++++++++++++++++--- pubspec.lock | 21 +++++++++++++++++++++ pubspec.yaml | 1 + 6 files changed, 51 insertions(+), 16 deletions(-) diff --git a/lib/pages/main_page.dart b/lib/pages/main_page.dart index f373582..7a5df4a 100644 --- a/lib/pages/main_page.dart +++ b/lib/pages/main_page.dart @@ -1,8 +1,8 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:smoke_cess_app/pages/pages_service.dart'; import 'package:smoke_cess_app/providers/settings_provider.dart'; -import 'package:smoke_cess_app/widgets/missing_config_popup.dart'; class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @@ -19,14 +19,12 @@ class MyHomePageState extends State { setState(() { _isConfigured ? _selectedIndex = index - : showDialog( + : AwesomeDialog( context: context, - builder: (BuildContext context) { - return const MissingConfigPopup( - title: 'Fehlende Konfiguration', - text: 'Bitte QR Code Scannen!', - ); - }); + dialogType: DialogType.info, + title: 'Fehlende Konfiguration', + desc: 'Bitte QR Code Scannen!', + ).show(); }); } diff --git a/lib/providers/input_provider.dart b/lib/providers/input_provider.dart index 5fec37c..1f4fefd 100644 --- a/lib/providers/input_provider.dart +++ b/lib/providers/input_provider.dart @@ -44,11 +44,11 @@ class InputProvider extends ChangeNotifier { notifyListeners(); } - void saveMood() { + Future saveMood() { Mood mood = Mood(_sliderValue.toInt(), _textController.text, DateTime.now()); - globals.databaseService.addMood(mood); _resetFields(); + return globals.databaseService.addMood(mood); } void saveRelapse() { diff --git a/lib/widgets/mood_form.dart b/lib/widgets/mood_form.dart index a997d01..b9a0e05 100644 --- a/lib/widgets/mood_form.dart +++ b/lib/widgets/mood_form.dart @@ -30,9 +30,8 @@ class MoodForm extends StatelessWidget { const SizedBox( height: 80, ), - ElevatedButton( - onPressed: () => inputModel.saveMood(), - child: const Text('Speichern'), + SubmitFormButton( + submitCallback: inputModel.saveMood, ) ], ); diff --git a/lib/widgets/submit_form_button.dart b/lib/widgets/submit_form_button.dart index 58f28c8..3242b18 100644 --- a/lib/widgets/submit_form_button.dart +++ b/lib/widgets/submit_form_button.dart @@ -1,15 +1,31 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; import 'package:flutter/material.dart'; class SubmitFormButton extends StatelessWidget { - final VoidCallback submitCallback; - const SubmitFormButton(this.submitCallback, {super.key}); + final Future Function() submitCallback; + const SubmitFormButton({super.key, required this.submitCallback}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(vertical: 16.0), child: ElevatedButton( - onPressed: submitCallback, + onPressed: () async { + int success = await submitCallback(); + success != 0 + ? AwesomeDialog( + context: context, + dialogType: DialogType.success, + title: 'Gespeichert', + desc: 'Der Eintrag wurde erfolgreich gespeichert', + ).show() + : AwesomeDialog( + context: context, + dialogType: DialogType.error, + title: 'Fehler', + desc: 'Der Eintrag konnte nicht gespeichert werden', + ).show(); + }, child: const Text('Speichern'), ), ); diff --git a/pubspec.lock b/pubspec.lock index b899dd9..08b0b74 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -64,6 +64,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.3" + awesome_dialog: + dependency: "direct main" + description: + name: awesome_dialog + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" boolean_selector: dependency: transitive description: @@ -177,6 +184,13 @@ packages: description: flutter source: sdk version: "0.0.0" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" http: dependency: transitive description: @@ -324,6 +338,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.0.5" + rive: + dependency: transitive + description: + name: rive + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.1" shared_preferences: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 9204ca9..5c61553 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,7 @@ dependencies: path: path_provider: ^2.0.12 provider: ^6.0.5 + awesome_dialog: ^3.0.2 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. From 591317df260fdef4ed67f3637f657b0f061db176 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 20:09:11 +0100 Subject: [PATCH 25/30] Added Submitformbutton to sleep and relapse --- lib/providers/input_provider.dart | 8 ++++---- lib/widgets/relapse_form.dart | 6 ++---- lib/widgets/sleep_form.dart | 7 ++++--- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/providers/input_provider.dart b/lib/providers/input_provider.dart index 1f4fefd..a61514f 100644 --- a/lib/providers/input_provider.dart +++ b/lib/providers/input_provider.dart @@ -51,17 +51,17 @@ class InputProvider extends ChangeNotifier { return globals.databaseService.addMood(mood); } - void saveRelapse() { + Future saveRelapse() { Relapse relapse = Relapse(_relapseCategory, _textController.text, DateTime.now()); - globals.databaseService.addRelapse(relapse); _resetFields(); + return globals.databaseService.addRelapse(relapse); } - void saveSleep(String wokeUpKey, String sleptKey) { + Future saveSleep(String wokeUpKey, String sleptKey) { Sleep sleep = Sleep(_sliderValue.toInt(), _textController.text, DateTime.now(), getTimeEntry(sleptKey), getTimeEntry(wokeUpKey)); - globals.databaseService.addSleep(sleep); _resetFields(); + return globals.databaseService.addSleep(sleep); } } diff --git a/lib/widgets/relapse_form.dart b/lib/widgets/relapse_form.dart index a00ab31..88e555c 100644 --- a/lib/widgets/relapse_form.dart +++ b/lib/widgets/relapse_form.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:smoke_cess_app/widgets/drop_down.dart'; +import 'package:smoke_cess_app/widgets/submit_form_button.dart'; import 'package:smoke_cess_app/widgets/text_formfield.dart'; import '../providers/input_provider.dart'; @@ -28,10 +29,7 @@ class RelapseForm extends StatelessWidget { const SizedBox( height: 80, ), - ElevatedButton( - onPressed: () => inputModel.saveRelapse(), - child: const Text('Speichern'), - ) + SubmitFormButton(submitCallback: inputModel.saveRelapse) ], ); } diff --git a/lib/widgets/sleep_form.dart b/lib/widgets/sleep_form.dart index 5cb7352..8b4389c 100644 --- a/lib/widgets/sleep_form.dart +++ b/lib/widgets/sleep_form.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:smoke_cess_app/widgets/elevated_card.dart'; import 'package:smoke_cess_app/widgets/slider.dart'; +import 'package:smoke_cess_app/widgets/submit_form_button.dart'; import 'package:smoke_cess_app/widgets/text_formfield.dart'; import 'package:smoke_cess_app/widgets/timepicker.dart'; @@ -41,9 +42,9 @@ class SleepForm extends StatelessWidget { const SizedBox( height: 80, ), - ElevatedButton( - onPressed: () => inputModel.saveSleep(wokeUpKey, sleptKey), - child: const Text('Speichern')) + SubmitFormButton( + submitCallback: () => inputModel.saveSleep(wokeUpKey, sleptKey), + ) ], ); } From bb96aaeef9544f78a354bcad9b927703dbc89423 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 20:30:24 +0100 Subject: [PATCH 26/30] Added new alerts to scanner page --- lib/pages/scanner_page.dart | 7 +++++++ lib/widgets/scanner.dart | 30 +++++++++++++----------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index 7e9df8f..29cf8a7 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,3 +1,4 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:smoke_cess_app/models/mood.dart'; @@ -32,6 +33,12 @@ class ScannerPage extends StatelessWidget { await loadSettingsFromLocalJSON(); settingsModel.initSettings(); NotificationService().setAllNotifications(); + AwesomeDialog( + context: context, + dialogType: DialogType.success, + title: 'Geschafft', + desc: 'Die Einstellung wurden erfolgreich gespeichert', + ).show(); } @override diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index a97e14d..0f65b74 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -1,3 +1,4 @@ +import 'package:awesome_dialog/awesome_dialog.dart'; import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:provider/provider.dart'; @@ -21,15 +22,12 @@ class MyScannerState extends State { void handleError() { setState(() { scanning = false; - showDialog( - context: context, - builder: (BuildContext context) { - return const MissingConfigPopup( - title: 'Scanfehler', - text: - 'Beim Scanen gab es wohl einen Fehler. Bitte erneut versuchen', - ); - }); + AwesomeDialog( + context: context, + dialogType: DialogType.error, + title: 'Upss', + desc: 'Da muss etwas schiefgelaufen sein!', + ).show(); }); } @@ -43,14 +41,12 @@ class MyScannerState extends State { NotificationService().setAllNotifications(); setState(() { scanning = false; - showDialog( - context: context, - builder: (BuildContext context) { - return MissingConfigPopup( - title: 'Konfiguration erfolgreich', - text: 'Du gehörst zu Gruppe ${settings.group}', - ); - }); + AwesomeDialog( + context: context, + dialogType: DialogType.success, + title: 'Geschafft', + desc: 'Der Code wurde erfolgreich gescannt!', + ).show(); }); } From afb63adb5c4e58727a78302bbdde1e03bff952be Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 20:34:14 +0100 Subject: [PATCH 27/30] Make sure to leave onDetect when successful --- lib/widgets/scanner.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index 0f65b74..a8b1b2b 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -55,7 +55,7 @@ class MyScannerState extends State { final List barcodes = capture.barcodes; for (final barcode in barcodes) { if (barcode.rawValue != null) { - handleSucces(barcode.rawValue); + return handleSucces(barcode.rawValue); } } } finally { From 88ec309f555e6c12c02cde416212aa8889ff48ff Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 20:36:59 +0100 Subject: [PATCH 28/30] Remove Errorhandling from scanner --- lib/widgets/scanner.dart | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index a8b1b2b..f7a5089 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -19,18 +19,6 @@ class MyScanner extends StatefulWidget { class MyScannerState extends State { bool scanning = false; - void handleError() { - setState(() { - scanning = false; - AwesomeDialog( - context: context, - dialogType: DialogType.error, - title: 'Upss', - desc: 'Da muss etwas schiefgelaufen sein!', - ).show(); - }); - } - void handleSucces(String? rawValue) { String qrText = rawValue!; Map json = stringToJSON(qrText); @@ -51,15 +39,11 @@ class MyScannerState extends State { } void onDetect(capture) { - try { - final List barcodes = capture.barcodes; - for (final barcode in barcodes) { - if (barcode.rawValue != null) { - return handleSucces(barcode.rawValue); - } + final List barcodes = capture.barcodes; + for (final barcode in barcodes) { + if (barcode.rawValue != null) { + return handleSucces(barcode.rawValue); } - } finally { - handleError(); } } From 2d88553ee8bf0be0228ae4b4fe1c3b41bf40ba06 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Mon, 27 Feb 2023 20:37:39 +0100 Subject: [PATCH 29/30] Remove unnessecary import --- lib/widgets/scanner.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/widgets/scanner.dart b/lib/widgets/scanner.dart index f7a5089..46f8c8a 100644 --- a/lib/widgets/scanner.dart +++ b/lib/widgets/scanner.dart @@ -7,7 +7,6 @@ import 'package:smoke_cess_app/services/json_service.dart'; import 'package:smoke_cess_app/services/settings_service.dart'; import '../providers/settings_provider.dart'; import '../services/notification_service.dart'; -import '../widgets/missing_config_popup.dart'; class MyScanner extends StatefulWidget { const MyScanner({super.key}); From 4fc602806c276e0e89fc1c4d5c80c2b109ab44b1 Mon Sep 17 00:00:00 2001 From: "k.mannweiler" <2012491@stud.hs-mannheim.de> Date: Wed, 1 Mar 2023 20:45:00 +0100 Subject: [PATCH 30/30] Fixed Visuals --- lib/services/pages_service.dart | 7 ++----- lib/widgets/drop_down.dart | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/services/pages_service.dart b/lib/services/pages_service.dart index c3b1bd8..8f3ab37 100644 --- a/lib/services/pages_service.dart +++ b/lib/services/pages_service.dart @@ -16,14 +16,11 @@ const pages = { }, 'Timer': { 'page': IntervalTimerPage(), - 'icon': Icon(Icons.smoke_free_outlined, color: Colors.black) + 'icon': Icon(Icons.timer_outlined, color: Colors.black) }, 'Rückfall': { 'page': RelapsePage(), - 'icon': Icon( - Icons.timer_outlined, - color: Colors.black, - ) + 'icon': Icon(Icons.smoke_free_outlined, color: Colors.black), }, 'Scanner': { 'page': ScannerPage(), diff --git a/lib/widgets/drop_down.dart b/lib/widgets/drop_down.dart index 845c42c..5f06d89 100644 --- a/lib/widgets/drop_down.dart +++ b/lib/widgets/drop_down.dart @@ -13,7 +13,6 @@ class DropDown extends StatelessWidget { value: _items.isEmpty ? null : _items[0], icon: const Icon(Icons.arrow_downward), elevation: 16, - style: const TextStyle(color: Colors.deepPurple), onChanged: (String? value) { inputModel.relapseCategory = value ?? ''; },