prodV1 #2

Open
RomanGolienko wants to merge 309 commits from prodV1 into main
16 changed files with 579 additions and 0 deletions
Showing only changes of commit 5f5c3135d8 - Show all commits

View File

@ -0,0 +1,75 @@
<?php
namespace App\Http\Controllers\admin\Catalog\Direction;
use App\Http\Controllers\Controller;
use App\Http\Requests\admin\Catalog\Direction\StoreDirectionProfileRequest;
use App\Http\Requests\admin\Catalog\Direction\UpdateDirectionProfileRequest;
use App\Models\Direction;
use App\Models\DirectionProfile;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
class DirectionProfileController extends Controller
{
public function index(): View
{
$directionProfiles = DirectionProfile::all();
return view('admin.catalog.direction.direction_profile.index', compact('directionProfiles'));
}
public function create(): View
{
$directions = Direction::pluck('name', 'id');
return view('admin.catalog.direction.direction_profile.create', compact('directions'));
}
public function store(StoreDirectionProfileRequest $request): RedirectResponse
{
$validated = $request->validated();
$directionProfile = new DirectionProfile();
$directionProfile->name = $validated['name'];
$directionProfile->description = $validated['description'];
$directionProfile->slug = $validated['slug'];
$directionProfile->position = $validated['position'];
$directionProfile->direction_id = $validated['direction_id'];
$directionProfile->save();
return redirect()->route('direction_profiles.index');
}
public function show(DirectionProfile $directionProfile): View
{
return view('admin.catalog.direction.direction_profile.show', compact('directionProfile'));
}
public function edit(DirectionProfile $directionProfile): View
{
$directions = Direction::pluck('name', 'id');
return view(
'admin.catalog.direction.direction_profile.edit',
compact('directionProfile','directions')
);
}
public function update(UpdateDirectionProfileRequest $request, DirectionProfile $directionProfile): RedirectResponse
{
$validated = $request->validated();
$directionProfile->name = $validated['name'];
$directionProfile->description = $validated['description'];
$directionProfile->slug = $validated['slug'];
$directionProfile->position = $validated['position'];
$directionProfile->direction_id = $validated['direction_id'];
$directionProfile->save();
return redirect()->route('direction_profiles.index');
}
public function destroy(DirectionProfile $directionProfile): RedirectResponse
{
$directionProfile->delete();
return redirect()->route('direction_profiles.index');
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Http\Requests\admin\Catalog\Direction;
use Illuminate\Foundation\Http\FormRequest;
class StoreDirectionProfileRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => 'required|string|max:255|unique:direction_profiles,name',
'description' => 'string',
'slug' => 'required|string|max:255|unique:direction_profiles,slug',
'direction_id' => 'required|int|numeric|max:255',
'position' => 'required|int|numeric|max:255',
];
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Http\Requests\admin\Catalog\Direction;
use Illuminate\Foundation\Http\FormRequest;
class UpdateDirectionProfileRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => "required|string|max:255|unique:direction_profiles,name,{$this->direction_profile->id}",
'description' => 'string',
'slug' => "required|string|max:255|unique:direction_profiles,slug,{$this->direction_profile->id}",
'direction_id' => 'required|int|numeric|max:255',
'position' => 'required|int|numeric|max:255',
];
}
}

View File

@ -49,4 +49,9 @@ class Direction extends Model
{
return $this->hasMany('App\Models\Cost', 'direction_id');
}
public function directionProfiles(): HasMany
{
return $this->hasMany('App\Models\DirectionProfile', 'direction_id');
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class DirectionProfile extends Model
{
use HasFactory;
protected $fillable = [
'id',
'name',
'description',
'slug',
'position',
'direction_id'
];
public function direction(): BelongsTo
{
return $this->belongsTo(Direction::class);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class DirectionProfileFactory extends Factory
{
public function definition(): array
{
return [
'name' => fake()->name(),
'description' => fake()->text(),
'slug' => fake()->slug(),
'position' => 1,
'direction_id' => 1,
];
}
}

View File

@ -0,0 +1,32 @@
<?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('direction_profiles', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->string('slug');
$table->string('position');
$table->foreignId('direction_id')->constrained('directions');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('direction_profiles');
}
};

View File

@ -35,6 +35,7 @@ class DatabaseSeeder extends Seeder
PlaceTypeSeeder::class,
PlaceSeeder::class,
CostSeeder::class,
DirectionProfileSeeder::class,
]);
$this->call([

View File

@ -0,0 +1,37 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class DirectionProfileSeeder extends Seeder
{
public function run(): void
{
DB::table('direction_profiles')->insert([
[
'name' => 'Государственно-правовой',
'description' => 'Государственно-правовой профиль',
'slug' => 'the-state-legal',
'position' => 1,
'direction_id' => 1,
],
[
'name' => 'Условно-правовой',
'description' => 'Условно-правовой профиль',
'slug' => 'probationary-profile',
'position' => 2,
'direction_id' => 1,
],
[
'name' => 'Цифровой Юрист',
'description' => 'Цифровой Юрист профиль',
'slug' => 'digital-lawyer',
'position' => 3,
'direction_id' => 1,
],
]);
}
}

View File

@ -0,0 +1,77 @@
@extends('layouts.admin_layout')
@section('content')
@auth()
<div class="row">
<div class="col">
<h1 class=""> Создать Профиль Подготовки</h1>
{{ Form::open(['url' => route('direction_profiles.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('direction_id', 'Направление подготовки') }}
</div>
<div class="mt-1">
{{ Form::select('direction_id', $directions, null, ['class' => 'form-select']) }}
</div>
<div>
@if ($errors->any())
{{ $errors->first('direction_id') }}
@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

View File

@ -0,0 +1,77 @@
@extends('layouts.admin_layout')
@section('content')
@auth()
<div class="row">
<div class="col">
<h1 class="">Изменить Профиль Подготовки</h1>
{{ Form::open(['url' => route('direction_profiles.update', $directionProfile), 'method' => 'PATCH', 'class' => '']) }}
<div class="col">
<div class="mt-3">
{{ Form::label('name', 'Название') }}
</div>
<div class="mt-1">
{{ Form::text('name', $directionProfile->name, ['class' => 'form-control']) }}
</div>
<div>
@if ($errors->any())
{{ $errors->first('name') }}
@endif
</div>
<div class="mt-3">
{{ Form::label('direction_id', 'Направление подготовки') }}
</div>
<div class="mt-1">
{{ Form::select('direction_id', $directions, $directionProfile->direction->id, ['class' => 'form-select']) }}
</div>
<div>
@if ($errors->any())
{{ $errors->first('direction_id') }}
@endif
</div>
<div class="mt-3">
{{ Form::label('description', 'Описание') }}
</div>
<div class="mt-1">
{{ Form::text('description', $directionProfile->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', $directionProfile->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', $directionProfile->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

View File

@ -0,0 +1,43 @@
@extends('layouts.admin_layout')
@section('content')
<div class="container">
<h2>Профили образования</h2>
<br>
<a href="{{ route('direction_profiles.create') }}" class="btn btn-primary">Создать Профиль образования</a>
<br>
<br>
<table class="table">
<thead class="border-b-2 border-solid border-black text-left" style="text-align: left">
<tr>
<th scope="col">Название</th>
<th scope="col">Направление подготовки</th>
<th scope="col">Описание</th>
<th scope="col">Позиция</th>
<th scope="col">URL</th>
<th scope="col">действия</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach($directionProfiles as $directionProfile)
<tr class="">
<td><a href="{{ route('direction_profiles.show', $directionProfile) }}">{{ $directionProfile->name }}</a></td>
<td><a href="{{ route('directions.show', $directionProfile->direction) }}">{{ $directionProfile->direction->name }}</a></td>
<td>{{ Str::words($directionProfile->description, 10, '...') }}</td>
<td>{{ $directionProfile->position }}</td>
<td>{{ $directionProfile->slug }}</td>
<td>
<a href="{{ route("direction_profiles.edit", $directionProfile) }}"
class="btn btn-secondary">редактировать</a>
<a rel="nofollow" data-method="delete" data-confirm="Вы действительно хотите удалить?"
href="{{ route('direction_profiles.destroy', $directionProfile) }}"
class="btn btn-danger">удалить</a>
</td>
</tr>
@endforeach
</tbody>
</table>
<br>
<br>
</div>
@endsection

View File

@ -0,0 +1,17 @@
@extends('layouts.admin_layout')
@section('content')
@auth()
<div class="container mt-4">
<h2>Название</h2>
<p>{{ $directionProfile->name }}</p>
<h2>Направление подготовки</h2>
<p><a href="{{ route('directions.show', $directionProfile->direction) }}">{{ $directionProfile->direction->name }}</a></p>
<h2>Описание</h2>
<p>{{ $directionProfile->description }}</p>
<h2>Позиция</h2>
<p>{{ $directionProfile->position }}</p>
<h2>URL</h2>
<p>{{ $directionProfile->slug }}</p>
</div>
@endauth
@endsection

View File

@ -65,6 +65,7 @@
<li class="list-group-item"><a href="{{ route('places.index') }}">Кол-во Мест</a></li>
<li class="list-group-item"><a href="{{ route('place_types.index') }}">Типы Мест</a></li>
<li class="list-group-item"><a href="{{ route('costs.index') }}">Стоимость об.</a></li>
<li class="list-group-item"><a href="{{ route('direction_profiles.index') }}">Профили подготовки</a></li>
</ul>
</aside>
<main class="col-10">@yield('content')</main>

View File

@ -3,6 +3,7 @@
use App\Http\Controllers\admin\AdmissionController;
use App\Http\Controllers\admin\Catalog\DepartmentController;
use App\Http\Controllers\admin\Catalog\Direction\CostController;
use App\Http\Controllers\admin\Catalog\Direction\DirectionProfileController;
use App\Http\Controllers\admin\Catalog\Direction\EducationFormController;
use App\Http\Controllers\admin\Catalog\Direction\EducationLevelController;
use App\Http\Controllers\admin\Catalog\Direction\EntranceExaminationController;
@ -65,6 +66,9 @@ Route::middleware(['auth', 'verified'])->prefix('admin')->group(function () {
Route::resource('/places', PlaceController::class);
Route::resource('/costs', CostController::class);
Route::resource('/direction_profiles', DirectionProfileController::class)
->scoped(['direction_profile' => 'slug']);
Route::resources([
'/documents' => DocumentController::class,
'/users' => UserController::class,

View File

@ -0,0 +1,117 @@
<?php
namespace Tests\Feature\admin\catalog\direction;
use App\Models\Department;
use App\Models\Direction;
use App\Models\DirectionProfile;
use App\Models\EducationalInstitution;
use App\Models\EducationForm;
use App\Models\EducationLevel;
use App\Models\Faculty;
use App\Models\Place;
use App\Models\PlaceType;
use App\Models\User;
use Tests\TestCase;
class DirectionProfileTest extends TestCase
{
private User $user;
private DirectionProfile $directionProfile;
private array $data;
protected function setUp(): void
{
parent::setUp();
EducationalInstitution::factory()->create();
Faculty::factory()->create();
Department::factory()->create();
EducationLevel::factory()->create();
EducationForm::factory()->create();
Direction::factory()->create();
$this->directionProfile = DirectionProfile::factory()->create();
$this->data = DirectionProfile::factory()->make()->only([
'name',
'position',
'description',
'slug',
'direction_id',
]);
$this->user = User::factory()->create([
'name' => 'admin',
'email' => 'test@example.com',
'password' => 123456
]);
}
public function testIndexDirectionProfilesPage(): void
{
$response = $this->actingAs($this->user)
->withSession(['banned' => false])
->get(route('direction_profiles.index'));
$response->assertOk();
}
public function testCreateDirectionProfilePage(): void
{
$response = $this->actingAs($this->user)
->withSession(['banned' => false])
->get(route('direction_profiles.create'));
$response->assertOk();
}
public function testStoreDirectionProfile(): void
{
$response = $this->actingAs($this->user)
->withSession(['banned' => false])
->post(route('direction_profiles.store', $this->data));
$response->assertRedirect(route('direction_profiles.index'));
$this->assertDatabaseHas('direction_profiles', $this->data);
}
public function testShowDirectionProfilePage(): void
{
$response = $this->actingAs($this->user)
->withSession(['banned' => false])
->get(route('direction_profiles.show', $this->directionProfile));
$response->assertOk();
}
public function testEditDirectionProfilePage(): void
{
$response = $this->actingAs($this->user)
->withSession(['banned' => false])
->get(route('direction_profiles.edit', $this->directionProfile));
$response->assertOk();
}
public function testUpdateDirectionProfile(): void
{
$response = $this->actingAs($this->user)
->withSession(['banned' => false])
->patch(route('direction_profiles.update', $this->directionProfile), $this->data);
$response->assertRedirect(route('direction_profiles.index'));
$this->assertDatabaseHas('direction_profiles', $this->data);
}
public function testDestroyDirectionProfile(): void
{
$response = $this->actingAs($this->user)
->withSession(['banned' => false])
->delete(route('direction_profiles.destroy', $this->directionProfile));
$response->assertRedirect(route('direction_profiles.index'));
$this->assertDatabaseMissing('direction_profiles', $this->directionProfile->toArray());
}
}