diff --git a/app/Containers/Education/Actions/GetEducationalProgramAction.php b/app/Containers/Education/Actions/GetEducationalProgramAction.php new file mode 100644 index 0000000..82d11d2 --- /dev/null +++ b/app/Containers/Education/Actions/GetEducationalProgramAction.php @@ -0,0 +1,30 @@ +getEducationalProgramBySlugTask->run($slug); + $formsEdu = $this->getEducationalFormsTask->run(); + $seo = $this->getSeoForModelTask->run($this->seoPageProvider, $programModel); + + $program = new EducationalProgramResource($programModel); + + return compact('program', 'formsEdu', 'seo'); + } +} diff --git a/app/Containers/Education/Actions/ListEducationalProgramsAction.php b/app/Containers/Education/Actions/ListEducationalProgramsAction.php new file mode 100644 index 0000000..df6083e --- /dev/null +++ b/app/Containers/Education/Actions/ListEducationalProgramsAction.php @@ -0,0 +1,76 @@ +value . md5(serialize($filters)); + + $activeCampaign = $this->getActiveAdmissionCampaignTask->run(); + $levelsEducational = $this->getEducationalLevelsTask->run(); + $formsEdu = $this->getEducationalFormsTask->run(); + $budgetEdu = $this->getEducationalBudgetsTask->run(); + $seo = $this->getSeoForCurrentPageTask->run($this->seoPageProvider); + $filtersData = $this->buildFiltersTask->run($filters); + + $naprs = Cache::remember($cacheKey, now()->addHours(), function () use ($request, $activeCampaign, $filters) { + return DirectionStudyResource::collection( + $this->listDirectionStudiesTask->run($activeCampaign, $filters) + ); + }); + + $data = [ + 'naprs' => $naprs, + 'campaignName' => $this->getAdmissionCampaignNameTask->run(), + 'levelsEducational' => $levelsEducational, + 'filters' => $filtersData, + 'formsEdu' => $formsEdu, + 'budgetEdu' => $budgetEdu, + 'direction_studies' => DirectionStudy::query() + ->withAdmissionCampaignByYear($activeCampaign->academic_year) + ->withActivePrograms() + ->get(), + 'seo' => $seo + ]; + + return $data; + } +} diff --git a/app/Containers/Education/Tasks/BuildFiltersTask.php b/app/Containers/Education/Tasks/BuildFiltersTask.php new file mode 100644 index 0000000..cd3087e --- /dev/null +++ b/app/Containers/Education/Tasks/BuildFiltersTask.php @@ -0,0 +1,53 @@ +filterBuilder->reset(); + + // Уровень образования + $this->filterBuilder->add( + key: 'level_filter', + type: 'level', + value: $filters['level'] ?? null, + param: 'level' + ); + + // Форма обучения + $this->filterBuilder->add( + key: 'formEdu_filter', + type: 'form', + value: $filters['form'] ?? null, + param: 'form' + ); + + // Бюджет + $this->filterBuilder->add( + key: 'budget_filter', + type: 'budget', + value: $filters['budget'] ?? null, + param: 'budget' + ); + + // Направление + $this->filterBuilder->add( + key: 'direction_filter', + type: 'direction', + value: $filters['direction'] ?? null, + param: 'direction' + ); + + return $this->filterBuilder->get(); + } +} diff --git a/app/Containers/Education/Tasks/GetActiveAdmissionCampaignTask.php b/app/Containers/Education/Tasks/GetActiveAdmissionCampaignTask.php new file mode 100644 index 0000000..94580d0 --- /dev/null +++ b/app/Containers/Education/Tasks/GetActiveAdmissionCampaignTask.php @@ -0,0 +1,17 @@ +value, now()->addDay(), function () { + return AdmissionCampaign::where('status', 1)->first(); + }); + } +} diff --git a/app/Containers/Education/Tasks/GetAdmissionCampaignNameTask.php b/app/Containers/Education/Tasks/GetAdmissionCampaignNameTask.php new file mode 100644 index 0000000..a024308 --- /dev/null +++ b/app/Containers/Education/Tasks/GetAdmissionCampaignNameTask.php @@ -0,0 +1,20 @@ +value . 'active_campaign_name'; + + return Cache::remember($cacheKey, now()->addHours(1), function () { + $campaign = AdmissionCampaign::query()->where('status', 1)->first(); + return $campaign->name; + }); + } +} diff --git a/app/Containers/Education/Tasks/GetEducationalBudgetsTask.php b/app/Containers/Education/Tasks/GetEducationalBudgetsTask.php new file mode 100644 index 0000000..b0ffbe3 --- /dev/null +++ b/app/Containers/Education/Tasks/GetEducationalBudgetsTask.php @@ -0,0 +1,26 @@ +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()]); + }); + } +} diff --git a/app/Containers/Education/Tasks/GetEducationalFormsTask.php b/app/Containers/Education/Tasks/GetEducationalFormsTask.php new file mode 100644 index 0000000..330ba81 --- /dev/null +++ b/app/Containers/Education/Tasks/GetEducationalFormsTask.php @@ -0,0 +1,26 @@ +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()]); + }); + } +} diff --git a/app/Containers/Education/Tasks/GetEducationalLevelsTask.php b/app/Containers/Education/Tasks/GetEducationalLevelsTask.php new file mode 100644 index 0000000..a761464 --- /dev/null +++ b/app/Containers/Education/Tasks/GetEducationalLevelsTask.php @@ -0,0 +1,18 @@ +addDay(), function () { + return EducationalProgram::distinct()->pluck('lvl_edu') + ->mapWithKeys(fn($level) => [$level->name => $level->getLabel()]); + }); + } +} diff --git a/app/Containers/Education/Tasks/GetEducationalProgramBySlugTask.php b/app/Containers/Education/Tasks/GetEducationalProgramBySlugTask.php new file mode 100644 index 0000000..945222a --- /dev/null +++ b/app/Containers/Education/Tasks/GetEducationalProgramBySlugTask.php @@ -0,0 +1,22 @@ +value . md5($slug); + + return Cache::remember($cacheKeyProgram, now()->addHours(1), function () use ($slug) { + return EducationalProgram::query() + ->where('slug', $slug) + ->with(['admission_plans', 'directionStudy', 'seo']) + ->firstOrFail(); + }); + } +} diff --git a/app/Containers/Education/Tasks/GetSeoForCurrentPageTask.php b/app/Containers/Education/Tasks/GetSeoForCurrentPageTask.php new file mode 100644 index 0000000..12b2f29 --- /dev/null +++ b/app/Containers/Education/Tasks/GetSeoForCurrentPageTask.php @@ -0,0 +1,17 @@ +addDay(), function () use ($seoPageProvider) { + return $seoPageProvider->getSeoForCurrentPage(); + }); + } +} diff --git a/app/Containers/Education/Tasks/GetSeoForModelTask.php b/app/Containers/Education/Tasks/GetSeoForModelTask.php new file mode 100644 index 0000000..10770a3 --- /dev/null +++ b/app/Containers/Education/Tasks/GetSeoForModelTask.php @@ -0,0 +1,18 @@ +slug); + return Cache::remember($cacheKeySeo, now()->addHours(1), function () use ($seoPageProvider, $model) { + return $seoPageProvider->getSeoForModel($model); + }); + } +} diff --git a/app/Containers/Education/Tasks/ListDirectionStudiesTask.php b/app/Containers/Education/Tasks/ListDirectionStudiesTask.php new file mode 100644 index 0000000..d565b9f --- /dev/null +++ b/app/Containers/Education/Tasks/ListDirectionStudiesTask.php @@ -0,0 +1,69 @@ +withAdmissionCampaignByYear($activeCampaign->academic_year) + ->withActivePrograms(); + + if (isset($filters['level'])) { + $query->where('lvl_edu', LevelEducational::fromName($filters['level'])->value); + } + + if (isset($filters['form'])) { + $this->applyFormFilter($query, $filters['form']); + } + + if (isset($filters['budget'])) { + $this->applyBudgetFilter($query, $filters['budget']); + } + + if (isset($filters['direction'])) { + $slugs = $filters['direction']; + if (is_array($slugs)) { + $query->whereIn('slug', $slugs); + } + } + + return $query->get(); + } + + 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.'"%'); + }); + }]); + } +} diff --git a/app/Containers/Education/UI/WEB/Controllers/ClientProgramController.php b/app/Containers/Education/UI/WEB/Controllers/ClientProgramController.php index 9290f59..2b82782 100644 --- a/app/Containers/Education/UI/WEB/Controllers/ClientProgramController.php +++ b/app/Containers/Education/UI/WEB/Controllers/ClientProgramController.php @@ -2,175 +2,32 @@ 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\Containers\Education\Actions\ListEducationalProgramsAction; +use App\Containers\Education\Actions\GetEducationalProgramAction; 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 Illuminate\Http\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 __construct( + private readonly ListEducationalProgramsAction $listEducationalProgramsAction, + private readonly GetEducationalProgramAction $getEducationalProgramAction, + ) {} 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'; + $filters = $request->only(['search', 'category', 'tag', 'sort', 'page', 'date', 'level', 'form', 'budget', 'direction']); - $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 - ]; + $data = $this->listEducationalProgramsAction->run($filters); 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'; + $data = $this->getEducationalProgramAction->run($slug); - $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')); + return Inertia::render('Client/Programs/Show', $data); } - - 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.'"%'); - }); - }]); - } -} \ No newline at end of file +}