add Subject resource
This commit is contained in:
parent
5f3c4449c0
commit
1462d70800
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\admin\Catalog\Direction;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\admin\Catalog\Direction\StoreExaminationTypeRequest;
|
||||
use App\Http\Requests\admin\Catalog\Direction\StoreSubjectRequest;
|
||||
use App\Http\Requests\admin\Catalog\Direction\UpdateExaminationTypeRequest;
|
||||
use App\Http\Requests\admin\Catalog\Direction\UpdateSubjectRequest;
|
||||
use App\Models\Subject;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
|
||||
class SubjectController extends Controller
|
||||
{
|
||||
public function index(): View
|
||||
{
|
||||
$subjects = Subject::all();
|
||||
return view('admin.catalog.direction.subject.index', compact('subjects'));
|
||||
}
|
||||
|
||||
public function create(): View
|
||||
{
|
||||
return view('admin.catalog.direction.subject.create');
|
||||
}
|
||||
|
||||
public function store(StoreSubjectRequest $request): RedirectResponse
|
||||
{
|
||||
$validated = $request->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');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\admin\Catalog\Direction;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreSubjectRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'position' => 'required|int|numeric|max:255',
|
||||
'name' => 'required|string|max:255|unique:subjects,name',
|
||||
'description' => 'string',
|
||||
'slug' => 'required|string|max:255|unique:subjects,slug',
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\admin\Catalog\Direction;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateEntranceExaminationRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\admin\Catalog\Direction;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateSubjectRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'position' => '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}",
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
class Subject extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
'slug',
|
||||
'position',
|
||||
];
|
||||
|
||||
public function entranceExaminations(): HasMany
|
||||
{
|
||||
return $this->hasMany('App\Models\EntranceExamination', 'subject_id');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
class SubjectFactory extends Factory
|
||||
{
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'name' => fake()->name(),
|
||||
'description' => fake()->text(),
|
||||
'slug' => fake()->slug(),
|
||||
'position' => fake()->randomDigit(),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('subjects', function (Blueprint $table) {
|
||||
$table->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');
|
||||
}
|
||||
};
|
|
@ -28,6 +28,7 @@ class DatabaseSeeder extends Seeder
|
|||
EducationLevelSeeder::class,
|
||||
EducationFormSeeder::class,
|
||||
ExaminationTypeSeeder::class,
|
||||
SubjectSeeder::class,
|
||||
DirectionSeeder::class,
|
||||
]);
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class SubjectSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
DB::table('subjects')->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',
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
@extends('layouts.admin_layout')
|
||||
@section('content')
|
||||
@auth()
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1 class=""> Создать Предмет</h1>
|
||||
{{ Form::open(['url' => route('subjects.store'), 'method' => 'POST', 'class' => '']) }}
|
||||
<div class="col">
|
||||
<div class="mt-3">
|
||||
{{ Form::label('name', 'Название') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('name', '', ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
||||
{{ $errors->first('name') }}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
{{ Form::label('description', 'Описание') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('description', '', ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
||||
{{ $errors->first('description') }}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
{{ Form::label('slug', 'URL') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('slug', '', ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
||||
{{ $errors->first('slug') }}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
{{ Form::label('position', 'Позиция') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('position', '', ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
||||
{{ $errors->first('position') }}
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
{{ Form::submit('Создать', ['class' => 'btn btn-primary']) }}
|
||||
</div>
|
||||
</div>
|
||||
{{ Form::close() }}
|
||||
</div>
|
||||
</div>
|
||||
@endauth
|
||||
@endsection
|
|
@ -4,14 +4,14 @@
|
|||
@auth()
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1 class="">Изменить тип экзамена</h1>
|
||||
{{ Form::open(['url' => route('examination_types.update', $examinationType), 'method' => 'PATCH', 'class' => '']) }}
|
||||
<h1 class="">Изменить предмет</h1>
|
||||
{{ Form::open(['url' => route('subjects.update', $subject), 'method' => 'PATCH', 'class' => '']) }}
|
||||
<div class="col">
|
||||
<div class="mt-3">
|
||||
{{ Form::label('name', 'Название') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('name', $examinationType->name, ['class' => 'form-control']) }}
|
||||
{{ Form::text('name', $subject->name, ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
||||
|
@ -23,7 +23,7 @@
|
|||
{{ Form::label('description', 'Описание') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('description', $examinationType->description, ['class' => 'form-control']) }}
|
||||
{{ Form::text('description', $subject->description, ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
||||
|
@ -35,7 +35,7 @@
|
|||
{{ Form::label('slug', 'URL') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('slug', $examinationType->slug, ['class' => 'form-control']) }}
|
||||
{{ Form::text('slug', $subject->slug, ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
||||
|
@ -47,7 +47,7 @@
|
|||
{{ Form::label('position', 'Позиция') }}
|
||||
</div>
|
||||
<div class="mt-1">
|
||||
{{ Form::text('position', $examinationType->position, ['class' => 'form-control']) }}
|
||||
{{ Form::text('position', $subject->position, ['class' => 'form-control']) }}
|
||||
</div>
|
||||
<div>
|
||||
@if ($errors->any())
|
|
@ -3,7 +3,7 @@
|
|||
<div class="container">
|
||||
<h2>Тип Экзамена</h2>
|
||||
<br>
|
||||
<a href="{{ route('examination_types.create') }}" class="btn btn-primary">Создать тип экзамена</a>
|
||||
<a href="{{ route('subjects.create') }}" class="btn btn-primary">Создать предмет</a>
|
||||
<br>
|
||||
<br>
|
||||
<table class="table">
|
||||
|
@ -18,17 +18,17 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($types as $type)
|
||||
@foreach($subjects as $subject)
|
||||
<tr class="">
|
||||
<td>{{ $type->position }}</td>
|
||||
<td><a href="{{ route('examination_types.show', $type) }}">{{ $type->name }}</a></td>
|
||||
<td>{{ Str::words($type->description, 10, '...') }}</td>
|
||||
<td>{{ $type->slug }}</td>
|
||||
<td>{{ $subject->position }}</td>
|
||||
<td><a href="{{ route('subjects.show', $subject) }}">{{ $subject->name }}</a></td>
|
||||
<td>{{ Str::words($subject->description, 10, '...') }}</td>
|
||||
<td>{{ $subject->slug }}</td>
|
||||
<td>
|
||||
<a href="{{ route("examination_types.edit", $type) }}"
|
||||
<a href="{{ route("subjects.edit", $subject) }}"
|
||||
class="btn btn-secondary">редактировать</a>
|
||||
<a rel="nofollow" data-method="delete" data-confirm="Вы действительно хотите удалить?"
|
||||
href="{{ route('examination_types.destroy', $type) }}"
|
||||
href="{{ route('subjects.destroy', $subject) }}"
|
||||
class="btn btn-danger">удалить</a>
|
||||
</td>
|
||||
</tr>
|
|
@ -0,0 +1,19 @@
|
|||
@extends('layouts.admin_layout')
|
||||
@section('content')
|
||||
@auth()
|
||||
<div class="container mt-4">
|
||||
<h2>Название</h2>
|
||||
<p>{{ $subject->name }}</p>
|
||||
<h2>Описание</h2>
|
||||
<p>{{ $subject->description }}</p>
|
||||
<h2>URL</h2>
|
||||
<p>{{ $subject->slug }}</p>
|
||||
<h2>Позиция</h2>
|
||||
<p>{{ $subject->position }}</p>
|
||||
<h2>Вступительные испытания</h2>
|
||||
@foreach($subject->entranceExaminations as $entranceExamination)
|
||||
<p><a href="{{ route('entrance_examinations.show', $entranceExamination) }}">{{ $entranceExamination->name }}</a></p>
|
||||
@endforeach
|
||||
</div>
|
||||
@endauth
|
||||
@endsection
|
|
@ -58,7 +58,8 @@
|
|||
<li class="list-group-item"><a href="{{ route('directions.index') }}">Направления</a></li>
|
||||
<li class="list-group-item"><a href="{{ route('education_levels.index') }}">Уровни образования</a></li>
|
||||
<li class="list-group-item"><a href="{{ route('education_forms.index') }}">Формы образования</a></li>
|
||||
<li class="list-group-item"><a href="{{ route('examination_types.index') }}">Тип Экзаменов</a></li>
|
||||
<li class="list-group-item"><a href="{{ route('examination_types.index') }}">Типы Экзаменов</a></li>
|
||||
<li class="list-group-item"><a href="{{ route('subjects.index') }}">Предметы</a></li>
|
||||
</ul>
|
||||
</aside>
|
||||
<main class="col-10">@yield('content')</main>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature\admin\catalog\direction;
|
||||
|
||||
use App\Models\ExaminationType;
|
||||
use App\Models\Subject;
|
||||
use App\Models\User;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SubjectTest extends TestCase
|
||||
{
|
||||
private User $user;
|
||||
private Subject $subject;
|
||||
private array $data;
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->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());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue