Skip to content

Commit

Permalink
Merge pull request #105 from NobodyForNothing/54-add-measurements-in-…
Browse files Browse the repository at this point in the history
…the-future

Fix selecting a time of day after the current time
  • Loading branch information
derdilla authored Jul 18, 2023
2 parents c725a8e + 0366174 commit 2b02c7d
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 9 deletions.
5 changes: 5 additions & 0 deletions lib/components/date_time_picker.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';

/// First shows a DatePicker for the day then shows a TimePicker for the time of day.
///
/// As per the decision of the material design team a TimePicker isn't able to limit the range
/// (https://github.com/flutter/flutter/issues/23717#issuecomment-966601311), therefore a manual check for the time of
/// day will be needed. Please refer to the validator on the AddMeasurementPage for an example
Future<DateTime?> showDateTimePicker({
required BuildContext context,
DateTime? initialDate,
Expand Down
3 changes: 2 additions & 1 deletion lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -336,5 +336,6 @@
"last30Days": "30 days",
"@last30Days": {},
"allowMissingValues": "Allow missing values",
"@allowMissingValues": {}
"@allowMissingValues": {},
"errTimeAfterNow": "The selected time of day is after this moment. We have automatically reset it to the current time. You can disable this validation in the settings!"
}
25 changes: 17 additions & 8 deletions lib/screens/add_measurement.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,23 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
if (settings.allowManualTimeInput) {
return GestureDetector(
onTap: () async {
final now = DateTime.now();
final selectionEnd = now.copyWith(minute: now.minute+5);
final messenger = ScaffoldMessenger.of(context);
final errTimeAfterNow = AppLocalizations.of(context)!.errTimeAfterNow;
var selectedTime = await showDateTimePicker(
context: context,
firstDate: DateTime.fromMillisecondsSinceEpoch(0),
lastDate: DateTime.now().copyWith(second: DateTime.now().second + 1),
lastDate: selectionEnd,
initialDate: _time);
if (selectedTime != null) {
if (settings.validateInputs && selectedTime.isAfter(selectionEnd)) {
messenger.showSnackBar(SnackBar(content: Text(errTimeAfterNow)));
if (selectedTime.hour > now.hour) selectedTime = selectedTime.copyWith(hour: now.hour);
if (selectedTime.minute > now.minute) selectedTime = selectedTime.copyWith(minute: now.minute);
} // validation for first date is not needed here as intervall starts at 00:00
setState(() {
_time = selectedTime;
_time = selectedTime!;
});
}
},
Expand All @@ -100,7 +109,7 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
initialValue: (_systolic ?? '').toString(),
hintText: AppLocalizations.of(context)!.sysLong,
basicValidation: !settings.allowMissingValues,
preValidion: (v) => _systolic = int.tryParse(v ?? ''),
preValidation: (v) => _systolic = int.tryParse(v ?? ''),
focusNode: _sysFocusNode,
additionalValidator: (String? value) {
_systolic = int.tryParse(value ?? '');
Expand All @@ -112,7 +121,7 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
initialValue: (_diastolic ?? '').toString(),
hintText: AppLocalizations.of(context)!.diaLong,
basicValidation: !settings.allowMissingValues,
preValidion: (v) => _diastolic = int.tryParse(v ?? ''),
preValidation: (v) => _diastolic = int.tryParse(v ?? ''),
additionalValidator: (String? value) {
if (settings.validateInputs && (int.tryParse(value ?? '') ?? 0) >= (_systolic ?? 1)) {
return AppLocalizations.of(context)?.errDiaGtSys;
Expand All @@ -126,7 +135,7 @@ class _AddMeasurementPageState extends State<AddMeasurementPage> {
initialValue: (_pulse ?? '').toString(),
hintText: AppLocalizations.of(context)!.pulLong,
basicValidation: !settings.allowMissingValues,
preValidion: (v) => _pulse = int.tryParse(v ?? ''),
preValidation: (v) => _pulse = int.tryParse(v ?? ''),
additionalValidator: (String? value) {
if (settings.validateInputs && (int.tryParse(value ?? '') ?? 0) >= 600) { // https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3273956/
return AppLocalizations.of(context)?.errUnrealistic;
Expand Down Expand Up @@ -202,11 +211,11 @@ class ValueInput extends StatelessWidget {
final String hintText;
final FocusNode? focusNode;
final bool basicValidation;
final void Function(String?)? preValidion;
final void Function(String?)? preValidation;
final FormFieldValidator<String> additionalValidator;

const ValueInput({super.key, required this.initialValue, required this.hintText, this.focusNode, this.basicValidation = true,
this.preValidion, required this.additionalValidator});
this.preValidation, required this.additionalValidator});

@override
Widget build(BuildContext context) {
Expand All @@ -223,7 +232,7 @@ class ValueInput extends StatelessWidget {
}
},
validator: (String? value) {
if (preValidion != null) preValidion!(value);
if (preValidation != null) preValidation!(value);
if (basicValidation) {
if (value == null || value.isEmpty || (int.tryParse(value) == null)) {
return AppLocalizations.of(context)?.errNaN;
Expand Down

0 comments on commit 2b02c7d

Please sign in to comment.