Commit e57c446

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2024-02-02 16:44:54
fix saving medicine intakes without defaults
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 29ec024
Changed files (2)
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: