Skip to content

Commit

Permalink
Merge pull request #115 from shoutingcatana/base-quantity
Browse files Browse the repository at this point in the history
edit meals: make base quantity customizable
  • Loading branch information
simonoppowa authored Sep 27, 2024
2 parents 25a7361 + 0c70159 commit 550a3f3
Show file tree
Hide file tree
Showing 13 changed files with 362 additions and 201 deletions.
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
use flake
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release

# nix related
result
.direnv/
59 changes: 59 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
description = "Flutter 3.19.x";
inputs = {
nixpkgs.url = "nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
config = {
android_sdk.accept_license = true;
allowUnfree = true;
};
};
androidPkgs = (pkgs.androidenv.composeAndroidPackages {
platformVersions = [ "27" "29" "31" "33" "34" ];
buildToolsVersions = [ "30.0.3" ];
includeEmulator = true;
includeSystemImages = true;
});
# TODO: graphics are a bit weird
emulator = pkgs.androidenv.emulateApp {
name = "flutter_emu";
platformVersion = "27";
abiVersion = "x86"; # armeabi-v7a, mips, x86_64
systemImageType = "google_apis_playstore";
deviceName = "pixel";
};
in
{
# run once:
# avdmanager create avd -n flutter_emulator -k 'system-images;android-27;google_apis_playstore;x86' -d pixel
# flutter emulators --launch flutter_emulator
# flutter pub run build_runner build --delete-conflicting-outputs
devShells.default = pkgs.mkShell {
ANDROID_SDK_ROOT = "${androidPkgs.androidsdk}/libexec/android-sdk";
buildInputs = [
pkgs.flutter319
pkgs.jdk17
androidPkgs.androidsdk
emulator # execute emulator with: run-test-emulator
];
};
});
}
24 changes: 17 additions & 7 deletions lib/features/edit_meal/presentation/bloc/edit_meal_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,29 @@ class EditMealBloc {
String brandsText,
String mealQuantityText,
String servingQuantityText,
String baseQuantity,
String? unitText,
String kcalText,
String carbsText,
String fatText,
String proteinText) {

final baseQuantityDouble = double.tryParse(baseQuantity);

final double factorTo100g = baseQuantityDouble != null ? (100/baseQuantityDouble): 1;

double? multiplyIfNotNull(double? nutritmentValue) {
return nutritmentValue != null ? nutritmentValue * factorTo100g: null;
}

final newMealNutriments = MealNutrimentsEntity(
energyKcal100: kcalText.toDoubleOrNull(),
carbohydrates100: carbsText.toDoubleOrNull(),
fat100: fatText.toDoubleOrNull(),
proteins100: proteinText.toDoubleOrNull(),
sugars100: oldMealEntity.nutriments.sugars100,
saturatedFat100: oldMealEntity.nutriments.saturatedFat100,
fiber100: oldMealEntity.nutriments.fiber100);
energyKcal100: multiplyIfNotNull(kcalText.toDoubleOrNull()),
carbohydrates100: multiplyIfNotNull(carbsText.toDoubleOrNull()),
fat100: multiplyIfNotNull(fatText.toDoubleOrNull()),
proteins100: multiplyIfNotNull(proteinText.toDoubleOrNull()),
sugars100: multiplyIfNotNull(oldMealEntity.nutriments.sugars100),
saturatedFat100: multiplyIfNotNull(oldMealEntity.nutriments.saturatedFat100),
fiber100: multiplyIfNotNull(oldMealEntity.nutriments.fiber100));

return MealEntity(
code: oldMealEntity.code,
Expand Down
55 changes: 38 additions & 17 deletions lib/features/edit_meal/presentation/edit_meal_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,30 @@ class _EditMealScreenState extends State<EditMealScreen> {
final _brandsTextController = TextEditingController();
final _mealQuantityTextController = TextEditingController();
final _servingQuantityTextController = TextEditingController();
final _baseQuantityTextController = TextEditingController();
final _kcalTextController = TextEditingController();
final _carbsTextController = TextEditingController();
final _fatTextController = TextEditingController();
final _proteinTextController = TextEditingController();

final _dropdownValues = ['g', 'ml', 'g/ml'];
final _units = ['g', 'ml', 'g/ml'];
late String? _dropdownUnitValue;
late List<DropdownMenuItem> _mealUnitDropdownItems;

String baseQuantity = "100";
String baseQuantityUnit = " g/ml";


@override
void initState() {
_editMealBloc = locator<EditMealBloc>();
super.initState();

_baseQuantityTextController.addListener(() {
setState(() {
baseQuantity = _baseQuantityTextController.text;
});
});
}

@override
Expand All @@ -72,11 +83,11 @@ class _EditMealScreenState extends State<EditMealScreen> {

_mealUnitDropdownItems = <DropdownMenuItem>[
DropdownMenuItem(
value: _dropdownValues[0], child: Text(S.of(context).gramUnit)),
value: _units[0], child: Text(S.of(context).gramUnit)),
DropdownMenuItem(
value: _dropdownValues[1], child: Text(S.of(context).milliliterUnit)),
value: _units[1], child: Text(S.of(context).milliliterUnit)),
DropdownMenuItem(
value: _dropdownValues[2],
value: _units[2],
child: Text(S.of(context).gramMilliliterUnit)),
];

Expand Down Expand Up @@ -135,7 +146,7 @@ class _EditMealScreenState extends State<EditMealScreen> {
decoration: InputDecoration(
labelText: S.of(context).mealSizeLabel,
border: const OutlineInputBorder()),
keyboardType: TextInputType.numberWithOptions(decimal: true),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
const SizedBox(height: 16),
TextFormField(
Expand All @@ -144,11 +155,11 @@ class _EditMealScreenState extends State<EditMealScreen> {
decoration: InputDecoration(
labelText: S.of(context).servingSizeLabel,
border: const OutlineInputBorder()),
keyboardType: TextInputType.numberWithOptions(decimal: true),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
const SizedBox(height: 16),
DropdownButtonFormField(
value: _dropdownUnitValue ?? _dropdownValues.first,
value: _dropdownUnitValue ?? _units.first,
items: _mealUnitDropdownItems,
onChanged: (text) {
_dropdownUnitValue = _switchDropdownUnit(text);
Expand All @@ -158,40 +169,49 @@ class _EditMealScreenState extends State<EditMealScreen> {
border: const OutlineInputBorder()),
),
const SizedBox(height: 48),
TextFormField(
controller: _baseQuantityTextController,
inputFormatters: CustomTextInputFormatter.doubleOnly(),
decoration: InputDecoration(
labelText: S.of(context).baseQuantityLabel,
border: const OutlineInputBorder()),
keyboardType: TextInputType.number,
),
const SizedBox(height: 48),
TextFormField(
controller: _kcalTextController,
inputFormatters: CustomTextInputFormatter.doubleOnly(),
decoration: InputDecoration(
labelText: S.of(context).mealKcalLabel,
labelText: S.of(context).mealKcalLabel+baseQuantity+baseQuantityUnit,
border: const OutlineInputBorder()),
keyboardType: TextInputType.numberWithOptions(decimal: true),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
const SizedBox(height: 16),
TextFormField(
controller: _carbsTextController,
inputFormatters: CustomTextInputFormatter.doubleOnly(),
decoration: InputDecoration(
labelText: S.of(context).mealCarbsLabel,
labelText: S.of(context).mealCarbsLabel+baseQuantity+baseQuantityUnit,
border: const OutlineInputBorder()),
keyboardType: TextInputType.numberWithOptions(decimal: true),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
const SizedBox(height: 16),
TextFormField(
controller: _fatTextController,
inputFormatters: CustomTextInputFormatter.doubleOnly(),
decoration: InputDecoration(
labelText: S.of(context).mealFatLabel,
labelText: S.of(context).mealFatLabel+baseQuantity+baseQuantityUnit,
border: const OutlineInputBorder()),
keyboardType: TextInputType.numberWithOptions(decimal: true),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
const SizedBox(height: 16),
TextFormField(
controller: _proteinTextController,
inputFormatters: CustomTextInputFormatter.doubleOnly(),
decoration: InputDecoration(
labelText: S.of(context).mealProteinLabel,
labelText: S.of(context).mealProteinLabel+baseQuantity+baseQuantityUnit,
border: const OutlineInputBorder()),
keyboardType: TextInputType.numberWithOptions(decimal: true),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
],
),
Expand All @@ -206,6 +226,7 @@ class _EditMealScreenState extends State<EditMealScreen> {
_brandsTextController.text,
_mealQuantityTextController.text,
_servingQuantityTextController.text,
_baseQuantityTextController.text,
_dropdownUnitValue,
_kcalTextController.text,
_carbsTextController.text,
Expand All @@ -228,8 +249,8 @@ class _EditMealScreenState extends State<EditMealScreen> {

String? _switchDropdownUnit(String? unit) {
String? dropdownValue;
if (!_dropdownValues.contains(unit)) {
dropdownValue = _dropdownValues.first;
if (!_units.contains(unit)) {
dropdownValue = _units.first;
} else {
dropdownValue = unit;
}
Expand Down
4 changes: 4 additions & 0 deletions lib/generated/intl/messages_de.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ class MessageLookup extends MessageLookupByLibrary {
"dinnerLabel": MessageLookupByLibrary.simpleMessage("Abendessen"),
"disclaimerText": MessageLookupByLibrary.simpleMessage(
"OpenNutriTracker ist keine medizinische Anwendung. Alle bereitgestellten Daten sind nicht validiert und sollten mit Vorsicht verwendet werden. Bitte pflegen Sie einen gesunden Lebensstil und konsultieren Sie einen Fachmann, wenn Sie Probleme haben. Die Verwendung während einer Krankheit, Schwangerschaft oder Stillzeit wird nicht empfohlen.\n\n\nDie Anwendung befindet sich noch in der Entwicklung. Fehler, Bugs und Abstürze können auftreten."),
"editItemDialogTitle":
MessageLookupByLibrary.simpleMessage("Eintrag aktualisieren"),
"editMealLabel":
MessageLookupByLibrary.simpleMessage("Mahlzeit bearbeiten"),
"energyLabel": MessageLookupByLibrary.simpleMessage("Energie"),
Expand Down Expand Up @@ -139,6 +141,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Neue Aufnahme hinzugefügt"),
"itemDeletedSnackbar":
MessageLookupByLibrary.simpleMessage("Eintrag gelöscht"),
"itemUpdatedSnackbar":
MessageLookupByLibrary.simpleMessage("Eintrag aktualisiert"),
"kcalLabel": MessageLookupByLibrary.simpleMessage("kcal"),
"kcalLeftLabel": MessageLookupByLibrary.simpleMessage("kcal übrig"),
"kgLabel": MessageLookupByLibrary.simpleMessage("kg"),
Expand Down
15 changes: 9 additions & 6 deletions lib/generated/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("GPL-3.0 license"),
"appTitle": MessageLookupByLibrary.simpleMessage("OpenNutriTracker"),
"appVersionName": m0,
"baseQuantityLabel":
MessageLookupByLibrary.simpleMessage("Base quantity (g/ml)"),
"betaVersionName": MessageLookupByLibrary.simpleMessage("[Beta]"),
"bmiInfo": MessageLookupByLibrary.simpleMessage(
"Body Mass Index (BMI) is a index to classify overweight and obesity in adults. It is defined as weight in kilograms divided by the square of height in meters (kg/m²).\n\nBMI does not differentiate between fat and muscle mass and can be misleading for some individuals."),
Expand Down Expand Up @@ -100,6 +102,8 @@ class MessageLookup extends MessageLookupByLibrary {
"dinnerLabel": MessageLookupByLibrary.simpleMessage("Dinner"),
"disclaimerText": MessageLookupByLibrary.simpleMessage(
"OpenNutriTracker is not a medical application. All data provided is not validated and should be used with caution. Please maintain a healthy lifestyle and consult a professional if you have any problems. Use during illness, pregnancy or lactation is not recommended.\n\n\nThe application is still under development. Errors, bugs and crashes may occur."),
"editItemDialogTitle":
MessageLookupByLibrary.simpleMessage("Edit item"),
"editMealLabel": MessageLookupByLibrary.simpleMessage("Edit meal"),
"energyLabel": MessageLookupByLibrary.simpleMessage("energy"),
"errorFetchingProductData": MessageLookupByLibrary.simpleMessage(
Expand Down Expand Up @@ -134,19 +138,18 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Added new intake"),
"itemDeletedSnackbar":
MessageLookupByLibrary.simpleMessage("Item deleted"),
"itemUpdatedSnackbar":
MessageLookupByLibrary.simpleMessage("Item updated"),
"kcalLabel": MessageLookupByLibrary.simpleMessage("kcal"),
"kcalLeftLabel": MessageLookupByLibrary.simpleMessage("kcal left"),
"kgLabel": MessageLookupByLibrary.simpleMessage("kg"),
"lunchExample":
MessageLookupByLibrary.simpleMessage("e.g. pizza, salad, rice ..."),
"lunchLabel": MessageLookupByLibrary.simpleMessage("Lunch"),
"mealBrandsLabel": MessageLookupByLibrary.simpleMessage("Brands"),
"mealCarbsLabel":
MessageLookupByLibrary.simpleMessage("carbs per 100 g/ml"),
"mealFatLabel":
MessageLookupByLibrary.simpleMessage("fat per 100 g/ml"),
"mealKcalLabel":
MessageLookupByLibrary.simpleMessage("kcal per 100 g/ml"),
"mealCarbsLabel": MessageLookupByLibrary.simpleMessage("carbs per"),
"mealFatLabel": MessageLookupByLibrary.simpleMessage("fat per"),
"mealKcalLabel": MessageLookupByLibrary.simpleMessage("kcal per"),
"mealNameLabel": MessageLookupByLibrary.simpleMessage("Meal name"),
"mealProteinLabel":
MessageLookupByLibrary.simpleMessage("protein per 100 g/ml"),
Expand Down
Loading

0 comments on commit 550a3f3

Please sign in to comment.