Fun with TimeOfDay

This commit is contained in:
Roland Geider
2020-12-22 12:54:47 +01:00
parent 571e933281
commit b29436d1e3
8 changed files with 133 additions and 29 deletions

View File

@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
num toNum(String e) {
@@ -48,20 +49,21 @@ String toDate(DateTime dateTime) {
* Converts a time to a date object.
* Needed e.g. when the wger api only sends a time but no date information.
*/
DateTime fromTime(String time) {
TimeOfDay stringToTime(String time) {
if (time == null) {
return null;
}
return DateTime.parse(DateFormat('yyyy-MM-dd').format(DateTime.now()).toString() + ' ' + time);
return TimeOfDay.fromDateTime(
DateTime.parse('2020-01-01 $time'),
);
}
/*
* Converts a datetime to time.
* Needed e.g. when the wger api only expects a time and no date information.
*/
String toTime(DateTime dateTime) {
if (dateTime == null) {
String timeToString(TimeOfDay time) {
if (time == null) {
return null;
}
return DateFormat.Hms().format(dateTime).toString();
return DefaultMaterialLocalizations().formatTimeOfDay(time, alwaysUse24HourFormat: true);
}

View File

@@ -155,6 +155,14 @@ class AppLocalizations {
);
}
String get time {
return Intl.message(
'Time',
name: 'time',
desc: 'The time of a meal or workout',
);
}
String get newEntry {
return Intl.message(
'New entry',

View File

@@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:intl/intl.dart';
import 'package:flutter/material.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/models/nutrition/meal_item.dart';
@@ -28,16 +28,11 @@ class Meal {
@JsonKey(required: true)
final int id;
@JsonKey(required: true, toJson: toTime, fromJson: fromTime)
final DateTime time;
/// returns the time component of the DateTime time as a string
String get getTime {
return DateFormat.jm().format(time).toString();
}
@JsonKey(required: true, toJson: timeToString, fromJson: stringToTime)
TimeOfDay time;
@JsonKey(required: true, name: 'meal_items')
final List<MealItem> mealItems;
List<MealItem> mealItems;
Meal({
this.id,

View File

@@ -10,16 +10,15 @@ Meal _$MealFromJson(Map<String, dynamic> json) {
$checkKeys(json, requiredKeys: const ['id', 'time', 'meal_items']);
return Meal(
id: json['id'] as int,
time: fromTime(json['time'] as String),
time: stringToTime(json['time'] as String),
mealItems: (json['meal_items'] as List)
?.map((e) =>
e == null ? null : MealItem.fromJson(e as Map<String, dynamic>))
?.map((e) => e == null ? null : MealItem.fromJson(e as Map<String, dynamic>))
?.toList(),
);
}
Map<String, dynamic> _$MealToJson(Meal instance) => <String, dynamic>{
'id': instance.id,
'time': toTime(instance.time),
'time': timeToString(instance.time),
'meal_items': instance.mealItems,
};

View File

@@ -114,7 +114,7 @@ class Exercises with ChangeNotifier {
//if (false) {
final exerciseData = json.decode(prefs.getString('exerciseData'));
if (DateTime.parse(exerciseData['expiresIn']).isAfter(DateTime.now())) {
exerciseData['results'].forEach((e) => _entries.add(Exercise.fromJson(e)));
exerciseData['exercises'].forEach((e) => _entries.add(Exercise.fromJson(e)));
log("Read exercise data from cache. Valid till ${exerciseData['expiresIn']}");
return;
}

View File

@@ -0,0 +1,106 @@
/*
* 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:flutter/material.dart';
import 'package:wger/helpers/json.dart';
import 'package:wger/locale/locales.dart';
import 'package:wger/models/nutrition/meal.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
class MealForm extends StatelessWidget {
Meal meal;
NutritionalPlan _plan;
MealForm(plan, [meal]) {
this._plan = plan;
this.meal = meal ?? Meal();
}
//MealForm(this._plan, {this.meal});
final _form = GlobalKey<FormState>();
final _timeController = TextEditingController(
text: timeToString(TimeOfDay.fromDateTime(DateTime.now())),
);
@override
Widget build(BuildContext context) {
return Container(
margin: EdgeInsets.all(20),
child: Form(
key: _form,
child: Column(
children: [
Text('tttttt'),
TextFormField(
decoration: InputDecoration(labelText: AppLocalizations.of(context).time),
controller: _timeController,
onTap: () async {
// Stop keyboard from appearing
FocusScope.of(context).requestFocus(new FocusNode());
// Open time picker
var pickedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
_timeController.text = timeToString(pickedTime);
},
onSaved: (newValue) {
meal.time = stringToTime(newValue);
},
onFieldSubmitted: (_) {},
),
ElevatedButton(
child: Text(AppLocalizations.of(context).save),
onPressed: () async {
if (!_form.currentState.validate()) {
return;
}
_form.currentState.save();
try {
//Provider.of<NutritionalPlans>(context, listen: false)
//.addMe(_plan)
// .addDay(Day(description: dayController.text, daysOfWeek: [1]), workout);
} catch (error) {
await showDialog(
context: context,
builder: (ctx) => AlertDialog(
title: Text('An error occurred!'),
content: Text('Something went wrong.'),
actions: <Widget>[
TextButton(
child: Text('Okay'),
onPressed: () {
Navigator.of(ctx).pop();
},
)
],
),
);
}
},
),
],
),
),
);
}
}

View File

@@ -58,17 +58,14 @@ class MealWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
//color: Colors.amber,
//width: double.infinity,
child: Card(
child: Column(
//mainAxisSize: MainAxisSize.max,
children: [
Container(
width: double.infinity,
decoration: BoxDecoration(color: Colors.black12),
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(_meal.getTime),
child: Text(_meal.time.format(context)),
),
..._meal.mealItems.map((item) => MealItemWidget(item)).toList(),
],

View File

@@ -21,6 +21,7 @@ import 'package:intl/intl.dart';
import 'package:wger/locale/locales.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/widgets/core/bottom_sheet.dart';
import 'package:wger/widgets/nutrition/forms.dart';
import 'package:wger/widgets/nutrition/meal.dart';
class NutritionalPlanDetailWidget extends StatefulWidget {
@@ -32,10 +33,6 @@ class NutritionalPlanDetailWidget extends StatefulWidget {
}
class _NutritionalPlanDetailWidgetState extends State<NutritionalPlanDetailWidget> {
Widget planForm = Form(
child: Text('forms come here...'),
);
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
@@ -61,7 +58,7 @@ class _NutritionalPlanDetailWidgetState extends State<NutritionalPlanDetailWidge
ElevatedButton(
child: Text(AppLocalizations.of(context).add),
onPressed: () {
showFormBottomSheet(context, 'Add meal form', planForm);
showFormBottomSheet(context, 'Add meal form', MealForm(widget._nutritionalPlan));
},
),
],