diff --git a/assets/calendar-clock.png b/assets/calendar-clock.png new file mode 100644 index 0000000..878e17e Binary files /dev/null and b/assets/calendar-clock.png differ diff --git a/assets/scale-bathroom.png b/assets/scale-bathroom.png new file mode 100644 index 0000000..7be63b0 Binary files /dev/null and b/assets/scale-bathroom.png differ diff --git a/lib/HomePage.dart b/lib/HomePage.dart index f673f18..148443e 100644 --- a/lib/HomePage.dart +++ b/lib/HomePage.dart @@ -1,7 +1,8 @@ -import 'dart:math'; +import 'dart:async'; import 'package:flutter/material.dart'; import 'package:weight_tracker/WeightListItem.dart'; +import 'package:weight_tracker/add_entry_dialog.dart'; import 'package:weight_tracker/model/WeightSave.dart'; class HomePage extends StatefulWidget { @@ -15,34 +16,46 @@ class HomePage extends StatefulWidget { class _HomePageState extends State { List weightSaves = new List(); - void _addWeightSave() { - setState(() { - weightSaves.add(new WeightSave( - new DateTime.now(), new Random().nextInt(100).toDouble())); - }); - } - @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text(widget.title), ), - body: new ListView( - children: weightSaves.map((WeightSave weightSave) { + body: new ListView.builder( + itemCount: weightSaves.length, + itemBuilder: (buildContext, index) { //calculating difference - double difference = weightSaves.first == weightSave + double difference = index == 0 ? 0.0 - : weightSave.weight - - weightSaves[weightSaves.indexOf(weightSave) - 1].weight; - return new WeightListItem(weightSave, difference); - }).toList(), + : weightSaves[index].weight - weightSaves[index - 1].weight; + return new WeightListItem(weightSaves[index], difference); + }, ), floatingActionButton: new FloatingActionButton( - onPressed: _addWeightSave, + onPressed: _openAddEntryDialog, tooltip: 'Add new weight entry', child: new Icon(Icons.add), ), ); } + + void _addWeightSave(WeightSave weightSave) { + setState(() { + weightSaves.add(weightSave); + }); + } + + Future _openAddEntryDialog() async { + WeightSave save = + await Navigator.of(context).push(new MaterialPageRoute( + builder: (BuildContext context) { + return new AddEntryDialog.add( + weightSaves.isNotEmpty ? weightSaves.last.weight : 60.0); + }, + fullscreenDialog: true)); + if (save != null) { + _addWeightSave(save); + } + } } diff --git a/lib/add_entry_dialog.dart b/lib/add_entry_dialog.dart new file mode 100644 index 0000000..e48b366 --- /dev/null +++ b/lib/add_entry_dialog.dart @@ -0,0 +1,242 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:meta/meta.dart'; +import 'package:numberpicker/numberpicker.dart'; +import 'package:weight_tracker/model/WeightSave.dart'; + +class AddEntryDialog extends StatefulWidget { + final double initialWeight; + final WeightSave weightSaveToEdit; + + AddEntryDialog.add(this.initialWeight) : weightSaveToEdit = null; + + AddEntryDialog.edit(this.weightSaveToEdit) + : initialWeight = weightSaveToEdit.weight; + + @override + AddEntryDialogState createState() { + if (weightSaveToEdit != null) { + return new AddEntryDialogState(weightSaveToEdit.dateTime, + weightSaveToEdit.weight, weightSaveToEdit.note); + } else { + return new AddEntryDialogState(new DateTime.now(), initialWeight, null); + } + } +} + +class AddEntryDialogState extends State { + DateTime _dateTime = new DateTime.now(); + double _weight; + String _note; + + AddEntryDialogState(this._dateTime, this._weight, this._note); + + @override + Widget build(BuildContext context) { + TextStyle headerTextStyle = Theme + .of(context) + .textTheme + .subhead + .copyWith(color: Colors.black, fontSize: 16.0); + return new Scaffold( + appBar: new AppBar( + title: const Text('New entry'), + actions: [ + new FlatButton( + onPressed: () { + Navigator + .of(context) + .pop(new WeightSave(_dateTime, _weight, _note)); + }, + child: new Text('SAVE', + style: Theme + .of(context) + .textTheme + .subhead + .copyWith(color: Colors.white))), + ], + ), + body: new DefaultTextStyle( + style: headerTextStyle, + child: new Container( + padding: new EdgeInsets.all(12.0), + child: new SingleChildScrollView( + child: new Column( + children: [ + new Padding( + padding: new EdgeInsets.all(8.0), + child: new DateTimeItem( + dateTime: _dateTime, + onChanged: (dateTime) => + setState(() => _dateTime = dateTime), + ), + ), + new Padding( + padding: new EdgeInsets.symmetric(horizontal: 8.0), + child: new InkWell( + onTap: () => _showWeightPicker(context), + child: new Padding( + padding: new EdgeInsets.only(top: 8.0), + child: new Row( + children: [ + new Image.asset( + "assets/scale-bathroom.png", + color: Colors.grey[500], + height: 24.0, + width: 24.0, + ), + new Padding( + padding: new EdgeInsets.only(left: 16.0), + child: new Text( + "$_weight kg", + style: headerTextStyle, + ), + ), + ], + ), + ), + ), + ), + new Padding( + padding: new EdgeInsets.symmetric( + vertical: 0.0, horizontal: 8.0), + child: new InkWell( + onTap: () => _showWeightPicker(context), + child: new Row( + children: [ + new Padding( + padding: new EdgeInsets.only(top: 4.0), + child: new Icon( + Icons.note_add, + color: Colors.grey[500], + )), + new Expanded( + child: new Padding( + padding: new EdgeInsets.only(left: 16.0), + child: new TextField( + decoration: new InputDecoration( + labelText: 'Optional note', + labelStyle: null, + ), + focusNode: new FocusNode(), + controller: + new TextEditingController(text: _note), + onSubmitted: (string) => + setState(() => _note = string), + maxLines: null, + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + )); + } + + _showWeightPicker(BuildContext context) { + showDialog( + context: context, + child: new NumberPickerDialog.decimal( + minValue: 1, + maxValue: 150, + initialDoubleValue: _weight, + title: new Text("Enter your weight"), + ), + ).then((value) { + if (value != null) { + setState(() => _weight = value); + } + }); + } +} + +class DateTimeItem extends StatelessWidget { + DateTimeItem({Key key, DateTime dateTime, @required this.onChanged}) + : assert(onChanged != null), + date = dateTime == null + ? new DateTime.now() + : new DateTime(dateTime.year, dateTime.month, dateTime.day), + time = dateTime == null + ? new DateTime.now() + : new TimeOfDay(hour: dateTime.hour, minute: dateTime.minute), + super(key: key); + + final DateTime date; + final TimeOfDay time; + final ValueChanged onChanged; + + @override + Widget build(BuildContext context) { + final ThemeData theme = Theme.of(context); + + return new Row( + children: [ + new Expanded( + child: new InkWell( + onTap: () { + _showDatePicker(context); + }, + child: new Container( + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: new Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + new Icon(Icons.today, color: Colors.grey[500]), + new Padding( + padding: new EdgeInsets.only(left: 16.0), + child: + new Text(new DateFormat('EEEE, MMMM d').format(date)), + ), + ], + ), + ), + ), + ), + new InkWell( + onTap: () { + _showTimePicker(context); + }, + child: new Container( + margin: const EdgeInsets.only(left: 8.0), + padding: const EdgeInsets.symmetric(vertical: 8.0), + child: new Row( + children: [ + new Text('$time'), + ], + ), + ), + ), + ], + ); + } + + Future _showDatePicker(BuildContext context) async { + DateTime dateTimePicked = await showDatePicker( + context: context, + initialDate: date, + firstDate: date.subtract(const Duration(days: 20000)), + lastDate: new DateTime.now()); + + if (dateTimePicked != null) { + onChanged(new DateTime(dateTimePicked.year, dateTimePicked.month, + dateTimePicked.day, time.hour, time.minute)); + } + } + + Future _showTimePicker(BuildContext context) async { + TimeOfDay timeOfDay = + await showTimePicker(context: context, initialTime: time); + + if (timeOfDay != null) { + onChanged(new DateTime( + date.year, date.month, date.day, timeOfDay.hour, timeOfDay.minute)); + } + } +} diff --git a/lib/model/WeightSave.dart b/lib/model/WeightSave.dart index a79e2e5..44f4249 100644 --- a/lib/model/WeightSave.dart +++ b/lib/model/WeightSave.dart @@ -1,6 +1,7 @@ class WeightSave { DateTime dateTime; double weight; + String note; - WeightSave(this.dateTime, this.weight); + WeightSave(this.dateTime, this.weight, this.note); } \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 7caa1f8..53003eb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,6 +4,7 @@ description: A new flutter project. dependencies: flutter: sdk: flutter + numberpicker: "^0.1.0" # For information on the generic Dart part of this file, see the # following page: https://www.dartlang.org/tools/pub/pubspec @@ -18,8 +19,8 @@ flutter: # To add assets to your application, add an assets section here, in # this "flutter" section, as in: - # assets: - # - images/a_dot_burr.jpeg + assets: + - assets/scale-bathroom.png # - images/a_dot_ham.jpeg # To add assets from package dependencies, first ensure the asset