Files
food-ai/client
dbastrikin 5096df2102 fix: fix menu generation errors and show planned meals on home screen
Backend fixes:
- migration 003: add 'menu' value to recipe_source enum (was causing SQLSTATE 22P02)
- migration 004: rename recipe_products→recipe_ingredients, product_id→ingredient_id (was causing SQLSTATE 42P01)
- dish/repository.go: fix INSERT INTO tags using $1/$1 for two columns → $1/$2 (was causing SQLSTATE 42P08)
- home/handler.go: replace non-existent saved_recipes table with correct joins (recipes→dishes→dish_translations, user_saved_recipes) so today's plan and recommendations load correctly
- reqlog: new slog.Handler wrapper that adds request_id and stack trace to ERROR-level logs
- all handlers: slog.Error→slog.ErrorContext so error logs include request context; writeError includes request_id in response body

Client:
- home_screen.dart: extend home screen to future dates, show planned meals as ghost entries
- l10n: add new localisation keys for home screen date navigation and planned meal UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:35:11 +02:00
..

FoodAI Client

Flutter-приложение для управления питанием с поддержкой iOS, Android и Web.

Стек

  • Flutter 3 / Dart 3 — фреймворк
  • Riverpod — управление состоянием
  • go_router — навигация с auth guard
  • Dio — HTTP-клиент с автоматическим обновлением токенов
  • Firebase Auth — аутентификация (email + Google)
  • flutter_secure_storage — безопасное хранение токенов
  • json_serializable — генерация сериализации моделей

Требования

  • Flutter SDK 3.x (flutter --version)
  • Dart SDK 3.9+
  • Android Studio или Xcode (для запуска на симуляторе/устройстве)
  • Chrome (для запуска в браузере)
  • Проект Firebase с включёнными Email и Google Sign-In

Быстрый старт

1. Установить зависимости

flutter pub get

2. Настроить Firebase

  1. Создайте проект в Firebase Console
  2. Включите Authentication → Sign-in method: Email/Password и Google

Android

  1. Project Settings (⚙️) → Your apps → иконка Android (🤖)
  2. Package name: com.foodai.food_ai
  3. Скачать google-services.json → положить в android/app/:
cp ~/Downloads/google-services.json android/app/google-services.json

iOS

  1. Project Settings (⚙️) → Your apps → иконка iOS (``)
  2. Bundle ID: com.foodai.foodAi
  3. Скачать GoogleService-Info.plist → добавить через Xcode в группу Runner:
open ios/Runner.xcworkspace
# Перетащить GoogleService-Info.plist в группу Runner в навигаторе Xcode

Web

  1. Project Settings (⚙️) → Your apps → иконка Web (</>)
  2. Nickname: FoodAI Web
  3. Скопировать полученный firebaseConfig в web/index.html, заменив YOUR_* placeholder'ы
  4. Убедиться, что localhost есть в списке авторизованных доменов: Authentication → SettingsAuthorized domains

Важно: не коммитить конфиг-файлы в git:

echo "android/app/google-services.json" >> .gitignore
echo "ios/Runner/GoogleService-Info.plist" >> .gitignore

3. Настроить URL бэкенда

Откройте lib/core/config/app_config.dart и укажите адрес API:

static const development = AppConfig(
  apiBaseUrl: 'http://10.0.2.2:9090', // Android-эмулятор → localhost:9090
  // apiBaseUrl: 'http://localhost:9090', // iOS-симулятор / Web
);

static const production = AppConfig(
  apiBaseUrl: 'https://api.food-ai.app',
);

Бэкенд по умолчанию поднимается на порту 9090 через Docker Compose (9090:8080).

4. Сгенерировать код

flutter pub run build_runner build --delete-conflicting-outputs

5. Запустить приложение

flutter run

Команды

Команда Описание
flutter pub get Установить зависимости
flutter run Запустить на подключённом устройстве/симуляторе
flutter run -d chrome Запустить в браузере (web)
flutter test Запустить все тесты
flutter analyze Статический анализ кода
flutter build apk Собрать APK для Android
flutter build ios Собрать для iOS
flutter pub run build_runner build Сгенерировать код (json_serializable)
flutter pub run build_runner watch Следить за изменениями и генерировать

Структура проекта

client/
├── lib/
│   ├── core/
│   │   ├── api/            # ApiClient (Dio), AuthInterceptor, исключения
│   │   ├── auth/           # AuthService, AuthNotifier (Riverpod), SecureStorage
│   │   ├── config/         # AppConfig (URL бэкенда по окружению)
│   │   ├── router/         # GoRouter с auth guard и MainShell
│   │   └── theme/          # Цвета и тема Material 3
│   ├── features/
│   │   ├── auth/           # LoginScreen, RegisterScreen
│   │   ├── home/           # HomeScreen (placeholder)
│   │   ├── menu/           # MenuScreen (placeholder)
│   │   ├── products/       # ProductsScreen (placeholder)
│   │   ├── profile/        # ProfileScreen (placeholder)
│   │   └── recipes/        # RecipesScreen (placeholder)
│   ├── shared/
│   │   └── models/         # User (json_serializable + user.g.dart)
│   ├── app.dart            # Корневой виджет
│   └── main.dart           # Точка входа, инициализация Firebase
└── test/
    ├── features/auth/      # Тесты LoginScreen, RegisterScreen
    └── shared/models/      # Тесты модели User

Навигация

Приложение использует go_router с guard-ом авторизации:

  • /login — экран входа (только для неавторизованных)
  • /register — экран регистрации
  • //home — главная (требует авторизации)
  • /products — продукты
  • /menu — меню дня
  • /recipes — рецепты
  • /profile — профиль пользователя

Неавторизованный пользователь автоматически перенаправляется на /login. После входа — на /home.