Files
food-ai/docs/plans/Summary.md
dbastrikin 79c32f226c docs: add Iteration 6 — profile screen
Describe ProfileService, profileProvider, ProfileScreen sections
(avatar, body params, goal/activity, daily calories, logout),
EditProfileSheet, and HomeScreen name integration.
No new backend endpoints needed — GET/PUT /profile already exist.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 15:59:09 +02:00

323 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FoodAI — План реализации
## Обзор итераций
| # | Итерация | Цель | Зависит от |
|---|----------|------|------------|
| 0 | Фундамент | Go-проект, БД, авторизация, Flutter-каркас | — |
| 1 | AI-рекомендации рецептов | GPT генерирует рецепты, Pexels фото, сохранение рецептов | 0 |
| 2 | Управление продуктами | CRUD продуктов, сроки хранения, ingredient_mappings | 0 |
| 3 | Распознавание продуктов | OCR чека, фото продуктов, фото блюд (GPT-4o Vision) | 1, 2 |
| 4 | Планирование меню | Меню на неделю, AI-генерация, список покупок, дневник | 1, 2 |
| 5 | Главный экран | Дашборд: калории, план на сегодня, истекающие продукты, рекомендации | 1, 2, 4 |
| 6 | Профиль | Просмотр и редактирование профиля, норма калорий, выход из аккаунта | 0 |
Дальнейшие итерации определяются приоритетами после MVP. Функциональность из TODO.md (дневник статистики, режим готовки, полировка) — следующий горизонт.
## Карта зависимостей
```
┌──────────────┐
│ 0. Фундамент │
└──────┬───────┘
┌────────────┴────────────┐
│ │
▼ ▼
┌────────────────────┐ ┌──────────────────┐
│ 1. AI-рекомендации │ │ 2. Продукты │
│ (Gemini+Pexels) │ │ + ingredient_ │
│ saved_recipes │ │ mappings │
└──────────┬─────────┘ └────────┬─────────┘
│ │
└────────────┬────────────┘
┌──────────┴──────────┐
│ │
▼ ▼
┌────────────────────┐ ┌─────────────────────┐
│ 3. Распознавание │ │ 4. Планирование │
│ продуктов │ │ меню │
│ (GPT-4o Vision) │ │ (GPT+Pexels) │
└────────────────────┘ └──────────┬──────────┘
┌─────────────────────┐
│ 5. Главный экран │
│ (дашборд) │
└─────────────────────┘
┌─────────────────────┐
│ 6. Профиль │ (зависит только от 0)
│ (просмотр + │
│ редактирование) │
└─────────────────────┘
```
**Параллельная разработка:** итерации 1 и 2 могут выполняться параллельно. Итерации 3 и 4 — тоже параллельно после завершения 1 и 2. Итерация 5 — после 4.
---
## Итерация 0: Фундамент
> **Детальный план:** [Iteration_0.md](./Iteration_0.md)
**Цель:** развернуть скелет проекта, базу данных, авторизацию и каркас мобильного приложения. После итерации можно зарегистрироваться, войти и увидеть пустые экраны.
**Зависимости:** нет.
### User Stories
#### Backend
| ID | Story | Описание |
|----|-------|----------|
| 0.1 | Инициализация Go-проекта | Структура проекта (cmd/, internal/, pkg/), go.mod, конфигурация (envconfig), логгер (slog), graceful shutdown |
| 0.2 | PostgreSQL + миграции | Подключение к PostgreSQL (pgx), система миграций (goose или golang-migrate). Начальная миграция: таблица `users` |
| 0.3 | HTTP-сервер + роутер | HTTP-сервер (net/http или chi), middleware (CORS, request ID, logging, recovery), healthcheck endpoint |
| 0.4 | Firebase Auth интеграция | Firebase Admin SDK. Middleware для верификации Firebase idToken. Выдача собственного JWT. Эндпоинты: `POST /auth/login`, `POST /auth/refresh`, `POST /auth/logout` |
| 0.5 | Таблица users | Миграция: users (id, firebase_uid, email, name, avatar_url, параметры тела, цель, preferences JSONB, plan, created_at). CRUD-сервис |
| 0.6 | Docker Compose | docker-compose.yml: PostgreSQL, приложение. Makefile с основными командами (migrate, run, test) |
#### Flutter
| ID | Story | Описание |
|----|-------|----------|
| 0.7 | Инициализация Flutter-проекта | Создание проекта, структура (features/, core/, shared/), подключение основных пакетов (dio, riverpod/bloc, go_router) |
| 0.8 | Firebase Auth во Flutter | Пакеты firebase_auth, google_sign_in, sign_in_with_apple. Экраны: вход (email + Google + Apple), регистрация. Хранение JWT в secure storage |
| 0.9 | Навигация и каркас экранов | Bottom Tab Bar (5 вкладок), пустые заглушки для каждого экрана, роутинг |
| 0.10 | API-клиент | Dio-клиент с interceptors: JWT-токен, refresh, error handling. Базовые модели (User) |
### Результат итерации
- Можно зарегистрироваться через email / Google / Apple
- Войти в приложение и увидеть 5 вкладок с заглушками
- Backend отвечает на healthcheck и auth-запросы
- БД содержит таблицу users с данными зарегистрированных пользователей
---
## Итерация 1: AI-рекомендации рецептов
> **Детальный план:** [Iteration_1.md](./Iteration_1.md)
**Цель:** реализовать ключевую функцию — персонализированные рецепты, сгенерированные Gemini, с фотографиями из Pexels и возможностью сохранять понравившиеся.
**Зависимости:** итерация 0.
### User Stories
#### Backend
| ID | Story | Описание |
|----|-------|----------|
| 1.1 | Gemini-клиент | Пакет internal/gemini. Интерфейс RecipeGenerator. GenerateRecipes(prompt) → []Recipe. Retry на невалидный JSON |
| 1.2 | Pexels-клиент | Пакет internal/pexels. SearchPhoto(query) → image_url. Параллельные запросы |
| 1.3 | Таблица saved_recipes | Миграция: id, user_id, title, description, cuisine, difficulty, prep/cook_time_min, servings, image_url, ingredients (JSONB), steps (JSONB), tags (JSONB), nutrition (JSONB), source, saved_at |
| 1.4 | GET /recommendations | Формирует промпт из профиля пользователя → Gemini → Pexels → ответ с image_url |
| 1.5 | CRUD saved_recipes | POST /saved-recipes, GET /saved-recipes, GET /saved-recipes/{id}, DELETE /saved-recipes/{id} |
#### Flutter
| ID | Story | Описание |
|----|-------|----------|
| 1.6 | RecommendationsScreen | Список карточек, skeleton-загрузка, кнопка 🔄 для перегенерации |
| 1.7 | RecipeDetailScreen | Фото, КБЖУ≈, ингредиенты, шаги, кнопка сохранить |
| 1.8 | SavedRecipesScreen | Список с удалением, пустое состояние |
### Результат итерации
- Пользователь открывает вкладку «Рецепты» и видит 5 персонализированных рецептов с фото
- Может сохранить рецепт, просмотреть детали, удалить из сохранённых
- КБЖУ помечены «≈» как приблизительные
---
## Итерация 2: Управление продуктами
> **Детальный план:** [Iteration_2.md](./Iteration_2.md)
**Цель:** пользователь может вести список своих продуктов вручную — добавлять через автодополнение (ingredient_mappings), редактировать, удалять, отслеживать сроки. Рекомендации становятся персонализированными: Gemini учитывает имеющиеся продукты.
**Зависимости:** итерация 0.
### User Stories
#### Backend
| ID | Story | Описание |
|----|-------|----------|
| 2.1 | Таблица products | Миграция: id, user_id, mapping_id (FK nullable), name, quantity, unit (ENUM), category, storage_days, added_at, expires_at (computed). Индексы по user_id, expires_at |
| 2.2 | Products CRUD API | `GET /products` (фильтры: category, expiring), `POST /products`, `PUT /products/{id}`, `DELETE /products/{id}`, `DELETE /products` (очистить все) |
| 2.3 | Частичное использование | `PATCH /products/{id}/consume` — уменьшить количество. Если количество = 0, предложить удаление |
| 2.4 | Массовое добавление | `POST /products/batch` — добавление нескольких продуктов за раз (после распознавания). Обработка дубликатов: проверка по mapping_id, предложение объединить |
| 2.5 | Дефолтные сроки хранения | `GET /products/storage-defaults`, `PUT /products/storage-defaults`. Хранение в user preferences (JSONB в таблице users) |
| 2.6 | Fuzzy matching при добавлении | При добавлении продукта — поиск по ingredient_mappings.aliases. Если найдено — автозаполнение: mapping_id, category, unit, storage_days, нутриенты |
#### Flutter
| ID | Story | Описание |
|----|-------|----------|
| 2.7 | Экран «Мои продукты» | Список продуктов по категориям, поиск, chip-фильтры, badge «осталось X дней» |
| 2.8 | Добавление/редактирование продукта | Форма: название, количество, единица, категория, период хранения. Выпадающее меню добавления (+) |
| 2.9 | Частичное использование | Модалка «Сколько осталось?» при свайпе или тапе |
| 2.10 | Очистить и перезаполнить | Контекстное меню (···) → подтверждение → очистка |
| 2.11 | Настройки сроков хранения | Экран из Профиля: список категорий с редактируемыми днями |
| 2.12 | Пустое состояние | Иллюстрация + CTA «Сфотографируйте продукты или сканируйте чек» |
### Результат итерации
- Пользователь может вручную добавить продукты, указать количество и сроки
- Видит «осталось X дней» для каждого продукта
- Может частично использовать продукт, удалить, очистить всё
- При добавлении — автоматический подбор категории, единицы, срока через fuzzy match
---
## Итерация 3: Распознавание продуктов
> **Детальный план:** [Iteration_3.md](./Iteration_3.md)
**Цель:** пользователь фотографирует чек, холодильник или блюдо — Gemini Vision распознаёт продукты и помогает заполнить список запасов.
**Зависимости:** итерации 1, 2.
### User Stories
#### Backend
| ID | Story | Описание |
|----|-------|----------|
| 3.1 | OCR чека | POST /ai/recognize-receipt: фото → Gemini Flash (vision) → JSON (name, qty, unit, confidence). Fuzzy match по ingredient_mappings |
| 3.2 | Фото продуктов | POST /ai/recognize-products: 13 фото → параллельные Gemini-запросы → дедупликация → JSON |
| 3.3 | Распознавание блюда | POST /ai/recognize-dish: фото → Gemini → {dish_name, weight_g, КБЖУ≈, confidence} |
| 3.4 | Авто-маппинг | Нераспознанный продукт → Gemini классифицирует → сохраняет в ingredient_mappings |
| 3.5 | S3 / multipart | Загрузка фото: multipart или presigned URL |
#### Flutter
| ID | Story | Описание |
|----|-------|----------|
| 3.6 | ScanScreen | Выбор режима: чек / продукты / блюдо. Камера + галерея |
| 3.7 | Экран подтверждения | Список с инлайн-редактированием, удалением, «Добавить ещё фото», CTA «В запасы» |
| 3.8 | Экран результата блюда | Фото, КБЖУ≈, кнопки «В дневник» / «Открыть рецепт» |
### Результат итерации
- Сфотографировал чек → список продуктов → подтвердил → добавил в запасы
- Сфотографировал холодильник → то же
- Сфотографировал блюдо → КБЖУ≈ → можно добавить в дневник
---
## Итерация 4: Планирование меню
> **Детальный план:** [Iteration_4.md](./Iteration_4.md)
**Цель:** пользователь получает полное меню на неделю от Gemini с учётом продуктов, целей и предпочтений. Автоматически формируется список покупок.
**Зависимости:** итерации 1, 2.
### User Stories
#### Backend
| ID | Story | Описание |
|----|-------|----------|
| 4.1 | Таблицы menu_plans, menu_items | Миграции. menu_items → saved_recipes |
| 4.2 | Таблица meal_diary | Миграция. Записи приёмов пищи |
| 4.3 | POST /ai/generate-menu | GPT генерирует 21 рецепт, Pexels параллельно, сохранение в БД |
| 4.4 | Menu CRUD | GET /menu?week=, PUT /menu/items/{id}, DELETE /menu/items/{id} |
| 4.5 | Shopping list | POST /shopping-list/generate (SQL-агрегация без AI), GET, PATCH check |
#### Flutter
| ID | Story | Описание |
|----|-------|----------|
| 4.6 | MenuScreen | 7-дневный вид, skeleton на генерацию, кнопка «Сгенерировать» |
| 4.7 | Замена рецепта | Тап «Изменить» → выбор из saved_recipes или перегенерация |
| 4.8 | ShoppingListScreen | Список по категориям, чекбоксы, «Поделиться» |
| 4.9 | DiaryScreen | Записи за день, «+ Добавить» |
### Результат итерации
- Пользователь получает меню на неделю одним запросом к GPT
- Все рецепты меню сохраняются в saved_recipes
- Из меню автоматически формируется список покупок (то, чего нет в запасах)
- Ведётся дневник питания
---
## Итерация 5: Главный экран
> **Детальный план:** [Iteration_5.md](./Iteration_5.md)
**Цель:** дашборд — сводка на сегодня, прогресс калорий, плановые приёмы пищи, предупреждение об истекающих продуктах, рекомендации рецептов.
**Зависимости:** итерации 1, 2, 4.
### User Stories
#### Backend
| ID | Story | Описание |
|----|-------|----------|
| 5.1 | GET /home/summary | Агрегирует: план на сегодня, калории дневника, истекающие продукты, последние рекомендации |
#### Flutter
| ID | Story | Описание |
|----|-------|----------|
| 5.2 | HomeScreen | Приветствие, кольцо калорий, план на сегодня, быстрые действия, баннер истекающих, блок рекомендаций |
| 5.3 | homeProvider | StateNotifier, обновление после scan/menu-генерации |
### Результат итерации
- Открываешь приложение — сразу видишь баланс калорий и план на день
- Предупреждение если продукты скоро истекут
- Рекомендации без нового AI-вызова (из ранее сохранённых)
---
## Итерация 6: Профиль
> **Детальный план:** [Iteration_6.md](./Iteration_6.md)
**Цель:** заменить заглушку вкладки «Профиль» полноценным экраном — просмотр данных, редактирование параметров тела и целей, отображение расчётной нормы калорий, выход из аккаунта.
**Зависимости:** итерация 0.
### User Stories
#### Backend
Новых эндпоинтов не требуется — `GET /profile` и `PUT /profile` реализованы в итерации 0.
#### Flutter
| ID | Story | Описание |
|----|-------|----------|
| 6.1 | ProfileService | `getProfile()``GET /profile`, `updateProfile()``PUT /profile` |
| 6.2 | profileProvider | `StateNotifier<AsyncValue<User>>`, методы `load()` и `update()` |
| 6.3 | ProfileScreen | Секции: аватар+имя, параметры тела, цель+активность, норма калорий, кнопка выхода |
| 6.4 | EditProfileSheet | Modal bottom sheet с формой редактирования всех параметров |
| 6.5 | HomeScreen — имя | Приветствие берёт имя из `profileProvider` вместо захардкоженного |
### Результат итерации
- Пользователь видит своё имя, email, параметры тела и цели
- Может обновить параметры — норма калорий пересчитывается автоматически сервером
- Может выйти из аккаунта с подтверждением
- Приветствие на главном экране показывает реальное имя пользователя
---
## Итоги
| Итерация | Цель | Ключевые API |
|----------|------|-------------|
| 0. Фундамент | Auth, профиль, каркас | Firebase |
| 1. AI-рекомендации | Рецепты + сохранение | GPT-4o-mini, Pexels |
| 2. Продукты | CRUD запасов, ingredient_mappings | — |
| 3. Распознавание | OCR чека, фото продуктов/блюда | GPT-4o Vision |
| 4. Меню | Недельное меню, список покупок | GPT-4o-mini, Pexels |
| 5. Главный экран | Дашборд: калории, план, истекающие, рекомендации | — |
| 6. Профиль | Параметры тела, цель, норма калорий, выход | — |
**MVP:** итерации 02 (авторизация + рекомендации + продукты) — пользователь получает персонализированные рецепты.
**Полный продукт:** итерации 04 — полный цикл: сфотографировал чек → получил меню → список покупок → дневник питания.