diff --git a/lib/mock/db_mock.dart b/lib/mock/db_mock.dart index e7c60c3..313cece 100644 --- a/lib/mock/db_mock.dart +++ b/lib/mock/db_mock.dart @@ -2,7 +2,9 @@ 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/models/workout.dart'; import 'package:smoke_cess_app/services/database_service.dart'; +// ignore: depend_on_referenced_packages import 'package:sqflite_common/sqlite_api.dart'; class DatabaseMock implements DatabaseService { @@ -29,6 +31,12 @@ class DatabaseMock implements DatabaseService { return Future.value(1); } + @override + Future addWorkout(Workout workout) { + _workoutRecords.add(workout); + return Future.value(1); + } + @override Future addRelapse(Relapse relapse) { _relapseRecords.add(relapse); @@ -36,7 +44,6 @@ class DatabaseMock implements DatabaseService { } @override - // TODO: implement database Future get database => DatabaseService.instance.database; @override diff --git a/lib/models/hiit_workout.dart b/lib/models/hiit_workout.dart deleted file mode 100644 index c4ec0da..0000000 --- a/lib/models/hiit_workout.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:smoke_cess_app/interface/db_record.dart'; - -class HIITWorkout implements DatabaseRecord { - 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/workout.dart b/lib/models/workout.dart new file mode 100644 index 0000000..0bba86a --- /dev/null +++ b/lib/models/workout.dart @@ -0,0 +1,28 @@ +import 'package:smoke_cess_app/interface/db_record.dart'; + +class Workout implements DatabaseRecord { + int _motivationBefore; + int _motivationAfter; + DateTime _workoutDate; + + Workout(this._motivationBefore, this._motivationAfter, this._workoutDate); + + @override + factory Workout.fromMap(Map map) { + return Workout(map['_workoutDuration'], map['_motivationBefore'], + map['_motivationAfter']); + } + + @override + String toCSV() => + "${_workoutDate.toIso8601String()}, $_motivationBefore, $_motivationAfter"; + + @override + Map toMap() { + return { + 'motivationBefore': _motivationBefore, + 'motivationAfter': _motivationAfter, + 'workoutDate': _workoutDate, + }; + } +} diff --git a/lib/pages/interval_page.dart b/lib/pages/interval_page.dart index f6d2fcd..1c0d64f 100644 --- a/lib/pages/interval_page.dart +++ b/lib/pages/interval_page.dart @@ -1,225 +1,32 @@ -import 'dart:async'; -import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:smoke_cess_app/providers/timer_provider.dart'; -import 'package:smoke_cess_app/widgets/popup_for_start_and_stop.dart'; -import 'package:smoke_cess_app/widgets/timer_widget.dart'; +import 'package:smoke_cess_app/providers/workout_provider.dart'; +import 'package:smoke_cess_app/widgets/mute_button.dart'; +import 'package:smoke_cess_app/widgets/workout_timer_widget.dart'; -import '../providers/input_provider.dart'; - -class IntervalTimerPage extends StatefulWidget { - const IntervalTimerPage({Key? key}) : super(key: key); - - @override - _IntervalTimerPageState createState() => _IntervalTimerPageState(); -} - -class _IntervalTimerPageState extends State { - final Duration _warmupDuration = const Duration(seconds: 5); - final Duration _cooldownDuration = const Duration(seconds: 5); - final Duration _highIntensityDuration = const Duration(seconds: 4); - final Duration _lowIntensityDuration = const Duration(seconds: 3); - late Duration _totalDuration = const Duration(minutes: 35); - AudioPlayer warmUpPlayer = AudioPlayer(); - AudioPlayer workoutPlayer = AudioPlayer(); - AudioPlayer coolDownPlayer = AudioPlayer(); - final AudioCache _audioCache = AudioCache(); - final int _numHighIntensityBlocks = 4; - final int _numLowIntensityBlocks = 3; - - Timer? _timer; - int _currentBlock = 0; - Duration _currentDuration = const Duration(); - bool _isPaused = true; - - @override - void initState() { - _currentDuration = _warmupDuration; - super.initState(); - } - - @override - void dispose() { - _timer?.cancel(); - super.dispose(); - } - - void _startTimer() async { - await showDialog( - context: context, - builder: (BuildContext context) { - return ChangeNotifierProvider( - create: (context) => InputProvider(), - child: const TimerStartStopPopup( - title: 'Motivation vor dem Training', - )); - }, - ); - _isPaused = false; - Source source = AssetSource('go.mp3'); - await AudioPlayer().play(source); - - _timer = Timer.periodic(const Duration(seconds: 1), (_) => _tick()); - Future.delayed(const Duration(seconds: 1)).then((value) { - _playWarmUpMusic(); - }); - } - - void _resetTimer() { - () async { - await coolDownPlayer.stop(); - await warmUpPlayer.stop(); - await workoutPlayer.stop(); - }(); - _isPaused = true; - _timer?.cancel(); - _currentBlock = 0; - _currentDuration = _warmupDuration; - _totalDuration = const Duration(minutes: 35); - setState(() {}); - showDialog( - context: context, - builder: (BuildContext context) { - return const TimerStartStopPopup( - title: 'Motivation nach dem Training', - ); - }, - ); - } - - Future _playWarmUpMusic() async { - Source source = AssetSource('warmUp.mp3'); - await warmUpPlayer.setReleaseMode(ReleaseMode.loop); - await warmUpPlayer.play(source); - } - - Future _playWorkoutMusic() async { - await warmUpPlayer.stop(); - Future.delayed(const Duration(microseconds: 600)).then((value) async { - Source source = AssetSource('workout.mp3'); - await workoutPlayer.setReleaseMode(ReleaseMode.loop); - await workoutPlayer.play(source); - }); - } - - Future _intervalChange() async { - Source source = AssetSource('beep.mp3'); - await AudioPlayer().play(source); - } - - void _tick() { - setState(() { - _currentDuration = Duration( - seconds: _currentDuration.inSeconds - 1, - ); - _totalDuration = Duration( - seconds: _totalDuration.inSeconds - 1, - ); - if (_currentDuration.inSeconds < 1) { - if (_currentBlock < _numHighIntensityBlocks + _numLowIntensityBlocks) { - _intervalChange(); - if (_currentBlock == 0) { - _playWorkoutMusic(); - } - _currentBlock++; - - if (_currentBlock % 2 == 1) { - _currentDuration = _highIntensityDuration; - } else { - _currentDuration = _lowIntensityDuration; - } - } else if (_currentBlock < _numHighIntensityBlocks * 2) { - _intervalChange(); - _currentBlock++; - _currentDuration = _cooldownDuration; - () async { - await workoutPlayer.stop(); - Source source = AssetSource('cool_down.mp3'); - await coolDownPlayer.setReleaseMode(ReleaseMode.loop); - await coolDownPlayer.play(source); - }(); - } else { - () async { - Future.delayed(const Duration(microseconds: 900)) - .then((value) async { - Source source = AssetSource('finish.mp3'); - await AudioPlayer().play(source); - }); - }(); - _resetTimer(); - } - } - }); - } - - String _formatDuration(Duration duration) { - String twoDigits(int n) => n.toString().padLeft(2, '0'); - final minutes = twoDigits(duration.inMinutes.remainder(60)); - final seconds = twoDigits(duration.inSeconds.remainder(60)); - return '$minutes:$seconds'; - } - - String _formatTotalDuration(Duration duration) { - final minutes = duration.inMinutes; - final seconds = duration.inSeconds.remainder(60); - return _formatDuration(Duration(minutes: minutes, seconds: seconds)); - } +class IntervalTimerPage extends StatelessWidget { + const IntervalTimerPage({super.key}); @override Widget build(BuildContext context) { - return ChangeNotifierProvider( - create: (context) => TimerProvider(), - child: TimerWidget( - duration: Duration(seconds: 5), - )); - return Center( - child: ChangeNotifierProvider( - create: (context) => InputProvider(), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - _currentBlock == 0 - ? 'Warm-up' - : _currentBlock % 2 == 1 - ? 'High Intensity' - : _currentBlock < _numHighIntensityBlocks * 2 - ? 'Low Intensity' - : 'Cool-down', - style: const TextStyle(fontSize: 32.0), - ), - const SizedBox(height: 16.0), - Text( - _formatDuration(_currentDuration), - style: const TextStyle(fontSize: 80.0), - ), - const SizedBox(height: 32.0), - Text( - 'Total: ${_formatTotalDuration(_totalDuration)}', - style: const TextStyle(fontSize: 24.0), - ), - const SizedBox(height: 32.0), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - IconButton( - icon: Icon(_isPaused - ? Icons.play_arrow_rounded - : Icons.stop_rounded), - iconSize: 48.0, - onPressed: () { - if (_isPaused) { - _startTimer(); - } else { - _resetTimer(); - } - }, - ), - // ), - ], - ), - ], - ))); + TimerProvider timerProvider = TimerProvider(); + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (context) => timerProvider), + ChangeNotifierProvider( + create: (context) => WorkoutProvider(timerProvider)), + ], + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: const [ + Align( + alignment: Alignment.topLeft, + child: MuteButton(), + ), + WorkoutTimerWidget() + ], + ), + ); } } diff --git a/lib/pages/scanner_page.dart b/lib/pages/scanner_page.dart index 29cf8a7..de394f9 100644 --- a/lib/pages/scanner_page.dart +++ b/lib/pages/scanner_page.dart @@ -17,15 +17,9 @@ class ScannerPage extends StatelessWidget { 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()); - } + moods; + sleeps; + relapses; } void loadJSON(BuildContext context) async { diff --git a/lib/providers/timer_provider.dart b/lib/providers/timer_provider.dart index 0601b39..ee34b19 100644 --- a/lib/providers/timer_provider.dart +++ b/lib/providers/timer_provider.dart @@ -9,7 +9,6 @@ class TimerProvider extends ChangeNotifier { void startTimer(Duration duration) { started = true; - print('starting timer'); _timer = Timer.periodic(const Duration(seconds: 1), ((timer) { if (timer.tick >= duration.inSeconds) { timer.cancel(); @@ -19,5 +18,8 @@ class TimerProvider extends ChangeNotifier { })); } - void stopTimer() => _timer?.cancel(); + void stopTimer() { + started = false; + _timer?.cancel(); + } } diff --git a/lib/providers/workout_provider.dart b/lib/providers/workout_provider.dart new file mode 100644 index 0000000..5c0a80b --- /dev/null +++ b/lib/providers/workout_provider.dart @@ -0,0 +1,123 @@ +import 'dart:async'; + +import 'package:audioplayers/audioplayers.dart'; +import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/models/workout.dart'; +import 'package:smoke_cess_app/providers/timer_provider.dart'; +import '../globals.dart' as globals; + +class WorkoutProvider extends ChangeNotifier { + TimerProvider timerProvider; + + final AudioPlayer _audioPlayer = AudioPlayer(); + late StreamSubscription _onCompleteSubscription; + final Source _finishedSoundSource = AssetSource('finish.mp3'); + final Source _beepSoundSource = AssetSource('beep.mp3'); + bool isWorkoutStarted = false; + bool isWorkoutComplete = false; + bool isMuted = false; + int motivationBefore = 50; + int motivationAfter = 50; + + void mutePlayer() { + isMuted = true; + _audioPlayer.setVolume(0); + notifyListeners(); + } + + void unMutePlayer() { + isMuted = false; + _audioPlayer.setVolume(1); + notifyListeners(); + } + + WorkoutProvider(this.timerProvider); + + final List _workoutPhases = [ + 'Warm-Up', + 'High Intensity', + 'Low Intensity', + 'High Intensity', + 'Low Intensity', + 'High Intensity', + 'Low Intensity', + 'High Intensity', + 'Cool-down' + ]; + int _workoutPhaseIndex = 0; + + String get currentPhase => _workoutPhases[_workoutPhaseIndex]; + Duration get currentPhaseDuration => + _workoutPhaseSettings[currentPhase]!['duration']; + bool get isPhaseComplete => + timerProvider.elapsedSeconds - currentPhaseDuration.inSeconds == 0; + Color get currentPhaseColor => _workoutPhaseSettings[currentPhase]!['color']; + AssetSource get currentPhaseSource => + _workoutPhaseSettings[currentPhase]!['source']; + /* bool get isWorkoutComplete => + _workoutPhaseIndex == _workoutPhases.length - 1 && isPhaseComplete; */ + + void nextPhase() { + _onCompleteSubscription.cancel(); + _audioPlayer.stop(); + if (_workoutPhaseIndex < _workoutPhases.length - 1) { + _audioPlayer.play(_beepSoundSource); + _workoutPhaseIndex += 1; + _onCompleteSubscription = _audioPlayer.onPlayerComplete.listen((event) { + _audioPlayer.play(currentPhaseSource); + }); + timerProvider.startTimer(currentPhaseDuration); + } else { + //workout completed + _audioPlayer.play(_finishedSoundSource); + stopWorkout(); + } + } + + void startWorkout() { + isWorkoutStarted = true; + isWorkoutComplete = false; + _audioPlayer.play(_beepSoundSource).whenComplete(() => null); + _onCompleteSubscription = _audioPlayer.onPlayerComplete.listen((event) { + _audioPlayer.play(currentPhaseSource); + }); + timerProvider.startTimer(currentPhaseDuration); + } + + void stopWorkout() { + isWorkoutStarted = false; + isWorkoutComplete = true; + _audioPlayer.stop(); + timerProvider.stopTimer(); + notifyListeners(); + } + + void saveWorkout() { + Workout workout = + Workout(motivationBefore, motivationAfter, DateTime.now()); + globals.databaseService.addWorkout(workout); + } +} + +Map> _workoutPhaseSettings = { + 'Warm-Up': { + 'duration': const Duration(seconds: 5), + 'source': AssetSource('warmUp.mp3'), + 'color': Colors.green + }, + 'High Intensity': { + 'duration': const Duration(seconds: 4), + 'source': AssetSource('workout.mp3'), + 'color': Colors.red + }, + 'Low Intensity': { + 'duration': const Duration(seconds: 3), + 'source': AssetSource('workout.mp3'), + 'color': Colors.orange + }, + 'Cool-down': { + 'duration': const Duration(seconds: 5), + 'source': AssetSource('cool_down.mp3'), + 'color': Colors.blue + } +}; diff --git a/lib/services/database_service.dart b/lib/services/database_service.dart index 030a5af..3996883 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/workout.dart'; import 'package:smoke_cess_app/models/relapse.dart'; import 'package:sqflite/sqflite.dart'; // ignore: depend_on_referenced_packages @@ -35,7 +36,6 @@ class DatabaseService { await db.execute(_createWorkoutTable); } - //TODO use generic function? Future> getMoodRecords() async { Database db = await instance.database; var moodRecords = await db.query('mood'); @@ -73,13 +73,17 @@ class DatabaseService { return await db.insert('sleep', sleep.toMap()); } + Future addWorkout(Workout workout) async { + Database db = await instance.database; + return await db.insert('workout', workout.toMap()); + } + Future addRelapse(Relapse relapse) async { Database db = await instance.database; return await db.insert('relapse', relapse.toMap()); } -} -String _createMoodTable = ''' + final String _createMoodTable = ''' CREATE TABLE IF NOT EXISTS mood( id INTEGER PRIMARY KEY, value INTEGER, @@ -88,7 +92,7 @@ String _createMoodTable = ''' ) '''; -String _createSleepTable = ''' + final String _createSleepTable = ''' CREATE TABLE IF NOT EXISTS sleep( id INTEGER PRIMARY KEY, value INTEGER, @@ -101,7 +105,7 @@ String _createSleepTable = ''' ) '''; -String _createRelapseTable = ''' + final String _createRelapseTable = ''' CREATE TABLE IF NOT EXISTS relapse( id INTEGER PRIMARY KEY, date TEXT, @@ -110,14 +114,12 @@ String _createRelapseTable = ''' ) '''; -String _createWorkoutTable = ''' + final 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/services/settings_service.dart b/lib/services/settings_service.dart index 8c7e7a7..f28556a 100644 --- a/lib/services/settings_service.dart +++ b/lib/services/settings_service.dart @@ -23,13 +23,6 @@ Future getMoodQueryMinutes() => _getIntSetting('mood_query_minutes'); Future getChessHours() => _getIntSetting('chess_hours'); Future getChessMinutes() => _getIntSetting('chess_minutes'); -void _setStringSetting(String settingKey, String settingValue) => - SharedPreferences.getInstance() - .then((pref) => pref.setString(settingKey, settingValue)); - -Future _getStringSetting(String settingKey) => - SharedPreferences.getInstance().then((pref) => pref.getString(settingKey)); - void _setIntSetting(String settingKey, int settingValue) => SharedPreferences.getInstance() .then((pref) => pref.setInt(settingKey, settingValue)); diff --git a/lib/widgets/mood_form.dart b/lib/widgets/mood_form.dart index b9a0e05..b461ce7 100644 --- a/lib/widgets/mood_form.dart +++ b/lib/widgets/mood_form.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:smoke_cess_app/models/mood.dart'; -import 'package:smoke_cess_app/services/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'; diff --git a/lib/widgets/mute_button.dart b/lib/widgets/mute_button.dart new file mode 100644 index 0000000..863bb52 --- /dev/null +++ b/lib/widgets/mute_button.dart @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:smoke_cess_app/providers/workout_provider.dart'; + +class MuteButton extends StatelessWidget { + const MuteButton({super.key}); + + @override + Widget build(BuildContext context) { + WorkoutProvider workoutProvider = context.watch(); + + return IconButton( + onPressed: workoutProvider.isMuted + ? workoutProvider.unMutePlayer + : workoutProvider.mutePlayer, + icon: Icon(workoutProvider.isMuted + ? Icons.volume_off_outlined + : Icons.volume_up_outlined), + ); + } +} diff --git a/lib/widgets/popup_for_start_and_stop.dart b/lib/widgets/popup_for_start_and_stop.dart index e1af268..77411a4 100644 --- a/lib/widgets/popup_for_start_and_stop.dart +++ b/lib/widgets/popup_for_start_and_stop.dart @@ -1,26 +1,52 @@ import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:smoke_cess_app/providers/input_provider.dart'; import 'package:smoke_cess_app/widgets/slider.dart'; -import 'package:smoke_cess_app/widgets/text_formfield.dart'; + +Future showMotivationPopup( + BuildContext context, Function onSave, String title) { + return showDialog( + context: context, + builder: (BuildContext context) { + return ChangeNotifierProvider( + create: (context) => InputProvider(), + child: TimerStartStopPopup( + title: title, + onSaveAction: onSave, + ), + ); + }, + ); +} class TimerStartStopPopup extends StatelessWidget { final String title; - - const TimerStartStopPopup({Key? key, required this.title}) : super(key: key); + final Function onSaveAction; + const TimerStartStopPopup( + {Key? key, required this.title, required this.onSaveAction}) + : super(key: key); @override Widget build(BuildContext context) { + InputProvider inputProvider = context.watch(); + return AlertDialog( title: Text(title), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, - children: const [ - Padding( - padding: const EdgeInsets.only(top: 8), + children: [ + const Padding( + padding: EdgeInsets.only(top: 8), child: MySlider(), ), - SizedBox(height: 16), - MyTextFormField('Beschreibe deinen Motivation'), + const SizedBox(height: 16), + ElevatedButton( + onPressed: () { + onSaveAction(inputProvider.sliderValue); + Navigator.pop(context); + }, + child: const Text('Speichern')) ], ), ); diff --git a/lib/widgets/timer_widget.dart b/lib/widgets/timer_widget.dart index 875697f..4cf1d51 100644 --- a/lib/widgets/timer_widget.dart +++ b/lib/widgets/timer_widget.dart @@ -14,11 +14,6 @@ class TimerWidget extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.center, children: [ Text(formatTime(duration.inSeconds - timerProvider.elapsedSeconds)), - ElevatedButton( - onPressed: () => timerProvider.started - ? timerProvider.stopTimer() - : timerProvider.startTimer(duration), - child: Text(timerProvider.started ? 'Stop' : 'Start')) ], ); } diff --git a/lib/widgets/workout_timer_widget.dart b/lib/widgets/workout_timer_widget.dart new file mode 100644 index 0000000..59f67d4 --- /dev/null +++ b/lib/widgets/workout_timer_widget.dart @@ -0,0 +1,78 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:smoke_cess_app/providers/workout_provider.dart'; +import 'package:smoke_cess_app/widgets/timer_widget.dart'; + +import '../providers/timer_provider.dart'; +import 'popup_for_start_and_stop.dart'; + +class WorkoutTimerWidget extends StatelessWidget { + const WorkoutTimerWidget({super.key}); + + @override + Widget build(BuildContext context) { + TimerProvider timerProvider = context.watch(); + WorkoutProvider workoutProvider = context.watch(); + + if (workoutProvider.isPhaseComplete && !workoutProvider.isWorkoutComplete) { + Timer(const Duration(milliseconds: 1), () => workoutProvider.nextPhase()); + } + + if (workoutProvider.isWorkoutComplete) { + Timer( + const Duration(milliseconds: 1), + () => showMotivationPopup(context, (double value) { + workoutProvider.motivationAfter = value.toInt(); + workoutProvider.saveWorkout(); + }, 'Motivation nach dem Training')); + } + + void handleStartStopWorkout() { + if (!workoutProvider.isWorkoutStarted) { + showMotivationPopup(context, (double value) { + workoutProvider.motivationBefore = value.toInt(); + workoutProvider.startWorkout(); + }, 'Motivation vor dem Training'); + } else { + workoutProvider.stopWorkout(); + showMotivationPopup( + context, + (double value) => workoutProvider.motivationAfter = value.toInt(), + 'Motivation nach dem Training'); + } + } + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(workoutProvider.currentPhase), + const SizedBox( + height: 20, + ), + Stack( + alignment: Alignment.center, + children: [ + SizedBox( + height: 100, + width: 100, + child: CircularProgressIndicator( + color: workoutProvider.currentPhaseColor, + value: (workoutProvider.currentPhaseDuration.inSeconds + .toDouble() - + timerProvider.elapsedSeconds) / + workoutProvider.currentPhaseDuration.inSeconds)), + TimerWidget(duration: workoutProvider.currentPhaseDuration), + ], + ), + const SizedBox( + height: 20, + ), + ElevatedButton( + onPressed: handleStartStopWorkout, + child: Text(timerProvider.started ? 'Stop' : 'Start')) + ], + ); + } +}