Commit e57c446
Changed files (2)
lib
components
dialoges
lib/components/dialoges/add_measurement_dialoge.dart
@@ -40,7 +40,9 @@ class AddEntryDialoge extends StatefulWidget {
}
class _AddEntryDialogeState extends State<AddEntryDialoge> {
- final formKey = GlobalKey<FormState>();
+ final recordFormKey = GlobalKey<FormState>();
+ final medicationFormKey = GlobalKey<FormState>();
+
final sysFocusNode = FocusNode();
final diaFocusNode = FocusNode();
final pulFocusNode = FocusNode();
@@ -80,6 +82,14 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
/// Newlines in the note field.
int _noteCurrentNewLineCount = 0;
+ /// Whether any of the measurement fields was once non-empty.
+ ///
+ /// Those fields are:
+ /// - sys, dia, pul
+ /// - note
+ /// - color
+ bool _measurementFormActive = false;
+
@override
void initState() {
super.initState();
@@ -109,7 +119,7 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
if (event is! KeyDownEvent) return false;
final isBackspace = event.logicalKey.keyId == 0x00100000008;
if (!isBackspace) return false;
- formKey.currentState?.save();
+ recordFormKey.currentState?.save(); // TODO: why?
if (diaFocusNode.hasFocus && diastolic == null
|| pulFocusNode.hasFocus && pulse == null
|| noteFocusNode.hasFocus && (notes?.isEmpty ?? true)
@@ -148,6 +158,7 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
},
);
+ /// Build a input for values in the measurement form (sys, dia, pul).
Widget _buildValueInput(AppLocalizations localizations, {
int? initialValue,
String? labelText,
@@ -168,19 +179,14 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
onSaved: onSaved,
controller: controller,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
- onChanged: (String? value) {
- if (value != null
- && value.isNotEmpty
+ onChanged: (String value) {
+ if (value.isNotEmpty) _measurementFormActive = true;
+ if (value.isNotEmpty
&& (int.tryParse(value) ?? -1) > 40) {
FocusScope.of(context).nextFocus();
}
},
validator: (String? value) {
- // Indicates that only a medicine intake is wanted.
- if (_showMedicineDosisInput && medicineDosis != null &&
- medicineId != null && systolic == null && diastolic == null &&
- pulse == null && notes == null && needlePin == null) return null;
-
if (!widget.settings.allowMissingValues
&& (value == null
|| value.isEmpty
@@ -214,12 +220,24 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
final localizations = AppLocalizations.of(context)!;
return FullscreenDialoge(
onActionButtonPressed: () {
- if (formKey.currentState?.validate() ?? false) {
- formKey.currentState?.save();
- MedicineIntake? intake;
+ assert(time != null);
+
+ BloodPressureRecord? record;
+ if (_measurementFormActive && (recordFormKey.currentState?.validate() ?? false)) {
+ recordFormKey.currentState?.save();
+ if (systolic != null || diastolic != null || pulse != null
+ || (notes ?? '').isNotEmpty || needlePin != null) {
+ record = BloodPressureRecord(time, systolic, diastolic, pulse,
+ notes ?? '', needlePin: needlePin,);
+ }
+ }
+
+ MedicineIntake? intake;
+ if (_showMedicineDosisInput && (medicationFormKey.currentState?.validate() ?? false)) {
+ medicationFormKey.currentState?.save();
if (_showMedicineDosisInput
&& medicineDosis != null
- && medicineId != null) {
+ && medicineId != null) { // TODO: check if this extra condition is needed
intake = MedicineIntake(
timestamp: time,
medicine: medications
@@ -227,98 +245,108 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
dosis: medicineDosis!,
);
}
- BloodPressureRecord? record;
- if (systolic != null || diastolic != null || pulse != null
- || (notes ?? '').isNotEmpty || needlePin != null) {
- record = BloodPressureRecord(time, systolic, diastolic, pulse,
- notes ?? '', needlePin: needlePin,);
- }
+ }
+ if (record != null && intake != null) {
+ Navigator.of(context).pop((record, intake));
+ }
+ if (record == null && !_measurementFormActive && intake != null) {
+ Navigator.of(context).pop((record, intake));
+ }
+ if (record != null && intake == null && medicineId == null) {
Navigator.of(context).pop((record, intake));
}
},
actionButtonText: localizations.btnSave,
bottomAppBar: widget.settings.bottomAppBars,
body: SizeChangedLayoutNotifier(
- child: Form(
- key: formKey,
- child: ListView(
- padding: const EdgeInsets.symmetric(horizontal: 8),
- children: [
- if (widget.settings.allowManualTimeInput)
- _buildTimeInput(localizations),
- const SizedBox(height: 16,),
- Row(
- mainAxisSize: MainAxisSize.min,
+ child: ListView(
+ padding: const EdgeInsets.symmetric(horizontal: 8),
+ children: [
+ if (widget.settings.allowManualTimeInput)
+ _buildTimeInput(localizations),
+ Form(
+ key: recordFormKey,
+ child: Column(
children: [
- _buildValueInput(localizations,
- focusNode: sysFocusNode,
- labelText: localizations.sysLong,
- controller: sysController,
- onSaved: (value) =>
- setState(() => systolic = int.tryParse(value ?? '')),
+ const SizedBox(height: 16,),
+ Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ _buildValueInput(localizations,
+ focusNode: sysFocusNode,
+ labelText: localizations.sysLong,
+ controller: sysController,
+ onSaved: (value) =>
+ setState(() => systolic = int.tryParse(value ?? '')),
+ ),
+ const SizedBox(width: 16,),
+ _buildValueInput(localizations,
+ labelText: localizations.diaLong,
+ initialValue: widget.initialRecord?.diastolic,
+ onSaved: (value) =>
+ setState(() => diastolic = int.tryParse(value ?? '')),
+ focusNode: diaFocusNode,
+ validator: (value) {
+ if (widget.settings.validateInputs
+ && (int.tryParse(value ?? '') ?? 0)
+ >= (int.tryParse(sysController.text) ?? 1)
+ ) {
+ return AppLocalizations.of(context)?.errDiaGtSys;
+ }
+ return null;
+ },
+ ),
+ const SizedBox(width: 16,),
+ _buildValueInput(localizations,
+ labelText: localizations.pulLong,
+ initialValue: widget.initialRecord?.pulse,
+ focusNode: pulFocusNode,
+ onSaved: (value) =>
+ setState(() => pulse = int.tryParse(value ?? '')),
+ ),
+ ],
),
- const SizedBox(width: 16,),
- _buildValueInput(localizations,
- labelText: localizations.diaLong,
- initialValue: widget.initialRecord?.diastolic,
- onSaved: (value) =>
- setState(() => diastolic = int.tryParse(value ?? '')),
- focusNode: diaFocusNode,
- validator: (value) {
- if (widget.settings.validateInputs
- && (int.tryParse(value ?? '') ?? 0)
- >= (int.tryParse(sysController.text) ?? 1)
- ) {
- return AppLocalizations.of(context)?.errDiaGtSys;
- }
- return null;
- },
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 16),
+ child: TextFormField(
+ initialValue: widget.initialRecord?.notes,
+ focusNode: noteFocusNode,
+ decoration: InputDecoration(
+ labelText: localizations.addNote,
+ ),
+ minLines: 1,
+ maxLines: 4,
+ onChanged: (value) {
+ if (value.isNotEmpty) _measurementFormActive = true;
+ final newLineCount = value.split('\n').length;
+ if (_noteCurrentNewLineCount != newLineCount) {
+ _noteCurrentNewLineCount = newLineCount;
+ Material.of(context).markNeedsPaint();
+ }
+ },
+ onSaved: (value) => setState(() => notes = value),
+ ),
),
- const SizedBox(width: 16,),
- _buildValueInput(localizations,
- labelText: localizations.pulLong,
- initialValue: widget.initialRecord?.pulse,
- focusNode: pulFocusNode,
- onSaved: (value) =>
- setState(() => pulse = int.tryParse(value ?? '')),
+ ColorSelectionListTile(
+ title: Text(localizations.color),
+ onMainColorChanged: (Color value) {
+ setState(() {
+ _measurementFormActive = true;
+ needlePin = (value == Colors.transparent) ? null
+ : MeasurementNeedlePin(value);
+ });
+ },
+ initialColor: needlePin?.color ?? Colors.transparent,
+ shape: _buildShapeBorder(needlePin?.color),
),
],
),
- Padding(
- padding: const EdgeInsets.symmetric(vertical: 16),
- child: TextFormField(
- initialValue: widget.initialRecord?.notes,
- focusNode: noteFocusNode,
- decoration: InputDecoration(
- labelText: localizations.addNote,
- ),
- minLines: 1,
- maxLines: 4,
- onChanged: (value) {
- final newLineCount = value.split('\n').length;
- if (_noteCurrentNewLineCount != newLineCount) {
- _noteCurrentNewLineCount = newLineCount;
- Material.of(context).markNeedsPaint();
- }
-
- },
- onSaved: (value) => setState(() => notes = value),
- ),
- ),
- ColorSelectionListTile(
- title: Text(localizations.color),
- onMainColorChanged: (Color value) {
- setState(() {
- needlePin = (value == Colors.transparent) ? null
- : MeasurementNeedlePin(value);
- });
- },
- initialColor: needlePin?.color ?? Colors.transparent,
- shape: _buildShapeBorder(needlePin?.color),
- ),
- if (medications.isNotEmpty && widget.initialRecord == null)
- Padding(
+ ),
+ if (medications.isNotEmpty && widget.initialRecord == null)
+ Form(
+ key: medicationFormKey,
+ child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Row(
children: [
@@ -336,7 +364,7 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
DropdownMenuItem(
child: Text(localizations.noMedication),
),
- ],
+ ], // TODO: auto select dosis on pick
onChanged: (v) {
setState(() {
if (v != null) {
@@ -361,13 +389,15 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
labelText: localizations.dosis,
),
keyboardType: TextInputType.number,
- onSaved: (value) => setState(() {
- final dosis = int.tryParse(value ?? '')?.toDouble()
- ?? double.tryParse(value ?? '');
- if(dosis != null && dosis > 0) medicineDosis = dosis;
- }),
+ onChanged: (value) {
+ setState(() {
+ final dosis = int.tryParse(value)?.toDouble()
+ ?? double.tryParse(value);
+ if(dosis != null && dosis > 0) medicineDosis = dosis;
+ });
+ },
inputFormatters: [FilteringTextInputFormatter.allow(
- RegExp(r'([0-9]+(\.([0-9]*))?)'),),],
+ RegExp(r'([0-9]+(\.([0-9]*))?)'),),],
validator: (String? value) {
if (!_showMedicineDosisInput) return null;
if (((int.tryParse(value ?? '')?.toDouble()
@@ -378,12 +408,12 @@ class _AddEntryDialogeState extends State<AddEntryDialoge> {
},
),
),
-
+
],
),
),
- ],
- ),
+ ),
+ ]
),
),
);
pubspec.lock
@@ -5,18 +5,18 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
- sha256: "36a321c3d2cbe01cbcb3540a87b8843846e0206df3e691fa7b23e19e78de6d49"
+ sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051
url: "https://pub.dev"
source: hosted
- version: "65.0.0"
+ version: "64.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
- sha256: dfe03b90ec022450e22513b5e5ca1f01c0c01de9c3fba2f7fd233cb57a6b9a07
+ sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893"
url: "https://pub.dev"
source: hosted
- version: "6.3.0"
+ version: "6.2.0"
archive:
dependency: transitive
description:
@@ -325,22 +325,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.0"
- leak_tracker:
- dependency: transitive
- description:
- name: leak_tracker
- sha256: "04be76c4a4bb50f14904e64749237e541e7c7bcf7ec0b196907322ab5d2fc739"
- url: "https://pub.dev"
- source: hosted
- version: "9.0.16"
- leak_tracker_testing:
- dependency: transitive
- description:
- name: leak_tracker_testing
- sha256: b06739349ec2477e943055aea30172c5c7000225f79dad4702e2ec0eda79a6ff
- url: "https://pub.dev"
- source: hosted
- version: "1.0.5"
lints:
dependency: transitive
description:
@@ -377,18 +361,18 @@ packages:
dependency: transitive
description:
name: material_color_utilities
- sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
+ sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev"
source: hosted
- version: "0.8.0"
+ version: "0.5.0"
meta:
dependency: transitive
description:
name: meta
- sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
+ sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
url: "https://pub.dev"
source: hosted
- version: "1.11.0"
+ version: "1.10.0"
mockito:
dependency: "direct dev"
description:
@@ -786,14 +770,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
- vm_service:
- dependency: transitive
- description:
- name: vm_service
- sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
- url: "https://pub.dev"
- source: hosted
- version: "13.0.0"
watcher:
dependency: transitive
description:
@@ -806,10 +782,10 @@ packages:
dependency: transitive
description:
name: web
- sha256: edc8a9573dd8c5a83a183dae1af2b6fd4131377404706ca4e5420474784906fa
+ sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
url: "https://pub.dev"
source: hosted
- version: "0.4.0"
+ version: "0.3.0"
win32:
dependency: transitive
description: