feat: implement Iteration 0 foundation (backend + Flutter client)
Backend (Go): - Project structure with chi router, pgxpool, goose migrations - JWT auth (access/refresh tokens) with Firebase token verification - NoopTokenVerifier for local dev without Firebase credentials - PostgreSQL user repository with atomic profile updates (transactions) - Mifflin-St Jeor calorie calculation based on profile data - REST API: POST /auth/login, /auth/refresh, /auth/logout, GET/PUT /profile, GET /health - Middleware: auth, CORS (localhost wildcard), logging, recovery, request_id - Unit tests (51 passing) and integration tests (testcontainers) - Docker Compose setup with postgres healthcheck and graceful shutdown Flutter client: - Riverpod state management with GoRouter navigation - Firebase Auth (email/password + Google sign-in with web popup support) - Platform-aware API URLs (web/Android/iOS) - Dio HTTP client with JWT auth interceptor and concurrent refresh handling - Secure token storage - Screens: Login, Register, Home (tabs: Menu, Recipes, Products, Profile) - Unit tests (17 passing) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
151
client/README.md
Normal file
151
client/README.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# 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`.
|
||||
Reference in New Issue
Block a user