Files
fitness/mobile/lib/models/meal_entry.dart
T

85 lines
2.7 KiB
Dart

enum MealType { breakfast, lunch, dinner, snack }
enum MealSource { manual, photoAi }
enum MealSyncStatus { pending, synced, failed }
class MealEntry {
MealEntry({
required this.id,
required this.name,
required this.mealType,
required this.calories,
required this.proteinGrams,
required this.carbohydrateGrams,
required this.fatGrams,
required this.consumedAt,
this.source = MealSource.manual,
this.notes = '',
this.syncStatus = MealSyncStatus.pending,
});
final String id;
final String name;
final MealType mealType;
final double calories;
final double proteinGrams;
final double carbohydrateGrams;
final double fatGrams;
final DateTime consumedAt;
final MealSource source;
final String notes;
MealSyncStatus syncStatus;
Map<String, dynamic> toMap() => {
'id': id,
'name': name,
'meal_type': mealType.name,
'calories': calories,
'protein_grams': proteinGrams,
'carbohydrate_grams': carbohydrateGrams,
'fat_grams': fatGrams,
'consumed_at': consumedAt.toUtc().toIso8601String(),
'source': source == MealSource.photoAi ? 'photo_ai' : 'manual',
'notes': notes,
'sync_status': syncStatus.name,
};
Map<String, dynamic> toApiPayload() => {
'client_meal_uuid': id,
'name': name,
'meal_type': mealType.name,
'calories': calories,
'protein_grams': proteinGrams,
'carbohydrate_grams': carbohydrateGrams,
'fat_grams': fatGrams,
'consumed_at': consumedAt.toUtc().toIso8601String(),
'source': source == MealSource.photoAi ? 'photo_ai' : 'manual',
'notes': notes,
};
factory MealEntry.fromMap(Map<String, dynamic> map) => MealEntry(
id: map['id'] as String,
name: map['name'] as String,
mealType: MealType.values.firstWhere(
(value) => value.name == map['meal_type'],
orElse: () => MealType.snack,
),
calories: _asDouble(map['calories']),
proteinGrams: _asDouble(map['protein_grams']),
carbohydrateGrams: _asDouble(map['carbohydrate_grams']),
fatGrams: _asDouble(map['fat_grams']),
consumedAt: DateTime.parse(map['consumed_at'] as String).toLocal(),
source: map['source'] == 'photo_ai' || map['source'] == 'photoAi'
? MealSource.photoAi
: MealSource.manual,
notes: map['notes'] as String? ?? '',
syncStatus: MealSyncStatus.values.firstWhere(
(value) => value.name == map['sync_status'],
orElse: () => MealSyncStatus.pending,
),
);
}
double _asDouble(dynamic value) => value is num ? value.toDouble() : 0;