From 5e60ea09ce47e874a568bfc928a965539f8012cf Mon Sep 17 00:00:00 2001 From: spinel Date: Sat, 11 Dec 2021 02:30:46 +0100 Subject: [PATCH] usability tweaks, number form field component, amount for log meals, models for recipe and ingredients --- TODO | 35 +- lib/components/forms.dart | 83 ++++- lib/models/ingredient.dart | 33 ++ lib/models/log_bolus.dart | 11 +- lib/models/log_meal.dart | 26 +- lib/models/recipe.dart | 59 ++++ lib/objectbox-model.json | 128 ++++++- lib/objectbox.g.dart | 321 ++++++++++++++++-- .../log/log_entry/log_bolus_detail.dart | 10 +- lib/screens/log/log_entry/log_entry.dart | 3 +- .../log/log_entry/log_meal_detail.dart | 257 +++++++------- lib/screens/log/log_entry/log_meal_list.dart | 4 +- lib/screens/meal/meal_detail.dart | 5 +- lib/utils/utils.dart | 2 +- 14 files changed, 775 insertions(+), 202 deletions(-) create mode 100644 lib/models/ingredient.dart create mode 100644 lib/models/recipe.dart diff --git a/TODO b/TODO index 0bc6177..6630ebb 100644 --- a/TODO +++ b/TODO @@ -1,10 +1,5 @@ -BUGFIXES: - MAIN TASKS: - Layout: - ✔ make components rounder/nicer/closer to new material style @done(21-12-10 04:10) General/Framework: - ✔ make sure 'null' isn't shown in text fields @done(21-12-10 04:23) ☐ show indicator and make all fields readonly if user somehow gets to a deleted record detail view ☐ clean up controllers (dispose method of each stateful widget) ☐ account for deleted/disabled elements in dropdowns @@ -12,17 +7,15 @@ MAIN TASKS: ☐ set name properties as unique (and add checks to forms) ☐ implement component for durations ☐ change placement of delete and floating button because its very easy to accidentally hit delete - ✔ hide details like accuracies etc when picking meals @done(21-12-10 06:12) - Basal/Bolus: - ✔ add save and close and next buttons on rate creations @done(21-12-10 06:12) - ✔ always calculate other glucose measurement from active one and make other one readonly @done(21-12-10 04:33) + Recipe: + ✔ add model for recipe @done(21-12-11 02:23) + ✔ add model for ingredient (relation betweeen recipe and meal) @done(21-12-11 02:23) + ☐ recipe list screen + ☐ recipe detail screen + ☐ add functionality to create a meal from a recipe Log Entry: - ✔ add save and close button @done(21-12-10 06:11) - ✔ move on to newly created entry after saving @done(21-12-10 06:11) - ☐ recalculate bolus upon deactivating 'set manually' option - ☐ account for delayed percentage setting on choosing meals - ☐ give option to specify quantity - ☐ give option to pick meal from a different log entry (that doesn't have an associated bolus yet and within certain time span) + ✔ give option to specify quantity @done(21-12-11 01:28) + ✔ give option to pick meal from a different log entry (that doesn't have an associated bolus yet and within certain time span) @done(21-12-11 02:22) Event Types: ☐ add colors as indicators for log entries (and later graphs in reports) Settings: @@ -38,11 +31,10 @@ FUTURE TASKS: General/Framework: ☐ setup objectbox sync server ☐ add explanations to each section - ☐ find a better way to work with multiple glucose measurements (or disable it?) + ✔ find a better way to work with multiple glucose measurements @done(21-12-11 02:23) ☐ evaluate if some fields should be readonly instead of completely hidden ☐ alternate languages ☐ log hba1c - ☐ add recipe calculator Reports: ☐ evaluate what type of reports there should be Log Overview: @@ -58,6 +50,15 @@ FUTURE TASKS: ☐ option to switch theme Archive: + ✔ make components rounder/nicer/closer to new material style @done(21-12-10 04:10) @project(MAIN TASKS.Layout) + ✔ make sure 'null' isn't shown in text fields @done(21-12-10 04:23) @project(MAIN TASKS.General/Framework) + ✔ hide details like accuracies etc when picking meals @done(21-12-10 06:12) @project(MAIN TASKS.General/Framework) + ✔ add save and close and next buttons on rate creations @done(21-12-10 06:12) @project(MAIN TASKS.Basal/Bolus) + ✔ always calculate other glucose measurement from active one and make other one readonly @done(21-12-10 04:33) @project(MAIN TASKS.Basal/Bolus) + ✔ add save and close button @done(21-12-10 06:11) @project(MAIN TASKS.Log Entry) + ✔ move on to newly created entry after saving @done(21-12-10 06:11) @project(MAIN TASKS.Log Entry) + ✔ recalculate bolus upon deactivating 'set manually' option @done(21-12-10 06:18) @project(MAIN TASKS.Log Entry) + ✔ account for delayed percentage setting on choosing meals @done(21-12-10 06:39) @project(MAIN TASKS.Log Entry) ✔ fix preloading of dropdown values (appear blank at first as of now) @done(21-12-09 05:31) @project(BUGFIXES.General/Framework) ✔ glucose target isn't displayed correctly anymore @done(21-12-09 05:31) @project(BUGFIXES.Log Entry) ✔ hide dropdown overlay on tapping anywhere else (especially menu) @done(21-12-07 21:04) @project(MAIN TASKS.General/Framework) diff --git a/lib/components/forms.dart b/lib/components/forms.dart index de9a804..fc0d76d 100644 --- a/lib/components/forms.dart +++ b/lib/components/forms.dart @@ -23,11 +23,11 @@ class _FormWrapperState extends State { children: [ Column( children: widget.fields - ?.map((e) => Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: e)) - .toList() ?? - [], + ?.map((e) => Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: e)) + .toList() ?? + [], ), Container( padding: const EdgeInsets.only(top: 10.0), @@ -164,3 +164,76 @@ class _TimeOfDayFormFieldState extends State { ); } } + +class NumberFormField extends StatefulWidget { + final TextEditingController controller; + final String label; + final String? suffix; + final void Function(double?) onChanged; + final double? min; + final double? max; + final double step; + + const NumberFormField( + {Key? key, + required this.controller, + required this.label, + this.suffix, + required this.onChanged, + this.min, + this.max, + this.step = 1}) + : super(key: key); + + @override + _NumberFormFieldState createState() => _NumberFormFieldState(); +} + +class _NumberFormFieldState extends State { + void onIncrease() { + double value = double.tryParse(widget.controller.text) ?? 0; + if (widget.max == null || value + widget.step <= widget.max!) { + value += widget.step; + widget.onChanged(value); + } + } + + void onDecrease() { + double value = double.tryParse(widget.controller.text) ?? 0; + if (widget.min == null || value - widget.step >= widget.min!) { + value -= widget.step; + widget.onChanged(value); + } + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: onDecrease, + icon: const Icon(Icons.remove), + ), + Expanded( + child: TextFormField( + controller: widget.controller, + decoration: InputDecoration( + labelText: widget.label, + suffixText: widget.suffix, + ), + keyboardType: const TextInputType.numberWithOptions(decimal: true), + onChanged: (value) async { + await Future.delayed(const Duration(seconds: 1)); + widget.onChanged(double.tryParse(value)); + }, + ), + ), + IconButton( + onPressed: onIncrease, + icon: const Icon(Icons.add), + ), + ], + ); + } +} diff --git a/lib/models/ingredient.dart b/lib/models/ingredient.dart new file mode 100644 index 0000000..7131e7c --- /dev/null +++ b/lib/models/ingredient.dart @@ -0,0 +1,33 @@ +import 'package:diameter/main.dart'; +import 'package:diameter/models/meal.dart'; +import 'package:diameter/models/recipe.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:diameter/objectbox.g.dart' show Ingredient_, Recipe_; + +@Entity(uid: 6950311793136068892) +@Sync() +class Ingredient { + static final Box box = objectBox.store.box(); + + // properties + int id; + bool deleted; + double amount; + + // relations + final recipe = ToOne(); + final ingredient = ToOne(); + + // constructor + Ingredient({ + this.id = 0, + this.deleted = false, + required this.amount, + }); + + static List getAllForRecipe(int id) { + QueryBuilder builder = box.query(Ingredient_.deleted.equals(false)); + builder.link(Ingredient_.recipe, Recipe_.id.equals(id)); + return builder.build().find(); + } +} \ No newline at end of file diff --git a/lib/models/log_bolus.dart b/lib/models/log_bolus.dart index aa2e615..1b45234 100644 --- a/lib/models/log_bolus.dart +++ b/lib/models/log_bolus.dart @@ -3,7 +3,7 @@ import 'package:diameter/models/bolus.dart'; import 'package:diameter/models/log_entry.dart'; import 'package:diameter/models/log_meal.dart'; import 'package:objectbox/objectbox.dart'; -import 'package:diameter/objectbox.g.dart' show LogBolus_, LogEntry_; +import 'package:diameter/objectbox.g.dart' show LogBolus_, LogEntry_, LogMeal_; @Entity(uid: 8033487006694871160) @Sync() @@ -67,7 +67,14 @@ class LogBolus { QueryBuilder builder = box.query(LogBolus_.deleted .equals(false) .and(LogBolus_.mgPerDlCorrection.notNull())); - builder.link(LogBolus_.logEntry, LogEntry_.id.equals(id)); + builder.link(LogBolus_.meal, LogMeal_.id.equals(id)); + return builder.build().find().isNotEmpty; + } + + static bool bolusForMealExists(int id) { + QueryBuilder builder = box.query(LogBolus_.deleted + .equals(false)); + builder.link(LogBolus_.meal, LogMeal_.id.equals(id)); return builder.build().find().isNotEmpty; } diff --git a/lib/models/log_meal.dart b/lib/models/log_meal.dart index 3789134..8c9c471 100644 --- a/lib/models/log_meal.dart +++ b/lib/models/log_meal.dart @@ -1,4 +1,5 @@ import 'package:diameter/main.dart'; +import 'package:diameter/models/log_bolus.dart'; import 'package:diameter/models/log_entry.dart'; import 'package:diameter/models/meal.dart'; import 'package:diameter/models/meal_category.dart'; @@ -19,9 +20,10 @@ class LogMeal { String value; double? carbsRatio; double? portionSize; - double? carbsPerPortion; + double? totalCarbs; String? notes; double? bolus; + double amount; // relations final logEntry = ToOne(); @@ -37,33 +39,47 @@ class LogMeal { this.id = 0, this.deleted = false, this.value = '', + this.amount = 1, this.carbsRatio, this.portionSize, - this.carbsPerPortion, + this.totalCarbs, this.notes, }); // methods static LogMeal? get(int id) => box.get(id); static void put(LogMeal logMeal) => box.put(logMeal); - static void remove(int id) { + static void remove(int id) { final item = box.get(id); if (item != null) { item.deleted = true; box.put(item); } } - + static List getAllForEntry(int id) { QueryBuilder builder = box.query(LogMeal_.deleted.equals(false)); builder.link(LogMeal_.logEntry, LogEntry_.id.equals(id)); return builder.build().find(); } + static List getRecentWithoutBolus(int id) { + final dateTime = LogEntry.get(id)?.time ?? DateTime.now(); + QueryBuilder builder = box.query(LogMeal_.deleted.equals(false)); + builder.link(LogMeal_.logEntry); + List results = builder.build().find(); + results.retainWhere((logMeal) { + final entryTime = logMeal.logEntry.target!.time; + return entryTime.isAfter(dateTime.subtract(const Duration(hours: 12))) && + entryTime.isBefore(dateTime.add(const Duration(hours: 12))) && !LogBolus.bolusForMealExists(logMeal.id); + }); + return results; + } + static double getTotalCarbsForEntry(int id) { QueryBuilder builder = box.query(LogMeal_.deleted.equals(false)); builder.link(LogMeal_.logEntry, LogEntry_.id.equals(id)); - return builder.build().property(LogMeal_.carbsPerPortion).sum(); + return builder.build().property(LogMeal_.totalCarbs).sum(); } @override diff --git a/lib/models/recipe.dart b/lib/models/recipe.dart new file mode 100644 index 0000000..6f29aa1 --- /dev/null +++ b/lib/models/recipe.dart @@ -0,0 +1,59 @@ +import 'package:diameter/main.dart'; +import 'package:diameter/models/meal.dart'; +import 'package:objectbox/objectbox.dart'; +import 'package:diameter/objectbox.g.dart' show Recipe_; + +@Entity(uid: 6497942314956341514) +@Sync() +class Recipe { + static final Box box = objectBox.store.box(); + + // properties + int id; + bool deleted; + String name; + double? carbsRatio; + double? portionSize; + double? carbsPerPortion; + int? delayedBolusDuration; + double? delayedBolusPercentage; + String? notes; + + // relations + final portion = ToOne(); + + // constructor + Recipe({ + this.id = 0, + this.deleted = false, + this.name = '', + this.carbsRatio, + this.portionSize, + this.carbsPerPortion, + this.delayedBolusDuration, + this.delayedBolusPercentage, + this.notes, + }); + + // methods + static Recipe? get(int id) => box.get(id); + static void put(Recipe recipe) => box.put(recipe); + + static List getAll() { + QueryBuilder builder = box.query(Recipe_.deleted.equals(false))..order(Recipe_.name); + return builder.build().find(); + } + + static void remove(int id) { + final item = box.get(id); + if (item != null) { + item.deleted = true; + box.put(item); + } + } + + @override + String toString() { + return name; + } +} diff --git a/lib/objectbox-model.json b/lib/objectbox-model.json index 13e2d15..542512e 100644 --- a/lib/objectbox-model.json +++ b/lib/objectbox-model.json @@ -346,7 +346,7 @@ }, { "id": "9:411177866700467286", - "lastPropertyId": "17:7341439841011629937", + "lastPropertyId": "19:8965198821438347033", "name": "LogMeal", "flags": 2, "properties": [ @@ -371,11 +371,6 @@ "name": "portionSize", "type": 8 }, - { - "id": "5:2215708755581938580", - "name": "carbsPerPortion", - "type": 8 - }, { "id": "6:8074052538574863399", "name": "bolus", @@ -446,6 +441,16 @@ "id": "17:7341439841011629937", "name": "deleted", "type": 1 + }, + { + "id": "18:7405129785654054238", + "name": "amount", + "type": 8 + }, + { + "id": "19:8965198821438347033", + "name": "totalCarbs", + "type": 8 } ], "relations": [] @@ -935,10 +940,114 @@ } ], "relations": [] + }, + { + "id": "18:6497942314956341514", + "lastPropertyId": "10:4370359747396560337", + "name": "Recipe", + "flags": 2, + "properties": [ + { + "id": "1:6426741154282018946", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:1167304402395485629", + "name": "deleted", + "type": 1 + }, + { + "id": "3:1244733840071626966", + "name": "name", + "type": 9 + }, + { + "id": "4:241621230513128588", + "name": "carbsRatio", + "type": 8 + }, + { + "id": "5:4678123663117222609", + "name": "portionSize", + "type": 8 + }, + { + "id": "6:780211923138281722", + "name": "carbsPerPortion", + "type": 8 + }, + { + "id": "7:763575433624979013", + "name": "delayedBolusDuration", + "type": 6 + }, + { + "id": "8:1225271130099322691", + "name": "delayedBolusPercentage", + "type": 8 + }, + { + "id": "9:8593446427752839266", + "name": "notes", + "type": 9 + }, + { + "id": "10:4370359747396560337", + "name": "portionId", + "type": 11, + "flags": 520, + "indexId": "29:5110151182694376118", + "relationTarget": "Meal" + } + ], + "relations": [] + }, + { + "id": "19:6950311793136068892", + "lastPropertyId": "5:6495065881132428893", + "name": "Ingredient", + "flags": 2, + "properties": [ + { + "id": "1:7766569281758551418", + "name": "id", + "type": 6, + "flags": 1 + }, + { + "id": "2:3830559702655088692", + "name": "deleted", + "type": 1 + }, + { + "id": "3:602057803225843875", + "name": "amount", + "type": 8 + }, + { + "id": "4:26686399245586953", + "name": "recipeId", + "type": 11, + "flags": 520, + "indexId": "30:5492781242713788590", + "relationTarget": "Recipe" + }, + { + "id": "5:6495065881132428893", + "name": "ingredientId", + "type": 11, + "flags": 520, + "indexId": "31:3277019237664417023", + "relationTarget": "Meal" + } + ], + "relations": [] } ], - "lastEntityId": "17:5041265995704044399", - "lastIndexId": "28:4563029809754152081", + "lastEntityId": "19:6950311793136068892", + "lastIndexId": "31:3277019237664417023", "lastRelationId": "0:0", "lastSequenceId": "0:0", "modelVersion": 5, @@ -975,7 +1084,8 @@ 7638848982383620744, 3282706593658092097, 596980591281311896, - 3633551763915044903 + 3633551763915044903, + 2215708755581938580 ], "retiredRelationUids": [], "version": 1 diff --git a/lib/objectbox.g.dart b/lib/objectbox.g.dart index 85ed8a2..ccfa2d9 100644 --- a/lib/objectbox.g.dart +++ b/lib/objectbox.g.dart @@ -15,6 +15,7 @@ import 'models/basal_profile.dart'; import 'models/bolus.dart'; import 'models/bolus_profile.dart'; import 'models/glucose_target.dart'; +import 'models/ingredient.dart'; import 'models/log_bolus.dart'; import 'models/log_entry.dart'; import 'models/log_event.dart'; @@ -24,6 +25,7 @@ import 'models/meal.dart'; import 'models/meal_category.dart'; import 'models/meal_portion_type.dart'; import 'models/meal_source.dart'; +import 'models/recipe.dart'; import 'models/settings.dart'; export 'package:objectbox/objectbox.dart'; // so that callers only have to import this file @@ -359,7 +361,7 @@ final _entities = [ ModelEntity( id: const IdUid(9, 411177866700467286), name: 'LogMeal', - lastPropertyId: const IdUid(17, 7341439841011629937), + lastPropertyId: const IdUid(19, 8965198821438347033), flags: 2, properties: [ ModelProperty( @@ -382,11 +384,6 @@ final _entities = [ name: 'portionSize', type: 8, flags: 0), - ModelProperty( - id: const IdUid(5, 2215708755581938580), - name: 'carbsPerPortion', - type: 8, - flags: 0), ModelProperty( id: const IdUid(6, 8074052538574863399), name: 'bolus', @@ -450,6 +447,16 @@ final _entities = [ id: const IdUid(17, 7341439841011629937), name: 'deleted', type: 1, + flags: 0), + ModelProperty( + id: const IdUid(18, 7405129785654054238), + name: 'amount', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(19, 8965198821438347033), + name: 'totalCarbs', + type: 8, flags: 0) ], relations: [], @@ -919,6 +926,105 @@ final _entities = [ flags: 0) ], relations: [], + backlinks: []), + ModelEntity( + id: const IdUid(18, 6497942314956341514), + name: 'Recipe', + lastPropertyId: const IdUid(10, 4370359747396560337), + flags: 2, + properties: [ + ModelProperty( + id: const IdUid(1, 6426741154282018946), + name: 'id', + type: 6, + flags: 1), + ModelProperty( + id: const IdUid(2, 1167304402395485629), + name: 'deleted', + type: 1, + flags: 0), + ModelProperty( + id: const IdUid(3, 1244733840071626966), + name: 'name', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(4, 241621230513128588), + name: 'carbsRatio', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(5, 4678123663117222609), + name: 'portionSize', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(6, 780211923138281722), + name: 'carbsPerPortion', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(7, 763575433624979013), + name: 'delayedBolusDuration', + type: 6, + flags: 0), + ModelProperty( + id: const IdUid(8, 1225271130099322691), + name: 'delayedBolusPercentage', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(9, 8593446427752839266), + name: 'notes', + type: 9, + flags: 0), + ModelProperty( + id: const IdUid(10, 4370359747396560337), + name: 'portionId', + type: 11, + flags: 520, + indexId: const IdUid(29, 5110151182694376118), + relationTarget: 'Meal') + ], + relations: [], + backlinks: []), + ModelEntity( + id: const IdUid(19, 6950311793136068892), + name: 'Ingredient', + lastPropertyId: const IdUid(5, 6495065881132428893), + flags: 2, + properties: [ + ModelProperty( + id: const IdUid(1, 7766569281758551418), + name: 'id', + type: 6, + flags: 1), + ModelProperty( + id: const IdUid(2, 3830559702655088692), + name: 'deleted', + type: 1, + flags: 0), + ModelProperty( + id: const IdUid(3, 602057803225843875), + name: 'amount', + type: 8, + flags: 0), + ModelProperty( + id: const IdUid(4, 26686399245586953), + name: 'recipeId', + type: 11, + flags: 520, + indexId: const IdUid(30, 5492781242713788590), + relationTarget: 'Recipe'), + ModelProperty( + id: const IdUid(5, 6495065881132428893), + name: 'ingredientId', + type: 11, + flags: 520, + indexId: const IdUid(31, 3277019237664417023), + relationTarget: 'Meal') + ], + relations: [], backlinks: []) ]; @@ -942,8 +1048,8 @@ Future openStore( ModelDefinition getObjectBoxModel() { final model = ModelInfo( entities: _entities, - lastEntityId: const IdUid(17, 5041265995704044399), - lastIndexId: const IdUid(28, 4563029809754152081), + lastEntityId: const IdUid(19, 6950311793136068892), + lastIndexId: const IdUid(31, 3277019237664417023), lastRelationId: const IdUid(0, 0), lastSequenceId: const IdUid(0, 0), retiredEntityUids: const [3095978685310268382], @@ -973,7 +1079,8 @@ ModelDefinition getObjectBoxModel() { 7638848982383620744, 3282706593658092097, 596980591281311896, - 3633551763915044903 + 3633551763915044903, + 2215708755581938580 ], retiredRelationUids: const [], modelVersion: 5, @@ -1311,12 +1418,11 @@ ModelDefinition getObjectBoxModel() { final valueOffset = fbb.writeString(object.value); final notesOffset = object.notes == null ? null : fbb.writeString(object.notes!); - fbb.startTable(18); + fbb.startTable(20); fbb.addInt64(0, object.id); fbb.addOffset(1, valueOffset); fbb.addFloat64(2, object.carbsRatio); fbb.addFloat64(3, object.portionSize); - fbb.addFloat64(4, object.carbsPerPortion); fbb.addFloat64(5, object.bolus); fbb.addOffset(8, notesOffset); fbb.addInt64(9, object.logEntry.targetId); @@ -1327,6 +1433,8 @@ ModelDefinition getObjectBoxModel() { fbb.addInt64(14, object.portionSizeAccuracy.targetId); fbb.addInt64(15, object.carbsRatioAccuracy.targetId); fbb.addBool(16, object.deleted); + fbb.addFloat64(17, object.amount); + fbb.addFloat64(18, object.totalCarbs); fbb.finish(fbb.endTable()); return object.id; }, @@ -1340,12 +1448,14 @@ ModelDefinition getObjectBoxModel() { .vTableGet(buffer, rootOffset, 36, false), value: const fb.StringReader().vTableGet(buffer, rootOffset, 6, ''), + amount: + const fb.Float64Reader().vTableGet(buffer, rootOffset, 38, 0), carbsRatio: const fb.Float64Reader() .vTableGetNullable(buffer, rootOffset, 8), portionSize: const fb.Float64Reader() .vTableGetNullable(buffer, rootOffset, 10), - carbsPerPortion: const fb.Float64Reader() - .vTableGetNullable(buffer, rootOffset, 12), + totalCarbs: const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 40), notes: const fb.StringReader() .vTableGetNullable(buffer, rootOffset, 20)) ..bolus = const fb.Float64Reader() @@ -1799,6 +1909,96 @@ ModelDefinition getObjectBoxModel() { const fb.Int64Reader().vTableGet(buffer, rootOffset, 16, 0)); return object; + }), + Recipe: EntityDefinition( + model: _entities[16], + toOneRelations: (Recipe object) => [object.portion], + toManyRelations: (Recipe object) => {}, + getId: (Recipe object) => object.id, + setId: (Recipe object, int id) { + object.id = id; + }, + objectToFB: (Recipe object, fb.Builder fbb) { + final nameOffset = fbb.writeString(object.name); + final notesOffset = + object.notes == null ? null : fbb.writeString(object.notes!); + fbb.startTable(11); + fbb.addInt64(0, object.id); + fbb.addBool(1, object.deleted); + fbb.addOffset(2, nameOffset); + fbb.addFloat64(3, object.carbsRatio); + fbb.addFloat64(4, object.portionSize); + fbb.addFloat64(5, object.carbsPerPortion); + fbb.addInt64(6, object.delayedBolusDuration); + fbb.addFloat64(7, object.delayedBolusPercentage); + fbb.addOffset(8, notesOffset); + fbb.addInt64(9, object.portion.targetId); + fbb.finish(fbb.endTable()); + return object.id; + }, + objectFromFB: (Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + + final object = Recipe( + id: const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0), + deleted: + const fb.BoolReader().vTableGet(buffer, rootOffset, 6, false), + name: + const fb.StringReader().vTableGet(buffer, rootOffset, 8, ''), + carbsRatio: const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 10), + portionSize: const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 12), + carbsPerPortion: const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 14), + delayedBolusDuration: const fb.Int64Reader() + .vTableGetNullable(buffer, rootOffset, 16), + delayedBolusPercentage: const fb.Float64Reader() + .vTableGetNullable(buffer, rootOffset, 18), + notes: const fb.StringReader() + .vTableGetNullable(buffer, rootOffset, 20)); + object.portion.targetId = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 22, 0); + object.portion.attach(store); + return object; + }), + Ingredient: EntityDefinition( + model: _entities[17], + toOneRelations: (Ingredient object) => + [object.recipe, object.ingredient], + toManyRelations: (Ingredient object) => {}, + getId: (Ingredient object) => object.id, + setId: (Ingredient object, int id) { + object.id = id; + }, + objectToFB: (Ingredient object, fb.Builder fbb) { + fbb.startTable(6); + fbb.addInt64(0, object.id); + fbb.addBool(1, object.deleted); + fbb.addFloat64(2, object.amount); + fbb.addInt64(3, object.recipe.targetId); + fbb.addInt64(4, object.ingredient.targetId); + fbb.finish(fbb.endTable()); + return object.id; + }, + objectFromFB: (Store store, ByteData fbData) { + final buffer = fb.BufferContext(fbData); + final rootOffset = buffer.derefObject(0); + + final object = Ingredient( + id: const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0), + deleted: + const fb.BoolReader().vTableGet(buffer, rootOffset, 6, false), + amount: + const fb.Float64Reader().vTableGet(buffer, rootOffset, 8, 0)); + object.recipe.targetId = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 10, 0); + object.recipe.attach(store); + object.ingredient.targetId = + const fb.Int64Reader().vTableGet(buffer, rootOffset, 12, 0); + object.ingredient.attach(store); + return object; }) }; @@ -2035,47 +2235,51 @@ class LogMeal_ { static final portionSize = QueryDoubleProperty(_entities[7].properties[3]); - /// see [LogMeal.carbsPerPortion] - static final carbsPerPortion = - QueryDoubleProperty(_entities[7].properties[4]); - /// see [LogMeal.bolus] - static final bolus = QueryDoubleProperty(_entities[7].properties[5]); + static final bolus = QueryDoubleProperty(_entities[7].properties[4]); /// see [LogMeal.notes] - static final notes = QueryStringProperty(_entities[7].properties[6]); + static final notes = QueryStringProperty(_entities[7].properties[5]); /// see [LogMeal.logEntry] static final logEntry = - QueryRelationToOne(_entities[7].properties[7]); + QueryRelationToOne(_entities[7].properties[6]); /// see [LogMeal.meal] static final meal = - QueryRelationToOne(_entities[7].properties[8]); + QueryRelationToOne(_entities[7].properties[7]); /// see [LogMeal.mealSource] static final mealSource = - QueryRelationToOne(_entities[7].properties[9]); + QueryRelationToOne(_entities[7].properties[8]); /// see [LogMeal.mealCategory] static final mealCategory = - QueryRelationToOne(_entities[7].properties[10]); + QueryRelationToOne(_entities[7].properties[9]); /// see [LogMeal.mealPortionType] static final mealPortionType = - QueryRelationToOne(_entities[7].properties[11]); + QueryRelationToOne(_entities[7].properties[10]); /// see [LogMeal.portionSizeAccuracy] static final portionSizeAccuracy = - QueryRelationToOne(_entities[7].properties[12]); + QueryRelationToOne(_entities[7].properties[11]); /// see [LogMeal.carbsRatioAccuracy] static final carbsRatioAccuracy = - QueryRelationToOne(_entities[7].properties[13]); + QueryRelationToOne(_entities[7].properties[12]); /// see [LogMeal.deleted] static final deleted = - QueryBooleanProperty(_entities[7].properties[14]); + QueryBooleanProperty(_entities[7].properties[13]); + + /// see [LogMeal.amount] + static final amount = + QueryDoubleProperty(_entities[7].properties[14]); + + /// see [LogMeal.totalCarbs] + static final totalCarbs = + QueryDoubleProperty(_entities[7].properties[15]); } /// [Meal] entity fields to define ObjectBox queries. @@ -2392,3 +2596,66 @@ class GlucoseTarget_ { static final color = QueryIntegerProperty(_entities[15].properties[6]); } + +/// [Recipe] entity fields to define ObjectBox queries. +class Recipe_ { + /// see [Recipe.id] + static final id = QueryIntegerProperty(_entities[16].properties[0]); + + /// see [Recipe.deleted] + static final deleted = + QueryBooleanProperty(_entities[16].properties[1]); + + /// see [Recipe.name] + static final name = QueryStringProperty(_entities[16].properties[2]); + + /// see [Recipe.carbsRatio] + static final carbsRatio = + QueryDoubleProperty(_entities[16].properties[3]); + + /// see [Recipe.portionSize] + static final portionSize = + QueryDoubleProperty(_entities[16].properties[4]); + + /// see [Recipe.carbsPerPortion] + static final carbsPerPortion = + QueryDoubleProperty(_entities[16].properties[5]); + + /// see [Recipe.delayedBolusDuration] + static final delayedBolusDuration = + QueryIntegerProperty(_entities[16].properties[6]); + + /// see [Recipe.delayedBolusPercentage] + static final delayedBolusPercentage = + QueryDoubleProperty(_entities[16].properties[7]); + + /// see [Recipe.notes] + static final notes = QueryStringProperty(_entities[16].properties[8]); + + /// see [Recipe.portion] + static final portion = + QueryRelationToOne(_entities[16].properties[9]); +} + +/// [Ingredient] entity fields to define ObjectBox queries. +class Ingredient_ { + /// see [Ingredient.id] + static final id = + QueryIntegerProperty(_entities[17].properties[0]); + + /// see [Ingredient.deleted] + static final deleted = + QueryBooleanProperty(_entities[17].properties[1]); + + /// see [Ingredient.amount] + static final amount = + QueryDoubleProperty(_entities[17].properties[2]); + + /// see [Ingredient.recipe] + static final recipe = + QueryRelationToOne(_entities[17].properties[3]); + + /// see [Ingredient.ingredient] + static final ingredient = + QueryRelationToOne(_entities[17].properties[4]); +} diff --git a/lib/screens/log/log_entry/log_bolus_detail.dart b/lib/screens/log/log_entry/log_bolus_detail.dart index 266fc0c..6c24681 100644 --- a/lib/screens/log/log_entry/log_bolus_detail.dart +++ b/lib/screens/log/log_entry/log_bolus_detail.dart @@ -81,7 +81,7 @@ class _LogBolusDetailScreenState extends State { reload(); _logEntry = LogEntry.get(widget.logEntryId); - _logMeals = LogMeal.getAllForEntry(widget.logEntryId); + _logMeals = LogMeal.getRecentWithoutBolus(widget.logEntryId); if (widget.id != 0) { _carbsController.text = (_logBolus!.carbs ?? '').toString(); @@ -163,8 +163,8 @@ class _LogBolusDetailScreenState extends State { _mealController.text = (_meal ?? '').toString(); }); if (_meal != null) { - if (_meal!.carbsPerPortion != null) { - _carbsController.text = (_meal!.carbsPerPortion).toString(); + if (_meal!.totalCarbs != null) { + _carbsController.text = (_meal!.totalCarbs).toString(); } if (_meal!.meal.hasValue) { if (_meal!.meal.target!.delayedBolusDuration != null) { @@ -198,9 +198,9 @@ class _LogBolusDetailScreenState extends State { void onSelectMeal(LogMeal? meal) { updateLogMeal(meal); - if (meal != null && meal.carbsPerPortion != null) { + if (meal != null && meal.totalCarbs != null) { setState(() { - _carbsController.text = meal.carbsPerPortion.toString(); + _carbsController.text = meal.totalCarbs.toString(); calculateBolus(); }); } diff --git a/lib/screens/log/log_entry/log_entry.dart b/lib/screens/log/log_entry/log_entry.dart index 886736b..81d31cc 100644 --- a/lib/screens/log/log_entry/log_entry.dart +++ b/lib/screens/log/log_entry/log_entry.dart @@ -214,8 +214,7 @@ class _LogEntryScreenState extends State { onDiscard: (context) => Navigator.pushReplacementNamed(context, '/log'), ); } else { - Navigator.pushReplacementNamed(context, '/log', - arguments: '${_isNew ? 'New' : ''} Log Entry Saved'); + Navigator.pop(context); } } diff --git a/lib/screens/log/log_entry/log_meal_detail.dart b/lib/screens/log/log_entry/log_meal_detail.dart index a40565c..7f0c01b 100644 --- a/lib/screens/log/log_entry/log_meal_detail.dart +++ b/lib/screens/log/log_entry/log_meal_detail.dart @@ -37,13 +37,16 @@ class _LogMealDetailScreenState extends State { bool _isSaving = false; bool _isExpanded = false; + double _amount = 1; + final GlobalKey _logMealForm = GlobalKey(); final ScrollController _scrollController = ScrollController(); final _valueController = TextEditingController(text: ''); + final _amountController = TextEditingController(text: ''); final _carbsRatioController = TextEditingController(text: ''); final _portionSizeController = TextEditingController(text: ''); - final _carbsPerPortionController = TextEditingController(text: ''); + final _totalCarbsController = TextEditingController(text: ''); final _notesController = TextEditingController(text: ''); Meal? _meal; @@ -81,10 +84,10 @@ class _LogMealDetailScreenState extends State { if (widget.id != 0) { _valueController.text = _logMeal!.value; + _amountController.text = _logMeal!.amount.toString(); _carbsRatioController.text = (_logMeal!.carbsRatio ?? '').toString(); _portionSizeController.text = (_logMeal!.portionSize ?? '').toString(); - _carbsPerPortionController.text = - (_logMeal!.carbsPerPortion ?? '').toString(); + _totalCarbsController.text = (_logMeal!.totalCarbs ?? '').toString(); _notesController.text = _logMeal!.notes ?? ''; _meal = _logMeal!.meal.target; @@ -102,6 +105,10 @@ class _LogMealDetailScreenState extends State { _carbsRatioAccuracyController.text = (_carbsRatioAccuracy ?? '').toString(); } + + if (_amountController.text == '') { + _amountController.text = '1'; + } } void reload({String? message}) { @@ -165,35 +172,18 @@ class _LogMealDetailScreenState extends State { Future onSelectMeal(Meal? meal) async { setState(() { _meal = meal; - _valueController.text = _mealController.text = (_meal ?? '').toString(); + _mealController.text = (_meal ?? '').toString(); + _valueController.text = _mealController.text; + _carbsRatioController.text = (meal?.carbsRatio ?? '').toString(); + _amountController.text = '1'; + _portionSizeController.text = (meal?.portionSize ?? '').toString(); + _totalCarbsController.text = (meal?.carbsPerPortion ?? '').toString(); }); - - if (meal != null) { - if (meal.carbsRatio != null) { - _carbsRatioController.text = meal.carbsRatio.toString(); - } - if (meal.portionSize != null) { - _portionSizeController.text = meal.portionSize.toString(); - } - if (meal.carbsPerPortion != null) { - _carbsPerPortionController.text = meal.carbsPerPortion.toString(); - } - if (meal.mealSource.hasValue) { - updateMealSource(meal.mealSource.target); - } - if (meal.mealCategory.hasValue) { - updateMealCategory(meal.mealCategory.target); - } - if (meal.mealPortionType.hasValue) { - updateMealPortionType(meal.mealPortionType.target); - } - if (meal.portionSizeAccuracy.hasValue) { - updatePortionSizeAccuracy(meal.portionSizeAccuracy.target); - } - if (meal.carbsRatioAccuracy.hasValue) { - updateCarbsRatioAccuracy(meal.carbsRatioAccuracy.target); - } - } + updateMealSource(meal?.mealSource.target); + updateMealCategory(meal?.mealCategory.target); + updateMealPortionType(meal?.mealPortionType.target); + updatePortionSizeAccuracy(meal?.portionSizeAccuracy.target); + updateCarbsRatioAccuracy(meal?.carbsRatioAccuracy.target); } void handleSaveAction() async { @@ -206,7 +196,7 @@ class _LogMealDetailScreenState extends State { value: _valueController.text, carbsRatio: double.tryParse(_carbsRatioController.text), portionSize: double.tryParse(_portionSizeController.text), - carbsPerPortion: double.tryParse(_carbsPerPortionController.text), + totalCarbs: double.tryParse(_totalCarbsController.text), ); logMeal.logEntry.targetId = widget.logEntryId; logMeal.meal.target = _meal; @@ -234,7 +224,7 @@ class _LogMealDetailScreenState extends State { _mealPortionType != null || double.tryParse(_carbsRatioController.text) != null || double.tryParse(_portionSizeController.text) != null || - double.tryParse(_carbsPerPortionController.text) != null || + double.tryParse(_totalCarbsController.text) != null || _carbsRatioAccuracy != null || _portionSizeAccuracy != null || _notesController.text != '')) || @@ -248,8 +238,8 @@ class _LogMealDetailScreenState extends State { _logMeal!.carbsRatio || double.tryParse(_portionSizeController.text) != _logMeal!.portionSize || - double.tryParse(_carbsPerPortionController.text) != - _logMeal!.carbsPerPortion || + double.tryParse(_totalCarbsController.text) != + _logMeal!.totalCarbs || _carbsRatioAccuracy != _logMeal!.carbsRatioAccuracy.target || _portionSizeAccuracy != @@ -265,37 +255,70 @@ class _LogMealDetailScreenState extends State { } } - void calculateThirdMeasurementOfPortionCarbsRelation( - {PortionCarbsParameter? parameterToBeCalculated}) { + void updateAmount(double? amount) { + double? previousAmount; + double? portionSize; + double? carbsRatio; + + previousAmount = _amount; + + setState(() { + _amountController.text = (amount ?? '').toString(); + _amount = amount ?? 1; + }); + + if (_carbsRatioController.text != '') { + carbsRatio = double.tryParse(_carbsRatioController.text); + } + if (_portionSizeController.text != '') { + portionSize = double.tryParse(_portionSizeController.text); + } + + if (amount != null && portionSize != null) { + setState(() { + portionSize = portionSize! / (previousAmount ?? 1) * amount; + _portionSizeController.text = portionSize.toString(); + }); + if (carbsRatio != null) { + setState(() { + _totalCarbsController.text = + Utils.calculateCarbs(carbsRatio!, portionSize!).toString(); + }); + } + } + } + + void calculateThirdMeasurementOfPortionCarbsRelation() { + int? amount; double? carbsRatio; double? portionSize; double? carbsPerPortion; - if (parameterToBeCalculated != PortionCarbsParameter.carbsRatio && - _carbsRatioController.text != '') { + if (_amountController.text != '') { + amount = int.tryParse(_amountController.text); + } + if (_carbsRatioController.text != '') { carbsRatio = double.tryParse(_carbsRatioController.text); } - if (parameterToBeCalculated != PortionCarbsParameter.portionSize && - _portionSizeController.text != '') { + if (_portionSizeController.text != '') { portionSize = double.tryParse(_portionSizeController.text); } - if (parameterToBeCalculated != PortionCarbsParameter.carbsPerPortion && - _carbsRatioController.text != '') { - carbsPerPortion = double.tryParse(_carbsPerPortionController.text); + if (_totalCarbsController.text != '') { + carbsPerPortion = double.tryParse(_totalCarbsController.text); } if (carbsRatio != null && portionSize != null && carbsPerPortion == null) { setState(() { - _carbsPerPortionController.text = - Utils.calculateCarbsPerPortion(carbsRatio!, portionSize!) + _totalCarbsController.text = + Utils.calculateCarbs(carbsRatio!, portionSize! * (amount ?? 1)) .toString(); }); } if (carbsRatio == null && portionSize != null && carbsPerPortion != null) { setState(() { - _carbsRatioController.text = - Utils.calculateCarbsRatio(carbsPerPortion!, portionSize!) - .toString(); + _carbsRatioController.text = Utils.calculateCarbsRatio( + carbsPerPortion!, portionSize! * (amount ?? 1)) + .toString(); }); } if (carbsRatio != null && portionSize == null && carbsPerPortion != null) { @@ -311,7 +334,7 @@ class _LogMealDetailScreenState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text(_isNew ? 'New Meal' : _logMeal!.value), + title: Text(_isNew ? 'New Meal for Log Entry' : _logMeal!.value), ), drawer: const Navigation(currentLocation: LogMealDetailScreen.routeName), body: Scrollbar( @@ -344,11 +367,7 @@ class _LogMealDetailScreenState extends State { selectedItem: _meal, label: 'Meal', items: _meals, - onChanged: (value) { - if (value != null) { - onSelectMeal(value); - } - }, + onChanged: onSelectMeal, ), ), IconButton( @@ -369,34 +388,14 @@ class _LogMealDetailScreenState extends State { ), ], ), - Row( - children: [ - Expanded( - child: TextFormField( - decoration: const InputDecoration( - labelText: 'Carbs ratio', - suffixText: '%', - ), - controller: _carbsRatioController, - keyboardType: const TextInputType.numberWithOptions( - decimal: true), - onChanged: (_) async { - await Future.delayed(const Duration(seconds: 1)); - calculateThirdMeasurementOfPortionCarbsRelation(); - }, - ), - ), - IconButton( - onPressed: () => - calculateThirdMeasurementOfPortionCarbsRelation( - parameterToBeCalculated: - PortionCarbsParameter.carbsRatio), - icon: const Icon(Icons.calculate), - ), - ], + NumberFormField( + controller: _amountController, + label: 'Amount', + suffix: _mealPortionType?.value, + min: 1, + onChanged: updateAmount, ), Row( - mainAxisSize: MainAxisSize.min, children: [ Expanded( child: TextFormField( @@ -413,24 +412,14 @@ class _LogMealDetailScreenState extends State { }, ), ), - IconButton( - onPressed: () => - calculateThirdMeasurementOfPortionCarbsRelation( - parameterToBeCalculated: - PortionCarbsParameter.portionSize), - icon: const Icon(Icons.calculate), - ), - ], - ), - Row( - children: [ + const SizedBox(width: 10), Expanded( child: TextFormField( - decoration: InputDecoration( - labelText: 'Carbs per portion', - suffixText: Settings.nutritionMeasurementSuffix, + decoration: const InputDecoration( + labelText: 'Carbs ratio', + suffixText: '%', ), - controller: _carbsPerPortionController, + controller: _carbsRatioController, keyboardType: const TextInputType.numberWithOptions( decimal: true), onChanged: (_) async { @@ -439,12 +428,21 @@ class _LogMealDetailScreenState extends State { }, ), ), - IconButton( - onPressed: () => - calculateThirdMeasurementOfPortionCarbsRelation( - parameterToBeCalculated: - PortionCarbsParameter.carbsPerPortion), - icon: const Icon(Icons.calculate), + const SizedBox(width: 10), + Expanded( + child: TextFormField( + decoration: InputDecoration( + labelText: 'Total carbs', + suffixText: Settings.nutritionMeasurementSuffix, + ), + controller: _totalCarbsController, + keyboardType: const TextInputType.numberWithOptions( + decimal: true), + onChanged: (_) async { + await Future.delayed(const Duration(seconds: 1)); + calculateThirdMeasurementOfPortionCarbsRelation(); + }, + ), ), ], ), @@ -480,11 +478,13 @@ class _LogMealDetailScreenState extends State { children: _isExpanded ? [ Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), + padding: + const EdgeInsets.symmetric(vertical: 5.0), child: Row( children: [ Expanded( - child: AutoCompleteDropdownButton( + child: + AutoCompleteDropdownButton( controller: _mealSourceController, selectedItem: _mealSource, label: 'Meal Source', @@ -497,11 +497,11 @@ class _LogMealDetailScreenState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => - _mealSource == null - ? const MealSourceDetailScreen() - : MealSourceDetailScreen( - id: _mealSource!.id), + builder: (context) => _mealSource == + null + ? const MealSourceDetailScreen() + : MealSourceDetailScreen( + id: _mealSource!.id), ), ).then((result) { updateMealSource(result?[1]); @@ -516,12 +516,13 @@ class _LogMealDetailScreenState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), + padding: + const EdgeInsets.symmetric(vertical: 5.0), child: Row( children: [ Expanded( - child: - AutoCompleteDropdownButton( + child: AutoCompleteDropdownButton< + MealCategory>( controller: _mealCategoryController, selectedItem: _mealCategory, label: 'Meal Category', @@ -553,7 +554,8 @@ class _LogMealDetailScreenState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), + padding: + const EdgeInsets.symmetric(vertical: 5.0), child: Row( children: [ Expanded( @@ -590,12 +592,14 @@ class _LogMealDetailScreenState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), + padding: + const EdgeInsets.symmetric(vertical: 5.0), child: Row( children: [ Expanded( child: AutoCompleteDropdownButton( - controller: _portionSizeAccuracyController, + controller: + _portionSizeAccuracyController, selectedItem: _portionSizeAccuracy, label: 'Portion Size Accuracy', items: _portionSizeAccuracies, @@ -607,10 +611,12 @@ class _LogMealDetailScreenState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => _portionSizeAccuracy == null - ? const AccuracyDetailScreen() - : AccuracyDetailScreen( - id: _portionSizeAccuracy!.id), + builder: (context) => + _portionSizeAccuracy == null + ? const AccuracyDetailScreen() + : AccuracyDetailScreen( + id: _portionSizeAccuracy! + .id), ), ).then((result) { updatePortionSizeAccuracy(result?[1]); @@ -625,7 +631,8 @@ class _LogMealDetailScreenState extends State { ), ), Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), + padding: + const EdgeInsets.symmetric(vertical: 5.0), child: Row( children: [ Expanded( @@ -642,10 +649,12 @@ class _LogMealDetailScreenState extends State { Navigator.push( context, MaterialPageRoute( - builder: (context) => _carbsRatioAccuracy == null - ? const AccuracyDetailScreen() - : AccuracyDetailScreen( - id: _carbsRatioAccuracy!.id), + builder: (context) => + _carbsRatioAccuracy == null + ? const AccuracyDetailScreen() + : AccuracyDetailScreen( + id: _carbsRatioAccuracy! + .id), ), ).then((result) { updateCarbsRatioAccuracy(result?[1]); diff --git a/lib/screens/log/log_entry/log_meal_list.dart b/lib/screens/log/log_entry/log_meal_list.dart index cfd6002..3bba521 100644 --- a/lib/screens/log/log_entry/log_meal_list.dart +++ b/lib/screens/log/log_entry/log_meal_list.dart @@ -89,9 +89,9 @@ class _LogMealListScreenState extends State { )), Expanded( child: Column( - children: ((meal.carbsPerPortion ?? 0) > 0) + children: ((meal.totalCarbs ?? 0) > 0) ? [ - Text(meal.carbsPerPortion!.toStringAsPrecision(3)), + Text(meal.totalCarbs!.toStringAsPrecision(3)), Text( '${Settings.nutritionMeasurementSuffix} carbs', textScaleFactor: 0.75), diff --git a/lib/screens/meal/meal_detail.dart b/lib/screens/meal/meal_detail.dart index 95f6b29..7ab2e28 100644 --- a/lib/screens/meal/meal_detail.dart +++ b/lib/screens/meal/meal_detail.dart @@ -246,8 +246,7 @@ class _MealDetailScreenState extends State { } } - void calculateThirdMeasurementOfPortionCarbsRelation( - {PortionCarbsParameter? changedParameter}) { + void calculateThirdMeasurementOfPortionCarbsRelation() { double? carbsRatio; double? portionSize; double? carbsPerPortion; @@ -265,7 +264,7 @@ class _MealDetailScreenState extends State { if (carbsRatio != null && portionSize != null && carbsPerPortion == null) { setState(() { _carbsPerPortionController.text = - Utils.calculateCarbsPerPortion(carbsRatio!, portionSize!) + Utils.calculateCarbs(carbsRatio!, portionSize!) .toString(); }); } diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 1e5e6e4..e49a6da 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -14,7 +14,7 @@ class Utils { return (mmolPerL * 18.018).round(); } - static double calculateCarbsPerPortion( + static double calculateCarbs( double carbsRatio, double portionSize) { return Utils.roundToDecimalPlaces(carbsRatio * portionSize / 100, 2); }