Commit 2272b92

derdilla <82763757+NobodyForNothing@users.noreply.github.com>
2023-12-27 15:55:49
implement medicine adding
Signed-off-by: derdilla <82763757+NobodyForNothing@users.noreply.github.com>
1 parent 6a9e373
Changed files (5)
lib/components/dialoges/add_medication_dialoge.dart
@@ -0,0 +1,104 @@
+import 'package:blood_pressure_app/components/dialoges/fullscreen_dialoge.dart';
+import 'package:blood_pressure_app/components/settings/color_picker_list_tile.dart';
+import 'package:blood_pressure_app/model/blood_pressure/medicine/medicine.dart';
+import 'package:blood_pressure_app/model/storage/settings_store.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_gen/gen_l10n/app_localizations.dart';
+
+class AddMedicationDialoge extends StatefulWidget {
+  const AddMedicationDialoge({super.key,
+    required this.settings
+  });
+
+  final Settings settings;
+
+  @override
+  State<AddMedicationDialoge> createState() => _AddMedicationDialogeState();
+}
+
+class _AddMedicationDialogeState extends State<AddMedicationDialoge> {
+  final formKey = GlobalKey<FormState>();
+  final nameFocusNode = FocusNode();
+
+  Color _color = Colors.transparent;
+  String? _designation;
+  double? _defaultDosis;
+
+
+  @override
+  void initState() {
+    super.initState();
+    nameFocusNode.requestFocus();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final localizations = AppLocalizations.of(context)!;
+    return FullscreenDialoge(
+      actionButtonText: localizations.btnSave,
+      onActionButtonPressed: () {
+        formKey.currentState?.save();
+        Navigator.of(context).pop(Medicine(
+          widget.settings.highestMedIndex,
+          designation: _designation ?? '',
+          color: _color,
+          defaultDosis: _defaultDosis
+        ));
+      },
+      bottomAppBar: widget.settings.bottomAppBars,
+      body: Form(
+        key: formKey,
+        child: ListView(
+          children: [
+            TextFormField(
+              focusNode: nameFocusNode,
+              decoration: _getInputDecoration(context, localizations.name),
+              onSaved: (value) => _designation = value,
+            ),
+            const SizedBox(height: 8,),
+            ColorSelectionListTile(
+              title: Text(localizations.color),
+              onMainColorChanged: (value) => setState(() {
+                _color = value;
+              }),
+              initialColor: _color,
+              shape: _getBorder(),
+            ),
+            const SizedBox(height: 8,),
+            TextFormField(
+              keyboardType: TextInputType.number,
+              decoration: _getInputDecoration(context, localizations.defaultDosis),
+              inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'([0-9]+(\.([0-9]*))?)')),],
+              onSaved: (value) => _defaultDosis = double.tryParse(value ?? '')
+                  ?? int.tryParse(value ?? '')?.toDouble(),
+            ),
+          ],
+        ),
+      ),
+    );
+  }
+
+  InputDecoration _getInputDecoration(BuildContext context, String? labelText) {
+    return InputDecoration(
+      hintText: labelText,
+      labelText: labelText,
+      errorMaxLines: 5,
+      border: _getBorder(),
+      enabledBorder: _getBorder(),
+    );
+  }
+
+  OutlineInputBorder _getBorder() => OutlineInputBorder(
+      borderSide: BorderSide(
+        width: 3,
+        color: Theme.of(context).primaryColor,
+      ),
+      borderRadius: BorderRadius.circular(20)
+  );
+}
+
+Future<Medicine?> showAddMedicineDialoge(BuildContext context, Settings settings) =>
+  showDialog<Medicine?>(context: context, builder: (context) => Dialog.fullscreen(
+    child: AddMedicationDialoge(settings: settings),
+  ));
\ No newline at end of file
lib/components/dialoges/fullscreen_dialoge.dart
@@ -7,7 +7,7 @@ class FullscreenDialoge extends StatelessWidget {
     this.body,
     required this.actionButtonText,
     this.onActionButtonPressed,
-    this.bottomAppBar = false,
+    required this.bottomAppBar,
     this.closeIcon = Icons.close,
   });
 
lib/l10n/app_en.arb
@@ -492,5 +492,9 @@
   "medications": "Medications",
   "@medications": {},
   "addMedication": "Add medication",
-  "@addMedication": {}
+  "@addMedication": {},
+  "name": "Name",
+  "@name": {},
+  "defaultDosis": "default dosis",
+  "@defaultDosis": {}
 }
lib/model/storage/settings_store.dart
@@ -39,6 +39,7 @@ class Settings extends ChangeNotifier {
     bool? useLegacyList,
     bool? bottomAppBars,
     List<Medicine>? medications,
+    int? highestMedIndex,
   }) {
     if (accentColor != null) _accentColor = accentColor;
     if (sysColor != null) _sysColor = sysColor;
@@ -62,6 +63,7 @@ class Settings extends ChangeNotifier {
     if (lastVersion != null) _lastVersion = lastVersion;
     if (bottomAppBars != null) _bottomAppBars = bottomAppBars;
     if (medications != null) _medications.addAll(medications);
+    if (highestMedIndex != null) _highestMedIndex = highestMedIndex;
     _language = language; // No check here, as null is the default as well.
   }
 
@@ -92,6 +94,7 @@ class Settings extends ChangeNotifier {
       bottomAppBars: ConvertUtil.parseBool(map['bottomAppBars']),
       medications: ConvertUtil.parseList<String>(map['medications'])?.map((e) =>
           Medicine.fromJson(jsonDecode(e))).toList(),
+      highestMedIndex: ConvertUtil.parseInt(map['highestMedIndex']),
     );
 
     // update
@@ -133,6 +136,7 @@ class Settings extends ChangeNotifier {
       'lastVersion': lastVersion,
       'bottomAppBars': bottomAppBars,
       'medications': medications.map((e) => jsonEncode(e)).toList(),
+      'highestMedIndex': highestMedIndex,
     };
 
   String toJson() => jsonEncode(toMap());
@@ -305,6 +309,7 @@ class Settings extends ChangeNotifier {
       UnmodifiableListView(_medications);
   void addMedication(Medicine medication) {
     _medications.add(medication);
+    _highestMedIndex += 1;
     notifyListeners();
   }
   void removeMedicationAt(int index) {
@@ -312,6 +317,10 @@ class Settings extends ChangeNotifier {
     _medications.removeAt(index);
     notifyListeners();
   }
+
+  int _highestMedIndex = 0;
+  /// Total amount of medicines created.
+  int get highestMedIndex => _highestMedIndex;
   
 // When adding fields notice the checklist at the top.
 }
lib/screens/subsettings/medicine_manager_screen.dart
@@ -1,8 +1,10 @@
+import 'package:blood_pressure_app/components/dialoges/add_medication_dialoge.dart';
 import 'package:blood_pressure_app/model/storage/settings_store.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_gen/gen_l10n/app_localizations.dart';
 import 'package:provider/provider.dart';
 
+/// Screen to view and edit medications saved in [Settings].
 class MedicineManagerScreen extends StatelessWidget {
   const MedicineManagerScreen({super.key});
 
@@ -33,12 +35,14 @@ class MedicineManagerScreen extends StatelessWidget {
                       leading: const Icon(Icons.add),
                       title: Text(localizations.addMedication),
                       onTap: () async {
+                        final medicine = await showAddMedicineDialoge(context, settings);
+                        if (medicine != null) settings.addMedication(medicine);;
                         // TODO
                       },
                     );
                   }
                   return ListTile(
-                    leading: Container(
+                    leading: medications[i-1].color == Colors.transparent ? null : Container(
                       width: 40.0,
                       height: 40.0,
                       decoration: BoxDecoration(
@@ -47,7 +51,7 @@ class MedicineManagerScreen extends StatelessWidget {
                       ),
                     ),
                     title: Text(medications[i-1].designation),
-                    subtitle: Text(medications[i-1].defaultDosis.toString()),
+                    subtitle: Text('${localizations.defaultDosis}: ${medications[i-1].defaultDosis?.toString()}'),
                     trailing: IconButton(
                       icon: const Icon(Icons.delete),
                       onPressed: () {