mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-19 07:50:52 +01:00
Move body weight chart to own widget
This commit is contained in:
@@ -19,8 +19,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/locale/locales.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
import 'package:wger/widgets/app_drawer.dart';
|
||||
import 'package:wger/widgets/weight/charts.dart';
|
||||
|
||||
class DashboardScreen extends StatefulWidget {
|
||||
static const routeName = '/dashboard';
|
||||
@@ -89,7 +91,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
leading: Icon(Icons.fitness_center),
|
||||
leading: Icon(Icons.restaurant),
|
||||
title: Text('Nutrition'),
|
||||
subtitle: Text('Nutrition overview, graphs, etc'),
|
||||
),
|
||||
@@ -114,14 +116,20 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
}
|
||||
|
||||
Widget getWeightCard() {
|
||||
final weightEntriesData = Provider.of<BodyWeight>(context);
|
||||
|
||||
return Card(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
leading: Icon(Icons.restaurant),
|
||||
leading: Icon(Icons.bar_chart),
|
||||
title: Text('Weight'),
|
||||
subtitle: Text('Weight overview, graphs, etc'),
|
||||
subtitle: Container(
|
||||
padding: EdgeInsets.all(15),
|
||||
height: 180,
|
||||
child: WeightChartWidget(weightEntriesData.items),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
|
||||
@@ -47,12 +47,6 @@ class _WeightScreenState extends State<WeightScreen> {
|
||||
Widget getAppBar() {
|
||||
return AppBar(
|
||||
title: Text('Weight'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.add),
|
||||
onPressed: () {},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -83,83 +77,84 @@ class _WeightScreenState extends State<WeightScreen> {
|
||||
|
||||
showWeightEntrySheet(BuildContext context) async {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return Container(
|
||||
margin: EdgeInsets.all(20),
|
||||
child: Form(
|
||||
key: _form,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
AppLocalizations.of(ctx).newEntry,
|
||||
style: Theme.of(ctx).textTheme.headline6,
|
||||
),
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return Container(
|
||||
margin: EdgeInsets.all(20),
|
||||
child: Form(
|
||||
key: _form,
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
AppLocalizations.of(ctx).newEntry,
|
||||
style: Theme.of(ctx).textTheme.headline6,
|
||||
),
|
||||
|
||||
// Weight date
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(ctx).date),
|
||||
controller: dateController,
|
||||
onTap: () async {
|
||||
// Stop keyboard from appearing
|
||||
FocusScope.of(ctx).requestFocus(new FocusNode());
|
||||
// Weight date
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(ctx).date),
|
||||
controller: dateController,
|
||||
onTap: () async {
|
||||
// Stop keyboard from appearing
|
||||
FocusScope.of(ctx).requestFocus(new FocusNode());
|
||||
|
||||
// Show Date Picker Here
|
||||
var pickedDate = await showDatePicker(
|
||||
context: ctx,
|
||||
initialDate: DateTime.now(),
|
||||
firstDate: DateTime(DateTime.now().year - 10),
|
||||
lastDate: DateTime.now(),
|
||||
);
|
||||
// Show Date Picker Here
|
||||
var pickedDate = await showDatePicker(
|
||||
context: ctx,
|
||||
initialDate: DateTime.now(),
|
||||
firstDate: DateTime(DateTime.now().year - 10),
|
||||
lastDate: DateTime.now(),
|
||||
);
|
||||
|
||||
dateController.text = toDate(pickedDate);
|
||||
},
|
||||
onSaved: (newValue) {
|
||||
weightEntry.date = DateTime.parse(newValue);
|
||||
},
|
||||
onFieldSubmitted: (_) {},
|
||||
),
|
||||
dateController.text = toDate(pickedDate);
|
||||
},
|
||||
onSaved: (newValue) {
|
||||
weightEntry.date = DateTime.parse(newValue);
|
||||
},
|
||||
onFieldSubmitted: (_) {},
|
||||
),
|
||||
|
||||
// Weight
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(ctx).weight),
|
||||
controller: weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
onFieldSubmitted: (_) {},
|
||||
onSaved: (newValue) {
|
||||
weightEntry.weight = double.parse(newValue);
|
||||
},
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text(AppLocalizations.of(ctx).save),
|
||||
onPressed: () async {
|
||||
// Validate and save the current values to the weightEntry
|
||||
final isValid = _form.currentState.validate();
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
_form.currentState.save();
|
||||
// Weight
|
||||
TextFormField(
|
||||
decoration: InputDecoration(labelText: AppLocalizations.of(ctx).weight),
|
||||
controller: weightController,
|
||||
keyboardType: TextInputType.number,
|
||||
onFieldSubmitted: (_) {},
|
||||
onSaved: (newValue) {
|
||||
weightEntry.weight = double.parse(newValue);
|
||||
},
|
||||
),
|
||||
ElevatedButton(
|
||||
child: Text(AppLocalizations.of(ctx).save),
|
||||
onPressed: () async {
|
||||
// Validate and save the current values to the weightEntry
|
||||
final isValid = _form.currentState.validate();
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
_form.currentState.save();
|
||||
|
||||
// Save the entry on the server
|
||||
try {
|
||||
await Provider.of<BodyWeight>(ctx, listen: false).addEntry(weightEntry);
|
||||
// Save the entry on the server
|
||||
try {
|
||||
await Provider.of<BodyWeight>(ctx, listen: false).addEntry(weightEntry);
|
||||
|
||||
// Saving was successful, reset the data
|
||||
weightController.clear();
|
||||
dateController.clear();
|
||||
weightEntry = WeightEntry();
|
||||
} on WgerHttpException catch (error) {
|
||||
showHttpExceptionErrorDialog(error, ctx);
|
||||
} catch (error) {
|
||||
showErrorDialog(error, context);
|
||||
}
|
||||
Navigator.of(ctx).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
// Saving was successful, reset the data
|
||||
weightController.clear();
|
||||
dateController.clear();
|
||||
weightEntry = WeightEntry();
|
||||
} on WgerHttpException catch (error) {
|
||||
showHttpExceptionErrorDialog(error, ctx);
|
||||
} catch (error) {
|
||||
showErrorDialog(error, context);
|
||||
}
|
||||
Navigator.of(ctx).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
47
lib/widgets/weight/charts.dart
Normal file
47
lib/widgets/weight/charts.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of wger Workout Manager <https://github.com/wger-project>.
|
||||
* Copyright (C) 2020 wger Team
|
||||
*
|
||||
* wger Workout Manager is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wger Workout Manager is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:wger/models/body_weight/weight_entry.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
|
||||
/// Weight chart widget
|
||||
class WeightChartWidget extends StatelessWidget {
|
||||
final List<WeightEntry> _entries;
|
||||
|
||||
/// [_entries] is a list of [WeightEntry] as returned e.g. by the
|
||||
/// [BodyWeight] provider.
|
||||
WeightChartWidget(this._entries);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return charts.TimeSeriesChart(
|
||||
[
|
||||
charts.Series<WeightEntry, DateTime>(
|
||||
id: 'Weight',
|
||||
colorFn: (_, __) => wgerChartSecondaryColor,
|
||||
domainFn: (WeightEntry weightEntry, _) => weightEntry.date,
|
||||
measureFn: (WeightEntry weightEntry, _) => weightEntry.weight,
|
||||
data: _entries,
|
||||
)
|
||||
],
|
||||
defaultRenderer: new charts.LineRendererConfig(includePoints: true),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,11 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:charts_flutter/flutter.dart' as charts;
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/models/body_weight/weight_entry.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
import 'package:wger/widgets/weight/charts.dart';
|
||||
|
||||
class WeightEntriesList extends StatelessWidget {
|
||||
@override
|
||||
@@ -33,18 +31,7 @@ class WeightEntriesList extends StatelessWidget {
|
||||
Container(
|
||||
padding: EdgeInsets.all(15),
|
||||
height: 220,
|
||||
child: charts.TimeSeriesChart(
|
||||
[
|
||||
charts.Series<WeightEntry, DateTime>(
|
||||
id: 'Weight',
|
||||
colorFn: (_, __) => wgerChartSecondaryColor,
|
||||
domainFn: (WeightEntry weightEntry, _) => weightEntry.date,
|
||||
measureFn: (WeightEntry weightEntry, _) => weightEntry.weight,
|
||||
data: weightEntriesData.items,
|
||||
)
|
||||
],
|
||||
defaultRenderer: new charts.LineRendererConfig(includePoints: true),
|
||||
),
|
||||
child: WeightChartWidget(weightEntriesData.items),
|
||||
),
|
||||
Divider(),
|
||||
Expanded(
|
||||
|
||||
Reference in New Issue
Block a user