diff --git a/app/Http/Controllers/Admin/CourseCategoryController.php b/app/Http/Controllers/Admin/CourseCategoryController.php new file mode 100755 index 0000000..a2b541a --- /dev/null +++ b/app/Http/Controllers/Admin/CourseCategoryController.php @@ -0,0 +1,118 @@ +middleware('auth'); + } + + public function index() + { + Gate::authorize('viewAny', CourseCategory::class); + + $categories = CourseCategory::tree(); + + return view('admin.course-categories.index', compact('categories')); + } + + public function create() + { + Gate::authorize('create', CourseCategory::class); + + $parentCategories = CourseCategory::whereNull('parent_id') + ->orderBy('name') + ->get(); + + return view('admin.course-categories.create', compact('parentCategories')); + } + + public function store(Request $request) + { + Gate::authorize('create', CourseCategory::class); + + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'slug' => 'nullable|string|max:255|unique:course_categories', + 'description' => 'nullable|string', + 'parent_id' => 'nullable|exists:course_categories,id', + 'sort_order' => 'integer', + ]); + + $validated['slug'] = $validated['slug'] ?? Str::slug($validated['name']); + $validated['is_active'] = $request->boolean('is_active'); + + CourseCategory::create($validated); + + return redirect()->route('admin.course-categories.index') + ->with('success', 'Категория успешно создана.'); + } + + public function show(CourseCategory $category) + { + Gate::authorize('view', $category); + + $category->load(['parent', 'children', 'courses']); + + return view('admin.course-categories.show', compact('category')); + } + + public function edit(CourseCategory $category) + { + Gate::authorize('update', $category); + + $parentCategories = CourseCategory::whereNull('parent_id') + ->where('id', '!=', $category->id) + ->orderBy('name') + ->get(); + + return view('admin.course-categories.edit', compact('category', 'parentCategories')); + } + + public function update(Request $request, CourseCategory $category) + { + Gate::authorize('update', $category); + + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'slug' => 'nullable|string|max:255|unique:course_categories,slug,' . $category->id, + 'description' => 'nullable|string', + 'parent_id' => 'nullable|exists:course_categories,id', + 'sort_order' => 'integer', + ]); + + $validated['slug'] = $validated['slug'] ?? Str::slug($validated['name']); + $validated['is_active'] = $request->boolean('is_active'); + + $category->update($validated); + + return redirect()->route('admin.course-categories.index') + ->with('success', 'Категория успешно обновлена.'); + } + + public function destroy(CourseCategory $category) + { + Gate::authorize('delete', $category); + + if ($category->courses()->count() > 0) { + return back()->with('error', 'Невозможно удалить категорию с курсами.'); + } + + if ($category->children()->count() > 0) { + return back()->with('error', 'Невозможно удалить категорию с подкатегориями.'); + } + + $category->delete(); + + return redirect()->route('admin.course-categories.index') + ->with('success', 'Категория успешно удалена.'); + } +} diff --git a/app/Models/CourseCategory.php b/app/Models/CourseCategory.php index f170673..26c44a3 100755 --- a/app/Models/CourseCategory.php +++ b/app/Models/CourseCategory.php @@ -38,4 +38,11 @@ class CourseCategory extends Model { return $this->hasMany(Course::class); } + + public function scopeTree($query) + { + return $query->with(['children', 'children.children'])->withCount('courses')->orderBy('sort_order')->get()->filter(function($cat) { + return is_null($cat->parent_id); + }); + } } diff --git a/app/Policies/CourseCategoryPolicy.php b/app/Policies/CourseCategoryPolicy.php new file mode 100755 index 0000000..69ccc64 --- /dev/null +++ b/app/Policies/CourseCategoryPolicy.php @@ -0,0 +1,34 @@ +hasRole(['Administrator', 'Manager', 'Curator']); + } + + public function view(User $user, CourseCategory $category): bool + { + return $user->hasRole(['Administrator', 'Manager', 'Curator']); + } + + public function create(User $user): bool + { + return $user->hasRole(['Administrator', 'Manager']); + } + + public function update(User $user, CourseCategory $category): bool + { + return $user->hasRole(['Administrator', 'Manager']); + } + + public function delete(User $user, CourseCategory $category): bool + { + return $user->hasRole(['Administrator']); + } +} diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index f9a79c5..7edbf4c 100755 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -2,9 +2,11 @@ namespace App\Providers; +use App\Models\CourseCategory; use App\Models\Group; use App\Models\Organization; use App\Models\User; +use App\Policies\CourseCategoryPolicy; use App\Policies\GroupPolicy; use App\Policies\OrganizationPolicy; use App\Policies\UserPolicy; @@ -18,6 +20,7 @@ class AuthServiceProvider extends ServiceProvider * @var array */ protected $policies = [ + CourseCategory::class => CourseCategoryPolicy::class, Organization::class => OrganizationPolicy::class, Group::class => GroupPolicy::class, User::class => UserPolicy::class, diff --git a/resources/views/admin/course-categories/_row.blade.php b/resources/views/admin/course-categories/_row.blade.php new file mode 100644 index 0000000..c97cd1e --- /dev/null +++ b/resources/views/admin/course-categories/_row.blade.php @@ -0,0 +1,26 @@ +@php + $children = $category->children ?? collect(); +@endphp + + + @if($level > 0)@endif + {{ $category->name }} + + {{ $category->slug }} + {{ $category->courses_count }} + @if($category->is_active)Активна@elseНе активна@endif + +
+ + @can('update', $category) + + @endcan + @can('delete', $category) +
@csrf @method('DELETE')
+ @endcan +
+ + +@foreach($children as $child) + @include('admin.course-categories._row', ['category' => $child, 'level' => $level + 1]) +@endforeach diff --git a/resources/views/admin/course-categories/create.blade.php b/resources/views/admin/course-categories/create.blade.php new file mode 100644 index 0000000..400b33e --- /dev/null +++ b/resources/views/admin/course-categories/create.blade.php @@ -0,0 +1,65 @@ +@extends('layouts.app') +@section('title', 'Добавить категорию') +@section('content') +
+
+ +
+
+

Добавить категорию

+ Назад +
+
+ @csrf +
+
+
+
+
+ + + @error('name')
{{ $message }}
@enderror +
+
+ + + @error('slug')
{{ $message }}
@enderror +
+
+ + +
+
+
+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ + Отмена +
+
+
+
+@endsection diff --git a/resources/views/admin/course-categories/index.blade.php b/resources/views/admin/course-categories/index.blade.php new file mode 100644 index 0000000..f99e922 --- /dev/null +++ b/resources/views/admin/course-categories/index.blade.php @@ -0,0 +1,32 @@ +@extends('layouts.app') +@section('title', 'Категории курсов') +@section('content') +
+
+ +
+
+

Категории курсов

+ @can('create', App\Models\CourseCategory::class) + Добавить категорию + @endcan +
+ @if(session('success'))
{{ session('success') }}
@endif + @if(session('error'))
{{ session('error') }}
@endif + +
+
+ + + + @foreach($categories as $category) + @include('admin.course-categories._row', ['category' => $category, 'level' => 0]) + @endforeach + +
НазваниеSlugКурсовСтатусДействия
+
+
+
+
+
+@endsection diff --git a/resources/views/partials/_sidebar.blade.php b/resources/views/partials/_sidebar.blade.php index 864b469..83d8750 100644 --- a/resources/views/partials/_sidebar.blade.php +++ b/resources/views/partials/_sidebar.blade.php @@ -19,6 +19,11 @@ Пользователи +