Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

edit meals: make base quantity customizable #115

Merged
merged 6 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading