diff --git a/app/Http/Controllers/Student/CourseController.php b/app/Http/Controllers/Student/CourseController.php new file mode 100755 index 0000000..73d6bb8 --- /dev/null +++ b/app/Http/Controllers/Student/CourseController.php @@ -0,0 +1,84 @@ +middleware('auth'); + } + + public function index() + { + $user = Auth::user(); + + // Получаем назначения для пользователя + $query = CourseAssignment::with(['course', 'group', 'organization']) + ->where('is_active', true) + ->where(function($q) use ($user) { + // Индивидуальные назначения + $q->where('type', 'individual') + ->where('user_id', $user->id); + + // Или назначения группе пользователя + if ($user->groups->count() > 0) { + $q->orWhere(function($sub) use ($user) { + $sub->where('type', 'group') + ->whereIn('group_id', $user->groups->pluck('id')); + }); + } + + // Или назначения организации пользователя + if ($user->organization_id) { + $q->orWhere(function($sub) use ($user) { + $sub->where('type', 'organization') + ->where('organization_id', $user->organization_id); + }); + } + }); + + $assignments = $query->get(); + + // Группируем по курсам + $courses = $assignments->unique('course_id')->map(function($assignment) { + return $assignment->course; + }); + + return view('student.courses.index', compact('courses', 'assignments')); + } + + public function show(Course $course) + { + $user = Auth::user(); + + // Проверяем доступ к курсу + $hasAccess = CourseAssignment::where('course_id', $course->id) + ->where('is_active', true) + ->where(function($q) use ($user) { + $q->where('type', 'individual')->where('user_id', $user->id) + ->orWhere(function($sub) use ($user) { + $sub->where('type', 'group') + ->whereIn('group_id', $user->groups->pluck('id')); + }) + ->orWhere(function($sub) use ($user) { + $sub->where('type', 'organization') + ->where('organization_id', $user->organization_id); + }); + })->exists(); + + if (!$hasAccess) { + abort(403, 'У вас нет доступа к этому курсу'); + } + + $course->load(['tests', 'category']); + + return view('student.courses.show', compact('course')); + } +} diff --git a/app/Http/Controllers/Student/TestController.php b/app/Http/Controllers/Student/TestController.php new file mode 100755 index 0000000..2ed5c64 --- /dev/null +++ b/app/Http/Controllers/Student/TestController.php @@ -0,0 +1,71 @@ +middleware('auth'); + } + + public function index() + { + $user = Auth::user(); + + // Получаем тесты из доступных курсов + $courseIds = CourseAssignment::where('is_active', true) + ->where(function($q) use ($user) { + $q->where('type', 'individual')->where('user_id', $user->id) + ->orWhere(function($sub) use ($user) { + $sub->where('type', 'group') + ->whereIn('group_id', $user->groups->pluck('id')); + }) + ->orWhere(function($sub) use ($user) { + $sub->where('type', 'organization') + ->where('organization_id', $user->organization_id); + }); + })->pluck('course_id'); + + $tests = Test::with(['course']) + ->whereIn('course_id', $courseIds) + ->where('is_active', true) + ->get(); + + return view('student.tests.index', compact('tests')); + } + + public function show(Test $test) + { + $user = Auth::user(); + + // Проверяем доступ к тесту через курс + $hasAccess = CourseAssignment::where('course_id', $test->course_id) + ->where('is_active', true) + ->where(function($q) use ($user) { + $q->where('type', 'individual')->where('user_id', $user->id) + ->orWhere(function($sub) use ($user) { + $sub->where('type', 'group') + ->whereIn('group_id', $user->groups->pluck('id')); + }) + ->orWhere(function($sub) use ($user) { + $sub->where('type', 'organization') + ->where('organization_id', $user->organization_id); + }); + })->exists(); + + if (!$hasAccess) { + abort(403, 'У вас нет доступа к этому тесту'); + } + + $test->load(['questions.answers', 'course']); + + return view('student.tests.show', compact('test')); + } +} diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 436dc10..41af60c 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -75,6 +75,23 @@ Панель управления + @if(Auth::user()->hasRole(['Administrator', 'Manager', 'Curator'])) + + @endif + + @endauth @@ -109,6 +125,44 @@ + @if(!Auth::check()) + + + @endif + @yield('content') diff --git a/resources/views/student/courses/index.blade.php b/resources/views/student/courses/index.blade.php new file mode 100644 index 0000000..c6bae47 --- /dev/null +++ b/resources/views/student/courses/index.blade.php @@ -0,0 +1,46 @@ +@extends('layouts.app') +@section('title', 'Мои курсы') +@section('content') +
+
+ +
+
+

Мои курсы

+
+ + @if(session('success'))
{{ session('success') }}
@endif + + @if($courses->count() > 0) +
+ @foreach($courses as $course) +
+
+ @if($course->image) + {{ $course->title }} + @endif +
+
{{ $course->title }}
+ @if($course->category) + {{ $course->category->name }} + @endif +

{{ Str::limit($course->description, 100) }}

+
+ +
+
+ @endforeach +
+ @else +
+ У вас пока нет доступных курсов +
+ @endif +
+
+
+@endsection diff --git a/resources/views/student/courses/show.blade.php b/resources/views/student/courses/show.blade.php new file mode 100644 index 0000000..60ead88 --- /dev/null +++ b/resources/views/student/courses/show.blade.php @@ -0,0 +1,62 @@ +@extends('layouts.app') +@section('title', $course->title) +@section('content') +
+
+ +
+
+

{{ $course->title }}

+ Назад +
+ +
+
+
+
+ @if($course->image) + {{ $course->title }} + @endif +

Описание

+

{{ $course->description ?? '—' }}

+ + @if($course->objectives) +

Цели обучения

+

{{ $course->objectives }}

+ @endif +
+
+
+ +
+
+
Информация
+
+ @if($course->category) +
Категория: {{ $course->category->name }}
+ @endif +
Тестов: {{ $course->tests->count() }}
+
+
+ + @if($course->tests->count() > 0) +
+
Тесты
+
+ @foreach($course->tests as $test) + +
+
{{ $test->title }}
+ {{ $test->questions->count() }} вопр. +
+
+ @endforeach +
+
+ @endif +
+
+
+
+
+@endsection diff --git a/resources/views/student/tests/index.blade.php b/resources/views/student/tests/index.blade.php new file mode 100644 index 0000000..7c84517 --- /dev/null +++ b/resources/views/student/tests/index.blade.php @@ -0,0 +1,53 @@ +@extends('layouts.app') +@section('title', 'Тесты') +@section('content') +
+
+ +
+
+

Тесты

+
+ + @if(session('success'))
{{ session('success') }}
@endif + + @if($tests->count() > 0) +
+
+
+ + + + + + + + + + + @foreach($tests as $test) + + + + + + + @endforeach + +
НазваниеКурсВопросовДействия
{{ $test->title }}{{ $test->course->title }}{{ $test->questions->count() }} + + Начать + +
+
+
+
+ @else +
+ У вас пока нет доступных тестов +
+ @endif +
+
+
+@endsection diff --git a/resources/views/student/tests/show.blade.php b/resources/views/student/tests/show.blade.php new file mode 100644 index 0000000..8f411dd --- /dev/null +++ b/resources/views/student/tests/show.blade.php @@ -0,0 +1,86 @@ +@extends('layouts.app') +@section('title', $test->title) +@section('content') +
+
+ +
+
+

{{ $test->title }}

+ Назад +
+ +
+
+
+
Информация о тесте
+
+
Курс: {{ $test->course->title }}
+
Вопросов: {{ $test->questions->count() }}
+ @if($test->passing_score) +
Проходной балл: {{ $test->passing_score }}%
+ @endif +
+
+
+ +
+
+
+ +
+
+
+
+ +
+
Вопросы
+
+
+ @foreach($test->questions as $index => $question) +
+

+ +

+
+
+

{{ $question->question_text }}

+ + @if($question->type === 'multiple_choice') +
+ @foreach($question->answers as $answer) +
+ + +
+ @endforeach +
+ @endif +
+
+
+ @endforeach +
+
+
+
+
+
+ +@push('scripts') + +@endpush +@endsection diff --git a/routes/web.php b/routes/web.php index 7d2f289..0929f1b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -16,6 +16,8 @@ use App\Http\Controllers\Api\OrganizationSearchController; use App\Http\Controllers\Api\GroupSearchController; use App\Http\Controllers\Api\UserSearchController; use App\Http\Controllers\Api\CourseSearchController; +use App\Http\Controllers\Student\CourseController as StudentCourseController; +use App\Http\Controllers\Student\TestController as StudentTestController; use App\Http\Controllers\DashboardController; use Illuminate\Support\Facades\Route; @@ -78,4 +80,12 @@ Route::middleware('auth')->group(function () { Route::get('/api/users/search', UserSearchController::class)->name('api.users.search'); Route::get('/api/courses/search', CourseSearchController::class)->name('api.courses.search'); }); + + // Учебная часть (требуется аутентификация) + Route::middleware('auth')->prefix('student')->name('student.')->group(function() { + Route::get('/courses', [StudentCourseController::class, 'index'])->name('courses.index'); + Route::get('/courses/{course}', [StudentCourseController::class, 'show'])->name('courses.show'); + Route::get('/tests', [StudentTestController::class, 'index'])->name('tests.index'); + Route::get('/tests/{test}', [StudentTestController::class, 'show'])->name('tests.show'); + }); });