Files
food-ai/docs/plans/Summary.md
dbastrikin 24219b611e 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>
2026-02-20 13:14:58 +02:00

41 KiB
Raw Blame History

FoodAI — План реализации

Обзор итераций

# Итерация Цель Зависит от
0 Фундамент Go-проект, БД, авторизация, Flutter-каркас
1 Справочник ингредиентов и рецепты Наполнение БД рецептами, маппинг ингредиентов 0
2 Управление продуктами CRUD продуктов, сроки хранения 0
3 AI-ядро Очереди, Gemini-адаптер, rate limiter, budget guard 0
4 AI-распознавание OCR чека, фото продуктов, фото блюд 2, 3
5 Каталог рецептов Поиск, фильтры, «из моих продуктов», замены 1, 2
6 Планирование меню Меню на неделю, AI-генерация, список покупок 3, 5
7 Дневник питания Записи, порции, трекер воды, калории 5
8 Режим готовки Пошаговая готовка, таймеры 5
9 Рекомендации и статистика Рекомендации на главной, графики, тренды 6, 7
10 Полировка Онбординг, пустые состояния, уведомления, отзывы 9

Карта зависимостей

                        ┌──────────────┐
                        │  0. Фундамент │
                        └──────┬───────┘
                               │
              ┌────────────────┼────────────────┐
              │                │                │
              ▼                ▼                ▼
     ┌────────────────┐ ┌───────────┐ ┌────────────────┐
     │ 1. Справочник  │ │ 2. Продук-│ │ 3. AI-ядро     │
     │ ингредиентов   │ │    ты     │ │ (очереди,      │
     │ + рецепты      │ │           │ │  Gemini)       │
     └───────┬────────┘ └─────┬─────┘ └───────┬────────┘
             │                │               │
             │           ┌────┴────┐          │
             │           │         │          │
             │           │    ┌────┴──────────┘
             │           │    │
             │           ▼    ▼
             │    ┌──────────────────┐
             │    │ 4. AI-распозна-  │
             │    │    вание         │
             │    └──────────────────┘
             │           │
             └─────┬─────┘
                   │
                   ▼
          ┌────────────────┐
          │ 5. Каталог     │
          │    рецептов    │
          └───────┬────────┘
                  │
       ┌──────────┼──────────┐
       │          │          │
       ▼          ▼          ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 6. Меню  │ │ 7. Днев- │ │ 8. Режим │
│ + список │ │ ник пита-│ │ готовки  │
│ покупок  │ │ ния      │ │          │
└─────┬────┘ └─────┬────┘ └──────────┘
      │            │
      └──────┬─────┘
             │
             ▼
    ┌────────────────┐
    │ 9. Рекоменда-  │
    │ ции + стат-ка  │
    └───────┬────────┘
            │
            ▼
    ┌────────────────┐
    │ 10. Полировка  │
    └────────────────┘

Параллельная разработка: итерации 1, 2, 3 могут выполняться параллельно. Итерации 6, 7, 8 — тоже параллельно после завершения 5.


Итерация 0: Фундамент

Детальный план: 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: Справочник ингредиентов и рецепты

Цель: наполнить БД каноническими ингредиентами и рецептами из Spoonacular. Это фундамент для всех фичей, связанных с рецептами, поиском и маппингом продуктов.

Зависимости: итерация 0.

User Stories

ID Story Описание
1.1 Таблица ingredient_mappings Миграция: id, canonical_name, spoonacular_id, aliases (JSONB), category, default_unit, нутриенты на 100г, storage_days. Индексы: GIN по aliases, UNIQUE по spoonacular_id
1.2 Импорт ингредиентов из Spoonacular CLI-команда / джоб: запрос Spoonacular Ingredient API → сохранение ~1000 базовых ингредиентов в ingredient_mappings
1.3 Таблица recipes Миграция: id, source, spoonacular_id, title, description, cuisine, difficulty, prep_time_min, калории, БЖУ, servings, image_url, ingredients (JSONB), steps (JSONB), tags (JSONB), avg_rating, review_count, created_by. Индексы: GIN по ingredients, full-text по title
1.4 Импорт рецептов из Spoonacular CLI-команда / джоб: импорт 5 00010 000 популярных рецептов. Маппинг ингредиентов рецепта на ingredient_mappings через spoonacular_id
1.5 Перевод рецептов Batch-джоб: перевод title, description, steps через Gemini Flash-Lite. Результат сохраняется в БД (поля title_ru, description_ru или отдельная таблица переводов)
1.6 Базовая локализация aliases Перевод aliases топ-200 ингредиентов на русский. Batch через Gemini или ручной маппинг

Результат итерации

  • БД содержит ~1 000 ингредиентов с русскими алиасами и нутриентами
  • БД содержит 5 00010 000 рецептов с переводами, ингредиентами, шагами, нутриентами
  • Каждый ингредиент рецепта связан с ingredient_mappings через spoonacular_id

Итерация 2: Управление продуктами

Цель: пользователь может вести список своих продуктов вручную — добавлять, редактировать, удалять, отслеживать сроки.

Зависимости: итерация 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: AI-ядро

Цель: построить инфраструктуру для AI-запросов: очереди, rate limiter, budget guard, адаптер Gemini. После итерации можно отправлять AI-запросы через API с контролем расхода.

Зависимости: итерация 0.

User Stories

ID Story Описание
3.1 AI Service интерфейсы Go-интерфейсы: FoodRecognizer, RecipeGenerator, MenuPlanner, NutritionEstimator. Структуры запросов и ответов
3.2 Gemini-адаптер Реализация интерфейсов через Gemini API (google/generative-ai-go). Structured JSON output. Обработка ошибок, retries
3.3 Таблица ai_tasks Миграция: id, user_id, task_type, status, priority, input/output_tokens, estimated_cost, queue/process_time_ms, created_at, completed_at. Индексы по user_id, status, created_at
3.4 Priority Queue Manager Две очереди (chan в Go): paid (N воркеров), free (1 воркер). Распределение RPM между очередями. Горутины-воркеры
3.5 Rate Limiter (per-user) Token bucket на горутинах. Конфигурируемые лимиты по тарифу (free: 20 req/час, paid: 100 req/час). HTTP 429 при превышении
3.6 Budget Guard Подсчёт дневных затрат по ai_tasks. Пороги: 80% → warn, 100% → free stop, 120% → all stop. Счётчик сбрасывается в полночь
3.7 AI API эндпоинты (заглушки) POST /ai/recognize-receipt, /ai/recognize-products, /ai/recognize-dish, /ai/suggest-recipes, /ai/generate-menu, /ai/substitute. Возвращают task_id (HTTP 202). GET /ai/tasks/{id} для polling
3.8 Логирование и мониторинг Каждый AI-запрос логируется в ai_tasks с токенами и стоимостью. Эндпоинт /admin/ai-stats для просмотра затрат

Результат итерации

  • AI-запросы проходят через очередь с приоритетами
  • Paid-пользователи обслуживаются быстрее
  • Расход бюджета контролируется, при превышении — graceful degradation
  • Все запросы логируются с точной стоимостью
  • API эндпоинты принимают запросы и возвращают результат через polling

Итерация 4: AI-распознавание

Цель: пользователь может фотографировать чеки, продукты и блюда — AI распознаёт и предлагает результат для корректировки.

Зависимости: итерации 2 (продукты), 3 (AI-ядро).

User Stories

Backend

ID Story Описание
4.1 OCR чека Реализация FoodRecognizer.RecognizeReceipt: фото → Gemini Flash (vision) → structured JSON (name, quantity, unit, category, price, confidence). Маппинг результатов на ingredient_mappings
4.2 Распознавание продуктов (фото) FoodRecognizer.RecognizeProducts: фото → Gemini Flash → JSON. Поддержка мультифото (объединение результатов, дедупликация). Маппинг на ingredient_mappings
4.3 Распознавание блюда FoodRecognizer.RecognizeDish: фото → Gemini Flash → dish_name, weight, calories, БЖУ, confidence. Full-text search по recipes.title для привязки к рецепту из БД
4.4 Авто-маппинг нераспознанных Если fuzzy match по aliases не нашёл ингредиент → разовый запрос к Gemini: определить canonical_name → сохранить в ingredient_mappings. Следующий запрос с таким же продуктом — без AI
4.5 Загрузка фото Эндпоинт для multipart upload фото. Сохранение в S3. Передача URL в AI-задачу

Flutter

ID Story Описание
4.6 Экран камеры (чек) Видоискатель, кнопка съёмки, выбор из галереи. Отправка на backend
4.7 Экран камеры (еда) Переключатель «Готовое блюдо» / «Продукты». Съёмка, отправка
4.8 Экран загрузки AI Анимация «Распознаём...» с индикатором. Polling по task_id
4.9 Экран корректировки (чек/фото продуктов) Список распознанных продуктов. Инлайн-редактирование: название, количество, единица, категория, срок хранения. Чекбоксы, удаление, добавление вручную, «Сделать ещё фото». Предупреждения о дубликатах. CTA «Добавить в мои продукты»
4.10 Экран результата (фото блюда) Фото, название, калории, БЖУ. Подтверждение / корректировка. Слайдер порции. Выбор приёма пищи. CTA «Записать в дневник»
4.11 Обработка ошибок AI Экран «Не удалось распознать» → «Переснять» / «Ввести вручную»

Результат итерации

  • Пользователь фотографирует чек → получает список продуктов → корректирует → добавляет в запасы
  • Фотографирует холодильник (несколько фото) → то же
  • Фотографирует блюдо → видит калории и БЖУ → может записать в дневник
  • Нераспознанные ингредиенты автоматически добавляются в справочник

Итерация 5: Каталог рецептов

Цель: пользователь может просматривать, искать и фильтровать рецепты. Видит, какие ингредиенты есть в запасах, а каких не хватает. Может добавить рецепт в избранное.

Зависимости: итерации 1 (рецепты в БД), 2 (продукты для проверки наличия).

User Stories

Backend

ID Story Описание
5.1 Поиск и фильтрация рецептов GET /recipes — фильтры: cuisine, difficulty, prep_time, calories_max, meal_type, diet_tags. Full-text search по title. Пагинация (cursor-based)
5.2 «Из моих продуктов» Фильтр: сопоставление ingredients[].mapping_id с products.mapping_id пользователя. Ранжирование по доле совпадения. На каждом рецепте: «Есть всё ✓» / «-N прод.»
5.3 Карточка рецепта с наличием GET /recipes/{id} — рецепт + для каждого ингредиента: есть / нет / замена 🔄. Итог: «Всё есть» / «Не хватает N»
5.4 Замены ингредиентов При — поиск замены: сначала в таблице ingredient_substitutions, затем (если нет) — запрос к Gemini, результат кешируется
5.5 Избранное POST /recipes/{id}/favorite, DELETE /recipes/{id}/favorite. Таблица favorites (user_id, recipe_id). GET /recipes?favorite=true
5.6 Дозапрос Spoonacular Если в локальной БД мало результатов по фильтрам — запрос к Spoonacular API (findByIngredients, complexSearch). Новые рецепты сохраняются в БД

Flutter

ID Story Описание
5.7 Экран каталога рецептов Сетка 2 колонки, поиск, chip-фильтры, кнопка «Из моих продуктов», панель фильтров (bottom sheet), бесконечный скролл
5.8 Карточка рецепта Фото, рейтинг, метаинформация (время/сложность/кухня), калории/БЖУ, регулятор порций, список ингредиентов с //🔄, описание. CTA «Начать готовить», «Добавить в меню»
5.9 Замены ингредиентов Строка «→ Замена: пармезан (есть)» под ингредиентом с 🔄
5.10 Кнопка «Добавить в список покупок» Недостающие ингредиенты → формирование позиций для списка покупок

Результат итерации

  • Пользователь ищет рецепты, фильтрует по кухне/сложности/времени/калориям
  • Видит, что можно приготовить из имеющихся продуктов
  • Для каждого рецепта — отметки наличия ингредиентов и предложения замен
  • Может добавить рецепт в избранное

Итерация 6: Планирование меню

Цель: пользователь может составлять меню на неделю — вручную или через AI-генерацию. Формируется список покупок.

Зависимости: итерации 3 (AI-ядро для генерации), 5 (каталог рецептов).

User Stories

Backend

ID Story Описание
6.1 Таблицы menu_plans и menu_items Миграции. menu_plans: id, user_id, week_start, template_name. menu_items: id, menu_plan_id, day_of_week, meal_type, recipe_id, servings
6.2 Menu CRUD GET /menu?week=, POST /menu/items, PUT /menu/items/{id}, DELETE /menu/items/{id}. Подсчёт калорий за день/неделю
6.3 AI-генерация меню POST /ai/generate-menu: backend отбирает кандидатов из БД (SQL по фильтрам + наличие ингредиентов) → формирует промпт с recipe_id → Gemini ранжирует → backend сохраняет menu_items
6.4 Шаблоны меню POST /menu/templates (сохранить), GET /menu/templates (список), POST /menu/from-template/{id} (применить). История прошлых меню
6.5 Таблица shopping_lists Миграция: id, user_id, menu_plan_id, items (JSONB). Автогенерация из меню: ингредиенты рецептов имеющиеся продукты = список
6.6 Shopping list API GET /shopping-list, POST /shopping-list/generate, PUT /shopping-list/items/{idx}, PATCH /shopping-list/items/{idx}/check, POST /shopping-list/items (ручная позиция)

Flutter

ID Story Описание
6.7 Экран меню Понедельный календарь, слоты по приёмам пищи, калорийность за день, drag-and-drop, контекстное меню (···), пустые слоты с подсказками
6.8 Добавление блюда в слот Модалка выбора дня + приёма пищи. Переход в каталог рецептов для выбора
6.9 AI-генерация Кнопка → экран параметров (период, кухня, сложность, из моих продуктов, калории) → генерация → отображение результата с возможностью заменить отдельные блюда
6.10 Шаблоны и история Выпадающее меню: сохранить как шаблон, загрузить из шаблона, из истории
6.11 Экран списка покупок Список по категориям, чекбоксы, свайп-удаление, ручное добавление, итого, «Поделиться», «Пересчитать из меню»
6.12 Переходный экран «Составить меню?» После добавления продуктов (чек/фото) → предложение сгенерировать меню с выбором параметров

Результат итерации

  • Пользователь составляет меню на неделю — вручную или AI-генерацией
  • AI подбирает рецепты из нашей БД с учётом продуктов, калорий, предпочтений
  • Формируется список покупок (автоматически из меню запасы)
  • Можно сохранять шаблоны и повторять удачные меню
  • После сканирования чека — плавный переход к генерации меню

Итерация 7: Дневник питания

Цель: пользователь ведёт учёт съеденного — записывает приёмы пищи, отслеживает калории и БЖУ, регулирует порции.

Зависимости: итерация 5 (рецепты для добавления из каталога).

User Stories

Backend

ID Story Описание
7.1 Таблица meal_diary Миграция: id, user_id, date, meal_type, recipe_id (nullable), name, portions, calories, protein, fat, carbs, source (menu/photo/manual/recipe), created_at
7.2 Diary CRUD GET /diary?date=, POST /diary, PUT /diary/{id}, DELETE /diary/{id}. Подсчёт итогов дня (калории, БЖУ)
7.3 Из меню в дневник При отметке «съедено» на главном экране → автосоздание записи в дневнике. Списание ингредиентов из продуктов
7.4 Трекер воды Таблица water_tracker (user_id, date, glasses). GET /stats/water?date=, PUT /stats/water
7.5 База продуктов для быстрого поиска Endpoint для поиска по ingredient_mappings: GET /ingredients/search?q=банан → название + нутриенты на порцию. Для перекусов без рецепта

Flutter

ID Story Описание
7.6 Экран дневника питания Навигация по дням, круговой прогресс калорий, прогресс-бары БЖУ, приёмы пищи, порции, «+ Добавить»
7.7 Модалка добавления Варианты: сфотографировать, из меню, из каталога, из избранного, быстрый поиск продукта, вручную
7.8 Указание порции Слайдер 0.5x3x при добавлении из рецепта. Пересчёт калорий/БЖУ
7.9 Быстрый поиск продукта Поле поиска → результаты из ingredient_mappings → тап → добавить в дневник с указанием количества
7.10 Трекер воды Ряд стаканов внизу дневника, тап = +1/-1
7.11 Главный экран — карточка калорий Круговой прогресс, тап → переход в дневник
7.12 Главный экран — «Сегодня в меню» Список из menu_items на сегодня с чекбоксами «съедено»

Результат итерации

  • Пользователь записывает приёмы пищи: из меню, каталога, фото или вручную
  • Регулирует порции, видит калории и БЖУ за день
  • На главном экране — прогресс калорий и чекбоксы «съедено»
  • Трекер воды

Итерация 8: Режим готовки

Цель: пользователь готовит блюдо по пошаговой инструкции с таймерами. После завершения — запись в дневник и оценка.

Зависимости: итерация 5 (карточка рецепта для запуска).

User Stories

ID Story Описание
8.1 Экран пошаговой готовки Фото шага, заголовок, описание (крупный шрифт), навигация «Назад»/«Далее», свайп, точечный индикатор прогресса
8.2 Таймеры Кнопка «Запустить таймер» на шагах с timer_seconds. Обратный отсчёт. Пауза, стоп. Несколько таймеров параллельно
8.3 Панель активных таймеров Фиксирована внизу. Показывает все запущенные таймеры с оставшимся временем
8.4 Уведомления таймера Push-уведомление + звук при завершении таймера. Модалка «Готово!»
8.5 Keep screen on Экран не гаснет в режиме готовки (wakelock)
8.6 Закрытие с подтверждением Кнопка ✕ → «Прервать готовку?»
8.7 Экран завершения «Приятного аппетита!» → «Записать в дневник» (с выбором порций), «Оценить рецепт», «Поделиться фото». Автосписание ингредиентов из запасов

Результат итерации

  • Пользователь готовит по шагам с фото и описанием
  • Запускает таймеры (параллельно), получает уведомления
  • По завершении — запись в дневник, оценка рецепта, списание продуктов

Итерация 9: Рекомендации и статистика

Цель: приложение проактивно рекомендует рецепты. Пользователь видит аналитику своего питания.

Зависимости: итерации 6 (меню), 7 (дневник — данные для статистики).

User Stories

Рекомендации

ID Story Описание
9.1 Рекомендации на главном экране Карусель «Рекомендуем приготовить». Алгоритм: (1) рецепты из продуктов с истекающим сроком, (2) полное совпадение ингредиентов, (3) предпочтения кухни. Endpoint: GET /recipes/recommended
9.2 «Готовили недавно» Секция на главном экране и в каталоге. Endpoint: GET /recipes/recent — последние 5 приготовленных (из meal_diary с source=recipe)
9.3 Секция «Для вас» в каталоге Персональные рекомендации на основе: оценок, предпочтений кухонь, истории. Endpoint: GET /recipes/recommended?section=personal
9.4 Подсказки в пустых слотах меню При пустом слоте меню — рекомендация на основе оставшихся калорий + продукты с истекающим сроком

Статистика

ID Story Описание
9.5 Endpoint статистики `GET /stats?period=week
9.6 Экран статистики Переключатель периода, столбчатая диаграмма калорий, stacked bar БЖУ, тренды (↑↓→), топ блюд
9.7 Переход из главного экрана Тап по прогресс-бару калорий → дневник или статистика

Результат итерации

  • На главном экране — рекомендации (приоритет на истекающие продукты) и «Готовили недавно»
  • В каталоге — секция «Для вас»
  • В меню — умные подсказки в пустых слотах
  • Графики калорий и БЖУ за неделю/месяц/3 месяца

Итерация 10: Полировка

Цель: довести приложение до продуктового качества — онбординг, пустые состояния, уведомления, отзывы, переходные экраны.

Зависимости: итерация 9.

User Stories

Онбординг

ID Story Описание
10.1 Экраны онбординга 5 шагов: приветствие (свайп-карточки), параметры тела, цель + расчёт нормы, ограничения + предпочтения кухонь, предложение добавить продукты
10.2 Сохранение данных онбординга PUT /profile с параметрами из онбординга. Сохранение предпочтений кухонь в preferences
10.3 Флаг прохождения онбординга Показывать только при первом входе. Флаг в secure storage

Пустые состояния и ошибки

ID Story Описание
10.4 Пустые состояния всех экранов Иллюстрация + текст + CTA для: продуктов, меню, дневника, статистики, рецептов (избранные)
10.5 Состояния ошибок Нет сети (баннер + оффлайн-данные), ошибка AI (переснять / ввести вручную), ошибка сервера (повторить)
10.6 Toast с отменой При удалении записи из дневника, продукта — toast «Удалено» + кнопка «Отменить» (5 сек)

Уведомления

ID Story Описание
10.7 Push-уведомления (FCM) Интеграция Firebase Cloud Messaging. Flutter: запрос разрешений, обработка
10.8 Уведомления о сроках продуктов Backend: cron-джоб утром → push «Молоко — осталось 1 день. Использовать в рецепте?»
10.9 Напоминания о приёмах пищи По расписанию (настраиваемое): «Время обеда! В меню: ...»
10.10 Вечернее напоминание о воде «Вы выпили 5 из 8 стаканов воды сегодня»

Отзывы

ID Story Описание
10.11 Таблица reviews Миграция: id, user_id, recipe_id, rating, text, photo_url, created_at. Пересчёт avg_rating, review_count в recipes
10.12 API отзывов GET /recipes/{id}/reviews (пагинация), POST /recipes/{id}/reviews
10.13 UI отзывов Секция в карточке рецепта, модалка написания отзыва (звёзды + текст + фото), полный список отзывов

Профиль

ID Story Описание
10.14 Экран профиля Аватар, параметры, цель, ограничения, предпочтения кухонь, ссылки (статистика, избранное, отзывы, сроки хранения, настройки)
10.15 Настройки приложения Экран: уведомления (вкл/выкл по типам), тема (светлая/тёмная/системная), норма воды, язык

Результат итерации

  • Новый пользователь проходит онбординг и сразу получает персонализированный опыт
  • Все экраны имеют осмысленные пустые состояния
  • Ошибки обрабатываются gracefully
  • Push-уведомления о сроках, приёмах пищи, воде
  • Можно оставлять отзывы к рецептам
  • Полноценный профиль с настройками

Итоги по объёму

Итерация Backend stories Flutter stories Всего
0. Фундамент 6 4 10
1. Ингредиенты + рецепты 6 0 6
2. Продукты 6 6 12
3. AI-ядро 8 0 8
4. AI-распознавание 5 6 11
5. Каталог рецептов 6 4 10
6. Меню + покупки 6 6 12
7. Дневник питания 5 7 12
8. Режим готовки 0 7 7
9. Рекомендации + стат-ка 4 3 7
10. Полировка 5 10 15
Итого 57 53 110

Приоритеты для MVP

Минимально жизнеспособный продукт — итерации 06:

  • Авторизация, продукты, AI-распознавание, рецепты, меню, список покупок
  • Позволяет пройти основной пользовательский сценарий: купил продукты → сфотографировал чек → получил меню → составил список покупок
  • 68 stories из 110 (62%)

Итерации 710 — расширение до полного продукта.