Migrate backend to Porto architecture and fix minor bugs

- Fully transitioned the backend to the Porto architectural pattern
- Improved code organization and maintainability
- Fixed minor bugs and inconsistencies
This commit is contained in:
F4ilji
2025-05-12 08:47:43 +05:00
parent 76deaf75f3
commit c01016a154
620 changed files with 16218 additions and 6073 deletions
@@ -0,0 +1,45 @@
<?php
namespace App\Containers\Education\Enums;
use Filament\Support\Contracts\HasLabel;
use Filament\Support\Contracts\HasColor;
enum TypeExam: int implements HasLabel, HasColor
{
case EGE = 1;
case INTERNAL_EXAM = 2;
case AVG_SCORE = 3;
case ACCREDITATION = 4;
public function getLabel(): ?string
{
return match ($this) {
self::EGE => 'ЕГЭ',
self::INTERNAL_EXAM => 'ВИ, проводимое организацией самостоятельно',
self::AVG_SCORE => 'Ср. балл документа об образовании',
self::ACCREDITATION => 'Аккредитация',
};
}
public function getColor(): string|array|null
{
return match ($this) {
self::EGE => 'primary',
self::INTERNAL_EXAM => 'info',
self::AVG_SCORE => 'success',
self::ACCREDITATION => 'warning',
};
}
public static function fromName(string $name): ?self
{
return match ($name) {
'EGE' => self::EGE,
'INTERNAL_EXAM' => self::INTERNAL_EXAM,
'AVG_SCORE' => self::AVG_SCORE,
'ACCREDITATION' => self::ACCREDITATION,
default => null,
};
}
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Education\Loaders;
class AliasesLoader
{
/**
* @var array
*/
public array $aliases = [];
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Education\Loaders;
class MiddlewareLoader
{
/**
* @var array
*/
public array $middleware = [];
/**
* @var array
*/
public array $middlewareGroups = [];
/**
* @var array
*/
public array $routeMiddleware = [];
/**
* @var array
*/
public array $middlewarePriority = [];
}
@@ -0,0 +1,11 @@
<?php
namespace App\Containers\Education\Loaders;
class ProvidersLoader
{
/**
* @var array
*/
public array $providers = [];
}
@@ -0,0 +1,36 @@
<?php
namespace App\Containers\Education\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
class AdmissionCampaign extends Model
{
use HasFactory;
protected $guarded = false;
protected $casts = [
'info' => 'array'
];
public function admission_plans(): HasMany
{
return $this->hasMany(AdmissionPlan::class, 'admission_campaigns_id', 'id');
}
public function educationalPrograms(): HasManyThrough
{
return $this->hasManyThrough(
EducationalProgram::class,
AdmissionPlan::class,
'admission_campaigns_id', // внешний ключ в AdmissionPlan
'id', // внешний ключ в EducationalPrograms
'id', // локальный ключ в AdmissionCampaign
'educational_programs_id' // локальный ключ в AdmissionPlan
);
}
}
@@ -0,0 +1,29 @@
<?php
namespace App\Containers\Education\Models;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AdmissionPlan extends Model
{
use HasFactory;
protected $guarded = false;
protected $casts = [
'exams' => 'array',
'contests' => 'array'
];
public function educationalProgram(): BelongsTo
{
return $this->belongsTo(EducationalProgram::class, 'educational_programs_id', 'id');
}
public function admissionCampaign(): BelongsTo
{
return $this->belongsTo(AdmissionCampaign::class, 'admission_campaigns_id', 'id');
}
}
@@ -0,0 +1,64 @@
<?php
namespace App\Containers\Education\Models;
use App\Ship\Enums\Education\LevelEducational;
use App\Ship\Models\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
class DirectionStudy extends Model
{
use HasFactory;
protected $guarded = false;
protected $casts = [
'lvl_edu' => LevelEducational::class,
];
public function programs(): HasMany
{
return $this->hasMany(EducationalProgram::class);
}
public function scopeWithActivePrograms(Builder $query): Builder
{
return $query->with(['programs' => function ($query) {
$query->whereHas('admission_plans.admissionCampaign', function ($q) {
$q->where('status', 1);
});
}]);
}
public function scopeWithActiveAdmissionCampaign(Builder $query): Builder
{
return $query->whereHas('programs.admission_plans.admissionCampaign', function ($q) {
$q->where('status', 1);
});
}
public function scopeWithAdmissionCampaignByYear(Builder $query, string $year): Builder
{
return $query->whereHas('programs.admission_plans.admissionCampaign', function ($q) use ($year) {
$q->where('status', 1)->where('academic_year', $year);
});
}
public function scopeForBachelorLevel(Builder $query): Builder
{
return $query->where('lvl_edu', LevelEducational::BACHELOR);
}
public function scopeForMiddleLevel(Builder $query): Builder
{
return $query->whereIn('lvl_edu', [LevelEducational::MIDDLE_LEVEL_SPECIALIST_TRAINING, LevelEducational::PREPARATION_OF_QUALIFIED_WORKERS]);
}
public function scopeForMasterLevel(Builder $query): Builder
{
return $query->where('lvl_edu', LevelEducational::MASTER);
}
}
@@ -0,0 +1,43 @@
<?php
namespace App\Containers\Education\Models;
use App\Containers\InstituteStructure\Models\Department;
use App\Ship\Enums\Education\LevelEducational;
use App\Ship\Models\Model;
use App\Ship\Traits\HasSeo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
class EducationalProgram extends Model
{
use HasFactory, HasSeo;
protected $guarded = false;
protected $casts = [
'program_features' => 'array',
'about_program' => 'array',
'learning_forms' => 'array',
'lvl_edu' => LevelEducational::class,
];
public function directionStudy(): BelongsTo
{
return $this->belongsTo(DirectionStudy::class);
}
public function departments(): BelongsToMany
{
return $this->belongsToMany(Department::class, 'program_department');
}
public function admission_plans(): HasMany
{
return $this->hasMany(AdmissionPlan::class, 'educational_programs_id', 'id');
}
}
@@ -0,0 +1,108 @@
<?php
namespace App\Containers\Education\Policies;
use App\Containers\User\Models\User;
use App\Containers\Education\Models\AdmissionCampaign;
use Illuminate\Auth\Access\HandlesAuthorization;
class AdmissionCampaignPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
return $user->can('view_any_admission::campaign');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, AdmissionCampaign $admissionCampaign): bool
{
return $user->can('view_admission::campaign');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_admission::campaign');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, AdmissionCampaign $admissionCampaign): bool
{
return $user->can('update_admission::campaign');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, AdmissionCampaign $admissionCampaign): bool
{
return $user->can('delete_admission::campaign');
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_admission::campaign');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, AdmissionCampaign $admissionCampaign): bool
{
return $user->can('force_delete_admission::campaign');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_admission::campaign');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, AdmissionCampaign $admissionCampaign): bool
{
return $user->can('restore_admission::campaign');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_admission::campaign');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, AdmissionCampaign $admissionCampaign): bool
{
return $user->can('replicate_admission::campaign');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_admission::campaign');
}
}
@@ -0,0 +1,108 @@
<?php
namespace App\Containers\Education\Policies;
use App\Containers\User\Models\User;
use App\Containers\Education\Models\AdmissionPlan;
use Illuminate\Auth\Access\HandlesAuthorization;
class AdmissionPlanPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
return $user->can('view_any_admission::plan');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, AdmissionPlan $admissionPlan): bool
{
return $user->can('view_admission::plan');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_admission::plan');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, AdmissionPlan $admissionPlan): bool
{
return $user->can('update_admission::plan');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, AdmissionPlan $admissionPlan): bool
{
return $user->can('delete_admission::plan');
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_admission::plan');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, AdmissionPlan $admissionPlan): bool
{
return $user->can('force_delete_admission::plan');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_admission::plan');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, AdmissionPlan $admissionPlan): bool
{
return $user->can('restore_admission::plan');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_admission::plan');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, AdmissionPlan $admissionPlan): bool
{
return $user->can('replicate_admission::plan');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_admission::plan');
}
}
@@ -0,0 +1,108 @@
<?php
namespace App\Containers\Education\Policies;
use App\Containers\User\Models\User;
use App\Containers\Education\Models\DirectionStudy;
use Illuminate\Auth\Access\HandlesAuthorization;
class DirectionStudyPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
return $user->can('view_any_direction::study');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, DirectionStudy $directionStudy): bool
{
return $user->can('view_direction::study');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_direction::study');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, DirectionStudy $directionStudy): bool
{
return $user->can('update_direction::study');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, DirectionStudy $directionStudy): bool
{
return $user->can('delete_direction::study');
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_direction::study');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, DirectionStudy $directionStudy): bool
{
return $user->can('force_delete_direction::study');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_direction::study');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, DirectionStudy $directionStudy): bool
{
return $user->can('restore_direction::study');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_direction::study');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, DirectionStudy $directionStudy): bool
{
return $user->can('replicate_direction::study');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_direction::study');
}
}
@@ -0,0 +1,108 @@
<?php
namespace App\Containers\Education\Policies;
use App\Containers\User\Models\User;
use App\Containers\Education\Models\EducationalProgram;
use Illuminate\Auth\Access\HandlesAuthorization;
class EducationalProgramPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
return $user->can('view_any_educational::program');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, EducationalProgram $educationalProgram): bool
{
return $user->can('view_educational::program');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->can('create_educational::program');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, EducationalProgram $educationalProgram): bool
{
return $user->can('update_educational::program');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, EducationalProgram $educationalProgram): bool
{
return $user->can('delete_educational::program');
}
/**
* Determine whether the user can bulk delete.
*/
public function deleteAny(User $user): bool
{
return $user->can('delete_any_educational::program');
}
/**
* Determine whether the user can permanently delete.
*/
public function forceDelete(User $user, EducationalProgram $educationalProgram): bool
{
return $user->can('force_delete_educational::program');
}
/**
* Determine whether the user can permanently bulk delete.
*/
public function forceDeleteAny(User $user): bool
{
return $user->can('force_delete_any_educational::program');
}
/**
* Determine whether the user can restore.
*/
public function restore(User $user, EducationalProgram $educationalProgram): bool
{
return $user->can('restore_educational::program');
}
/**
* Determine whether the user can bulk restore.
*/
public function restoreAny(User $user): bool
{
return $user->can('restore_any_educational::program');
}
/**
* Determine whether the user can replicate.
*/
public function replicate(User $user, EducationalProgram $educationalProgram): bool
{
return $user->can('replicate_educational::program');
}
/**
* Determine whether the user can reorder.
*/
public function reorder(User $user): bool
{
return $user->can('reorder_educational::program');
}
}
@@ -0,0 +1,15 @@
<?php
namespace App\Containers\Education\UI\API\Controllers;
use App\Containers\Education\Models\AdmissionCampaign;
use App\Ship\Controllers\Controller;
class AcademicYearController extends Controller
{
public function __invoke()
{
$activeCampaign = AdmissionCampaign::query()->where('status', 1)->firstOrFail();
return $activeCampaign->academic_year;
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Containers\Education\UI\API\Controllers;
use App\Http\Controllers\Controller;
use App\Jobs\CreateAdmissionPlan;
use App\Jobs\CreateDirectionStudy;
use App\Jobs\CreateEducationalProgram;
use App\Services\Vicon\EducationalProgram\EducationalProgramService;
class UpdateAdmissionPlansDataApiController extends Controller
{
public function index()
{
$this->clearAndCreateAdmissionPlans();
return redirect()->route('index');
}
private function clearAndCreateAdmissionPlans() : void
{
dispatch(new CreateAdmissionPlan());
}
}
@@ -0,0 +1,28 @@
<?php
namespace App\Containers\Education\UI\API\Controllers;
use App\Http\Controllers\Controller;
use App\Jobs\CreateDirectionStudy;
use App\Jobs\CreateEducationalProgram;
use App\Services\Vicon\EducationalProgram\EducationalProgramService;
class UpdateEduDataApiController extends Controller
{
public function index()
{
$this->updateOrCreateDirectionStudy();
$this->updateOrCreateEducationProgram();
return redirect()->route('index');
}
private function updateOrCreateDirectionStudy() : void
{
dispatch(new CreateDirectionStudy());
}
private function updateOrCreateEducationProgram() : void
{
dispatch(new CreateEducationalProgram());
}
}
@@ -0,0 +1,13 @@
<?php
use App\Containers\Education\UI\API\Controllers\AcademicYearController;
use App\Containers\Education\UI\API\Controllers\UpdateAdmissionPlansDataApiController;
use App\Containers\Education\UI\API\Controllers\UpdateEduDataApiController;
use Illuminate\Support\Facades\Route;
Route::get('/getAcademicYear', AcademicYearController::class)->name('academic.year');
Route::middleware(['auth', 'superadmin'])->group(function () {
Route::get('/get-edu-program-data', [UpdateEduDataApiController::class, 'index']);
Route::get('/get-admission-plans-data', [UpdateAdmissionPlansDataApiController::class, 'index']);
});
@@ -0,0 +1,176 @@
<?php
namespace App\Containers\Education\UI\WEB\Controllers;
use App\Containers\Education\Models\AdmissionCampaign;
use App\Containers\Education\Models\AdmissionPlan;
use App\Containers\Education\Models\DirectionStudy;
use App\Containers\Education\Models\EducationalProgram;
use App\Containers\Education\UI\WEB\Transformers\DirectionStudyResource;
use App\Containers\Education\UI\WEB\Transformers\EducationalProgramResource;
use App\Ship\Contracts\SeoServiceInterface;
use App\Ship\Controllers\Controller;
use App\Ship\Enums\CacheKeys;
use App\Ship\Enums\Education\BudgetEducation;
use App\Ship\Enums\Education\FormEducation;
use App\Ship\Enums\Education\LevelEducational;
use App\Ship\Requests\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
use Inertia\Inertia;
class ClientProgramController extends Controller
{
public function __construct(readonly SeoServiceInterface $seoPageProvider){}
public function index(Request $request): \Inertia\Response
{
$cacheKey = CacheKeys::EDUCATION_PROGRAMS_PREFIX->value . md5(serialize($request->all()));
$cacheKeyLevels = 'education_levels_list';
$cacheKeyForms = 'education_forms_list';
$cacheKeyBudgets = 'education_budgets_list';
$cacheKeySeo = 'education_programs_seo';
$activeCampaign = Cache::remember(CacheKeys::ADMISSION_CAMPAIGNS_PREFIX->value, now()->addDay(), function () {
return AdmissionCampaign::where('status', 1)->first();
});
$levelsEducational = Cache::remember($cacheKeyLevels, now()->addDay(), function () {
return EducationalProgram::distinct()->pluck('lvl_edu')
->mapWithKeys(fn($level) => [$level->name => $level->getLabel()]);
});
$formsEdu = Cache::remember($cacheKeyForms, now()->addDay(), function () {
return AdmissionPlan::distinct()
->pluck('contests')
->flatten(1)
->filter(fn ($item) => isset($item['form_education']))
->pluck('form_education')
->unique()
->map(fn ($item) => FormEducation::tryFrom((int)$item))
->filter()
->mapWithKeys(fn ($form) => [$form->name => $form->getLabel()]);
});
$budgetEdu = Cache::remember($cacheKeyBudgets, now()->addDay(), function () {
return AdmissionPlan::distinct()
->pluck('contests')
->flatten(1)
->filter(fn ($item) => isset($item['places']['form_budget']))
->pluck('places.form_budget')
->unique()
->map(fn ($item) => BudgetEducation::tryFrom($item))
->filter()
->mapWithKeys(fn ($form) => [$form->name => $form->getLabel()]);
});
$seo = Cache::remember($cacheKeySeo, now()->addDay(), function () {
return $this->seoPageProvider->getSeoForCurrentPage();
});
$naprs = Cache::remember($cacheKey, now()->addHours(), function () use ($request, $activeCampaign) {
return DirectionStudyResource::collection(
DirectionStudy::query()
->withAdmissionCampaignByYear($activeCampaign->academic_year)
->withActivePrograms()
// ->with('programs.admission_plans')
->when($request->input('level'), fn($q, $level) =>
$q->where('lvl_edu', LevelEducational::fromName($level)->value))
->when($request->input('form'), fn($q, $form) =>
$this->applyFormFilter($q, $form))
->when($request->input('budget'), fn($q, $budget) =>
$this->applyBudgetFilter($q, $budget))
->when($request->input('direction'), fn($q, $slugs) =>
is_array($slugs) ? $q->whereIn('slug', $slugs) : $q)
->get()
);
});
$data = [
'naprs' => $naprs,
'campaignName' => $this->getAdmissionCampaignName(),
'levelsEducational' => $levelsEducational,
'filters' => [
'level_filter' => ['type' => 'level', 'value' => $request->input('level'), 'param' => 'level'],
'budget_filter' => ['type' => 'budget', 'value' => $request->input('budget'), 'param' => 'budget'],
'formEdu_filter' => ['type' => 'form', 'value' => $request->input('form'), 'param' => 'form'],
'direction_filter' => ['type' => 'direction', 'value' => $request->input('direction'), 'param' => 'direction'],
],
'formsEdu' => $formsEdu,
'budgetEdu' => $budgetEdu,
'direction_studies' => DirectionStudy::query()
->withAdmissionCampaignByYear($activeCampaign->academic_year)
->withActivePrograms()
->get(),
'seo' => $seo
];
return Inertia::render('Client/Programs/Index', $data);
}
public function show(string $slug): \Inertia\Response
{
$cacheKeyProgram = CacheKeys::EDUCATION_PROGRAM_PREFIX->value . md5($slug);
$cacheKeySeo = CacheKeys::EDUCATION_PROGRAM_PREFIX->value . 'seo_' . md5($slug);
$cacheKeyForms = 'education_forms_list';
$programModel = Cache::remember($cacheKeyProgram, now()->addHours(1), function () use ($slug) {
return EducationalProgram::query()
->where('slug', $slug)
->with(['admission_plans', 'directionStudy', 'seo'])
->firstOrFail();
});
$formsEdu = Cache::remember($cacheKeyForms, now()->addDay(), function () {
return collect(BudgetEducation::cases())
->mapWithKeys(fn($form) => [$form->value => $form->getLabel()]);
});
$seo = Cache::remember($cacheKeySeo, now()->addHours(1), function () use ($programModel) {
return $this->seoPageProvider->getSeoForModel($programModel);
});
$program = new EducationalProgramResource($programModel);
return Inertia::render('Client/Programs/Show', compact('program', 'formsEdu', 'seo'));
}
private function getAdmissionCampaignName(): string
{
$cacheKey = CacheKeys::EDUCATION_PROGRAM_PREFIX->value . 'active_campaign_name';
return Cache::remember($cacheKey, now()->addHours(1), function () {
$campaign = AdmissionCampaign::query()->where('status', 1)->first();
return $campaign->name;
});
}
private function applyFormFilter($query, $form)
{
$formValue = Str::of(FormEducation::fromName($form)->value)->toString();
$query->whereHas('programs.admission_plans', function ($query) use ($formValue) {
$query->whereJsonContains('contests', ['form_education' => $formValue]);
})
->with(['programs' => function ($query) use ($formValue) {
$query->whereHas('admission_plans', function ($q) use ($formValue) {
$q->whereJsonContains('contests', ['form_education' => $formValue]);
});
}]);
}
private function applyBudgetFilter($query, $budget): void
{
$budgetValue = Str::of(BudgetEducation::fromName($budget)->value)->toString();
$query->whereHas('programs.admission_plans', function ($query) use ($budgetValue) {
$query->where('contests', 'like', '%"form_budget":"'.$budgetValue.'"%');
})
->with(['programs' => function ($query) use ($budgetValue) {
$query->whereHas('admission_plans', function ($query) use ($budgetValue) {
$query->where('contests', 'like', '%"form_budget":"'.$budgetValue.'"%');
});
}]);
}
}
@@ -0,0 +1,12 @@
<?php
use App\Containers\Education\UI\WEB\Controllers\ClientProgramController;
use Illuminate\Support\Facades\Route;
Route::middleware('access-check')->group(function () {
Route::get('/programs/', [ClientProgramController::class, 'index'])->name('client.program.index');
Route::get('/program/{slug}', [ClientProgramController::class, 'show'])->name('client.program.show');
});
@@ -0,0 +1,18 @@
<?php
namespace App\Containers\Education\UI\WEB\Transformers;
use App\Ship\Resources\JsonResource;
class DirectionStudyResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'code' => $this->code,
'programs' => EducationalProgramBasicResource::collection($this->programs),
];
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Containers\Education\UI\WEB\Transformers;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class EducationalProgramBasicResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'slug' => $this->slug
];
}
}
@@ -0,0 +1,40 @@
<?php
namespace App\Containers\Education\UI\WEB\Transformers;
use App\Ship\Enums\Education\FormEducation;
use App\Ship\Resources\JsonResource;
class EducationalProgramResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'about_program' => $this->about_program,
'program_features' => $this->program_features,
'inner_code' => $this->inner_code,
'lvl_edu' => $this->lvl_edu->getLabel(),
'status' => $this->status,
// 'lang_stud' => $this->lang_stud,
'learning_forms' => $this->transformLearningForms($this->learning_forms),
'directionStudy' => $this->directionStudy,
'admissionPlans' => $this->admission_plans,
];
}
private function transformLearningForms(array $learningForms): array
{
return array_map(function ($form) {
$formId = $form['form_id'];
$formEnum = FormEducation::from($formId); // Получаем enum по form_id
return [
'form_edu' => $formEnum->getLabel(), // Значение из enum
'period_data' => $form['period_data'],
];
}, $learningForms);
}
}