diff --git a/lib/pages/sleep_page.dart b/lib/pages/sleep_page.dart index 281c580..e736f44 100644 --- a/lib/pages/sleep_page.dart +++ b/lib/pages/sleep_page.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:smoke_cess_app/widgets/sleep_form.dart'; class SleepPage extends StatelessWidget { const SleepPage({super.key}); @override Widget build(BuildContext context) { - return const Center(child: Text('Hier wird Schlafqualität abgefragt')); + return const Center(child: SleepForm()); } } diff --git a/lib/widgets/elevated_card.dart b/lib/widgets/elevated_card.dart new file mode 100644 index 0000000..eba4532 --- /dev/null +++ b/lib/widgets/elevated_card.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; + +class ElevatedCard extends StatelessWidget { + final Widget child; + final String title; + + const ElevatedCard({ + Key? key, + required this.child, + required this.title, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Card( + elevation: 4.0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + fontSize: 18.0, + fontWeight: FontWeight.bold, + ), + ), + SizedBox(height: 8.0), + child, + ], + ), + ), + ); + } +} diff --git a/lib/widgets/mood_form.dart b/lib/widgets/mood_form.dart index fa7d175..23ea2b7 100644 --- a/lib/widgets/mood_form.dart +++ b/lib/widgets/mood_form.dart @@ -12,7 +12,7 @@ class MoodForm extends StatefulWidget { class _MoodFormState extends State { final GlobalKey _moodFormKey = GlobalKey(); - MySlider slider = const MySlider(); + MySlider slider = const MySlider('Bewerte deine Stimmung'); String _textInput = ""; void submitForm() { @@ -35,7 +35,7 @@ class _MoodFormState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ slider, - MyTextFormField(onFormFieldSave), + MyTextFormField('Beschreibe deine Stimmung', onFormFieldSave), SubmitFormButton(submitForm) ], )); diff --git a/lib/widgets/sleep_form.dart b/lib/widgets/sleep_form.dart new file mode 100644 index 0000000..52eefe8 --- /dev/null +++ b/lib/widgets/sleep_form.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.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'; + +class SleepForm extends StatefulWidget { + const SleepForm({Key? key}) : super(key: key); + + @override + State createState() => _SleepFormState(); +} + +class _SleepFormState extends State { + final GlobalKey _sleepFormKey = GlobalKey(); + MySlider slider = const MySlider(''); + String _textInput = ""; + TimePicker sleepTimePicker = TimePicker( + const TimeOfDay(hour: 22, minute: 00), + ); + TimePicker wakeUpTimePicker = TimePicker( + const TimeOfDay(hour: 8, minute: 00), + ); + + void submitForm() { + if (_sleepFormKey.currentState!.validate()) { + _sleepFormKey.currentState?.save(); //call every onSave Method + //TODO Businesslogik aufrufen! + print(_textInput); + print(slider.getSliderValue()); + print('Eingeschlafen um: ${sleepTimePicker.getCurrentTime}'); + _sleepFormKey.currentState?.reset(); + } + } + + void onFormFieldSave(String? newValue) => _textInput = newValue!; + + @override + Widget build(BuildContext context) { + return Form( + key: _sleepFormKey, + child: Stack( + children: [ + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ElevatedCard( + title: 'Einschlafzeit', + child: sleepTimePicker, + ), + const SizedBox(height: 16), + ElevatedCard( + title: 'Aufwachzeit', + child: wakeUpTimePicker, + ), + const SizedBox(height: 16), + ElevatedCard( + title: 'Schlafbewertung', + child: slider, + ), + const SizedBox(height: 16), + ElevatedCard( + title: 'Schlafbeschreibung', + child: MyTextFormField( + 'Beschreibe deinen Schlaf', onFormFieldSave), + ), + const SizedBox( + height: 80, + ), + ], + ), + ), + Positioned( + bottom: 0, + right: 0, + child: SizedBox( + width: 140, + height: 80, + child: SubmitFormButton(submitForm), + ), + ), + ], + ), + ); + } +} diff --git a/lib/widgets/slider.dart b/lib/widgets/slider.dart index fb8e063..9d896b7 100644 --- a/lib/widgets/slider.dart +++ b/lib/widgets/slider.dart @@ -3,7 +3,8 @@ import 'package:flutter/material.dart'; double _currentSliderValue = 50; class MySlider extends StatefulWidget { - const MySlider({super.key}); + final String _title; + const MySlider(this._title, {Key? key}) : super(key: key); @override State createState() => SliderState(); @@ -14,24 +15,80 @@ class MySlider extends StatefulWidget { } class SliderState extends State { + TextEditingController _textFieldController = TextEditingController(); + String? _errorText; + + @override + void initState() { + super.initState(); + _textFieldController.text = _currentSliderValue.toStringAsFixed(0); + } + @override Widget build(BuildContext context) { - return Column( - children: [ - const Text('Bewerte deine Stimmung'), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Slider( - value: _currentSliderValue, - max: 100, - label: _currentSliderValue.round().toString(), - onChanged: (double value) => - {setState((() => _currentSliderValue = value))}), - Text(_currentSliderValue.round().toString()) - ], - ) - ], + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(widget._title), + SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: Slider( + value: _currentSliderValue, + min: 1, + max: 100, + divisions: 99, + label: _currentSliderValue.round().toString(), + onChanged: (double value) { + setState(() { + _currentSliderValue = value; + _textFieldController.text = _currentSliderValue.toStringAsFixed(0); + _errorText = null; + }); + }, + ), + ), + SizedBox(width: 16), + SizedBox( + width: 100, + child: TextFormField( + controller: _textFieldController, + keyboardType: TextInputType.number, + decoration: InputDecoration( + labelText: 'Stimmung', + errorText: _errorText, + ), + onChanged: (text) { + if (text.isEmpty) { + setState(() { + _currentSliderValue = 1; + _textFieldController.clear(); + _errorText = null; + }); + return; + } + final value = double.tryParse(text); + if (value == null || value < 1 || value > 100) { + setState(() { + _textFieldController.clear(); + _errorText = 'Please enter a value between 1 and 100.'; + }); + return; + } + setState(() { + _currentSliderValue = value; + _errorText = null; + }); + }, + ), + ), + ], + ), + ], + ), ); } } diff --git a/lib/widgets/text_formfield.dart b/lib/widgets/text_formfield.dart index b8a7d02..102a350 100644 --- a/lib/widgets/text_formfield.dart +++ b/lib/widgets/text_formfield.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; class MyTextFormField extends StatelessWidget { + final String _description; final Function(String?) onSaveAction; const MyTextFormField( + this._description, this.onSaveAction, { super.key, }); @@ -11,7 +13,7 @@ class MyTextFormField extends StatelessWidget { Widget build(BuildContext context) { return TextFormField( onSaved: onSaveAction, - decoration: const InputDecoration(hintText: 'Beschreibe deine Stimmung?'), + decoration: InputDecoration(hintText: _description), validator: (String? value) => value == null || value.isEmpty ? 'Text eingeben' : null, keyboardType: TextInputType.multiline, diff --git a/lib/widgets/timepicker.dart b/lib/widgets/timepicker.dart new file mode 100644 index 0000000..5e97af5 --- /dev/null +++ b/lib/widgets/timepicker.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; + +class TimePicker extends StatefulWidget { + TimeOfDay _initialTime; + TimePicker(this._initialTime, {Key? key}); + + TimeOfDay get getCurrentTime => _initialTime; + + @override + State createState() => TimePickerState(); +} + + +class TimePickerState extends State { + TimePickerState(); + + @override + Widget build(BuildContext context) { + return Center( + child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + Text( + '${widget._initialTime.hour.toString().padLeft(2, '0')}:${widget._initialTime.minute.toString().padLeft(2, '0')}', + style: const TextStyle(fontSize: 22), + ), + const SizedBox(width: 16), + ElevatedButton( + onPressed: () async { + //TODO auslagern + TimeOfDay? newTime = await showTimePicker( + context: context, + initialTime: widget._initialTime, + builder: (context, child) { + return MediaQuery( + data: MediaQuery.of(context) + .copyWith(alwaysUse24HourFormat: true), + child: child!, + ); + }, + ); + if (newTime == null) return; + setState(() { + widget._initialTime = newTime; + }); + }, + child: const Text('Zeit einstellen')) + ]), + ); + } +}