feat: meal tracking, dish recognition UX improvements, English AI prompts
Backend: - Translate all recognition prompts (receipt, products, dish) from Russian to English - Add lang parameter to Recognizer interface and pass locale.FromContext in handlers - DishResult type uses candidates array for multi-candidate responses Client: - Add meal tracking: diary provider, date selector, meal type model - DishResult parser: backward-compatible with legacy flat format and new candidates format - DishResultScreen: sticky bottom button, full-width portion/meal-type inputs, КБЖУ disclaimer moved under nutrition card, add date field to diary POST body - Recognition prompts now return dish/product names in user's preferred language - Onboarding, profile, home screen visual updates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
29
client/lib/shared/models/meal_type.dart
Normal file
29
client/lib/shared/models/meal_type.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
/// A configurable meal type that the user tracks throughout the day.
|
||||
class MealTypeOption {
|
||||
final String id;
|
||||
final String label;
|
||||
final String emoji;
|
||||
|
||||
const MealTypeOption({
|
||||
required this.id,
|
||||
required this.label,
|
||||
required this.emoji,
|
||||
});
|
||||
}
|
||||
|
||||
/// All meal types available for selection.
|
||||
const kAllMealTypes = [
|
||||
MealTypeOption(id: 'breakfast', label: 'Завтрак', emoji: '🌅'),
|
||||
MealTypeOption(id: 'second_breakfast', label: 'Второй завтрак', emoji: '☕'),
|
||||
MealTypeOption(id: 'lunch', label: 'Обед', emoji: '🍽️'),
|
||||
MealTypeOption(id: 'afternoon_snack', label: 'Полдник', emoji: '🥗'),
|
||||
MealTypeOption(id: 'dinner', label: 'Ужин', emoji: '🌙'),
|
||||
MealTypeOption(id: 'snack', label: 'Перекус', emoji: '🍎'),
|
||||
];
|
||||
|
||||
/// Default meal type IDs assigned to new users.
|
||||
const kDefaultMealTypeIds = ['breakfast', 'lunch', 'dinner'];
|
||||
|
||||
/// Returns the [MealTypeOption] for the given [id], or null if not found.
|
||||
MealTypeOption? mealTypeById(String id) =>
|
||||
kAllMealTypes.where((option) => option.id == id).firstOrNull;
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
import 'meal_type.dart';
|
||||
|
||||
part 'user.g.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
@@ -59,4 +61,12 @@ class User {
|
||||
bool get hasCompletedOnboarding =>
|
||||
heightCm != null && weightKg != null && dateOfBirth != null &&
|
||||
gender != null && goal != null && activity != null;
|
||||
|
||||
/// Returns the user's configured meal type IDs from preferences,
|
||||
/// falling back to the default set if not yet configured.
|
||||
List<String> get mealTypes {
|
||||
final value = preferences['meal_types'];
|
||||
if (value is List && value.isNotEmpty) return List<String>.from(value);
|
||||
return List<String>.from(kDefaultMealTypeIds);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user