diff --git a/lib/interface/db_record.dart b/lib/interface/db_record.dart index f5c56c8..ed213ec 100644 --- a/lib/interface/db_record.dart +++ b/lib/interface/db_record.dart @@ -1,3 +1,5 @@ abstract class DatabaseRecord { String toCSV(); + Map toMap(); + DatabaseRecord.fromDatabase(Map map); } diff --git a/lib/main.dart b/lib/main.dart index 16aa6f2..bf9da73 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,14 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/pages/main_page.dart'; +import 'package:smoke_cess_app/service/database_service.dart'; import 'package:smoke_cess_app/service/notification_service.dart'; import 'package:timezone/data/latest.dart' as tz; void main() { // to ensure all the widgets are initialized. WidgetsFlutterBinding.ensureInitialized(); - + //init database + DatabaseService.instance; tz.initializeTimeZones(); NotificationService().initNotification(); runApp(const MyApp()); @@ -19,6 +21,6 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { - return MaterialApp(title: _title, home: MyHomePage()); + return const MaterialApp(title: _title, home: MyHomePage()); } } diff --git a/lib/models/hiit_workout.dart b/lib/models/hiit_workout.dart index 9aa69eb..c4ec0da 100644 --- a/lib/models/hiit_workout.dart +++ b/lib/models/hiit_workout.dart @@ -1,15 +1,32 @@ import 'package:smoke_cess_app/interface/db_record.dart'; class HIITWorkout implements DatabaseRecord { - final Duration _workoutDuration; - final String _commentBefore; - final String _commentAfter; - final DateTime _workoutDate; + Duration _workoutDuration; + String _commentBefore; + String _commentAfter; + DateTime _workoutDate; HIITWorkout(this._workoutDuration, this._commentBefore, this._commentAfter, this._workoutDate); + //TODO Felder anpassen + @override + factory HIITWorkout.fromMap(Map map) { + return HIITWorkout(map['_workoutDuration'], map['_commentBefore'], + map['_commentAfter'], map['_workoutDate']); + } + @override String toCSV() => "${_workoutDate.toIso8601String()}, $_workoutDuration, $_commentBefore, $_commentAfter"; + + @override + Map toMap() { + return { + 'workoutDuration': _workoutDuration, + 'commentBefore': _commentBefore, + 'commentAfter': _commentAfter, + 'workoutDate': _workoutDate, + }; + } } diff --git a/lib/models/mood.dart b/lib/models/mood.dart index d17061a..562b2b4 100644 --- a/lib/models/mood.dart +++ b/lib/models/mood.dart @@ -1,14 +1,29 @@ import 'package:smoke_cess_app/interface/db_record.dart'; class Mood implements DatabaseRecord { - final double _moodValue; + final int _moodValue; final String _comment; final DateTime _date; Mood(this._moodValue, this._comment, this._date); + @override + factory Mood.fromDatabase(Map map) { + DateTime date = DateTime.parse(map['date']); + return Mood(map['value'], map['comment'], date); + } + @override String toCSV() { - return "${_date.toIso8601String()}, ${_moodValue.round().toString()}, $_comment"; + return "${_date.toIso8601String()}, $_moodValue, $_comment"; + } + + @override + Map toMap() { + return { + 'value': _moodValue, + 'comment': _comment, + 'date': _date.toIso8601String(), + }; } } diff --git a/lib/models/sleep.dart b/lib/models/sleep.dart index f94be2e..d5335a8 100644 --- a/lib/models/sleep.dart +++ b/lib/models/sleep.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:smoke_cess_app/interface/db_record.dart'; class Sleep implements DatabaseRecord { - final double _sleepQualityValue; + final int _sleepQualityValue; final String _comment; final DateTime _date; final TimeOfDay _sleepedAt; @@ -11,8 +11,31 @@ class Sleep implements DatabaseRecord { Sleep(this._sleepQualityValue, this._comment, this._date, this._sleepedAt, this._wokeUpAt); + @override + factory Sleep.fromDatabase(Map map) { + DateTime date = DateTime.parse(map['date']); + TimeOfDay sleepedAt = + TimeOfDay(hour: map['sleepedAtHour'], minute: map['sleepedAtMinute']); + TimeOfDay wokeUpAt = + TimeOfDay(hour: map['wokeUpAtHour'], minute: map['wokeUpAtMinute']); + return Sleep(map['value'], map['comment'], date, sleepedAt, wokeUpAt); + } + @override String toCSV() { - return "${_date.toIso8601String()}, ${_sleepQualityValue.round().toString()}, $_sleepedAt, $_wokeUpAt, $_comment"; + return "${_date.toIso8601String()}, $_sleepQualityValue, ${_sleepedAt.hour}:${_sleepedAt.minute}, ${_wokeUpAt.hour}:${_wokeUpAt.minute}, $_comment"; + } + + @override + Map toMap() { + return { + 'value': _sleepQualityValue, + 'comment': _comment, + 'date': _date.toIso8601String(), + 'sleepedAtHour': _sleepedAt.hour, + 'sleepedAtMinute': _sleepedAt.minute, + 'wokeUpAtHour': _wokeUpAt.hour, + 'wokeUpAtMinute': _wokeUpAt.minute, + }; } } diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index b21b523..c382990 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -1,10 +1,13 @@ import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; +import 'package:smoke_cess_app/models/mood.dart'; import 'package:smoke_cess_app/models/settings.dart'; +import 'package:smoke_cess_app/service/database_service.dart'; import 'package:smoke_cess_app/service/json_service.dart'; import 'package:smoke_cess_app/service/settings_service.dart'; import 'package:smoke_cess_app/service/notification_service.dart'; +import '../models/sleep.dart'; import '../widgets/missing_config_popup.dart'; class ScannerPage extends StatefulWidget { @@ -71,6 +74,23 @@ class ScannerPageState extends State { NotificationService().setAllNotifications(); }, child: const Text('Read JSON'), + ), + const SizedBox(height: 30), + ElevatedButton( + style: ElevatedButton.styleFrom( + textStyle: const TextStyle(fontSize: 20)), + onPressed: () async { + List moods = await DatabaseService.instance.getMoodRecords(); + List sleeps = + await DatabaseService.instance.getSleepRecords(); + for (Mood mood in moods) { + print(mood.toCSV()); + } + for (Sleep sleep in sleeps) { + print(sleep.toCSV()); + } + }, + child: const Text('Export'), ) ], )); diff --git a/lib/service/database_service.dart b/lib/service/database_service.dart new file mode 100644 index 0000000..26973f4 --- /dev/null +++ b/lib/service/database_service.dart @@ -0,0 +1,108 @@ +import 'dart:async'; + +import 'package:path/path.dart'; +import 'package:smoke_cess_app/models/mood.dart'; +import 'package:sqflite/sqflite.dart'; +// ignore: depend_on_referenced_packages +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; + +import '../models/sleep.dart'; + +class DatabaseService { + DatabaseService._privateConstructor(); + static final DatabaseService instance = DatabaseService._privateConstructor(); + + static Database? _database; + Future get database async => _database ??= await _initDatabase(); + + Future _initDatabase() async { + Directory documentsDirectory = await getApplicationDocumentsDirectory(); + String path = join(documentsDirectory.path, 'database.db'); + return await openDatabase(path, + version: 1, onCreate: _onCreate, onOpen: _createTablesIfNotExists); + } + + Future _onCreate(Database db, int version) async { + await _createTablesIfNotExists(db); + } + + Future _createTablesIfNotExists(Database db) async { + await db.execute(_createMoodTable); + await db.execute(_createSleepTable); + await db.execute(_createRelapseTable); + await db.execute(_createWorkoutTable); + } + + //TODO use generic function? + Future> getMoodRecords() async { + Database db = await instance.database; + var moodRecords = await db.query('mood'); + List moodList = moodRecords.isNotEmpty + ? moodRecords.map((e) => Mood.fromDatabase(e)).toList() + : []; + return moodList; + } + + Future> getSleepRecords() async { + Database db = await instance.database; + var sleepRecords = await db.query('sleep'); + List sleepList = sleepRecords.isNotEmpty + ? sleepRecords.map((e) => Sleep.fromDatabase(e)).toList() + : []; + return sleepList; + } + + Future addMood(Mood mood) async { + Database db = await instance.database; + return await db.insert('mood', mood.toMap()); + } + + Future addSleep(Sleep sleep) async { + Database db = await instance.database; + return await db.insert('sleep', sleep.toMap()); + } +} + +String _createMoodTable = ''' + CREATE TABLE IF NOT EXISTS mood( + id INTEGER PRIMARY KEY, + value INTEGER, + date TEXT, + comment TEXT + ) + '''; + +String _createSleepTable = ''' + CREATE TABLE IF NOT EXISTS sleep( + id INTEGER PRIMARY KEY, + value INTEGER, + date TEXT, + comment TEXT, + sleepedAtHour INTEGER, + sleepedAtMinute INTEGER, + wokeUpAtHour INTEGER, + wokeUpAtMinute INTEGER + ) + '''; + +String _createRelapseTable = ''' + CREATE TABLE IF NOT EXISTS relapse( + id INTEGER PRIMARY KEY, + date TEXT, + comment TEXT, + reason TEXT + ) + '''; + +String _createWorkoutTable = ''' + CREATE TABLE IF NOT EXISTS workout( + id INTEGER PRIMARY KEY, + date TEXT, + motivationBefore INTEGER, + commentBefore TEXT, + motivationAfter INTEGER, + commentAfter TEXT, + completed INTEGER + ) + '''; diff --git a/lib/widgets/mood_form.dart b/lib/widgets/mood_form.dart index 6447a0d..20031df 100644 --- a/lib/widgets/mood_form.dart +++ b/lib/widgets/mood_form.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/models/mood.dart'; +import 'package:smoke_cess_app/service/database_service.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'; @@ -20,9 +22,9 @@ class _MoodFormState extends State { void submitForm() { if (_moodFormKey.currentState!.validate()) { _moodFormKey.currentState?.save(); //call every onSave Method - //TODO Businesslogik aufrufen! - print(_textInput); - print(slider.sliderValue); + Mood mood = + Mood(slider.getSliderValue().toInt(), _textInput, DateTime.now()); + DatabaseService.instance.addMood(mood); _moodFormKey.currentState?.reset(); } } diff --git a/lib/widgets/sleep_form.dart b/lib/widgets/sleep_form.dart index ba1259c..732a27a 100644 --- a/lib/widgets/sleep_form.dart +++ b/lib/widgets/sleep_form.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/models/sleep.dart'; +import 'package:smoke_cess_app/service/database_service.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'; @@ -26,10 +28,13 @@ class _SleepFormState extends State { void submitForm() { if (_sleepFormKey.currentState!.validate()) { _sleepFormKey.currentState?.save(); //call every onSave Method - //TODO Businesslogik aufrufen! - print(_textInput); - print(slider.sliderValue); - print('Eingeschlafen um: ${sleepTimePicker.getCurrentTime}'); + Sleep sleep = Sleep( + slider.getSliderValue().toInt(), + _textInput, + DateTime.now(), + sleepTimePicker.getCurrentTime, + wakeUpTimePicker.getCurrentTime); + DatabaseService.instance.addSleep(sleep); _sleepFormKey.currentState?.reset(); } } diff --git a/pubspec.lock b/pubspec.lock index 57b3f29..fea7a33 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -234,14 +234,14 @@ packages: source: hosted version: "3.0.0" path: - dependency: transitive + dependency: "direct main" description: name: path url: "https://pub.dartlang.org" source: hosted version: "1.8.2" path_provider: - dependency: transitive + dependency: "direct main" description: name: path_provider url: "https://pub.dartlang.org" @@ -371,6 +371,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.0" + sqflite: + dependency: "direct main" + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.4+1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.2+2" stack_trace: dependency: transitive description: @@ -392,6 +406,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" term_glyph: dependency: transitive description: @@ -457,4 +478,4 @@ packages: version: "6.1.0" sdks: dart: ">=2.18.2 <3.0.0" - flutter: ">=3.0.0" + flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index e0c215d..6e3127c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: A new Flutter project. # The following line prevents the package from being accidentally published to # pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: "none" # Remove this line if you wish to publish to pub.dev +publish_to: 'none' # Remove this line if you wish to publish to pub.dev # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -20,7 +20,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.0+1 environment: - sdk: ">=2.18.2 <3.0.0" + sdk: '>=2.18.2 <3.0.0' # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -31,6 +31,9 @@ environment: dependencies: flutter: sdk: flutter + sqflite: + path: + path_provider: ^2.0.12 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.