# 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. Установить зависимости ```bash flutter pub get ``` ### 2. Настроить Firebase 1. Создайте проект в [Firebase Console](https://console.firebase.google.com) 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/`: ```bash 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`: ```bash 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 → **Settings** → **Authorized domains** > **Важно:** не коммитить конфиг-файлы в git: > ```bash > echo "android/app/google-services.json" >> .gitignore > echo "ios/Runner/GoogleService-Info.plist" >> .gitignore > ``` ### 3. Настроить URL бэкенда Откройте `lib/core/config/app_config.dart` и укажите адрес API: ```dart 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. Сгенерировать код ```bash flutter pub run build_runner build --delete-conflicting-outputs ``` ### 5. Запустить приложение ```bash 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`.