Commit 7a6fea6
Changed files (6)
app
lib
features
measurement_list
l10n
test
app/lib/features/input/add_bodyweight_dialoge.dart
@@ -0,0 +1,42 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:health_data_store/health_data_store.dart';
+
+/// A simple dialoge to enter one weight value in kg.
+///
+/// Returns a [Weight] on submission.
+class AddBodyweightDialoge extends StatelessWidget {
+ /// Create a simple dialoge to enter one weight value in kg.
+ const AddBodyweightDialoge({super.key});
+
+ @override
+ Widget build(BuildContext context) => Dialog(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 6.0, horizontal: 2.0),
+ child: TextFormField(
+ autofocus: true,
+ decoration: InputDecoration(
+ labelText: AppLocalizations.of(context)!.weight,
+ suffix: const Text('kg'),
+ ),
+ inputFormatters: [FilteringTextInputFormatter.allow(RegExp('[0-9,.]'))],
+ keyboardType: const TextInputType.numberWithOptions(decimal: true),
+ autovalidateMode: AutovalidateMode.onUnfocus,
+ validator: (value) {
+ if (value == null
+ || value.isEmpty
+ || double.tryParse(value) == null
+ ) {
+ return AppLocalizations.of(context)!.errNaN;
+ }
+ return null;
+ },
+ onFieldSubmitted: (text) {
+ final value = double.tryParse(text);
+ if (value != null) Navigator.of(context).pop(Weight.kg(value));
+ },
+ ),
+ ),
+ );
+}
app/lib/features/input/add_measurement_dialoge.dart
@@ -2,6 +2,7 @@ import 'dart:async';
import 'package:blood_pressure_app/components/fullscreen_dialoge.dart';
import 'package:blood_pressure_app/features/bluetooth/bluetooth_input.dart';
+import 'package:blood_pressure_app/features/input/add_bodyweight_dialoge.dart';
import 'package:blood_pressure_app/features/input/forms/date_time_form.dart';
import 'package:blood_pressure_app/features/settings/tiles/color_picker_list_tile.dart';
import 'package:blood_pressure_app/model/blood_pressure/pressure_unit.dart';
@@ -403,6 +404,21 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
),
),
),
+
+ if (settings.weightInput)
+ ListTile(
+ title: Text(localizations.enterWeight),
+ leading: const Icon(Icons.scale),
+ trailing: const Icon(Icons.arrow_forward_ios),
+ onTap: () async {
+ final repo = context.read<BodyweightRepository>();
+ final weight = await showDialog<Weight>(context: context, builder: (_) => const AddBodyweightDialoge());
+ if (weight != null) {
+ await repo.add(BodyweightRecord(time: time, weight: weight));
+ if (context.mounted) Navigator.pop(context);
+ }
+ },
+ ),
],
),
),
app/lib/features/measurement_list/weight_list.dart
@@ -29,7 +29,7 @@ class WeightList extends StatelessWidget {
);
},
);
- }
+ }// TODO: delete
String _buildWeightText(Weight w) {
String weightStr = w.kg.toStringAsFixed(2);
app/lib/l10n/app_en.arb
@@ -518,5 +518,9 @@
"errCantCreateArchive": "Can''t create archive. Please report the bug if possible.",
"@errCantCreateArchive": {},
"activateWeightFeatures": "Activate weight related features",
- "@weightInput": {}
+ "@weightInput": {},
+ "weight": "Weight",
+ "@weight": {},
+ "enterWeight": "Enter weight",
+ "@enterWeight": {}
}
\ No newline at end of file
app/test/features/input/add_bodyweight_dialoge_test.dart
@@ -0,0 +1,49 @@
+import 'package:blood_pressure_app/features/input/add_bodyweight_dialoge.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:health_data_store/health_data_store.dart';
+
+import '../../util.dart';
+
+void main() {
+ testWidgets('shows weight input weight', (tester) async {
+ await tester.pumpWidget(materialApp(const AddBodyweightDialoge()));
+ final localizations = await AppLocalizations.delegate.load(const Locale('en'));
+
+ expect(find.byType(TextFormField), findsOneWidget);
+ expect(find.text(localizations.weight), findsOneWidget);
+ expect(find.text('kg'), findsOneWidget);
+
+ await tester.enterText(find.byType(TextFormField), '123.45');
+ });
+ testWidgets('error on invalid input', (tester) async {
+ await tester.pumpWidget(materialApp(const AddBodyweightDialoge()));
+ final localizations = await AppLocalizations.delegate.load(const Locale('en'));
+
+ expect(find.text(localizations.errNaN), findsNothing);
+
+ await tester.enterText(find.byType(TextFormField), 'invalid input');
+ await tester.testTextInput.receiveAction(TextInputAction.done);
+ await tester.pumpAndSettle();
+
+ expect(find.text(localizations.errNaN), findsOneWidget);
+ });
+ testWidgets('creates weight from input', (tester) async {
+ Weight? res;
+ await tester.pumpWidget(materialApp(Builder(
+ builder: (context) => GestureDetector(
+ onTap: () async => res = await showDialog<Weight>(context: context, builder: (_) => const AddBodyweightDialoge()),
+ child: const Text('X'),
+ ),
+ )));
+ await tester.tap(find.text('X'));
+ await tester.pumpAndSettle();
+
+ await tester.enterText(find.byType(TextFormField), '123.45');
+ await tester.testTextInput.receiveAction(TextInputAction.done);
+ await tester.pumpAndSettle();
+
+ expect(res, Weight.kg(123.45));
+ });
+}
app/test/features/input/add_measurement_dialoge_test.dart
@@ -1,4 +1,5 @@
import 'package:blood_pressure_app/features/bluetooth/bluetooth_input.dart';
+import 'package:blood_pressure_app/features/input/add_bodyweight_dialoge.dart';
import 'package:blood_pressure_app/features/input/add_measurement_dialoge.dart';
import 'package:blood_pressure_app/features/settings/tiles/color_picker_list_tile.dart';
import 'package:blood_pressure_app/model/storage/settings_store.dart';
@@ -634,5 +635,29 @@ void main() {
expect(find.descendant(of: focusedTextFormField, matching: find.text('Pulse')), findsNothing);
expect(find.descendant(of: focusedTextFormField, matching: find.text('Note (optional)')), findsWidgets);
});
+ testWidgets('opens weight input if necessary', (tester) async {
+ final repo = MockBodyweightRepository();
+ await tester.pumpWidget(appBase(Builder(
+ builder: (context) => TextButton(onPressed: () => showAddEntryDialoge(context, MockMedRepo([])), child: const Text('X'))
+ ), settings: Settings(weightInput: true), weightRepo: repo));
+ final localizations = await AppLocalizations.delegate.load(const Locale('en'));
+ await tester.tap(find.text('X'));
+ await tester.pumpAndSettle();
+
+ expect(find.text(localizations.enterWeight), findsOneWidget);
+ expect(find.byIcon(Icons.scale), findsOneWidget);
+ await tester.tap(find.text(localizations.enterWeight));
+ await tester.pumpAndSettle();
+
+ expect(repo.data, isEmpty);
+ await tester.enterText(find.descendant(
+ of: find.byType(AddBodyweightDialoge),
+ matching: find.byType(TextFormField)
+ ), '123.45');
+ await tester.testTextInput.receiveAction(TextInputAction.done);
+ await tester.pumpAndSettle();
+ expect(repo.data, hasLength(1));
+ expect(repo.data[0].weight, Weight.kg(123.45));
+ });
});
}