laravel-12-tech-specs/task03-online-courses.md

19 KiB
Raw Blame History

Техническое задание: Платформа для онлайн-курсов

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

Веб-платформа для публикации и прохождения онлайн-курсов с отслеживанием прогресса студентов и системой тестирования. Проект закрепляет навыки CRUD, вложенных сущностей (курс → уроки → тесты), разграничения прав и совместной работы через Git.

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


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

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

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

2.2. Каталог курсов

  • Просмотр списка доступных курсов с пагинацией
  • Фильтрация по категориям
  • Детальная страница курса (описание, автор, список уроков, рейтинг)
  • Запись на курс (кнопка «Записаться»)

2.3. Управление курсами (преподаватель/админ)

  • CRUD курсов: название, описание, обложка, категория, уровень сложности
  • Вложенный CRUD уроков внутри курса:
    • Название урока, порядковый номер, тип (текст/видео)
    • Текстовое содержание (WYSIWYG или markdown)
    • URL видео (опционально, YouTube/Vimeo embed)
  • CRUD тестов/викторин к урокам:
    • Вопросы с вариантами ответов
    • Один или несколько правильных ответов
    • Проходной балл (в процентах)

2.4. Прохождение курса (студент)

  • Список записанных курсов (личный кабинет)
  • Последовательное прохождение уроков
  • Отметка урока как пройденного
  • Сдача теста после урока (или в конце курса)
  • Просмотр результатов теста (правильные/неправильные ответы)
  • Прогресс-бар прохождения курса (в процентах)

2.5. Панель преподавателя

  • Мои курсы (созданные мной)
  • Список студентов по каждому курсу
  • Прогресс каждого студента
  • Статистика: количество курсов, студентов, средний балл

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

  • Управление пользователями и ролями
  • Модерация курсов (скрыть/показать)
  • Общая статистика платформы

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

Таблица users

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
name VARCHAR(255) Имя
email VARCHAR(255) Email (unique)
password VARCHAR(255) Хеш пароля
role ENUM('admin', 'instructor', 'student') Роль
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

Таблица courses

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
title VARCHAR(255) Название курса
slug VARCHAR(255) URL-идентификатор (unique)
description TEXT Описание
cover_image VARCHAR(255) | NULL Обложка курса
difficulty_level ENUM('beginner', 'intermediate', 'advanced') Уровень
instructor_id BIGINT UNSIGNED Преподаватель (FK → users)
category_id BIGINT UNSIGNED Категория (FK → categories)
is_published BOOLEAN Опубликован ли
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица lessons

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
course_id BIGINT UNSIGNED Курс (FK → courses)
title VARCHAR(255) Название урока
position INT Порядковый номер
content_type ENUM('text', 'video') Тип контента
content TEXT Содержимое (текст или URL видео)
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица quizzes

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
lesson_id BIGINT UNSIGNED Урок (FK → lessons)
title VARCHAR(255) Название теста
passing_score INT Проходной балл (%)
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица quiz_questions

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
quiz_id BIGINT UNSIGNED Тест (FK → quizzes)
question TEXT Вопрос
position INT Порядковый номер
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица quiz_answers

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
question_id BIGINT UNSIGNED Вопрос (FK → quiz_questions)
answer_text VARCHAR(255) Текст ответа
is_correct BOOLEAN Правильный ли
created_at TIMESTAMP
updated_at TIMESTAMP

Таблица course_user (запись на курс)

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
course_id BIGINT UNSIGNED FK → courses
user_id BIGINT UNSIGNED FK → users
progress INT Прогресс в процентах (0100)
enrolled_at TIMESTAMP Дата записи
completed_at TIMESTAMP | NULL Дата завершения

Таблица lesson_progress

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
user_id BIGINT UNSIGNED FK → users
lesson_id BIGINT UNSIGNED FK → lessons
is_completed BOOLEAN Пройден ли
completed_at TIMESTAMP | NULL

Таблица quiz_results

Поле Тип Описание
id BIGINT UNSIGNED Первичный ключ
user_id BIGINT UNSIGNED FK → users
quiz_id BIGINT UNSIGNED FK → quizzes
score INT Набранный балл (%)
passed BOOLEAN Сдал ли
taken_at TIMESTAMP Дата прохождения

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

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

// Аутентифицированные маршруты
Route::middleware('auth')->group(function () {
    // Запись на курс
    Route::post('/courses/{course}/enroll', [CourseController::class, 'enroll'])->name('courses.enroll');

    // Прохождение курса
    Route::prefix('my-courses')->name('my-courses.')->group(function () {
        Route::get('/', [StudentCourseController::class, 'index'])->name('index');
        Route::get('/{course}', [StudentCourseController::class, 'show'])->name('show');
        Route::get('/{course}/lessons/{lesson}', [LessonController::class, 'show'])->name('lessons.show');
        Route::post('/{course}/lessons/{lesson}/complete', [LessonController::class, 'complete'])->name('lessons.complete');

        // Тесты
        Route::get('/{course}/quizzes/{quiz}', [QuizController::class, 'take'])->name('quizzes.take');
        Route::post('/{course}/quizzes/{quiz}/submit', [QuizController::class, 'submit'])->name('quizzes.submit');
    });

    // Преподаватель
    Route::prefix('instructor')->name('instructor.')->middleware('can:be-instructor')->group(function () {
        Route::resource('courses', InstructorCourseController::class);
        Route::resource('courses.lessons', InstructorLessonController::class)->scoped(['courses' => 'course']);
        Route::resource('lessons.quizzes', InstructorQuizController::class)->scoped(['lessons' => 'lesson']);
        Route::resource('quizzes.questions', InstructorQuestionController::class)->scoped(['quizzes' => 'quiz']);
        Route::get('courses/{course}/students', [InstructorCourseController::class, 'students'])->name('courses.students');
        Route::get('dashboard', [InstructorDashboardController::class, 'index'])->name('dashboard');
    });

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

Контроллеры

  • CourseController — публичный каталог и запись
  • StudentCourseController — прохождение курсов студентом
  • LessonController — просмотр уроков и отметка пройденными
  • QuizController — прохождение тестов
  • InstructorCourseController — CRUD курсов преподавателем
  • InstructorLessonController — CRUD уроков
  • InstructorQuizController — CRUD тестов
  • InstructorQuestionController — CRUD вопросов
  • InstructorDashboardController — панель преподавателя
  • AdminUserController, AdminCourseController, AdminDashboardController — админка

5. Роли, Gates и Policies

Роли

Роль Описание
admin Полный доступ, модерация курсов, управление пользователями
instructor Создание/редактирование своих курсов, просмотр студентов
student Запись на курсы, прохождение уроков и тестов

Gates

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

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

Policies

CoursePolicy:

  • view — все (если опубликован), автор или admin (если не опубликован)
  • create — instructor или admin
  • update, delete — автор курса или admin
  • enroll — student (не записан на этот курс)

LessonPolicy:

  • view — студент, записанный на курс, или преподаватель/admin
  • create, update, delete — преподаватель курса или admin

QuizPolicy:

  • view — студент, записанный на курс, или преподаватель/admin
  • take — студент, записанный на курс
  • create, update, delete — преподаватель курса или admin

QuizResultPolicy:

  • view — владелец результата или преподаватель/admin
  • create — все студенты

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

Компоненты

  • Навбар — логотип, каталог, «Мои курсы», профиль
  • Карточки курсов — обложка, название, автор, уровень (бейдж), прогресс-бар
  • Страница курса — описание, список уроков (accordion), кнопка записи
  • Страница урока — контент (текст или embed видео), кнопка «Отметить пройденным»
  • Прогресс-бар — Bootstrap progress для отображения прохождения курса
  • Accordion — список уроков курса
  • Тест — форма с radio/checkbox, кнопка отправки, результат
  • Дашборд преподавателя — статистика (карточки), таблица студентов
  • Адаптивная сеткаcol-md-4 для карточек, col-md-8 + col-md-4 для основного контента и сайдбара

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

  • Начальный — bg-success
  • Средний — bg-warning
  • Продвинутый — bg-danger

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

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

Участник Модуль Ветки
Участник A Курсы, категории, обложки, дашборд преподавателя feature/courses-crud, feature/categories, feature-course-covers
Участник B Уроки, тесты, вопросы, прохождение тестов feature/lessons-crud, feature/quizzes, feature-quiz-questions

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

Участник Модуль Ветки
Участник A Курсы, категории, загрузка обложек feature/courses-crud, feature/categories, feature-course-covers
Участник B Уроки, тесты, вопросы feature/lessons-crud, feature/quizzes, feature-quiz-questions
Участник C Запись на курс, прогресс, прохождение тестов, UI feature/enrollment, feature-progress-tracking, feature-student-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/courses-crud
   checkout develop
   branch feature/lessons-crud
   checkout feature/courses-crud
   commit id: "feat: add courses CRUD with covers"
   commit id: "feat: add categories CRUD"
   checkout feature/lessons-crud
   commit id: "feat: add lessons CRUD"
   commit id: "feat: add quizzes system"
   checkout develop
   merge feature/courses-crud tag: "PR + review"
   merge feature/lessons-crud 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/courses-crud
   checkout develop
   branch feature/lessons-crud
   checkout develop
   branch feature/enrollment
   checkout feature/courses-crud
   commit id: "feat: add courses CRUD with covers"
   commit id: "feat: add instructor dashboard"
   checkout feature/lessons-crud
   commit id: "feat: add lessons CRUD"
   commit id: "feat: add quizzes system"
   checkout feature/enrollment
   commit id: "feat: add enrollment flow"
   commit id: "feat: add progress tracking"
   checkout develop
   merge feature/courses-crud tag: "PR + review"
   merge feature/lessons-crud tag: "PR + review"
   merge feature/enrollment tag: "PR + review"
   checkout main
   merge develop tag: "release v1.1"

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

Обязательно

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

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

  • Рейтинг курса (средняя оценка студентов)
  • Сертификат при завершении курса (генерация PDF)
  • Поиск курсов по названию/описанию
  • Фильтрация по уровню сложности
  • Тесты: перемешивание вопросов и ответов
  • Soft Deletes для курсов и уроков

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

  1. Рейтинг курсов: студенты оценивают курс после завершения (15 звёзд)
  2. Сертификаты: генерация PDF-сертификата при 100% прохождении
  3. Обсуждения: комментарии к урокам (вложенные, как на YouTube)
  4. Тесты: таймер на прохождение теста, автоматическая отправка по истечении
  5. API: RESTful API для каталога курсов и прохождения
  6. Тесты: PHPUnit Feature-тесты для QuizController
  7. Events & Listeners: событие «урок пройден» → обновление прогресса

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