mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
addded measurements to dashboard, categories card refactor
This commit is contained in:
@@ -41,6 +41,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
DashboardWorkoutWidget(),
|
||||
DashboardNutritionWidget(),
|
||||
DashboardWeightWidget(),
|
||||
DashboardMeasurementsWidget(),
|
||||
const DashboardCalendarWidget(),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:carousel_slider/carousel_slider.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
@@ -35,14 +36,20 @@ import 'package:wger/screens/workout_plan_screen.dart';
|
||||
import 'package:wger/theme/theme.dart';
|
||||
import 'package:wger/widgets/core/charts.dart';
|
||||
import 'package:wger/widgets/core/core.dart';
|
||||
import 'package:wger/widgets/measurements/categories_card.dart';
|
||||
import 'package:wger/widgets/nutrition/charts.dart';
|
||||
import 'package:wger/widgets/nutrition/forms.dart';
|
||||
import 'package:wger/widgets/weight/forms.dart';
|
||||
import 'package:wger/widgets/workouts/forms.dart';
|
||||
|
||||
import '../../providers/measurement.dart';
|
||||
import '../../screens/measurement_entries_screen.dart';
|
||||
import '../measurements/forms.dart';
|
||||
|
||||
class DashboardNutritionWidget extends StatefulWidget {
|
||||
@override
|
||||
_DashboardNutritionWidgetState createState() => _DashboardNutritionWidgetState();
|
||||
_DashboardNutritionWidgetState createState() =>
|
||||
_DashboardNutritionWidgetState();
|
||||
}
|
||||
|
||||
class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
@@ -53,7 +60,8 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_plan = Provider.of<NutritionPlansProvider>(context, listen: false).currentPlan;
|
||||
_plan =
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false).currentPlan;
|
||||
_hasContent = _plan != null;
|
||||
}
|
||||
|
||||
@@ -96,7 +104,8 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
icon: const Icon(Icons.history_edu),
|
||||
color: wgerPrimaryButtonColor,
|
||||
onPressed: () {
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false).logMealToDiary(meal);
|
||||
Provider.of<NutritionPlansProvider>(context, listen: false)
|
||||
.logMealToDiary(meal);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
@@ -127,7 +136,8 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Text('${item.amount.toStringAsFixed(0)} ${AppLocalizations.of(context).g}'),
|
||||
Text(
|
||||
'${item.amount.toStringAsFixed(0)} ${AppLocalizations.of(context).g}'),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -147,7 +157,9 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
return const Text('');
|
||||
}
|
||||
|
||||
return _showDetail ? const Icon(Icons.expand_less) : const Icon(Icons.expand_more);
|
||||
return _showDetail
|
||||
? const Icon(Icons.expand_less)
|
||||
: const Icon(Icons.expand_more);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -157,7 +169,9 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
_hasContent ? _plan!.description : AppLocalizations.of(context).nutritionalPlan,
|
||||
_hasContent
|
||||
? _plan!.description
|
||||
: AppLocalizations.of(context).nutritionalPlan,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
subtitle: Text(
|
||||
@@ -186,7 +200,8 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
height: 180,
|
||||
child: NutritionalPlanPieChartWidget(_plan!.nutritionalValues),
|
||||
child:
|
||||
NutritionalPlanPieChartWidget(_plan!.nutritionalValues),
|
||||
)
|
||||
],
|
||||
),
|
||||
@@ -218,8 +233,9 @@ class _DashboardNutritionWidgetState extends State<DashboardNutritionWidget> {
|
||||
TextButton(
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.pushNamed(NutritionalPlanScreen.routeName, arguments: _plan);
|
||||
Navigator.of(context).pushNamed(
|
||||
NutritionalPlanScreen.routeName,
|
||||
arguments: _plan);
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -253,7 +269,7 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
leading: const FaIcon(
|
||||
FontAwesomeIcons.weightScale,
|
||||
FontAwesomeIcons.weight,
|
||||
color: Colors.black,
|
||||
),
|
||||
trailing: IconButton(
|
||||
@@ -286,9 +302,11 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
child: Text(
|
||||
AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(WeightScreen.routeName);
|
||||
Navigator.of(context)
|
||||
.pushNamed(WeightScreen.routeName);
|
||||
}),
|
||||
],
|
||||
),
|
||||
@@ -309,6 +327,101 @@ class _DashboardWeightWidgetState extends State<DashboardWeightWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
class DashboardMeasurementsWidget extends StatefulWidget {
|
||||
@override
|
||||
_DashboardMeasurementsWidgetState createState() =>
|
||||
_DashboardMeasurementsWidgetState();
|
||||
}
|
||||
|
||||
class _DashboardMeasurementsWidgetState
|
||||
extends State<DashboardMeasurementsWidget> {
|
||||
int _current = 0;
|
||||
final CarouselController _controller = CarouselController();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final _provider = Provider.of<MeasurementProvider>(context, listen: false);
|
||||
|
||||
var items = _provider.categories
|
||||
.map(
|
||||
(item) => CategoriesCard(item),
|
||||
)
|
||||
.toList();
|
||||
return Consumer<BodyWeightProvider>(
|
||||
builder: (context, workoutProvider, child) => Card(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
AppLocalizations.of(context).measurements,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
leading: const FaIcon(
|
||||
FontAwesomeIcons.weight,
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
if (items.isNotEmpty)
|
||||
Column(children: [
|
||||
CarouselSlider(
|
||||
items: items,
|
||||
carouselController: _controller,
|
||||
options: CarouselOptions(
|
||||
autoPlay: false,
|
||||
enlargeCenterPage: false,
|
||||
viewportFraction: 1,
|
||||
enableInfiniteScroll: false,
|
||||
aspectRatio: 1.1,
|
||||
onPageChanged: (index, reason) {
|
||||
setState(() {
|
||||
_current = index;
|
||||
});
|
||||
}),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: items.asMap().entries.map((entry) {
|
||||
return GestureDetector(
|
||||
onTap: () => _controller.animateToPage(entry.key),
|
||||
child: Container(
|
||||
width: 12.0,
|
||||
height: 12.0,
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: 8.0, horizontal: 4.0),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: (Theme.of(context).brightness ==
|
||||
Brightness.dark
|
||||
? Colors.white
|
||||
: wgerPrimaryColor)
|
||||
.withOpacity(
|
||||
_current == entry.key ? 0.9 : 0.4)),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
])
|
||||
else
|
||||
NothingFound(
|
||||
AppLocalizations.of(context).noWeightEntries,
|
||||
AppLocalizations.of(context).newEntry,
|
||||
WeightForm(),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class DashboardWorkoutWidget extends StatefulWidget {
|
||||
@override
|
||||
_DashboardWorkoutWidgetState createState() => _DashboardWorkoutWidgetState();
|
||||
@@ -332,7 +445,9 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
return const Text('');
|
||||
}
|
||||
|
||||
return _showDetail ? const Icon(Icons.expand_less) : const Icon(Icons.expand_more);
|
||||
return _showDetail
|
||||
? const Icon(Icons.expand_less)
|
||||
: const Icon(Icons.expand_more);
|
||||
}
|
||||
|
||||
List<Widget> getContent() {
|
||||
@@ -364,7 +479,8 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
color: wgerPrimaryButtonColor,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pushNamed(GymModeScreen.routeName, arguments: day);
|
||||
Navigator.of(context)
|
||||
.pushNamed(GymModeScreen.routeName, arguments: day);
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -386,7 +502,8 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
children: [
|
||||
Text(s.exerciseObj.name),
|
||||
const SizedBox(width: 10),
|
||||
MutedText(set.getSmartRepr(s.exerciseObj).join('\n')),
|
||||
MutedText(
|
||||
set.getSmartRepr(s.exerciseObj).join('\n')),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@@ -411,7 +528,9 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(
|
||||
_hasContent ? _workoutPlan!.name : AppLocalizations.of(context).labelWorkoutPlan,
|
||||
_hasContent
|
||||
? _workoutPlan!.name
|
||||
: AppLocalizations.of(context).labelWorkoutPlan,
|
||||
style: Theme.of(context).textTheme.headline4,
|
||||
),
|
||||
subtitle: Text(
|
||||
@@ -453,8 +572,8 @@ class _DashboardWorkoutWidgetState extends State<DashboardWorkoutWidget> {
|
||||
TextButton(
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.of(context)
|
||||
.pushNamed(WorkoutPlanScreen.routeName, arguments: _workoutPlan);
|
||||
Navigator.of(context).pushNamed(WorkoutPlanScreen.routeName,
|
||||
arguments: _workoutPlan);
|
||||
},
|
||||
),
|
||||
],
|
||||
|
||||
@@ -24,6 +24,7 @@ import 'package:wger/screens/form_screen.dart';
|
||||
import 'package:wger/screens/measurement_entries_screen.dart';
|
||||
import 'package:wger/widgets/core/charts.dart';
|
||||
|
||||
import 'categories_card.dart';
|
||||
import 'forms.dart';
|
||||
|
||||
class CategoriesList extends StatelessWidget {
|
||||
@@ -37,58 +38,7 @@ class CategoriesList extends StatelessWidget {
|
||||
itemBuilder: (context, index) {
|
||||
final currentCategory = _provider.categories[index];
|
||||
|
||||
return Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
currentCategory.name,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.all(10),
|
||||
height: 220,
|
||||
child: MeasurementChartWidget(
|
||||
currentCategory.entries
|
||||
.map((e) => MeasurementChartEntry(e.value, e.date))
|
||||
.toList(),
|
||||
unit: currentCategory.unit,
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
MeasurementEntriesScreen.routeName,
|
||||
arguments: currentCategory.id,
|
||||
);
|
||||
}),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Navigator.pushNamed(
|
||||
context,
|
||||
FormScreen.routeName,
|
||||
arguments: FormScreenArguments(
|
||||
AppLocalizations.of(context).newEntry,
|
||||
MeasurementEntryForm(currentCategory.id!),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return CategoriesCard(currentCategory);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
70
lib/widgets/measurements/categories_card.dart
Normal file
70
lib/widgets/measurements/categories_card.dart
Normal file
@@ -0,0 +1,70 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../models/measurements/measurement_category.dart';
|
||||
import '../../screens/form_screen.dart';
|
||||
import '../../screens/measurement_entries_screen.dart';
|
||||
import '../core/charts.dart';
|
||||
import 'forms.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class CategoriesCard extends StatelessWidget {
|
||||
MeasurementCategory currentCategory;
|
||||
|
||||
CategoriesCard(this.currentCategory);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Text(
|
||||
currentCategory.name,
|
||||
style: Theme.of(context).textTheme.headline6,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.all(10),
|
||||
height: 220,
|
||||
child: MeasurementChartWidget(
|
||||
currentCategory.entries
|
||||
.map((e) => MeasurementChartEntry(e.value, e.date))
|
||||
.toList(),
|
||||
unit: currentCategory.unit,
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: Text(AppLocalizations.of(context).goToDetailPage),
|
||||
onPressed: () {
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
MeasurementEntriesScreen.routeName,
|
||||
arguments: currentCategory.id,
|
||||
);
|
||||
}),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await Navigator.pushNamed(
|
||||
context,
|
||||
FormScreen.routeName,
|
||||
arguments: FormScreenArguments(
|
||||
AppLocalizations.of(context).newEntry,
|
||||
MeasurementEntryForm(currentCategory.id!),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
35
pubspec.lock
35
pubspec.lock
@@ -42,7 +42,7 @@ packages:
|
||||
name: async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
version: "2.9.0"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -141,6 +141,13 @@ packages:
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.3.0"
|
||||
carousel_slider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: carousel_slider
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.1.1"
|
||||
change:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -154,7 +161,7 @@ packages:
|
||||
name: characters
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
charcode:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -217,7 +224,7 @@ packages:
|
||||
name: clock
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
code_builder:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -287,7 +294,7 @@ packages:
|
||||
name: fake_async
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
version: "1.3.1"
|
||||
ffi:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -552,7 +559,7 @@ packages:
|
||||
name: json_serializable
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
version: "6.4.0"
|
||||
klizma:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -594,21 +601,21 @@ packages:
|
||||
name: matcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.11"
|
||||
version: "0.12.12"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.4"
|
||||
version: "0.1.5"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.7.0"
|
||||
version: "1.8.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -664,7 +671,7 @@ packages:
|
||||
name: path
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.1"
|
||||
version: "1.8.2"
|
||||
path_drawing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -879,7 +886,7 @@ packages:
|
||||
name: source_span
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.8.2"
|
||||
version: "1.9.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -907,7 +914,7 @@ packages:
|
||||
name: string_scanner
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
version: "1.1.1"
|
||||
table_calendar:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -921,14 +928,14 @@ packages:
|
||||
name: term_glyph
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.2.1"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.4.9"
|
||||
version: "0.4.12"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -956,7 +963,7 @@ packages:
|
||||
name: url_launcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "6.1.6"
|
||||
version: "6.1.5"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -51,9 +51,10 @@ dependencies:
|
||||
rive: ^0.9.1
|
||||
shared_preferences: ^2.0.15
|
||||
table_calendar: ^3.0.7
|
||||
url_launcher: ^6.1.6
|
||||
url_launcher: ^6.1.5
|
||||
flutter_barcode_scanner: ^2.0.0
|
||||
video_player: ^2.4.7
|
||||
carousel_slider: ^4.1.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@@ -62,7 +63,7 @@ dev_dependencies:
|
||||
# sdk: flutter
|
||||
build_runner: ^2.2.1
|
||||
flutter_launcher_icons: ^0.10.0
|
||||
json_serializable: ^6.4.1
|
||||
json_serializable: ^6.3.2
|
||||
mockito: ^5.3.2
|
||||
network_image_mock: ^2.1.1
|
||||
flutter_lints: ^2.0.1
|
||||
|
||||
Reference in New Issue
Block a user