laravel-12-tech-specs/task07-recipe-catalog.md

19 KiB
Raw Permalink Blame History

Техническое задание: Каталог рецептов с рейтингом

1. Описание проекта

Кулинарная платформа для публикации рецептов, комментирования и оценки блюд. Проект закрепляет навыки CRUD, отношений многие-ко-многим (рецепт ↔ ингредиенты), расчёта среднего рейтинга, разграничения прав и совместной работы через Git.

Команда: 23 человека


2. Функциональные требования

2.1. Аутентификация и регистрация

  • Регистрация, вход, выход (Laravel Breeze)

2.2. Каталог рецептов

  • Просмотр списка рецептов с пагинацией
  • Фильтрация по категориям (завтрак, обед, ужин, выпечка, десерты, напитки)
  • Поиск по названию и ингредиентам
  • Сортировка по дате добавления, рейтингу, времени приготовления
  • Детальная страница рецепта

2.3. Управление рецептами (автор/админ)

  • CRUD рецептов: название, описание, категория, время приготовления, количество порций, изображение, сложность
  • Пошаговое приготовление (несколько шагов, каждое — отдельная запись)
  • Привязка ингредиентов с количеством и единицей измерения
  • Загрузка изображения рецепта (валидация: jpg/png, макс. 2MB)

2.4. Ингредиенты

  • Справочник ингредиентов (название, единица измерения по умолчанию)
  • CRUD ингредиентов (админ)
  • Привязка к рецептам (многие-ко-многим) с указанием количества и единицы

2.5. Комментарии

  • Добавление комментариев к рецепту
  • Удаление своего комментария
  • Удаление любого комментария (админ/автор рецепта)
  • Пагинация комментариев

2.6. Оценки и рейтинг

  • Оценка рецепта (15 звёзд) — один голос на пользователя
  • Отображение среднего рейтинга на карточке и странице рецепта
  • Автоматический пересчёт среднего рейтинга

2.7. Избранное

  • Добавление рецепта в избранное
  • Список избранных рецептов (личный кабинет)

2.8. Личный кабинет автора

  • Мои рецепты
  • Статистика: количество рецептов, средний рейтинг, количество комментариев
  • Избранные рецепты

2.9. Панель администратора

  • Управление пользователями и ролями
  • CRUD ингредиентов (справочник)
  • Модерация рецептов и комментариев
  • Общая статистика

3. Структура базы данных

Таблица users

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
name VARCHAR(255) Имя
email VARCHAR(255) Email (unique)
password VARCHAR(255) Хеш пароля
role ENUM('admin', 'author', 'user') Роль
avatar VARCHAR(255) | NULL Аватар
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица categories

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
name VARCHAR(255) Название категории
slug VARCHAR(255) URL-идентификатор (unique)
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица recipes

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
title VARCHAR(255) Название рецепта
slug VARCHAR(255) URL-идентификатор (unique)
description TEXT Краткое описание
image VARCHAR(255) | NULL Изображение
category_id BIGINT UNSIGNED Категория (FK → categories)
author_id BIGINT UNSIGNED Автор (FK → users)
cooking_time INT Время приготовления (минуты)
servings INT Количество порций
difficulty ENUM('easy', 'medium', 'hard') Сложность
rating DECIMAL(3, 2) | NULL Средний рейтинг (0.005.00)
rating_count INT Количество оценок
is_published BOOLEAN Опубликован ли
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица recipe_steps

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
recipe_id BIGINT UNSIGNED Рецепт (FK → recipes)
step_number INT Порядковый номер шага
description TEXT Описание шага
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица ingredients

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
name VARCHAR(255) Название ингредиента (unique)
default_unit VARCHAR(50) Единица измерения по умолчанию (г, мл, шт, ст.л.)
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица ingredient_recipe (многие-ко-многим)

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
recipe_id BIGINT UNSIGNED FK → recipes
ingredient_id BIGINT UNSIGNED FK → ingredients
quantity DECIMAL(10, 2) Количество
unit VARCHAR(50) Единица измерения

Таблица comments

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
body TEXT Текст комментария
user_id BIGINT UNSIGNED Автор (FK → users)
recipe_id BIGINT UNSIGNED Рецепт (FK → recipes)
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица ratings

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
user_id BIGINT UNSIGNED FK → users
recipe_id BIGINT UNSIGNED FK → recipes
rating TINYINT Оценка (15)
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица recipe_user (избранное)

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
user_id BIGINT UNSIGNED FK → users
recipe_id BIGINT UNSIGNED FK → recipes
added_at TIMESTAMP

4. Маршруты и контроллеры

// Публичные маршруты
Route::get('/', [RecipeController::class, 'index'])->name('recipes.index');
Route::get('/recipes/{recipe:slug}', [RecipeController::class, 'show'])->name('recipes.show');

// Аутентифицированные маршруты
Route::middleware('auth')->group(function () {
    // Оценки
    Route::post('/recipes/{recipe}/rate', [RatingController::class, 'store'])->name('recipes.rate');

    // Избранное
    Route::get('/favorites', [FavoriteController::class, 'index'])->name('favorites.index');
    Route::post('/recipes/{recipe}/favorite', [FavoriteController::class, 'toggle'])->name('recipes.favorite');

    // Комментарии
    Route::resource('recipes.comments', CommentController::class)->scoped(['recipes' => 'recipe'])->only(['store', 'destroy']);

    // Мои рецепты (автор)
    Route::prefix('my-recipes')->name('my-recipes.')->middleware('can:be-author')->group(function () {
        Route::resource('recipes', AuthorRecipeController::class);
        Route::get('dashboard', [AuthorDashboardController::class, 'index'])->name('dashboard');
    });

    // Админка
    Route::prefix('admin')->name('admin.')->middleware('can:access-admin-panel')->group(function () {
        Route::resource('users', AdminUserController::class);
        Route::resource('ingredients', AdminIngredientController::class);
        Route::patch('recipes/{recipe}/toggle-publish', [AdminRecipeController::class, 'togglePublish'])->name('recipes.publish');
        Route::get('dashboard', [AdminDashboardController::class, 'index'])->name('dashboard');
    });
});

Контроллеры

  • RecipeController — публичный каталог и детальный просмотр
  • AuthorRecipeController — CRUD рецептов автором
  • RatingController — добавление/обновление оценки
  • FavoriteController — управление избранным
  • CommentController — создание/удаление комментариев
  • AuthorDashboardController — панель автора
  • AdminUserController, AdminIngredientController, AdminRecipeController, AdminDashboardController — админка

5. Роли, Gates и Policies

Роли

Роль Описание
admin Полный доступ, модерация, CRUD ингредиентов, управление пользователями
author Создание/редактирование своих рецептов, управление комментариями к своим рецептам
user Просмотр каталога, комментирование, оценка, добавление в избранное

Gates

Gate::define('be-author', function (User $user) {
    return in_array($user->role, ['admin', 'author']);
});

Gate::define('access-admin-panel', function (User $user) {
    return $user->role === 'admin';
});

Policies

RecipePolicy:

  • view — все (если опубликован), автор/admin (если не опубликован)
  • create — author или admin
  • update, delete — автор рецепта или admin
  • rate — user (ещё не оценивал этот рецепт)

CommentPolicy:

  • create — все аутентифицированные
  • delete — автор комментария, автор рецепта или admin

IngredientPolicy:

  • view — все
  • create, update, delete — только admin

6. Требования к интерфейсу (Bootstrap 5)

Компоненты

  • Навбар — логотип, каталог, «Избранное», «Мои рецепты», профиль
  • Карточки рецептов — изображение, название, категория (бейдж), время (иконка + текст), рейтинг (звёзды)
  • Страница рецепта — большое изображение, описание, ингредиенты (таблица), шаги приготовления (нумерованный список), комментарии, форма оценки
  • Звёздный рейтинг — интерактивные звёзды (radio buttons + стилизация)
  • Форма рецепта — Bootstrap-форма с загрузкой изображения, динамическое добавление шагов и ингредиентов
  • Таблица ингредиентов — название, количество, единица измерения
  • Дашборд автора — статистика (карточки), список моих рецептов
  • Адаптивная сеткаcol-md-4 для карточек, col-md-8 + col-md-4 для основного контента и сайдбара

Цветовая схема сложности

  • Лёгкий — bg-success
  • Средний — bg-warning
  • Сложный — bg-danger

Цветовая схема категорий

  • Завтрак — bg-info
  • Обед — bg-primary
  • Ужин — bg-dark
  • Выпечка — bg-warning
  • Десерты — bg-pink
  • Напитки — bg-light text-dark

7. Git-workflow для команды

Распределение модулей (для 2 человек)

Участник Модуль Ветки
Участник A Рецепты, категории, шаги, ингредиенты, каталог feature/recipes-crud, feature/categories, feature-recipe-steps
Участник B Оценки, комментарии, избранное, дашборд, UI feature-ingredients, feature-recipe-ingredients-m2m, feature-ratings

Распределение модулей (для 3 человек)

Участник Модуль Ветки
Участник A Рецепты, категории, шаги приготовления, загрузка изображений feature/recipes-crud, feature/categories, feature-recipe-steps
Участник B Ингредиенты, многие-ко-многим, оценки, расчёт рейтинга feature-ingredients, feature-recipe-ingredients-m2m, feature-ratings
Участник C Комментарии, избранное, каталог, UI, дашборд feature-comments, feature-favorites, feature-recipe-catalog-ui

Правила

  1. Ветка develop — основная ветка разработки
  2. Каждый участник создаёт фич-ветки от develop
  3. Минимум 3 PR на участника
  4. Обязательный код-ревью перед мёржем
  5. Conventional Commits

Визуализация workflow (2 участника)

gitGraph
   commit id: "init" tag: "v1.0"
   branch develop
   checkout develop
   branch feature/recipes-crud
   checkout develop
   branch feature-ingredients
   checkout feature/recipes-crud
   commit id: "feat: add recipes CRUD"
   commit id: "feat: add recipe steps"
   checkout feature-ingredients
   commit id: "feat: add ingredients m2m"
   commit id: "feat: add ratings system"
   checkout develop
   merge feature/recipes-crud tag: "PR + review"
   merge feature-ingredients tag: "PR + review"
   checkout main
   merge develop tag: "release v1.1"

Визуализация workflow (3 участника)

gitGraph
   commit id: "init" tag: "v1.0"
   branch develop
   checkout develop
   branch feature/recipes-crud
   checkout develop
   branch feature-ingredients
   checkout develop
   branch feature-comments
   checkout feature/recipes-crud
   commit id: "feat: add recipes CRUD"
   commit id: "feat: add recipe categories"
   checkout feature-ingredients
   commit id: "feat: add ingredients m2m"
   commit id: "feat: add ratings system"
   checkout feature-comments
   commit id: "feat: add recipe comments"
   commit id: "feat: add favorites system"
   checkout develop
   merge feature/recipes-crud tag: "PR + review"
   merge feature-ingredients tag: "PR + review"
   merge feature-comments tag: "PR + review"
   checkout main
   merge develop tag: "release v1.1"

8. Критерии приёмки

Обязательно

  • CRUD рецептов с загрузкой изображений
  • CRUD категорий рецептов
  • Шаги приготовления (CRUD внутри рецепта)
  • Справочник ингредиентов (CRUD, только админ)
  • Привязка ингредиентов к рецептам (многие-ко-многим с количеством и единицей)
  • Оценка рецепта (15 звёзд, один голос на пользователя)
  • Автоматический расчёт среднего рейтинга
  • Комментарии к рецептам (создание + удаление)
  • Избранное (добавление/удаление)
  • Панель автора (мои рецепты, статистика)
  • Policies: пользователь не может редактировать чужие рецепты
  • Адаптивная Bootstrap-вёрстка
  • Flash-сообщения
  • Пагинация каталога и комментариев
  • Git-история: минимум 3 ветки на участника, PR с ревью

Дополнительно (бонусные баллы)

  • Поиск рецептов по названию и ингредиентам
  • Фильтрация по времени приготовления и сложности
  • Сортировка по рейтингу, дате, времени приготовления
  • Печать рецепта (кнопка «Распечатать» → print-friendly страница)
  • Мягкое удаление рецептов и комментариев
  • Тесты: PHPUnit Feature-тесты для RatingController
  • API: RESTful API для каталога рецептов

9. Дополнительные задания (для продвинутых)

  1. Масштабирование рецепта: калькулятор для пересчёта ингредиентов на другое количество порций
  2. Планировщик питания: календарь с рецептами на неделю
  3. Коллекции: пользовательские подборки рецептов (как плейлисты)
  4. Тесты: PHPUnit Feature-тесты для RecipeController и RatingController
  5. API: RESTful API для каталога и создания рецептов
  6. Queue: асинхронный пересчёт рейтинга при большом количестве оценок
  7. Events & Listeners: событие «новая оценка» → пересчёт рейтинга

10. Рекомендуемые материалы