diff --git a/app/Http/Controllers/admin/Catalog/Direction/SubjectController.php b/app/Http/Controllers/admin/Catalog/Direction/SubjectController.php
new file mode 100644
index 0000000..800ae0d
--- /dev/null
+++ b/app/Http/Controllers/admin/Catalog/Direction/SubjectController.php
@@ -0,0 +1,72 @@
+validated();
+
+ $subject = new Subject();
+ $subject->name = $validated['name'];
+ $subject->description = $validated['description'];
+ $subject->slug = $validated['slug'];
+ $subject->position = $validated['position'];
+ $subject->save();
+
+ return redirect()->route('subjects.index');
+ }
+
+ public function show(Subject $subject): View
+ {
+ return view('admin.catalog.direction.subject.show', compact('subject'));
+ }
+
+ public function edit(Subject $subject): View
+ {
+ return view('admin.catalog.direction.subject.edit', compact('subject'));
+ }
+
+ public function update(UpdateSubjectRequest $request, Subject $subject): RedirectResponse
+ {
+ $validated = $request->validated();
+
+ $subject->name = $validated['name'];
+ $subject->description = $validated['description'];
+ $subject->slug = $validated['slug'];
+ $subject->position = $validated['position'];
+ $subject->save();
+
+ return redirect()->route('subjects.index');
+ }
+
+ public function destroy(Subject $subject): RedirectResponse
+ {
+ if ($subject->entranceExaminations()->exists()) {
+ return back();
+ }
+ $subject->delete();
+ return redirect()->route('subjects.index');
+ }
+}
diff --git a/app/Http/Requests/admin/Catalog/Direction/StoreSubjectRequest.php b/app/Http/Requests/admin/Catalog/Direction/StoreSubjectRequest.php
new file mode 100644
index 0000000..966f2a4
--- /dev/null
+++ b/app/Http/Requests/admin/Catalog/Direction/StoreSubjectRequest.php
@@ -0,0 +1,23 @@
+ 'required|int|numeric|max:255',
+ 'name' => 'required|string|max:255|unique:subjects,name',
+ 'description' => 'string',
+ 'slug' => 'required|string|max:255|unique:subjects,slug',
+ ];
+ }
+}
diff --git a/app/Http/Requests/admin/Catalog/Direction/UpdateEntranceExaminationRequest.php b/app/Http/Requests/admin/Catalog/Direction/UpdateEntranceExaminationRequest.php
new file mode 100644
index 0000000..fef7be6
--- /dev/null
+++ b/app/Http/Requests/admin/Catalog/Direction/UpdateEntranceExaminationRequest.php
@@ -0,0 +1,20 @@
+ 'required|int|numeric|max:255',
+ 'description' => 'string',
+ 'slug' => [
+ 'string',
+ 'required',
+ 'max:255',
+ "unique:subjects,slug,{$this->subject->id}",
+ ],
+ 'name' => [
+ 'required',
+ 'string',
+ 'max:255',
+ "unique:subjects,name,{$this->subject->id}",
+ ],
+ ];
+ }
+}
diff --git a/app/Models/Subject.php b/app/Models/Subject.php
new file mode 100644
index 0000000..e1fdb9c
--- /dev/null
+++ b/app/Models/Subject.php
@@ -0,0 +1,25 @@
+hasMany('App\Models\EntranceExamination', 'subject_id');
+ }
+}
diff --git a/database/factories/SubjectFactory.php b/database/factories/SubjectFactory.php
new file mode 100644
index 0000000..e761e71
--- /dev/null
+++ b/database/factories/SubjectFactory.php
@@ -0,0 +1,18 @@
+ fake()->name(),
+ 'description' => fake()->text(),
+ 'slug' => fake()->slug(),
+ 'position' => fake()->randomDigit(),
+ ];
+ }
+}
diff --git a/database/migrations/2024_02_15_075912_create_subjects_table.php b/database/migrations/2024_02_15_075912_create_subjects_table.php
new file mode 100644
index 0000000..d36c7b8
--- /dev/null
+++ b/database/migrations/2024_02_15_075912_create_subjects_table.php
@@ -0,0 +1,31 @@
+id();
+ $table->integer('position');
+ $table->string('name');
+ $table->text('description')->nullable();
+ $table->string('slug');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('subjects');
+ }
+};
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index 04e3826..fb798da 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -28,6 +28,7 @@ class DatabaseSeeder extends Seeder
EducationLevelSeeder::class,
EducationFormSeeder::class,
ExaminationTypeSeeder::class,
+ SubjectSeeder::class,
DirectionSeeder::class,
]);
diff --git a/database/seeders/SubjectSeeder.php b/database/seeders/SubjectSeeder.php
new file mode 100644
index 0000000..ad646c0
--- /dev/null
+++ b/database/seeders/SubjectSeeder.php
@@ -0,0 +1,33 @@
+insert([
+ [
+ 'name' => 'Обществознание',
+ 'description' => 'social studies',
+ 'position' => '1',
+ 'slug' => 'social-studies',
+ ],
+ [
+ 'name' => 'Русский язык',
+ 'description' => 'a Russian language course',
+ 'position' => '2',
+ 'slug' => 'russian-language',
+ ],
+ [
+ 'name' => 'математика',
+ 'description' => 'mathematics',
+ 'position' => '3',
+ 'slug' => 'mathematics',
+ ],
+ ]);
+ }
+}
diff --git a/resources/views/admin/catalog/direction/subject/create.blade.php b/resources/views/admin/catalog/direction/subject/create.blade.php
new file mode 100644
index 0000000..5ae0bf2
--- /dev/null
+++ b/resources/views/admin/catalog/direction/subject/create.blade.php
@@ -0,0 +1,65 @@
+@extends('layouts.admin_layout')
+@section('content')
+ @auth()
+
+
+
Создать Предмет
+ {{ Form::open(['url' => route('subjects.store'), 'method' => 'POST', 'class' => '']) }}
+
+
+ {{ Form::label('name', 'Название') }}
+
+
+ {{ Form::text('name', '', ['class' => 'form-control']) }}
+
+
+ @if ($errors->any())
+ {{ $errors->first('name') }}
+ @endif
+
+
+
+ {{ Form::label('description', 'Описание') }}
+
+
+ {{ Form::text('description', '', ['class' => 'form-control']) }}
+
+
+ @if ($errors->any())
+ {{ $errors->first('description') }}
+ @endif
+
+
+
+ {{ Form::label('slug', 'URL') }}
+
+
+ {{ Form::text('slug', '', ['class' => 'form-control']) }}
+
+
+ @if ($errors->any())
+ {{ $errors->first('slug') }}
+ @endif
+
+
+
+ {{ Form::label('position', 'Позиция') }}
+
+
+ {{ Form::text('position', '', ['class' => 'form-control']) }}
+
+
+ @if ($errors->any())
+ {{ $errors->first('position') }}
+ @endif
+
+
+
+ {{ Form::submit('Создать', ['class' => 'btn btn-primary']) }}
+
+
+ {{ Form::close() }}
+
+
+ @endauth
+@endsection
diff --git a/resources/views/admin/catalog/direction/examination_type/edit.blade.php b/resources/views/admin/catalog/direction/subject/edit.blade.php
similarity index 75%
rename from resources/views/admin/catalog/direction/examination_type/edit.blade.php
rename to resources/views/admin/catalog/direction/subject/edit.blade.php
index 5998ef2..e25fea9 100644
--- a/resources/views/admin/catalog/direction/examination_type/edit.blade.php
+++ b/resources/views/admin/catalog/direction/subject/edit.blade.php
@@ -4,14 +4,14 @@
@auth()
-
Изменить тип экзамена
- {{ Form::open(['url' => route('examination_types.update', $examinationType), 'method' => 'PATCH', 'class' => '']) }}
+
Изменить предмет
+ {{ Form::open(['url' => route('subjects.update', $subject), 'method' => 'PATCH', 'class' => '']) }}
{{ Form::label('name', 'Название') }}
- {{ Form::text('name', $examinationType->name, ['class' => 'form-control']) }}
+ {{ Form::text('name', $subject->name, ['class' => 'form-control']) }}
@if ($errors->any())
@@ -23,7 +23,7 @@
{{ Form::label('description', 'Описание') }}
- {{ Form::text('description', $examinationType->description, ['class' => 'form-control']) }}
+ {{ Form::text('description', $subject->description, ['class' => 'form-control']) }}
@if ($errors->any())
@@ -35,7 +35,7 @@
{{ Form::label('slug', 'URL') }}
- {{ Form::text('slug', $examinationType->slug, ['class' => 'form-control']) }}
+ {{ Form::text('slug', $subject->slug, ['class' => 'form-control']) }}
@if ($errors->any())
@@ -47,7 +47,7 @@
{{ Form::label('position', 'Позиция') }}
- {{ Form::text('position', $examinationType->position, ['class' => 'form-control']) }}
+ {{ Form::text('position', $subject->position, ['class' => 'form-control']) }}
@if ($errors->any())
diff --git a/resources/views/admin/catalog/direction/examination_type/index.blade.php b/resources/views/admin/catalog/direction/subject/index.blade.php
similarity index 65%
rename from resources/views/admin/catalog/direction/examination_type/index.blade.php
rename to resources/views/admin/catalog/direction/subject/index.blade.php
index 3cc2417..23888fc 100644
--- a/resources/views/admin/catalog/direction/examination_type/index.blade.php
+++ b/resources/views/admin/catalog/direction/subject/index.blade.php
@@ -3,7 +3,7 @@
Тип Экзамена
-
Создать тип экзамена
+
Создать предмет
@@ -18,17 +18,17 @@
- @foreach($types as $type)
+ @foreach($subjects as $subject)
- {{ $type->position }} |
- {{ $type->name }} |
- {{ Str::words($type->description, 10, '...') }} |
- {{ $type->slug }} |
+ {{ $subject->position }} |
+ {{ $subject->name }} |
+ {{ Str::words($subject->description, 10, '...') }} |
+ {{ $subject->slug }} |
- редактировать
удалить
|
diff --git a/resources/views/admin/catalog/direction/subject/show.blade.php b/resources/views/admin/catalog/direction/subject/show.blade.php
new file mode 100644
index 0000000..b2b1b96
--- /dev/null
+++ b/resources/views/admin/catalog/direction/subject/show.blade.php
@@ -0,0 +1,19 @@
+@extends('layouts.admin_layout')
+@section('content')
+ @auth()
+
+
Название
+
{{ $subject->name }}
+
Описание
+
{{ $subject->description }}
+
URL
+
{{ $subject->slug }}
+
Позиция
+
{{ $subject->position }}
+
Вступительные испытания
+ @foreach($subject->entranceExaminations as $entranceExamination)
+
{{ $entranceExamination->name }}
+ @endforeach
+
+ @endauth
+@endsection
diff --git a/resources/views/layouts/admin_layout.blade.php b/resources/views/layouts/admin_layout.blade.php
index 140dd25..c2bda8d 100644
--- a/resources/views/layouts/admin_layout.blade.php
+++ b/resources/views/layouts/admin_layout.blade.php
@@ -58,7 +58,8 @@
Направления
Уровни образования
Формы образования
- Тип Экзаменов
+ Типы Экзаменов
+ Предметы
@yield('content')
diff --git a/routes/admin.php b/routes/admin.php
index 520742d..b4016da 100644
--- a/routes/admin.php
+++ b/routes/admin.php
@@ -5,6 +5,7 @@ use App\Http\Controllers\admin\Catalog\DepartmentController;
use App\Http\Controllers\admin\Catalog\Direction\EducationFormController;
use App\Http\Controllers\admin\Catalog\Direction\EducationLevelController;
use App\Http\Controllers\admin\Catalog\Direction\ExaminationTypeController;
+use App\Http\Controllers\admin\Catalog\Direction\SubjectController;
use App\Http\Controllers\admin\Catalog\DirectionController;
use App\Http\Controllers\admin\Catalog\EducationalInstitutionController;
use App\Http\Controllers\admin\Catalog\FacultyController;
@@ -45,6 +46,9 @@ Route::middleware(['auth', 'verified'])->prefix('admin')->group(function () {
Route::resource('/examination_types', ExaminationTypeController::class)
->scoped(['examination_type' => 'slug']);
+ Route::resource('/subjects', SubjectController::class)
+ ->scoped(['subject' => 'slug']);
+
Route::resources([
'/documents' => DocumentController::class,
'/users' => UserController::class,
diff --git a/tests/Feature/admin/catalog/direction/SubjectTest.php b/tests/Feature/admin/catalog/direction/SubjectTest.php
new file mode 100644
index 0000000..44cd9a1
--- /dev/null
+++ b/tests/Feature/admin/catalog/direction/SubjectTest.php
@@ -0,0 +1,102 @@
+subject = Subject::factory()->create();
+
+ $this->data = Subject::factory()->make()->only([
+ 'name',
+ 'description',
+ 'position',
+ 'slug',
+ ]);
+
+ $this->user = User::factory()->create([
+ 'name' => 'admin',
+ 'email' => 'test@example.com',
+ 'password' => 123456
+ ]);
+ }
+
+ public function testIndexSubjectsPage(): void
+ {
+ $response = $this->actingAs($this->user)
+ ->withSession(['banned' => false])
+ ->get(route('subjects.index'));
+
+ $response->assertOk();
+ }
+
+ public function testCreateSubjectPage(): void
+ {
+ $response = $this->actingAs($this->user)
+ ->withSession(['banned' => false])
+ ->get(route('subjects.create'));
+
+ $response->assertOk();
+ }
+
+ public function testStoreSubject(): void
+ {
+ $response = $this->actingAs($this->user)
+ ->withSession(['banned' => false])
+ ->post(route('subjects.store', $this->data));
+
+ $response->assertRedirect(route('subjects.index'));
+
+ $this->assertDatabaseHas('subjects', $this->data);
+ }
+
+ public function testShowSubjectPage(): void
+ {
+ $response = $this->actingAs($this->user)
+ ->withSession(['banned' => false])
+ ->get(route('subjects.show', $this->subject));
+
+ $response->assertOk();
+ }
+
+ public function testEditSubjectPage(): void
+ {
+ $response = $this->actingAs($this->user)
+ ->withSession(['banned' => false])
+ ->get(route('subjects.edit', $this->subject));
+
+ $response->assertOk();
+ }
+
+ public function testUpdateSubject(): void
+ {
+ $response = $this->actingAs($this->user)
+ ->withSession(['banned' => false])
+ ->patch(route('subjects.update', $this->subject), $this->data);
+
+ $response->assertRedirect(route('subjects.index'));
+
+ $this->assertDatabaseHas('subjects', $this->data);
+ }
+
+ public function testDestroySubject(): void
+ {
+ $response = $this->actingAs($this->user)
+ ->withSession(['banned' => false])
+ ->delete(route('subjects.destroy', $this->subject));
+
+ $response->assertRedirect(route('subjects.index'));
+
+ $this->assertDatabaseMissing('subjects', $this->subject->toArray());
+ }
+}