Skip to content

Commit

Permalink
29 my zone app settings tab (#36)
Browse files Browse the repository at this point in the history
* got that profile rocking

* track data loading

* skeletons 1

* macros part of onboarding

* got rid of macro

* progress

* weight better

* steps almost good

* refreshing nicely

* clean up activity data

* scanner fixed

* rename

* refactored all to activityManager

* save last logged weight

* pre redo

* style almost complete
  • Loading branch information
seesharpguy authored Jan 5, 2025
1 parent 7b3339a commit e65c8a0
Show file tree
Hide file tree
Showing 61 changed files with 3,321 additions and 1,685 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ generate:
dart run build_runner build --delete-conflicting-outputs

mobile: generate
flutter run --target lib/main.dart
flutter run --profile --target lib/main.dart

build-android: generate
flutter build appbundle --release --target lib/main.dart
Expand Down
Binary file added assets/images/powered_by_fatsecret.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 14 additions & 11 deletions lib/app/models/activity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,36 +27,39 @@ class HeartRateRecord {
}
}

/// Class representing a calorie burned record.
class CalorieBurnedRecord {
class ZonePointRecord {
final String uuid;
final double numericValue;
final String unit;
final int zonePoints;
final DateTime dateFrom;
final DateTime dateTo;
final String sourceName;

CalorieBurnedRecord({
ZonePointRecord({
required this.uuid,
required this.numericValue,
required this.unit,
required this.zonePoints,
required this.dateFrom,
required this.dateTo,
required this.sourceName,
});

factory CalorieBurnedRecord.fromJson(Map<String, dynamic> json) {
return CalorieBurnedRecord(
factory ZonePointRecord.fromJson(Map<String, dynamic> json) {
return ZonePointRecord(
uuid: json['uuid'],
numericValue: (json['value']['numericValue'] as num).toDouble(),
unit: json['unit'],
zonePoints: json['zonePoints'] as int,
dateFrom: DateTime.parse(json['dateFrom']),
dateTo: DateTime.parse(json['dateTo']),
sourceName: json['sourceName'],
);
}
}

class WeightDataRecord {
final String date;
final double weight;

WeightDataRecord(this.date, this.weight);
}

/// Class representing a step record.
class StepRecord {
final String uuid;
Expand Down
155 changes: 142 additions & 13 deletions lib/app/models/food.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:health/health.dart';
import 'package:openfoodfacts/openfoodfacts.dart' as openfoodfacts;
import 'dart:convert';

class FoodSearchResponse {
final int totalHits;
Expand Down Expand Up @@ -46,62 +47,109 @@ class OpenFoodFactsFood {
final brand = product.brands ?? 'N/A';
final nutriments = product.nutriments;

// Conversion factor from 100g to 1 oz (1 oz = 28.3495g)
const double gramsPerOunce = 28.3495;

// Determine if conversion is needed based on nutrition_data_per
final isPer100g = product.nutrimentDataPer == '100g';

List<OpenFoodFactsNutriment> nutrients = [
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.energyKCal.name,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.energyKCal, openfoodfacts.PerSize.serving) ??
openfoodfacts.Nutrient.energyKCal,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'kcal'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.proteins.name,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.proteins, openfoodfacts.PerSize.serving) ??
openfoodfacts.Nutrient.proteins,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'g'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.fat.name,
amount: nutriments?.getValue(openfoodfacts.Nutrient.fat, openfoodfacts.PerSize.serving) ??
amount: nutriments?.getValue(
openfoodfacts.Nutrient.fat,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'g'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.carbohydrates.name,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.carbohydrates, openfoodfacts.PerSize.serving) ??
openfoodfacts.Nutrient.carbohydrates,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'g'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.sugars.name,
amount:
nutriments?.getValue(openfoodfacts.Nutrient.sugars, openfoodfacts.PerSize.serving) ??
0.0,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.sugars,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'g'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.saturatedFat.name,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.saturatedFat, openfoodfacts.PerSize.serving) ??
openfoodfacts.Nutrient.saturatedFat,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'g'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.sodium.name,
amount:
nutriments?.getValue(openfoodfacts.Nutrient.sodium, openfoodfacts.PerSize.serving) ??
0.0,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.sodium,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'g'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.cholesterol.name,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.cholesterol, openfoodfacts.PerSize.serving) ??
openfoodfacts.Nutrient.cholesterol,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'mg'),
OpenFoodFactsNutriment(
name: openfoodfacts.Nutrient.potassium.name,
amount: nutriments?.getValue(
openfoodfacts.Nutrient.potassium, openfoodfacts.PerSize.serving) ??
openfoodfacts.Nutrient.potassium,
isPer100g
? openfoodfacts.PerSize.oneHundredGrams
: openfoodfacts.PerSize.serving) ??
0.0,
unitName: 'g'),
];

// Convert nutrients to 1 oz serving size if nutrition_data_per is '100g'
if (isPer100g) {
nutrients = nutrients.map((nutrient) {
return OpenFoodFactsNutriment(
name: nutrient.name,
amount: (nutrient.amount / 100) * gramsPerOunce,
unitName: nutrient.unitName,
);
}).toList();
product.servingSize = '1 oz';
product.servingQuantity = 1.0;
}

// Parse serving size
String servingSizeStr = product.servingSize ?? '';
double servingSize = product.servingQuantity ?? 0.0;
Expand Down Expand Up @@ -599,3 +647,84 @@ class UsdaFoodNutrient {
);
}
}

class FatSecretFood {
final String foodId;
final String foodName;
final String foodType;
final String foodUrl;
final List<String> foodImages; // Assuming a list of image URLs
final List<FatSecretServing> servings;

FatSecretFood({
required this.foodId,
required this.foodName,
required this.foodType,
required this.foodUrl,
required this.foodImages,
required this.servings,
});

factory FatSecretFood.fromJson(Map<String, dynamic> json) {
return FatSecretFood(
foodId: json['food_id'],
foodName: json['food_name'],
foodType: json['food_type'],
foodUrl: json['food_url'],
foodImages: List<String>.from(json['food_images']['food_image'].map((img) => img['image_url'])),
servings: List<FatSecretServing>.from(json['servings']['serving'].map((serving) => FatSecretServing.fromJson(serving))),
);
}
}

class FatSecretServing {
final String servingId;
final String servingDescription;
final double calories;
final double protein;
final double fat;
final double carbohydrates;

FatSecretServing({
required this.servingId,
required this.servingDescription,
required this.calories,
required this.protein,
required this.fat,
required this.carbohydrates,
});

factory FatSecretServing.fromJson(Map<String, dynamic> json) {
return FatSecretServing(
servingId: json['serving_id'],
servingDescription: json['serving_description'],
calories: double.parse(json['calories']),
protein: double.parse(json['protein']),
fat: double.parse(json['fat']),
carbohydrates: double.parse(json['carbohydrate']),
);
}
}

class FatSecretFoodSearchResult {
final int maxResults;
final int totalResults;
final int pageNumber;
final List<FatSecretFood> foods;

FatSecretFoodSearchResult({
required this.maxResults,
required this.totalResults,
required this.pageNumber,
required this.foods,
});

factory FatSecretFoodSearchResult.fromJson(Map<String, dynamic> json) {
return FatSecretFoodSearchResult(
maxResults: json['foods_search']['max_results'],
totalResults: json['foods_search']['total_results'],
pageNumber: json['foods_search']['page_number'],
foods: List<FatSecretFood>.from(json['foods_search']['results']['food'].map((food) => FatSecretFood.fromJson(food))),
);
}
}
30 changes: 19 additions & 11 deletions lib/app/models/user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,64 +34,72 @@ class Zone2User {

class ZoneSettings {
final Timestamp journeyStartDate;
final int dailyWaterGoalInOz;
final int dailyZonePointsGoal;
final double dailyCalorieIntakeGoal;
final double dailyCaloriesBurnedGoal;
final int dailyStepsGoal;
int dailyWaterGoalInOz;
int dailyZonePointsGoal;
double dailyCalorieIntakeGoal;
int dailyStepsGoal;
final String reasonForStartingJourney;
final double initialWeightInLbs;
final double targetWeightInLbs;
final double heightInInches;
final int heightInFeet;
final String birthDate;
final String gender;
double zone2ProteinTarget;
double zone2CarbsTarget;
double zone2FatTarget;

ZoneSettings(
{required this.journeyStartDate,
required this.dailyWaterGoalInOz,
required this.dailyZonePointsGoal,
required this.dailyCalorieIntakeGoal,
required this.dailyCaloriesBurnedGoal,
required this.dailyStepsGoal,
required this.reasonForStartingJourney,
required this.initialWeightInLbs,
required this.targetWeightInLbs,
required this.heightInInches,
required this.heightInFeet,
required this.birthDate,
required this.gender});
required this.gender,
required this.zone2ProteinTarget,
required this.zone2CarbsTarget,
required this.zone2FatTarget});

factory ZoneSettings.fromJson(Map data) {
return ZoneSettings(
journeyStartDate: data['journeyStartDate'] as Timestamp? ?? Timestamp.now(),
dailyWaterGoalInOz: (data['dailyWaterGoalInOz'] as num?)?.toInt() ?? 100,
dailyZonePointsGoal: (data['dailyZonePointsGoal'] as num?)?.toInt() ?? 100,
dailyCalorieIntakeGoal: (data['dailyCalorieIntakeGoal'] as num?)?.toDouble() ?? 0.0,
dailyCaloriesBurnedGoal: (data['dailyCaloriesBurnedGoal'] as num?)?.toDouble() ?? 0.0,
dailyStepsGoal: (data['dailyStepsGoal'] as num?)?.toInt() ?? 10000,
reasonForStartingJourney: data['reasonForStartingJourney'] as String? ?? '',
initialWeightInLbs: (data['initialWeightInLbs'] as num?)?.toDouble() ?? 0.0,
targetWeightInLbs: (data['targetWeightInLbs'] as num?)?.toDouble() ?? 0.0,
heightInInches: (data['heightInInches'] as num?)?.toDouble() ?? 0.0,
heightInFeet: (data['heightInFeet'] as num?)?.toInt() ?? 0,
birthDate: data['birthDate'] as String? ?? '',
gender: data['gender'] as String? ?? '');
gender: data['gender'] as String? ?? '',
zone2ProteinTarget: (data['zone2ProteinTarget'] as num?)?.toDouble() ?? 0.0,
zone2CarbsTarget: (data['zone2CarbsTarget'] as num?)?.toDouble() ?? 0.0,
zone2FatTarget: (data['zone2FatTarget'] as num?)?.toDouble() ?? 0.0);
}

Map<String, dynamic> toJson() => {
"journeyStartDate": journeyStartDate,
"dailyWaterGoalInOz": dailyWaterGoalInOz,
"dailyZonePointsGoal": dailyZonePointsGoal,
"dailyCalorieIntakeGoal": dailyCalorieIntakeGoal,
"dailyCaloriesBurnedGoal": dailyCaloriesBurnedGoal,
"dailyStepsGoal": dailyStepsGoal,
"reasonForStartingJourney": reasonForStartingJourney,
"initialWeightInLbs": initialWeightInLbs,
"targetWeightInLbs": targetWeightInLbs,
"heightInInches": heightInInches,
"heightInFeet": heightInFeet,
"birthDate": birthDate,
"gender": gender
"gender": gender,
"zone2ProteinTarget": zone2ProteinTarget,
"zone2CarbsTarget": zone2CarbsTarget,
"zone2FatTarget": zone2FatTarget
};
}
Loading

0 comments on commit e65c8a0

Please sign in to comment.