diff --git a/lib/models/body_weight/weight_entry.dart b/lib/models/body_weight/weight_entry.dart index 7b41c625..827ccf7d 100644 --- a/lib/models/body_weight/weight_entry.dart +++ b/lib/models/body_weight/weight_entry.dart @@ -29,7 +29,7 @@ class WeightEntry { @JsonKey(required: true, fromJson: stringToNum, toJson: numToString) late num weight = 0; - @JsonKey(required: true, toJson: dateToYYYYMMDD) + @JsonKey(required: true) late DateTime date; WeightEntry({this.id, weight, DateTime? date}) { diff --git a/lib/models/body_weight/weight_entry.g.dart b/lib/models/body_weight/weight_entry.g.dart index c1c690d5..8295b62b 100644 --- a/lib/models/body_weight/weight_entry.g.dart +++ b/lib/models/body_weight/weight_entry.g.dart @@ -21,5 +21,5 @@ WeightEntry _$WeightEntryFromJson(Map json) { Map _$WeightEntryToJson(WeightEntry instance) => { 'id': instance.id, 'weight': numToString(instance.weight), - 'date': dateToYYYYMMDD(instance.date), + 'date': instance.date.toIso8601String(), }; diff --git a/lib/screens/weight_screen.dart b/lib/screens/weight_screen.dart index 3110c3a5..6c91935c 100644 --- a/lib/screens/weight_screen.dart +++ b/lib/screens/weight_screen.dart @@ -32,8 +32,6 @@ class WeightScreen extends StatelessWidget { @override Widget build(BuildContext context) { - final lastWeightEntry = context.read().getNewestEntry(); - return Scaffold( appBar: EmptyAppBar(AppLocalizations.of(context).weight), floatingActionButton: FloatingActionButton( @@ -44,7 +42,7 @@ class WeightScreen extends StatelessWidget { FormScreen.routeName, arguments: FormScreenArguments( AppLocalizations.of(context).newEntry, - WeightForm(lastWeightEntry?.copyWith(id: null, date: DateTime.now())), + WeightForm(), ), ); }, diff --git a/lib/widgets/weight/forms.dart b/lib/widgets/weight/forms.dart index d91cdbea..755cc18d 100644 --- a/lib/widgets/weight/forms.dart +++ b/lib/widgets/weight/forms.dart @@ -21,38 +21,41 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:wger/helpers/consts.dart'; -import 'package:wger/helpers/date.dart'; -import 'package:wger/helpers/json.dart'; import 'package:wger/l10n/generated/app_localizations.dart'; import 'package:wger/models/body_weight/weight_entry.dart'; import 'package:wger/providers/body_weight.dart'; class WeightForm extends StatelessWidget { final _form = GlobalKey(); - final dateController = TextEditingController(); - final weightController = TextEditingController(); + final dateController = TextEditingController(text: ''); + final timeController = TextEditingController(text: ''); + final weightController = TextEditingController(text: ''); - late final WeightEntry _weightEntry; + final WeightEntry _weightEntry; - WeightForm([WeightEntry? weightEntry]) { - _weightEntry = weightEntry ?? WeightEntry(date: DateTime.now()); - weightController.text = ''; - dateController.text = dateToYYYYMMDD(_weightEntry.date)!; - } + WeightForm([WeightEntry? weightEntry]) + : _weightEntry = weightEntry ?? WeightEntry(date: DateTime.now()); @override Widget build(BuildContext context) { final numberFormat = NumberFormat.decimalPattern(Localizations.localeOf(context).toString()); + final dateFormat = DateFormat.yMd(Localizations.localeOf(context).languageCode); + final timeFormat = DateFormat.Hm(Localizations.localeOf(context).languageCode); if (weightController.text.isEmpty && _weightEntry.weight != 0) { weightController.text = numberFormat.format(_weightEntry.weight); } + if (dateController.text.isEmpty) { + dateController.text = dateFormat.format(_weightEntry.date); + } + if (timeController.text.isEmpty) { + timeController.text = TimeOfDay.fromDateTime(_weightEntry.date).format(context); + } return Form( key: _form, child: Column( children: [ - // Weight date TextFormField( key: const Key('dateInput'), // Stop keyboard from appearing @@ -72,24 +75,51 @@ class WeightForm extends StatelessWidget { initialDate: _weightEntry.date, firstDate: DateTime(DateTime.now().year - 10), lastDate: DateTime.now(), - selectableDayPredicate: (day) { - // Always allow the current initial date - if (day.isSameDayAs(_weightEntry.date)) { - return true; - } - - // if the date is known, don't allow it - return Provider.of(context, listen: false).findByDate(day) == - null; - }, ); if (pickedDate != null) { - dateController.text = dateToYYYYMMDD(pickedDate)!; + dateController.text = dateFormat.format(pickedDate); } }, onSaved: (newValue) { - _weightEntry.date = DateTime.parse(newValue!); + final date = dateFormat.parse(newValue!); + _weightEntry.date = _weightEntry.date.copyWith( + year: date.year, + month: date.month, + day: date.day, + ); + }, + ), + TextFormField( + key: const Key('timeInput'), + // Stop keyboard from appearing + readOnly: true, + decoration: InputDecoration( + labelText: AppLocalizations.of(context).time, + suffixIcon: const Icon( + Icons.access_time_outlined, + key: Key('clockIcon'), + ), + ), + enableInteractiveSelection: false, + controller: timeController, + onTap: () async { + final pickedTime = await showTimePicker( + context: context, + initialTime: TimeOfDay.fromDateTime(_weightEntry.date), + ); + + if (pickedTime != null) { + timeController.text = pickedTime.format(context); + } + }, + onSaved: (newValue) { + final time = timeFormat.parse(newValue!); + _weightEntry.date = _weightEntry.date.copyWith( + hour: time.hour, + minute: time.minute, + second: time.second, + ); }, ), diff --git a/lib/widgets/weight/weight_overview.dart b/lib/widgets/weight/weight_overview.dart index 0a39fb4b..404ef853 100644 --- a/lib/widgets/weight/weight_overview.dart +++ b/lib/widgets/weight/weight_overview.dart @@ -84,7 +84,7 @@ class WeightOverview extends StatelessWidget { subtitle: Text( DateFormat.yMd( Localizations.localeOf(context).languageCode, - ).format(currentEntry.date), + ).add_Hm().format(currentEntry.date), ), trailing: PopupMenuButton( itemBuilder: (BuildContext context) { diff --git a/test/core/settings_test.mocks.dart b/test/core/settings_test.mocks.dart index bad6f310..5f661123 100644 --- a/test/core/settings_test.mocks.dart +++ b/test/core/settings_test.mocks.dart @@ -1009,7 +1009,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i20.NutritionPlans @override _i18.Future<_i13.Ingredient?> searchIngredientWithBarcode(String? barcode) => (super.noSuchMethod( Invocation.method( - #searchIngredientWithCode, + #searchIngredientWithBarcode, [barcode], ), returnValue: _i18.Future<_i13.Ingredient?>.value(), diff --git a/test/nutrition/nutritional_meal_form_test.mocks.dart b/test/nutrition/nutritional_meal_form_test.mocks.dart index 8f61b4fc..ef8ea874 100644 --- a/test/nutrition/nutritional_meal_form_test.mocks.dart +++ b/test/nutrition/nutritional_meal_form_test.mocks.dart @@ -414,7 +414,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i8.NutritionPlansP @override _i9.Future<_i7.Ingredient?> searchIngredientWithBarcode(String? barcode) => (super.noSuchMethod( Invocation.method( - #searchIngredientWithCode, + #searchIngredientWithBarcode, [barcode], ), returnValue: _i9.Future<_i7.Ingredient?>.value(), diff --git a/test/nutrition/nutritional_plan_form_test.mocks.dart b/test/nutrition/nutritional_plan_form_test.mocks.dart index 979f854f..5d42b480 100644 --- a/test/nutrition/nutritional_plan_form_test.mocks.dart +++ b/test/nutrition/nutritional_plan_form_test.mocks.dart @@ -414,7 +414,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i8.NutritionPlansP @override _i9.Future<_i7.Ingredient?> searchIngredientWithBarcode(String? barcode) => (super.noSuchMethod( Invocation.method( - #searchIngredientWithCode, + #searchIngredientWithBarcode, [barcode], ), returnValue: _i9.Future<_i7.Ingredient?>.value(), diff --git a/test/weight/weight_form_test.dart b/test/weight/weight_form_test.dart index 9a1bfaa2..0a821a37 100644 --- a/test/weight/weight_form_test.dart +++ b/test/weight/weight_form_test.dart @@ -34,11 +34,21 @@ void main() { ); } - testWidgets('The form is prefilled with the data from an entry', (WidgetTester tester) async { + testWidgets('Correctly prefills and localizes the data - en', (WidgetTester tester) async { await tester.pumpWidget(createWeightForm(weightEntry: testWeightEntry1)); await tester.pumpAndSettle(); - expect(find.text('2021-01-01'), findsOneWidget); + expect(find.text('1/1/2021'), findsOneWidget); + expect(find.text('3:30 PM'), findsOneWidget); + expect(find.text('80'), findsOneWidget); + }); + + testWidgets('Correctly prefills and localizes the data - de', (WidgetTester tester) async { + await tester.pumpWidget(createWeightForm(weightEntry: testWeightEntry1, locale: 'de')); + await tester.pumpAndSettle(); + + expect(find.text('1.1.2021'), findsOneWidget); + expect(find.text('15:30'), findsOneWidget); expect(find.text('80'), findsOneWidget); }); diff --git a/test/weight/weight_model_test.dart b/test/weight/weight_model_test.dart index 0866d83e..ac97ccf6 100644 --- a/test/weight/weight_model_test.dart +++ b/test/weight/weight_model_test.dart @@ -22,11 +22,15 @@ import 'package:wger/models/body_weight/weight_entry.dart'; void main() { group('fetchPost', () { test('Test that the weight entries are correctly converted to json', () { - WeightEntry weightEntry = WeightEntry(id: 1, weight: 80, date: DateTime(2020, 12, 31)); - expect(weightEntry.toJson(), {'id': 1, 'weight': '80', 'date': '2020-12-31'}); + expect( + WeightEntry(id: 1, weight: 80, date: DateTime(2020, 12, 31, 12, 34)).toJson(), + {'id': 1, 'weight': '80', 'date': '2020-12-31T12:34:00.000'}, + ); - weightEntry = WeightEntry(id: 2, weight: 70.2, date: DateTime(2020, 12, 01)); - expect(weightEntry.toJson(), {'id': 2, 'weight': '70.2', 'date': '2020-12-01'}); + expect( + WeightEntry(id: 2, weight: 70.2, date: DateTime(2020, 12, 01)).toJson(), + {'id': 2, 'weight': '70.2', 'date': '2020-12-01T00:00:00.000'}, + ); }); test('Test that the weight entries are correctly converted from json', () { diff --git a/test/weight/weight_provider_test.dart b/test/weight/weight_provider_test.dart index 08ce8c66..65938435 100644 --- a/test/weight/weight_provider_test.dart +++ b/test/weight/weight_provider_test.dart @@ -70,8 +70,10 @@ void main() { path: 'api/v2/weightentry/', ); when(mockBaseProvider.makeUrl(any, query: anyNamed('query'))).thenReturn(uri); - when(mockBaseProvider.post({'id': null, 'weight': '80', 'date': '2021-01-01'}, uri)) - .thenAnswer((_) => Future.value({'id': 25, 'date': '2021-01-01', 'weight': '80'})); + when(mockBaseProvider.post( + {'id': null, 'weight': '80', 'date': '2021-01-01T00:00:00.000'}, + uri, + )).thenAnswer((_) => Future.value({'id': 25, 'date': '2021-01-01', 'weight': '80'})); // Act final BodyWeightProvider provider = BodyWeightProvider(mockBaseProvider); diff --git a/test/weight/weight_screen_test.dart b/test/weight/weight_screen_test.dart index 9488ad12..b47f2ba7 100644 --- a/test/weight/weight_screen_test.dart +++ b/test/weight/weight_screen_test.dart @@ -43,7 +43,6 @@ void main() { setUp(() { mockWeightProvider = MockBodyWeightProvider(); when(mockWeightProvider.items).thenReturn(getWeightEntries()); - when(mockWeightProvider.getNewestEntry()).thenReturn(null); mockUserProvider = MockUserProvider(); when(mockUserProvider.profile).thenReturn(tProfile1); diff --git a/test/weight/weight_screen_test.mocks.dart b/test/weight/weight_screen_test.mocks.dart index 7e1e2737..f0fb8ed9 100644 --- a/test/weight/weight_screen_test.mocks.dart +++ b/test/weight/weight_screen_test.mocks.dart @@ -739,7 +739,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i16.NutritionPlans @override _i11.Future<_i9.Ingredient?> searchIngredientWithBarcode(String? barcode) => (super.noSuchMethod( Invocation.method( - #searchIngredientWithCode, + #searchIngredientWithBarcode, [barcode], ), returnValue: _i11.Future<_i9.Ingredient?>.value(), diff --git a/test_data/body_weight.dart b/test_data/body_weight.dart index b9f89200..ac806a69 100644 --- a/test_data/body_weight.dart +++ b/test_data/body_weight.dart @@ -18,8 +18,8 @@ import 'package:wger/models/body_weight/weight_entry.dart'; -final testWeightEntry1 = WeightEntry(id: 1, weight: 80, date: DateTime(2021, 01, 01)); -final testWeightEntry2 = WeightEntry(id: 2, weight: 81, date: DateTime(2021, 01, 10)); +final testWeightEntry1 = WeightEntry(id: 1, weight: 80, date: DateTime(2021, 01, 01, 15, 30)); +final testWeightEntry2 = WeightEntry(id: 2, weight: 81, date: DateTime(2021, 01, 10, 10, 0)); List getWeightEntries() { return [testWeightEntry1, testWeightEntry2];