Files
food-ai/client
dbastrikin b9b9e9fe11 feat: implement Iteration 2 — product management
Backend:
- migrations/005: add pg_trgm extension + search indexes on ingredient_mappings
- migrations/006: products table with computed expires_at column
- ingredient: add Search method (aliases + ILIKE + trgm) + HTTP handler
- product: full package — model, repository (CRUD + BatchCreate + ListForPrompt), handler
- gemini: add AvailableProducts field to RecipeRequest, include in prompt
- recommendation: add ProductLister interface, load user products for personalised prompts
- server/main: wire ingredient and product handlers with new routes

Flutter:
- models: Product, IngredientMapping with json_serializable
- ProductService: getProducts, createProduct, updateProduct, deleteProduct, searchIngredients
- ProductsNotifier: create/update/delete with optimistic delete
- ProductsScreen: expiring-soon section, normal section, swipe-to-delete, edit bottom sheet
- AddProductScreen: name field with 300ms debounce autocomplete, qty/unit/days fields
- app_router: /products/add route + Badge on Products nav tab showing expiring count
- MainShell converted to ConsumerWidget for badge reactivity

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 23:22:30 +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.