diff --git a/lib/bar_graph/bar_data.dart b/lib/bar_graph/bar_data.dart index 3231511..be7b531 100644 --- a/lib/bar_graph/bar_data.dart +++ b/lib/bar_graph/bar_data.dart @@ -1,6 +1,6 @@ +import 'package:shleappy/data/session.dart'; import 'individual_bar.dart'; -// TODO class BarData { final List amounts; List barData = []; @@ -10,7 +10,7 @@ class BarData { void initBarData() { barData = List.generate( amounts.length, - (index) => IndividualBar(day: Day.values[index%7], amount: amounts[index]), + (index) => IndividualBar(day: index, amount: amounts[index]), ); } } \ No newline at end of file diff --git a/lib/bar_graph/individual_bar.dart b/lib/bar_graph/individual_bar.dart index e408ff3..b65909b 100644 --- a/lib/bar_graph/individual_bar.dart +++ b/lib/bar_graph/individual_bar.dart @@ -1,8 +1,6 @@ -enum Day { sun, mon, tue, wed, thu, fri, sat } - class IndividualBar { - final Day day; - final double amount; + int day; + double amount; IndividualBar({ required this.day, diff --git a/lib/bar_graph/sleep_amount_bar.dart b/lib/bar_graph/sleep_amount_bar.dart index 1e73ab3..77007d3 100644 --- a/lib/bar_graph/sleep_amount_bar.dart +++ b/lib/bar_graph/sleep_amount_bar.dart @@ -39,7 +39,7 @@ class SleepAmountBar extends StatelessWidget { ), barGroups: sleepAmountBarData.barData.map((data) { return BarChartGroupData( - x: data.day.index, + x: data.day/* .index */, barRods: [ BarChartRodData( // bar chart rogs style diff --git a/lib/line_graph/line_data.dart b/lib/line_graph/line_data.dart index fe63a5c..21ea529 100644 --- a/lib/line_graph/line_data.dart +++ b/lib/line_graph/line_data.dart @@ -1,6 +1,5 @@ import 'line_point.dart'; -//TODO class LineData { final List ratings; List lineData = []; diff --git a/lib/screens/calendar_screen.dart b/lib/screens/calendar_screen.dart index cbfdef1..5edeedb 100644 --- a/lib/screens/calendar_screen.dart +++ b/lib/screens/calendar_screen.dart @@ -16,19 +16,21 @@ class CalendarScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final chosenProvider = sleepWeekWidget.chosenProvider; final SleepSession? chosen = ref.watch(chosenProvider); - return Center( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - flex: 3, - child: sleepWeekWidget, - ), - Expanded( - flex: 5, - child: _sessionInfoWithBorder(chosen, context, ref), - ), - ], + return SafeArea( + child: Center( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + flex: 3, + child: sleepWeekWidget, + ), + Expanded( + flex: 5, + child: _sessionInfoWithBorder(chosen, context, ref), + ), + ], + ), ), ); } @@ -116,7 +118,7 @@ class CalendarScreen extends ConsumerWidget { ), Align( alignment: Alignment.bottomRight, - child: Visibility.maintain( + child: Visibility( visible: chosen != null, child: Padding( padding: const EdgeInsets.all(16), diff --git a/lib/screens/dialogs/dialog_windows.dart b/lib/screens/dialogs/dialog_windows.dart index afd6a6e..1608aa3 100644 --- a/lib/screens/dialogs/dialog_windows.dart +++ b/lib/screens/dialogs/dialog_windows.dart @@ -1,9 +1,10 @@ -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart' hide DatePickerTheme; import 'package:shleappy/data/history.dart'; import 'package:shleappy/data/session.dart'; import 'package:shleappy/screens/dialogs/mood_selection.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shleappy/screens/home_screen.dart'; +import 'package:omni_datetime_picker/omni_datetime_picker.dart' as dtp; final ratingProvider = StateProvider((ref) => 1); @@ -11,61 +12,175 @@ class DialogWindows { static void showFeedbackDialog(BuildContext context, WidgetRef ref) { final TextEditingController controller = TextEditingController(); showDialog( - context: context, - barrierDismissible: false, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: Theme.of(context).scaffoldBackgroundColor, - content: SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const SizedBox( - height: 35, - ), - Text("How did you sleep?", - style: TextStyle( - fontSize: 30, - fontWeight: FontWeight.w200, - color: Theme.of(context).focusColor)), - const SizedBox( - height: 35, - ), - RatingStars( - leftCaption: "Terrible", - rightCaption: "Great", - ), - const SizedBox( - height: 25, - ), - Text("Leave additional comments", - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w100, - color: Theme.of(context).shadowColor)), - const SizedBox( - height: 5, - ), - SizedBox( - width: 250, - child: TextField( - controller: controller, - style: TextStyle(color: Theme.of(context).focusColor), - decoration: InputDecoration( - border: OutlineInputBorder( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + content: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("How did you sleep?", + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.w200, + color: Theme.of(context).focusColor)), + const SizedBox( + height: 35, + ), + RatingStars( + leftCaption: "Terrible", + rightCaption: "Great", + ), + const SizedBox( + height: 25, + ), + Text("Leave additional comments", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w100, + color: Theme.of(context).shadowColor)), + const SizedBox( + height: 5, + ), + SizedBox( + width: 250, + child: TextField( + controller: controller, + style: TextStyle(color: Theme.of(context).focusColor), + decoration: InputDecoration( + border: OutlineInputBorder( + borderSide: BorderSide( + color: Theme.of(context).shadowColor, + ), + ), + ), + ), + ), + const SizedBox( + height: 25, + ), + SizedBox( + height: 60, + width: 170, + child: OutlinedButton( + onPressed: () { + String text = controller.text; + ref + .read(SleepSessionHistoryNotifier.provider.notifier) + .putItem(SleepSession( + started: ref.read(startSleepTimeProvider), + ended: ref.read(endSleepTimeProvider), + quality: ref.read(ratingProvider), + comment: text)); + + ref.read(ratingProvider.notifier).state = 1; + Navigator.of(context).pop(); + }, + child: Text( + "Proceed", + style: TextStyle(color: Theme.of(context).focusColor), + ), + ), + ), + ], + ), + ), + ), + ); + }, + ); + } + + //TODO dev only!! + static void showEditorDialog(BuildContext context, WidgetRef ref) { + final TextEditingController controller = TextEditingController(); + showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AlertDialog( + backgroundColor: Theme.of(context).scaffoldBackgroundColor, + content: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + child: const Text("Start time"), + onPressed: () { + dtp + .showOmniDateTimePicker( + context: context, + initialDate: DateTime.now(), + ) + .then((value) { + ref.read(startSleepTimeProvider.notifier).state = + value!; + }); + }, + ), + TextButton( + child: const Text("End time"), + onPressed: () { + dtp + .showOmniDateTimePicker( + context: context, + initialDate: DateTime.now(), + ) + .then((value) { + ref.read(endSleepTimeProvider.notifier).state = value!; + }); + }, + ), + Text("How did you sleep?", + style: TextStyle( + fontSize: 30, + fontWeight: FontWeight.w200, + color: Theme.of(context).focusColor)), + const SizedBox( + height: 35, + ), + RatingStars( + leftCaption: "Terrible", + rightCaption: "Great", + ), + const SizedBox( + height: 25, + ), + Text("Leave additional comments", + style: TextStyle( + fontSize: 15, + fontWeight: FontWeight.w100, + color: Theme.of(context).shadowColor)), + const SizedBox( + height: 5, + ), + SizedBox( + width: 250, + child: TextField( + controller: controller, + style: TextStyle(color: Theme.of(context).focusColor), + decoration: InputDecoration( + border: OutlineInputBorder( borderSide: BorderSide( - color: Theme.of(context).shadowColor, - )), + color: Theme.of(context).shadowColor, + ), + ), + ), ), ), - ), - const SizedBox( - height: 25, - ), - SizedBox( - height: 60, - width: 170, - child: OutlinedButton( + const SizedBox( + height: 25, + ), + SizedBox( + height: 60, + width: 170, + child: OutlinedButton( onPressed: () { String text = controller.text; ref @@ -79,16 +194,18 @@ class DialogWindows { ref.read(ratingProvider.notifier).state = 1; Navigator.of(context).pop(); }, - child: Text("Proceed", - style: - TextStyle(color: Theme.of(context).focusColor))), - ), - const SizedBox( - height: 35, - ), - ], - )), - ); - }); + child: Text( + "Proceed", + style: TextStyle(color: Theme.of(context).focusColor), + ), + ), + ), + ], + ), + ), + ), + ); + }, + ); } } diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index 65d87a7..914ef38 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -17,6 +17,18 @@ class HomeScreen extends ConsumerWidget { PreferredSizeWidget _homeAppBar(BuildContext context) { return AppBar( backgroundColor: Theme.of(context).splashColor, + // TODO dev only!! + leading: Visibility.maintain( + visible: false, + child: Consumer( + builder: (context, ref, widget) => IconButton( + icon: const Icon(Icons.add), + onPressed: () { + DialogWindows.showEditorDialog(context, ref); + }, + ), + ), + ), actions: [ Padding( padding: const EdgeInsets.all(8.0), diff --git a/lib/screens/statistics_screen.dart b/lib/screens/statistics_screen.dart index 93d3504..ab8b7a7 100644 --- a/lib/screens/statistics_screen.dart +++ b/lib/screens/statistics_screen.dart @@ -1,49 +1,97 @@ import 'package:flutter/material.dart'; - +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:date_only_field/date_only_field_with_extensions.dart'; +import 'package:intl/intl.dart'; import 'package:shleappy/bar_graph/sleep_amount_bar.dart'; +import 'package:shleappy/data/history.dart'; +import 'package:shleappy/data/session.dart'; import 'package:shleappy/line_graph/rating_line.dart'; - -class StatisticsScreen extends StatefulWidget { +class StatisticsScreen extends ConsumerStatefulWidget { const StatisticsScreen({super.key}); @override - State createState() => _StatisticsScreenState(); + ConsumerState createState() => _StatisticsScreenState(); } -class _StatisticsScreenState extends State { - int selectedIndex = 0; +class _StatisticsScreenState extends ConsumerState { + DateTime _currentStartOfWeek = _getStartOfWeek(DateTime.now()); + + static DateTime _getStartOfWeek(DateTime date) { + int daysToSubtract = date.weekday % 7; + return DateTime(date.year, date.month, date.day - daysToSubtract); + } + + void _goToPreviousWeek() { + setState(() { + _currentStartOfWeek = + _currentStartOfWeek.subtract(const Duration(days: 7)); + }); + } + + void _goToNextWeek() { + setState(() { + _currentStartOfWeek = _currentStartOfWeek.add(const Duration(days: 7)); + }); + } + + List getAmounts(List sessions) { + List result = List.filled(7, 0); + for (var session in sessions) { + if (session.ended + .isAfter(_currentStartOfWeek.add(const Duration(days: 6))) || + session.ended.isBefore(_currentStartOfWeek)) continue; + int day = session.ended.weekday % 7; + result[day] += session.durationInMins / 60; + } + return result; + } + + List getRatings(List sessions) { + List result = []; + for (var session in sessions) { + if (session.ended + .isAfter(_currentStartOfWeek.add(const Duration(days: 6))) || + session.ended.isBefore(_currentStartOfWeek)) continue; + result.add(session.quality); + } + return result; + } @override Widget build(BuildContext context) { double screenWidth = MediaQuery.of(context).size.width; double screenHeight = MediaQuery.of(context).size.height; + final endOfWeek = _currentStartOfWeek.add(const Duration(days: 6)); + final sleepSessions = ref + .watch(SleepSessionHistoryNotifier.provider) + .intervalInDays(Date.fromDateTime(_currentStartOfWeek), + Date.fromDateTime(endOfWeek)); + // sessions to test + /* final sleepSessions = [ + SleepSession(started: DateTime(2024, 7, 6, 21), ended: DateTime(2024, 7, 7, 7), quality: SleepQuality.none), + SleepSession(started: DateTime(2024, 6, 30, 10), ended: DateTime(2024, 6, 30, 12), quality: SleepQuality.none), + ]; */ return Scaffold( appBar: AppBar( title: Text( - 'Put week dates here', - style: TextStyle(color: Theme.of(context).focusColor), - ), // TODO put weeks dates - + '${DateFormat.MMMd().format(_currentStartOfWeek)} - ${DateFormat.MMMd().format(endOfWeek)}'), actions: [ IconButton( - onPressed: () {}, + onPressed: _goToPreviousWeek, icon: const Icon(Icons.chevron_left), ), - IconButton( - onPressed: () {}, + onPressed: _goToNextWeek, icon: const Icon(Icons.chevron_right), ), ], - backgroundColor: Theme.of(context).scaffoldBackgroundColor, ), - body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox(height: MediaQuery.sizeOf(context).height * 0.01), + SizedBox(height: screenHeight * 0.01), Text( 'Sleep Hours per Day', @@ -54,15 +102,14 @@ class _StatisticsScreenState extends State { color: Theme.of(context).focusColor), ), - SizedBox(height: MediaQuery.sizeOf(context).height * 0.03), - + SizedBox(height: screenHeight * 0.03), + SizedBox( - height: MediaQuery.sizeOf(context).height * 0.3, - child: - const SleepAmountBar(weeklySummary: [5, 8, 9, 7, 6, 8, 10]), + height: screenHeight * 0.3, + width: screenWidth * 0.9, + child: SleepAmountBar(weeklySummary: getAmounts(sleepSessions)), ), - - SizedBox(height: MediaQuery.sizeOf(context).height * 0.03), + SizedBox(height: screenHeight * 0.03), Text( 'Sleep Rating', @@ -73,7 +120,7 @@ class _StatisticsScreenState extends State { color: Theme.of(context).focusColor), ), - SizedBox(height: MediaQuery.sizeOf(context).height * 0.02), + SizedBox(height: screenHeight * 0.02), Container( height: screenHeight * 0.3, @@ -89,8 +136,8 @@ class _StatisticsScreenState extends State { right: screenWidth * 0.03, top: screenHeight * 0.03, bottom: screenHeight * 0.03), - child: const RatingLine( - weeklyRatings: [3, 0, 2, -1, -5, 4, 2, 5, 0, 1]), + child: RatingLine( + weeklyRatings: getRatings(sleepSessions)), ), ], ), diff --git a/lib/statistics_screen.dart b/lib/statistics_screen.dart deleted file mode 100644 index ff12741..0000000 --- a/lib/statistics_screen.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:intl/intl.dart'; - -import 'bar_graph/sleep_amount_bar.dart'; -import 'line_graph/rating_line.dart'; -import 'data/session.dart'; -import 'data/history.dart'; - -class StatisticsScreen extends ConsumerStatefulWidget { - const StatisticsScreen({super.key}); - - @override - ConsumerState createState() => _StatisticsScreenState(); -} - -class _StatisticsScreenState extends ConsumerState { - DateTime _currentStartOfWeek = _getStartOfWeek(DateTime.now()); - - static DateTime _getStartOfWeek(DateTime date) { - int daysToSubtract = date.weekday % 7; - return DateTime(date.year, date.month, date.day - daysToSubtract); - } - - void _goToPreviousWeek() { - setState(() { - _currentStartOfWeek = - _currentStartOfWeek.subtract(const Duration(days: 7)); - }); - } - - void _goToNextWeek() { - setState(() { - _currentStartOfWeek = _currentStartOfWeek.add(const Duration(days: 7)); - }); - } - - List getAmounts(List sessions) { - List result = List.filled(7, 0); - for (var session in sessions) { - if (session.ended - .isAfter(_currentStartOfWeek.add(const Duration(days: 6)))) continue; - int day = session.ended.weekday % 7; - result[day] += session.durationInMins / 60; - } - return result; - } - - List getRatings(List sessions) { - List result = []; - for (var session in sessions) { - if (session.ended - .isAfter(_currentStartOfWeek.add(const Duration(days: 6)))) continue; - result.add(session.quality); - } - return result; - } - - @override - Widget build(BuildContext context) { - final endOfWeek = _currentStartOfWeek.add(const Duration(days: 6)); - final sleepSessions = ref - .watch(SleepSessionHistoryNotifier.provider) - .intervalInDays(_currentStartOfWeek, endOfWeek); - // sessions to test - /* final sleepSessions = [ - SleepSession(started: DateTime(2024, 7, 6, 21), ended: DateTime(2024, 7, 7, 7), quality: SleepQuality.none), - SleepSession(started: DateTime(2024, 6, 30, 10), ended: DateTime(2024, 6, 30, 12), quality: SleepQuality.none), - ]; */ - - return Scaffold( - appBar: AppBar( - title: Text( - '${DateFormat.MMMd().format(_currentStartOfWeek)} - ${DateFormat.MMMd().format(endOfWeek)}'), - actions: [ - IconButton( - onPressed: _goToPreviousWeek, - icon: const Icon(Icons.chevron_left), - ), - IconButton( - onPressed: _goToNextWeek, - icon: const Icon(Icons.chevron_right), - ), - ], - ), - body: Center( - child: Column( - // add here some nice aligment pls - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( - height: MediaQuery.sizeOf(context).height * 0.3, - width: MediaQuery.sizeOf(context).width * 0.9, - child: SleepAmountBar(weeklySummary: getAmounts(sleepSessions)), - ), - SizedBox(height: MediaQuery.sizeOf(context).height * 0.1), - SizedBox( - height: MediaQuery.sizeOf(context).height * 0.3, - width: MediaQuery.sizeOf(context).width * 0.85, - child: RatingLine(weeklyRatings: getRatings(sleepSessions)), - ), - ], - ), - ), - ); - } -} diff --git a/lib/ui/week_list.dart b/lib/ui/week_list.dart index 85f3e84..fd99c6f 100644 --- a/lib/ui/week_list.dart +++ b/lib/ui/week_list.dart @@ -189,7 +189,7 @@ class _WeekGrid extends ConsumerWidget { flex = 0; } ++flex; - if (c.pisSameAs(iter.current.endDate)) { + if (c.pisSameAs(iter.current.endDate) || c.pisSameAs(week.end)) { widgets.add(Flexible( fit: FlexFit.tight, flex: flex, diff --git a/pubspec.lock b/pubspec.lock index ec11a90..5683a82 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -46,6 +46,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.11.0" + bloc: + dependency: transitive + description: + name: bloc + sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e" + url: "https://pub.dev" + source: hosted + version: "8.1.4" boolean_selector: dependency: transitive description: @@ -219,6 +227,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_bloc: + dependency: transitive + description: + name: flutter_bloc + sha256: b594505eac31a0518bdcb4b5b79573b8d9117b193cc80cc12e17d639b10aa27a + url: "https://pub.dev" + source: hosted + version: "8.1.6" flutter_lints: dependency: "direct dev" description: @@ -368,6 +384,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.12.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + omni_datetime_picker: + dependency: "direct main" + description: + name: omni_datetime_picker + sha256: "554eb966e84f8d196cf6e189384141db46a79a192d1a360277ead98e5d6036bd" + url: "https://pub.dev" + source: hosted + version: "2.0.2" package_config: dependency: transitive description: @@ -448,6 +480,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" + provider: + dependency: transitive + description: + name: provider + sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c + url: "https://pub.dev" + source: hosted + version: "6.1.2" pub_semver: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 550b92d..b7e36ac 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.1 +version: 1.0.0 environment: sdk: '>=3.4.1 <4.0.0' @@ -33,12 +33,13 @@ dependencies: sdk: flutter flutter_riverpod: ^2.5.1 cupertino_icons: ^1.0.6 + fl_chart: ^0.68.0 hive_flutter: ^1.1.0 date_only_field: ^0.0.14 - fl_chart: ^0.68.0 collection: ^1.18.0 table_calendar: ^3.0.9 intl: ^0.18.1 + omni_datetime_picker: ^2.0.2 dev_dependencies: flutter_test: diff --git a/test/history_test.dart b/test/history_test.dart index dad0dfa..fa6ca5c 100644 --- a/test/history_test.dart +++ b/test/history_test.dart @@ -19,7 +19,7 @@ void main() { sessionList.add(SleepSession( started: starts[i], ended: ends[i], - quality: SleepQuality.none, + quality: 0, )); } var history = SleepSessionHistory(sessionList);