This commit is contained in:
F4ilji
2026-04-07 17:54:26 +05:00
parent 04adba6682
commit 936b1fb5b0
468 changed files with 43498 additions and 4176 deletions
@@ -0,0 +1,110 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\AcademicJournals\CreateAcademicJournalAction;
use App\Containers\Dashboard\Actions\AcademicJournals\DeleteAcademicJournalAction;
use App\Containers\Dashboard\Actions\AcademicJournals\ListAcademicJournalsAction;
use App\Containers\Dashboard\Actions\AcademicJournals\UpdateAcademicJournalAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreAcademicJournalRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateAcademicJournalRequest;
use App\Containers\Science\Models\AcademicJournal;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
class AcademicJournalController extends Controller
{
public function __construct(
private readonly ListAcademicJournalsAction $listAcademicJournalsAction,
private readonly CreateAcademicJournalAction $createAcademicJournalAction,
private readonly UpdateAcademicJournalAction $updateAcademicJournalAction,
private readonly DeleteAcademicJournalAction $deleteAcademicJournalAction,
) {}
/**
* Display a listing of academic journals
*/
public function index(Request $request): Response
{
$filters = $request->only(['search']);
$data = $this->listAcademicJournalsAction->run($filters);
return Inertia::render('Dashboard/AcademicJournals/Index', $data);
}
/**
* Show the form for creating a new journal
*/
public function create(): Response
{
return Inertia::render('Dashboard/AcademicJournals/Create');
}
/**
* Store a newly created journal
*/
public function store(StoreAcademicJournalRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createAcademicJournalAction->run($validated);
return redirect()->route('dashboard.academic-journals.index')
->with('success', 'Научный журнал успешно создан!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании журнала: ' . $e->getMessage());
}
}
/**
* Show the form for editing the specified journal
*/
public function edit(AcademicJournal $academicJournal): Response
{
return Inertia::render('Dashboard/AcademicJournals/Edit', [
'journal' => $academicJournal,
]);
}
/**
* Update the specified journal
*/
public function update(UpdateAcademicJournalRequest $request, AcademicJournal $academicJournal): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateAcademicJournalAction->run($academicJournal, $validated);
return redirect()->route('dashboard.academic-journals.index')
->with('success', 'Научный журнал успешно обновлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении журнала: ' . $e->getMessage());
}
}
/**
* Remove the specified journal
*/
public function destroy(AcademicJournal $academicJournal): RedirectResponse
{
try {
$this->deleteAcademicJournalAction->run($academicJournal);
return redirect()->route('dashboard.academic-journals.index')
->with('success', 'Научный журнал успешно удален!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении журнала: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,165 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\AdditionalEducation\Models\AdditionalEducation;
use App\Containers\Dashboard\Actions\AdditionalEducations\CreateAdditionalEducationAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\DeleteAdditionalEducationAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\ListAdditionalEducationsAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\UpdateAdditionalEducationAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreAdditionalEducationRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateAdditionalEducationRequest;
use App\Http\Controllers\Controller;
use App\Services\Filament\Domain\Seo\SeoGeneratorService;
use App\Ship\Contracts\SeoDescriptionInterface;
use App\Ship\Contracts\SeoTitleInterface;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class AdditionalEducationController extends Controller
{
public function __construct(
private readonly ListAdditionalEducationsAction $listAdditionalEducationsAction,
private readonly CreateAdditionalEducationAction $createAdditionalEducationAction,
private readonly UpdateAdditionalEducationAction $updateAdditionalEducationAction,
private readonly DeleteAdditionalEducationAction $deleteAdditionalEducationAction,
private readonly SeoGeneratorService $seoGeneratorService,
) {}
/**
* Показывает список программ дополнительного образования
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'category_id', 'form_education', 'is_active']);
$data = $this->listAdditionalEducationsAction->run($filters);
return Inertia::render('Dashboard/AdditionalEducations/Index', $data);
}
/**
* Показывает форму создания программы
*/
public function create(): \Inertia\Response
{
$data = $this->listAdditionalEducationsAction->run([]);
return Inertia::render('Dashboard/AdditionalEducations/Create', [
'categories' => $data['categories'],
'educationForms' => $data['educationForms'],
]);
}
/**
* Создает новую программу дополнительного образования
*/
public function store(StoreAdditionalEducationRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$education = $this->createAdditionalEducationAction->run($validated);
$this->createSeo($education);
return redirect()->route('dashboard.additional-educations.index')
->with('success', 'Программа дополнительного образования успешно создана!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании программы: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования программы
*/
public function edit(AdditionalEducation $additionalEducation): \Inertia\Response
{
$additionalEducation->load(['category', 'seo']);
$data = $this->listAdditionalEducationsAction->run([]);
return Inertia::render('Dashboard/AdditionalEducations/Edit', [
'education' => $additionalEducation,
'categories' => $data['categories'],
'educationForms' => $data['educationForms'],
]);
}
/**
* Обновляет существующую программу дополнительного образования
*/
public function update(UpdateAdditionalEducationRequest $request, AdditionalEducation $additionalEducation): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateAdditionalEducationAction->run($additionalEducation, $validated);
$this->updateSeo($additionalEducation);
return redirect()->route('dashboard.additional-educations.index')
->with('success', 'Программа дополнительного образования успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении программы: ' . $e->getMessage());
}
}
/**
* Удаляет программу дополнительного образования
*/
public function destroy(AdditionalEducation $additionalEducation): RedirectResponse
{
try {
$this->deleteAdditionalEducationAction->run($additionalEducation);
return redirect()->route('dashboard.additional-educations.index')
->with('success', 'Программа дополнительного образования успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении программы: ' . $e->getMessage());
}
}
/**
* Генерирует и создает SEO данные
*/
private function createSeo(AdditionalEducation $record): void
{
$seoData = $this->generateSeoData($record);
$record->seo()->create($seoData);
}
/**
* Обновляет SEO данные
*/
private function updateSeo(AdditionalEducation $record): void
{
if ($record->seo()->exists()) {
$record->seo()->update($this->generateSeoData($record));
} else {
$this->createSeo($record);
}
}
/**
* Генерирует SEO данные из записи
*/
private function generateSeoData(AdditionalEducation $record): array
{
return $this->seoGeneratorService->generate([
'title' => $record instanceof SeoTitleInterface
? $record->getSeoTitle()
: $record->title,
'content' => $record instanceof SeoDescriptionInterface
? $record->getSeoDescription()
: ($record->content ?? []),
'preview' => $record->preview ?? null,
]);
}
}
@@ -0,0 +1,90 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers\AdditionalEducations;
use App\Containers\AdditionalEducation\Models\AdditionalEducationCategory;
use App\Containers\Dashboard\Actions\AdditionalEducations\Categories\CreateCategoryAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\Categories\DeleteCategoryAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\Categories\ListCategoriesAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\Categories\UpdateCategoryAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreCategoryRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateCategoryRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
class CategoryController extends Controller
{
public function __construct(
private readonly ListCategoriesAction $listCategoriesAction,
private readonly CreateCategoryAction $createCategoryAction,
private readonly UpdateCategoryAction $updateCategoryAction,
private readonly DeleteCategoryAction $deleteCategoryAction,
) {}
public function index(\Illuminate\Http\Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'direction_id', 'is_active']);
$data = $this->listCategoriesAction->run($filters);
return Inertia::render('Dashboard/AdditionalEducations/Categories/Index', $data);
}
public function create(): \Inertia\Response
{
$data = $this->listCategoriesAction->run([]);
return Inertia::render('Dashboard/AdditionalEducations/Categories/Create', [
'directions' => $data['directions'],
]);
}
public function store(StoreCategoryRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createCategoryAction->run($validated);
return redirect()->route('dashboard.additional-educations.categories.index')
->with('success', 'Категория дополнительного образования успешно создана!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при создании категории: ' . $e->getMessage());
}
}
public function edit(AdditionalEducationCategory $category): \Inertia\Response
{
$category->load(['direction']);
$data = $this->listCategoriesAction->run([]);
return Inertia::render('Dashboard/AdditionalEducations/Categories/Edit', [
'category' => $category,
'directions' => $data['directions'],
]);
}
public function update(UpdateCategoryRequest $request, AdditionalEducationCategory $category): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateCategoryAction->run($category, $validated);
return redirect()->route('dashboard.additional-educations.categories.index')
->with('success', 'Категория успешно обновлена!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при обновлении категории: ' . $e->getMessage());
}
}
public function destroy(AdditionalEducationCategory $category): RedirectResponse
{
try {
$this->deleteCategoryAction->run($category);
return redirect()->route('dashboard.additional-educations.categories.index')
->with('success', 'Категория успешно удалена!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении категории: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,83 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers\AdditionalEducations;
use App\Containers\AdditionalEducation\Models\DirectionAdditionalEducation;
use App\Containers\Dashboard\Actions\AdditionalEducations\Directions\CreateDirectionAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\Directions\DeleteDirectionAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\Directions\ListDirectionsAction;
use App\Containers\Dashboard\Actions\AdditionalEducations\Directions\UpdateDirectionAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreDirectionRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateDirectionRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DirectionController extends Controller
{
public function __construct(
private readonly ListDirectionsAction $listDirectionsAction,
private readonly CreateDirectionAction $createDirectionAction,
private readonly UpdateDirectionAction $updateDirectionAction,
private readonly DeleteDirectionAction $deleteDirectionAction,
) {}
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'is_active']);
$data = $this->listDirectionsAction->run($filters);
return Inertia::render('Dashboard/AdditionalEducations/Directions/Index', $data);
}
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/AdditionalEducations/Directions/Create');
}
public function store(StoreDirectionRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createDirectionAction->run($validated);
return redirect()->route('dashboard.additional-educations.directions.index')
->with('success', 'Направление дополнительного образования успешно создано!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при создании направления: ' . $e->getMessage());
}
}
public function edit(DirectionAdditionalEducation $direction): \Inertia\Response
{
return Inertia::render('Dashboard/AdditionalEducations/Directions/Edit', [
'direction' => $direction,
]);
}
public function update(UpdateDirectionRequest $request, DirectionAdditionalEducation $direction): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateDirectionAction->run($direction, $validated);
return redirect()->route('dashboard.additional-educations.directions.index')
->with('success', 'Направление успешно обновлено!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при обновлении направления: ' . $e->getMessage());
}
}
public function destroy(DirectionAdditionalEducation $direction): RedirectResponse
{
try {
$this->deleteDirectionAction->run($direction);
return redirect()->route('dashboard.additional-educations.directions.index')
->with('success', 'Направление успешно удалено!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении направления: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,110 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Education\Models\AdmissionCampaign;
use App\Containers\Dashboard\Actions\AdmissionCampaigns\CreateAdmissionCampaignAction;
use App\Containers\Dashboard\Actions\AdmissionCampaigns\DeleteAdmissionCampaignAction;
use App\Containers\Dashboard\Actions\AdmissionCampaigns\ListAdmissionCampaignsAction;
use App\Containers\Dashboard\Actions\AdmissionCampaigns\UpdateAdmissionCampaignAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreAdmissionCampaignRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateAdmissionCampaignRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class AdmissionCampaignController extends Controller
{
public function __construct(
private readonly ListAdmissionCampaignsAction $listAdmissionCampaignsAction,
private readonly CreateAdmissionCampaignAction $createAdmissionCampaignAction,
private readonly UpdateAdmissionCampaignAction $updateAdmissionCampaignAction,
private readonly DeleteAdmissionCampaignAction $deleteAdmissionCampaignAction,
) {}
/**
* Показывает список приемных кампаний
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'status', 'academic_year']);
$data = $this->listAdmissionCampaignsAction->run($filters);
return Inertia::render('Dashboard/AdmissionCampaigns/Index', $data);
}
/**
* Показывает форму создания кампании
*/
public function create(): \Inertia\Response
{
$data = $this->listAdmissionCampaignsAction->run([]);
return Inertia::render('Dashboard/AdmissionCampaigns/Create', [
'statuses' => $data['statuses'],
'academicYears' => $data['academicYears'],
]);
}
/**
* Создает новую приемную кампанию
*/
public function store(StoreAdmissionCampaignRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createAdmissionCampaignAction->run($validated);
return redirect()->route('dashboard.admission-campaigns.index')
->with('success', 'Приемная кампания успешно создана!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при создании кампании: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования кампании
*/
public function edit(AdmissionCampaign $admissionCampaign): \Inertia\Response
{
$data = $this->listAdmissionCampaignsAction->run([]);
return Inertia::render('Dashboard/AdmissionCampaigns/Edit', [
'campaign' => $admissionCampaign,
'statuses' => $data['statuses'],
'academicYears' => $data['academicYears'],
]);
}
/**
* Обновляет существующую приемную кампанию
*/
public function update(UpdateAdmissionCampaignRequest $request, AdmissionCampaign $admissionCampaign): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateAdmissionCampaignAction->run($admissionCampaign, $validated);
return redirect()->route('dashboard.admission-campaigns.index')
->with('success', 'Приемная кампания успешно обновлена!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при обновлении кампании: ' . $e->getMessage());
}
}
/**
* Удаляет приемную кампанию
*/
public function destroy(AdmissionCampaign $admissionCampaign): RedirectResponse
{
try {
$this->deleteAdmissionCampaignAction->run($admissionCampaign);
return redirect()->route('dashboard.admission-campaigns.index')
->with('success', 'Приемная кампания успешно удалена!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении кампании: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,92 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Education\Models\AdmissionPlan;
use App\Containers\Dashboard\Actions\AdmissionPlans\CreateAdmissionPlanAction;
use App\Containers\Dashboard\Actions\AdmissionPlans\DeleteAdmissionPlanAction;
use App\Containers\Dashboard\Actions\AdmissionPlans\ListAdmissionPlansAction;
use App\Containers\Dashboard\Actions\AdmissionPlans\UpdateAdmissionPlanAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreAdmissionPlanRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateAdmissionPlanRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
class AdmissionPlanController extends Controller
{
public function __construct(
private readonly ListAdmissionPlansAction $listAdmissionPlansAction,
private readonly CreateAdmissionPlanAction $createAdmissionPlanAction,
private readonly UpdateAdmissionPlanAction $updateAdmissionPlanAction,
private readonly DeleteAdmissionPlanAction $deleteAdmissionPlanAction,
) {}
public function index(\Illuminate\Http\Request $request): \Inertia\Response
{
$filters = $request->only(['admission_campaigns_id', 'educational_programs_id']);
$data = $this->listAdmissionPlansAction->run($filters);
return Inertia::render('Dashboard/AdmissionPlans/Index', $data);
}
public function create(): \Inertia\Response
{
$data = $this->listAdmissionPlansAction->run([]);
return Inertia::render('Dashboard/AdmissionPlans/Create', [
'admissionCampaigns' => $data['admissionCampaigns'],
'educationalPrograms' => $data['educationalPrograms'],
]);
}
public function store(StoreAdmissionPlanRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createAdmissionPlanAction->run($validated);
return redirect()->route('dashboard.admission-plans.index')
->with('success', 'План приема успешно создан!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при создании плана: ' . $e->getMessage());
}
}
public function edit(AdmissionPlan $admissionPlan): \Inertia\Response
{
$admissionPlan->load(['educationalProgram', 'admissionCampaign']);
$data = $this->listAdmissionPlansAction->run([]);
return Inertia::render('Dashboard/AdmissionPlans/Edit', [
'plan' => $admissionPlan,
'admissionCampaigns' => $data['admissionCampaigns'],
'educationalPrograms' => $data['educationalPrograms'],
]);
}
public function update(UpdateAdmissionPlanRequest $request, AdmissionPlan $admissionPlan): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateAdmissionPlanAction->run($admissionPlan, $validated);
return redirect()->route('dashboard.admission-plans.index')
->with('success', 'План приема успешно обновлен!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при обновлении плана: ' . $e->getMessage());
}
}
public function destroy(AdmissionPlan $admissionPlan): RedirectResponse
{
try {
$this->deleteAdmissionPlanAction->run($admissionPlan);
return redirect()->route('dashboard.admission-plans.index')
->with('success', 'План приема успешно удален!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении плана: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,91 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Article\Models\Category;
use App\Containers\Dashboard\Actions\Categories\CreateCategoryAction;
use App\Containers\Dashboard\Actions\Categories\DeleteCategoryAction;
use App\Containers\Dashboard\Actions\Categories\ListCategoriesAction;
use App\Containers\Dashboard\Actions\Categories\UpdateCategoryAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreNewsCategoryRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateNewsCategoryRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class CategoryController extends Controller
{
public function __construct(
private readonly ListCategoriesAction $listCategoriesAction,
private readonly CreateCategoryAction $createCategoryAction,
private readonly UpdateCategoryAction $updateCategoryAction,
private readonly DeleteCategoryAction $deleteCategoryAction,
) {}
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'is_active']);
$data = $this->listCategoriesAction->run($filters);
return Inertia::render('Dashboard/Categories/Index', $data);
}
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/Categories/Create');
}
public function store(StoreNewsCategoryRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createCategoryAction->run($validated);
return redirect()->route('dashboard.categories.index')
->with('success', 'Категория успешно создана!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании категории: ' . $e->getMessage());
}
}
public function edit(Category $category): \Inertia\Response
{
return Inertia::render('Dashboard/Categories/Edit', [
'category' => $category,
]);
}
public function update(UpdateNewsCategoryRequest $request, Category $category): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateCategoryAction->run($category, $validated);
return redirect()->route('dashboard.categories.index')
->with('success', 'Категория успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении категории: ' . $e->getMessage());
}
}
public function destroy(Category $category): RedirectResponse
{
try {
$this->deleteCategoryAction->run($category);
return redirect()->route('dashboard.categories.index')
->with('success', 'Категория успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении категории: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,109 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\ContactWidgets\CreateContactWidgetAction;
use App\Containers\Dashboard\Actions\ContactWidgets\DeleteContactWidgetAction;
use App\Containers\Dashboard\Actions\ContactWidgets\ListContactWidgetsAction;
use App\Containers\Dashboard\Actions\ContactWidgets\UpdateContactWidgetAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreContactWidgetRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateContactWidgetRequest;
use App\Containers\Widget\Models\ContactWidget;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class ContactWidgetController extends Controller
{
public function __construct(
private readonly ListContactWidgetsAction $listContactWidgetsAction,
private readonly CreateContactWidgetAction $createContactWidgetAction,
private readonly UpdateContactWidgetAction $updateContactWidgetAction,
private readonly DeleteContactWidgetAction $deleteContactWidgetAction,
) {}
/**
* Показывает список контактных виджетов
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'is_active']);
$data = $this->listContactWidgetsAction->run($filters);
return Inertia::render('Dashboard/ContactWidgets/Index', $data);
}
/**
* Показывает форму создания виджета
*/
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/ContactWidgets/Create');
}
/**
* Создает новый контактный виджет
*/
public function store(StoreContactWidgetRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createContactWidgetAction->run($validated);
return redirect()->route('dashboard.contact-widgets.index')
->with('success', 'Контактный виджет успешно создан!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании виджета: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования виджета
*/
public function edit(ContactWidget $contactWidget): \Inertia\Response
{
return Inertia::render('Dashboard/ContactWidgets/Edit', [
'widget' => $contactWidget,
]);
}
/**
* Обновляет контактный виджет
*/
public function update(UpdateContactWidgetRequest $request, ContactWidget $contactWidget): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateContactWidgetAction->run($contactWidget, $validated);
return redirect()->route('dashboard.contact-widgets.index')
->with('success', 'Контактный виджет успешно обновлён!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении виджета: ' . $e->getMessage());
}
}
/**
* Удаляет контактный виджет
*/
public function destroy(ContactWidget $contactWidget): RedirectResponse
{
try {
$this->deleteContactWidgetAction->run($contactWidget);
return redirect()->route('dashboard.contact-widgets.index')
->with('success', 'Контактный виджет успешно удалён!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении виджета: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,14 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Http\Controllers\Controller;
use Inertia\Inertia;
class CreateSliderController extends Controller
{
public function __invoke(): \Inertia\Response
{
return Inertia::render('Dashboard/Sliders/Create');
}
}
@@ -0,0 +1,149 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\CustomForms\CreateCustomFormAction;
use App\Containers\Dashboard\Actions\CustomForms\DeleteCustomFormAction;
use App\Containers\Dashboard\Actions\CustomForms\DeleteFormResponseAction;
use App\Containers\Dashboard\Actions\CustomForms\ListCustomFormsAction;
use App\Containers\Dashboard\Actions\CustomForms\ListFormResponsesAction;
use App\Containers\Dashboard\Actions\CustomForms\UpdateCustomFormAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreCustomFormRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateCustomFormRequest;
use App\Containers\Widget\Models\CustomForm;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class CustomFormController extends Controller
{
public function __construct(
private readonly ListCustomFormsAction $listCustomFormsAction,
private readonly CreateCustomFormAction $createCustomFormAction,
private readonly UpdateCustomFormAction $updateCustomFormAction,
private readonly DeleteCustomFormAction $deleteCustomFormAction,
private readonly ListFormResponsesAction $listFormResponsesAction,
private readonly DeleteFormResponseAction $deleteFormResponseAction,
) {}
/**
* Показывает список пользовательских форм
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'status']);
$data = $this->listCustomFormsAction->run($filters);
return Inertia::render('Dashboard/CustomForms/Index', $data);
}
/**
* Показывает форму создания формы
*/
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/CustomForms/Create');
}
/**
* Создает новую пользовательскую форму
*/
public function store(StoreCustomFormRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createCustomFormAction->run($validated);
return redirect()->route('dashboard.custom-forms.index')
->with('success', 'Пользовательская форма успешно создана!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании формы: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования формы
*/
public function edit(CustomForm $customForm): \Inertia\Response
{
return Inertia::render('Dashboard/CustomForms/Edit', [
'form' => $customForm,
]);
}
/**
* Обновляет пользовательскую форму
*/
public function update(UpdateCustomFormRequest $request, CustomForm $customForm): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateCustomFormAction->run($customForm, $validated);
return redirect()->route('dashboard.custom-forms.index')
->with('success', 'Пользовательская форма успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении формы: ' . $e->getMessage());
}
}
/**
* Удаляет пользовательскую форму
*/
public function destroy(CustomForm $customForm): RedirectResponse
{
try {
$this->deleteCustomFormAction->run($customForm);
return redirect()->route('dashboard.custom-forms.index')
->with('success', 'Пользовательская форма успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении формы: ' . $e->getMessage());
}
}
/**
* Показывает ответы на форму
*/
public function responses(CustomForm $customForm, \Illuminate\Http\Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'checked']);
$data = $this->listFormResponsesAction->run($customForm, $filters);
return Inertia::render('Dashboard/CustomForms/Responses', $data);
}
/**
* Переключает статус просмотра ответа
*/
public function toggleResponseChecked(CustomForm $customForm, \App\Containers\Widget\Models\CustomFormResponse $response): RedirectResponse
{
$response->update(['checked' => !$response->checked]);
return back();
}
/**
* Удаляет ответ на форму
*/
public function destroyResponse(CustomForm $customForm, \App\Containers\Widget\Models\CustomFormResponse $response): RedirectResponse
{
try {
$this->deleteFormResponseAction->run($response);
return back()->with('success', 'Ответ успешно удал!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении ответа: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,160 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Departments\CreateDepartmentAction;
use App\Containers\Dashboard\Actions\Departments\UpdateDepartmentAction;
use App\Containers\Dashboard\Actions\Departments\DeleteDepartmentAction;
use App\Containers\Dashboard\Actions\Departments\ListDepartmentsAction;
use App\Containers\Dashboard\Actions\Departments\ListDepartmentWorkersAction;
use App\Containers\Dashboard\Actions\Departments\ListDepartmentTeachersAction;
use App\Containers\Dashboard\Actions\Departments\ListDepartmentProgramsAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreDepartmentRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateDepartmentRequest;
use App\Containers\Education\Models\EducationalProgram;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\InstituteStructure\Models\Faculty;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DepartmentController extends Controller
{
public function __construct(
private readonly ListDepartmentsAction $listDepartmentsAction,
private readonly ListDepartmentWorkersAction $listDepartmentWorkersAction,
private readonly ListDepartmentTeachersAction $listDepartmentTeachersAction,
private readonly ListDepartmentProgramsAction $listDepartmentProgramsAction,
private readonly CreateDepartmentAction $createDepartmentAction,
private readonly UpdateDepartmentAction $updateDepartmentAction,
private readonly DeleteDepartmentAction $deleteDepartmentAction,
) {}
/**
* Показывает список кафедр
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'faculty_id', 'is_active']);
$data = $this->listDepartmentsAction->run($filters);
// Добавляем список факультетов для фильтра
$data['faculties'] = Faculty::query()
->orderBy('title')
->get(['id', 'title']);
return Inertia::render('Dashboard/Departments/Index', $data);
}
/**
* Показывает форму создания кафедры
*/
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/Departments/Create', [
'faculties' => Faculty::query()
->orderBy('title')
->get(['id', 'title']),
]);
}
/**
* Создает новую кафедру
*/
public function store(StoreDepartmentRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createDepartmentAction->run($validated);
return redirect()->route('dashboard.departments.index')
->with('success', 'Кафедра успешно создана!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании кафедры: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования кафедры
*/
public function edit(Department $department): \Inertia\Response
{
$department->load(['faculty', 'seo']);
// Получаем список работников
$workersData = $this->listDepartmentWorkersAction->run($department, []);
$teachersData = $this->listDepartmentTeachersAction->run($department, []);
$programsData = $this->listDepartmentProgramsAction->run($department, []);
// Получаем список доступных пользователей
$availableWorkers = User::whereHas('userDetail')
->whereDoesntHave('departments_work', fn($q) => $q->where('departments.id', $department->id))
->orderBy('name')
->get(['id', 'name']);
$availableTeachers = User::whereHas('userDetail')
->whereDoesntHave('departments_teach', fn($q) => $q->where('departments.id', $department->id))
->orderBy('name')
->get(['id', 'name']);
// Получаем список доступных программ (только опубликованные)
$availablePrograms = EducationalProgram::where('status', 'published')
->whereDoesntHave('departments', fn($q) => $q->where('departments.id', $department->id))
->orderBy('name')
->get(['id', 'name', 'status']);
return Inertia::render('Dashboard/Departments/Edit', [
'department' => $department,
'workers' => $workersData['workers'],
'availableWorkers' => $availableWorkers,
'teachers' => $teachersData['teachers'],
'availableTeachers' => $availableTeachers,
'programs' => $programsData['programs'],
'availablePrograms' => $availablePrograms,
'faculties' => Faculty::query()
->orderBy('title')
->get(['id', 'title']),
]);
}
/**
* Обновляет существующую кафедру
*/
public function update(UpdateDepartmentRequest $request, Department $department): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateDepartmentAction->run($department, $validated);
return redirect()->route('dashboard.departments.index')
->with('success', 'Кафедра успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении кафедры: ' . $e->getMessage());
}
}
/**
* Удаляет кафедру
*/
public function destroy(Department $department): RedirectResponse
{
try {
$this->deleteDepartmentAction->run($department);
return redirect()->route('dashboard.departments.index')
->with('success', 'Кафедра успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении кафедры: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,81 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Departments\AttachDepartmentProgramAction;
use App\Containers\Dashboard\Actions\Departments\DetachDepartmentProgramAction;
use App\Containers\Dashboard\Actions\Departments\ListDepartmentProgramsAction;
use App\Containers\Dashboard\UI\WEB\Requests\AttachDepartmentProgramRequest;
use App\Containers\Education\Models\EducationalProgram;
use App\Containers\InstituteStructure\Models\Department;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DepartmentProgramController extends Controller
{
public function __construct(
private readonly ListDepartmentProgramsAction $listDepartmentProgramsAction,
private readonly AttachDepartmentProgramAction $attachDepartmentProgramAction,
private readonly DetachDepartmentProgramAction $detachDepartmentProgramAction,
) {}
/**
* Показывает список образовательных программ кафедры
*/
public function index(Department $department, Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'status']);
$data = $this->listDepartmentProgramsAction->run($department, $filters);
// Получаем список доступных программ для прикрепления (только опубликованные)
$availablePrograms = EducationalProgram::where('status', 'published')
->whereDoesntHave('departments', fn($q) => $q->where('departments.id', $department->id))
->orderBy('name')
->get(['id', 'name', 'status']);
return Inertia::render('Dashboard/Departments/Programs/Index', [
'department' => $department,
'programs' => $data['programs'],
'availablePrograms' => $availablePrograms,
'filters' => $data['filters'],
]);
}
/**
* Прикрепляет программу к кафедре
*/
public function attach(Department $department, AttachDepartmentProgramRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$program = EducationalProgram::findOrFail($validated['program_id']);
$this->attachDepartmentProgramAction->run($department, $program);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Программа успешно добавлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при добавлении программы: ' . $e->getMessage());
}
}
/**
* Открепляет программу от кафедры
*/
public function detach(Department $department, EducationalProgram $program): RedirectResponse
{
try {
$this->detachDepartmentProgramAction->run($department, $program);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Программа удалена из кафедры!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении программы: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,102 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Departments\AttachDepartmentTeacherAction;
use App\Containers\Dashboard\Actions\Departments\DetachDepartmentTeacherAction;
use App\Containers\Dashboard\Actions\Departments\ListDepartmentTeachersAction;
use App\Containers\Dashboard\Actions\Departments\UpdateDepartmentTeacherAction;
use App\Containers\Dashboard\UI\WEB\Requests\AttachDepartmentTeacherRequest;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DepartmentTeacherController extends Controller
{
public function __construct(
private readonly ListDepartmentTeachersAction $listDepartmentTeachersAction,
private readonly AttachDepartmentTeacherAction $attachDepartmentTeacherAction,
private readonly UpdateDepartmentTeacherAction $updateDepartmentTeacherAction,
private readonly DetachDepartmentTeacherAction $detachDepartmentTeacherAction,
) {}
/**
* Показывает список преподавателей кафедры
*/
public function index(Department $department, Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'position']);
$data = $this->listDepartmentTeachersAction->run($department, $filters);
// Получаем список доступных пользователей для прикрепления
$availableUsers = User::whereHas('userDetail')
->whereDoesntHave('departments_teach', fn($q) => $q->where('departments.id', $department->id))
->orderBy('name')
->get(['id', 'name']);
return Inertia::render('Dashboard/Departments/Teachers/Index', [
'department' => $department,
'teachers' => $data['teachers'],
'availableUsers' => $availableUsers,
'filters' => $data['filters'],
]);
}
/**
* Прикрепляет преподавателя к кафедре
*/
public function attach(Department $department, AttachDepartmentTeacherRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$user = User::findOrFail($validated['user_id']);
$this->attachDepartmentTeacherAction->run($department, $user, $validated);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Преподаватель успешно добавлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при добавлении преподавателя: ' . $e->getMessage());
}
}
/**
* Обновляет данные преподавателя
*/
public function update(Department $department, User $teacher, AttachDepartmentTeacherRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateDepartmentTeacherAction->run($department, $teacher, $validated);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Данные преподавателя обновлены!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении преподавателя: ' . $e->getMessage());
}
}
/**
* Открепляет преподавателя от кафедры
*/
public function detach(Department $department, User $teacher): RedirectResponse
{
try {
$this->detachDepartmentTeacherAction->run($department, $teacher);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Преподаватель удален из кафедры!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении преподавателя: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,102 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Departments\AttachDepartmentWorkerAction;
use App\Containers\Dashboard\Actions\Departments\DetachDepartmentWorkerAction;
use App\Containers\Dashboard\Actions\Departments\ListDepartmentWorkersAction;
use App\Containers\Dashboard\Actions\Departments\UpdateDepartmentWorkerAction;
use App\Containers\Dashboard\UI\WEB\Requests\AttachDepartmentWorkerRequest;
use App\Containers\InstituteStructure\Models\Department;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DepartmentWorkerController extends Controller
{
public function __construct(
private readonly ListDepartmentWorkersAction $listDepartmentWorkersAction,
private readonly AttachDepartmentWorkerAction $attachDepartmentWorkerAction,
private readonly UpdateDepartmentWorkerAction $updateDepartmentWorkerAction,
private readonly DetachDepartmentWorkerAction $detachDepartmentWorkerAction,
) {}
/**
* Показывает список сотрудников кафедры
*/
public function index(Department $department, Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'position']);
$data = $this->listDepartmentWorkersAction->run($department, $filters);
// Получаем список доступных пользователей для прикрепления
$availableUsers = User::whereHas('userDetail')
->whereDoesntHave('departments_work', fn($q) => $q->where('departments.id', $department->id))
->orderBy('name')
->get(['id', 'name']);
return Inertia::render('Dashboard/Departments/Workers/Index', [
'department' => $department,
'workers' => $data['workers'],
'availableUsers' => $availableUsers,
'filters' => $data['filters'],
]);
}
/**
* Прикрепляет сотрудника к кафедре
*/
public function attach(Department $department, AttachDepartmentWorkerRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$user = User::findOrFail($validated['user_id']);
$this->attachDepartmentWorkerAction->run($department, $user, $validated);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Сотрудник успешно добавлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при добавлении сотрудника: ' . $e->getMessage());
}
}
/**
* Обновляет данные сотрудника
*/
public function update(Department $department, User $worker, AttachDepartmentWorkerRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateDepartmentWorkerAction->run($department, $worker, $validated);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Данные сотрудника обновлены!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении сотрудника: ' . $e->getMessage());
}
}
/**
* Открепляет сотрудника от кафедры
*/
public function detach(Department $department, User $worker): RedirectResponse
{
try {
$this->detachDepartmentWorkerAction->run($department, $worker);
return redirect()->route('dashboard.departments.edit', $department->id)
->with('success', 'Сотрудник удален из кафедры!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении сотрудника: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\DeleteSlideAction;
use App\Containers\Widget\Models\Slide;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
class DestroySlideController extends Controller
{
public function __construct(
private readonly DeleteSlideAction $deleteSlideAction,
) {}
public function __invoke(Slide $slide): JsonResponse
{
$this->deleteSlideAction->run($slide);
return response()->json([
'success' => true,
]);
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\DeleteSliderAction;
use App\Containers\Widget\Models\Slider;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
class DestroySliderController extends Controller
{
public function __construct(
private readonly DeleteSliderAction $deleteSliderAction,
) {}
public function __invoke(Slider $slider): RedirectResponse
{
$this->deleteSliderAction->run($slider);
return redirect()->route('dashboard.sliders.index')
->with('success', 'Слайдер удален');
}
}
@@ -0,0 +1,90 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Education\Models\DirectionStudy;
use App\Containers\Dashboard\Actions\DirectionStudies\CreateDirectionStudyAction;
use App\Containers\Dashboard\Actions\DirectionStudies\DeleteDirectionStudyAction;
use App\Containers\Dashboard\Actions\DirectionStudies\ListDirectionStudiesAction;
use App\Containers\Dashboard\Actions\DirectionStudies\UpdateDirectionStudyAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreDirectionStudyRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateDirectionStudyRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DirectionStudyController extends Controller
{
public function __construct(
private readonly ListDirectionStudiesAction $listDirectionStudiesAction,
private readonly CreateDirectionStudyAction $createDirectionStudyAction,
private readonly UpdateDirectionStudyAction $updateDirectionStudyAction,
private readonly DeleteDirectionStudyAction $deleteDirectionStudyAction,
) {}
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'lvl_edu']);
$data = $this->listDirectionStudiesAction->run($filters);
return Inertia::render('Dashboard/DirectionStudies/Index', $data);
}
public function create(): \Inertia\Response
{
$data = $this->listDirectionStudiesAction->run([]);
return Inertia::render('Dashboard/DirectionStudies/Create', [
'educationLevels' => $data['educationLevels'],
]);
}
public function store(StoreDirectionStudyRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createDirectionStudyAction->run($validated);
return redirect()->route('dashboard.direction-studies.index')
->with('success', 'Направление подготовки успешно создано!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при создании направления: ' . $e->getMessage());
}
}
public function edit(DirectionStudy $directionStudy): \Inertia\Response
{
$data = $this->listDirectionStudiesAction->run([]);
return Inertia::render('Dashboard/DirectionStudies/Edit', [
'direction' => $directionStudy,
'educationLevels' => $data['educationLevels'],
]);
}
public function update(UpdateDirectionStudyRequest $request, DirectionStudy $directionStudy): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateDirectionStudyAction->run($directionStudy, $validated);
return redirect()->route('dashboard.direction-studies.index')
->with('success', 'Направление подготовки успешно обновлено!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при обновлении направления: ' . $e->getMessage());
}
}
public function destroy(DirectionStudy $directionStudy): RedirectResponse
{
try {
$this->deleteDirectionStudyAction->run($directionStudy);
return redirect()->route('dashboard.direction-studies.index')
->with('success', 'Направление подготовки успешно удалено!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении направления: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,125 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Divisions\CreateDivisionAction;
use App\Containers\Dashboard\Actions\Divisions\UpdateDivisionAction;
use App\Containers\Dashboard\Actions\Divisions\DeleteDivisionAction;
use App\Containers\Dashboard\Actions\Divisions\ListDivisionWorkersAction;
use App\Containers\Dashboard\Actions\Divisions\ListDivisionsAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreDivisionRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateDivisionRequest;
use App\Containers\InstituteStructure\Models\Division;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DivisionController extends Controller
{
public function __construct(
private readonly ListDivisionsAction $listDivisionsAction,
private readonly ListDivisionWorkersAction $listDivisionWorkersAction,
private readonly CreateDivisionAction $createDivisionAction,
private readonly UpdateDivisionAction $updateDivisionAction,
private readonly DeleteDivisionAction $deleteDivisionAction,
) {}
/**
* Показывает список подразделений
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'is_active']);
$data = $this->listDivisionsAction->run($filters);
return Inertia::render('Dashboard/Divisions/Index', $data);
}
/**
* Показывает форму создания подразделения
*/
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/Divisions/Create');
}
/**
* Создает новое подразделение
*/
public function store(StoreDivisionRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createDivisionAction->run($validated);
return redirect()->route('dashboard.divisions.index')
->with('success', 'Подразделение успешно создано!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании подразделения: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования подразделения
*/
public function edit(Division $division): \Inertia\Response
{
$division->load(['seo']);
// Получаем список работников
$workersData = $this->listDivisionWorkersAction->run($division, []);
// Получаем список доступных пользователей
$availableWorkers = User::whereHas('userDetail')
->whereDoesntHave('divisions', fn($q) => $q->where('divisions.id', $division->id))
->orderBy('name')
->get(['id', 'name']);
return Inertia::render('Dashboard/Divisions/Edit', [
'division' => $division,
'workers' => $workersData['workers'],
'availableWorkers' => $availableWorkers,
]);
}
/**
* Обновляет существующее подразделение
*/
public function update(UpdateDivisionRequest $request, Division $division): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateDivisionAction->run($division, $validated);
return redirect()->route('dashboard.divisions.index')
->with('success', 'Подразделение успешно обновлено!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении подразделения: ' . $e->getMessage());
}
}
/**
* Удаляет подразделение
*/
public function destroy(Division $division): RedirectResponse
{
try {
$this->deleteDivisionAction->run($division);
return redirect()->route('dashboard.divisions.index')
->with('success', 'Подразделение успешно удалено!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении подразделения: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,102 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Divisions\AttachDivisionWorkerAction;
use App\Containers\Dashboard\Actions\Divisions\DetachDivisionWorkerAction;
use App\Containers\Dashboard\Actions\Divisions\ListDivisionWorkersAction;
use App\Containers\Dashboard\Actions\Divisions\UpdateDivisionWorkerAction;
use App\Containers\Dashboard\UI\WEB\Requests\AttachDivisionWorkerRequest;
use App\Containers\InstituteStructure\Models\Division;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class DivisionWorkerController extends Controller
{
public function __construct(
private readonly ListDivisionWorkersAction $listDivisionWorkersAction,
private readonly AttachDivisionWorkerAction $attachDivisionWorkerAction,
private readonly UpdateDivisionWorkerAction $updateDivisionWorkerAction,
private readonly DetachDivisionWorkerAction $detachDivisionWorkerAction,
) {}
/**
* Показывает список сотрудников подразделения
*/
public function index(Division $division, Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'position']);
$data = $this->listDivisionWorkersAction->run($division, $filters);
// Получаем список доступных пользователей для прикрепления
$availableUsers = User::whereHas('userDetail')
->whereDoesntHave('divisions', fn($q) => $q->where('divisions.id', $division->id))
->orderBy('name')
->get(['id', 'name']);
return Inertia::render('Dashboard/Divisions/Workers/Index', [
'division' => $division,
'workers' => $data['workers'],
'availableUsers' => $availableUsers,
'filters' => $data['filters'],
]);
}
/**
* Прикрепляет сотрудника к подразделению
*/
public function attach(Division $division, AttachDivisionWorkerRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$user = User::findOrFail($validated['user_id']);
$this->attachDivisionWorkerAction->run($division, $user, $validated);
return redirect()->route('dashboard.divisions.edit', $division->id)
->with('success', 'Сотрудник успешно добавлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при добавлении сотрудника: ' . $e->getMessage());
}
}
/**
* Обновляет данные сотрудника
*/
public function update(Division $division, User $worker, AttachDivisionWorkerRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateDivisionWorkerAction->run($division, $worker, $validated);
return redirect()->route('dashboard.divisions.edit', $division->id)
->with('success', 'Данные сотрудника обновлены!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении сотрудника: ' . $e->getMessage());
}
}
/**
* Открепляет сотрудника от подразделения
*/
public function detach(Division $division, User $worker): RedirectResponse
{
try {
$this->detachDivisionWorkerAction->run($division, $worker);
return redirect()->route('dashboard.divisions.edit', $division->id)
->with('success', 'Сотрудник удален из подразделения!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении сотрудника: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Article\Models\Post;
use App\Containers\Dashboard\Actions\Sliders\ListSlidesAction;
use App\Containers\Widget\Models\Slider;
use App\Http\Controllers\Controller;
use Inertia\Inertia;
class EditSliderController extends Controller
{
public function __construct(
private readonly ListSlidesAction $listSlidesAction,
) {}
public function __invoke(Slider $slider): \Inertia\Response
{
$slider->load('slides');
$slides = $this->listSlidesAction->run($slider);
$posts = Post::where('status', 'published')
->orderBy('created_at', 'desc')
->get(['id', 'title', 'slug']);
return Inertia::render('Dashboard/Sliders/Edit', [
'slider' => $slider,
'slides' => $slides,
'posts' => $posts,
]);
}
}
@@ -0,0 +1,120 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\EducationalGroups\CreateEducationalGroupAction;
use App\Containers\Dashboard\Actions\EducationalGroups\UpdateEducationalGroupAction;
use App\Containers\Dashboard\Actions\EducationalGroups\DeleteEducationalGroupAction;
use App\Containers\Dashboard\Actions\EducationalGroups\ListEducationalGroupsAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreEducationalGroupRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateEducationalGroupRequest;
use App\Containers\Schedule\Models\EducationalGroup;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class EducationalGroupController extends Controller
{
public function __construct(
private readonly ListEducationalGroupsAction $listEducationalGroupsAction,
private readonly CreateEducationalGroupAction $createEducationalGroupAction,
private readonly UpdateEducationalGroupAction $updateEducationalGroupAction,
private readonly DeleteEducationalGroupAction $deleteEducationalGroupAction,
) {}
/**
* Показывает список учебных групп
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'faculty_id', 'education_form_id']);
$data = $this->listEducationalGroupsAction->run($filters);
return Inertia::render('Dashboard/EducationalGroups/Index', $data);
}
/**
* Показывает форму создания группы
*/
public function create(): \Inertia\Response
{
$data = $this->listEducationalGroupsAction->run([]);
return Inertia::render('Dashboard/EducationalGroups/Create', [
'faculties' => $data['faculties'],
'educationForms' => $data['educationForms'],
]);
}
/**
* Создает новую учебную группу
*/
public function store(StoreEducationalGroupRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createEducationalGroupAction->run($validated);
return redirect()->route('dashboard.educational-groups.index')
->with('success', 'Учебная группа успешно создана!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании учебной группы: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования группы
*/
public function edit(EducationalGroup $educationalGroup): \Inertia\Response
{
$educationalGroup->load(['faculty']);
$data = $this->listEducationalGroupsAction->run([]);
return Inertia::render('Dashboard/EducationalGroups/Edit', [
'group' => $educationalGroup,
'faculties' => $data['faculties'],
'educationForms' => $data['educationForms'],
]);
}
/**
* Обновляет существующую учебную группу
*/
public function update(UpdateEducationalGroupRequest $request, EducationalGroup $educationalGroup): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateEducationalGroupAction->run($educationalGroup, $validated);
return redirect()->route('dashboard.educational-groups.index')
->with('success', 'Учебная группа успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении учебной группы: ' . $e->getMessage());
}
}
/**
* Удаляет учебную группу
*/
public function destroy(EducationalGroup $educationalGroup): RedirectResponse
{
try {
$this->deleteEducationalGroupAction->run($educationalGroup);
return redirect()->route('dashboard.educational-groups.index')
->with('success', 'Учебная группа успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении учебной группы: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,95 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Education\Models\EducationalProgram;
use App\Containers\Dashboard\Actions\EducationalPrograms\CreateEducationalProgramAction;
use App\Containers\Dashboard\Actions\EducationalPrograms\DeleteEducationalProgramAction;
use App\Containers\Dashboard\Actions\EducationalPrograms\ListEducationalProgramsAction;
use App\Containers\Dashboard\Actions\EducationalPrograms\UpdateEducationalProgramAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreEducationalProgramRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateEducationalProgramRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class EducationalProgramController extends Controller
{
public function __construct(
private readonly ListEducationalProgramsAction $listEducationalProgramsAction,
private readonly CreateEducationalProgramAction $createEducationalProgramAction,
private readonly UpdateEducationalProgramAction $updateEducationalProgramAction,
private readonly DeleteEducationalProgramAction $deleteEducationalProgramAction,
) {}
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'lvl_edu', 'status', 'direction_study_id']);
$data = $this->listEducationalProgramsAction->run($filters);
return Inertia::render('Dashboard/EducationalPrograms/Index', $data);
}
public function create(): \Inertia\Response
{
$data = $this->listEducationalProgramsAction->run([]);
return Inertia::render('Dashboard/EducationalPrograms/Create', [
'statuses' => $data['statuses'],
'educationLevels' => $data['educationLevels'],
'directionStudies' => $data['directionStudies'],
]);
}
public function store(StoreEducationalProgramRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createEducationalProgramAction->run($validated);
return redirect()->route('dashboard.educational-programs.index')
->with('success', 'Образовательная программа успешно создана!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при создании программы: ' . $e->getMessage());
}
}
public function edit(EducationalProgram $educationalProgram): \Inertia\Response
{
$educationalProgram->load(['directionStudy']);
$data = $this->listEducationalProgramsAction->run([]);
return Inertia::render('Dashboard/EducationalPrograms/Edit', [
'program' => $educationalProgram,
'statuses' => $data['statuses'],
'educationLevels' => $data['educationLevels'],
'directionStudies' => $data['directionStudies'],
]);
}
public function update(UpdateEducationalProgramRequest $request, EducationalProgram $educationalProgram): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateEducationalProgramAction->run($educationalProgram, $validated);
return redirect()->route('dashboard.educational-programs.index')
->with('success', 'Образовательная программа успешно обновлена!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при обновлении программы: ' . $e->getMessage());
}
}
public function destroy(EducationalProgram $educationalProgram): RedirectResponse
{
try {
$this->deleteEducationalProgramAction->run($educationalProgram);
return redirect()->route('dashboard.educational-programs.index')
->with('success', 'Образовательная программа успешно удалена!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении программы: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,125 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Faculties\CreateFacultyAction;
use App\Containers\Dashboard\Actions\Faculties\UpdateFacultyAction;
use App\Containers\Dashboard\Actions\Faculties\DeleteFacultyAction;
use App\Containers\Dashboard\Actions\Faculties\ListFacultyWorkersAction;
use App\Containers\Dashboard\Actions\Faculties\ListFacultiesAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreFacultyRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateFacultyRequest;
use App\Containers\InstituteStructure\Models\Faculty;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class FacultyController extends Controller
{
public function __construct(
private readonly ListFacultiesAction $listFacultiesAction,
private readonly ListFacultyWorkersAction $listFacultyWorkersAction,
private readonly CreateFacultyAction $createFacultyAction,
private readonly UpdateFacultyAction $updateFacultyAction,
private readonly DeleteFacultyAction $deleteFacultyAction,
) {}
/**
* Показывает список факультетов
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'is_active']);
$data = $this->listFacultiesAction->run($filters);
return Inertia::render('Dashboard/Faculties/Index', $data);
}
/**
* Показывает форму создания факультета
*/
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/Faculties/Create');
}
/**
* Создает новый факультет
*/
public function store(StoreFacultyRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createFacultyAction->run($validated);
return redirect()->route('dashboard.faculties.index')
->with('success', 'Факультет успешно создан!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании факультета: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования факультета
*/
public function edit(Faculty $faculty): \Inertia\Response
{
$faculty->load(['seo']);
// Получаем список работников
$workersData = $this->listFacultyWorkersAction->run($faculty, []);
// Получаем список доступных пользователей
$availableWorkers = User::whereHas('userDetail')
->whereDoesntHave('faculties', fn($q) => $q->where('faculties.id', $faculty->id))
->orderBy('name')
->get(['id', 'name']);
return Inertia::render('Dashboard/Faculties/Edit', [
'faculty' => $faculty,
'workers' => $workersData['workers'],
'availableWorkers' => $availableWorkers,
]);
}
/**
* Обновляет существующий факультет
*/
public function update(UpdateFacultyRequest $request, Faculty $faculty): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateFacultyAction->run($faculty, $validated);
return redirect()->route('dashboard.faculties.index')
->with('success', 'Факультет успешно обновлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении факультета: ' . $e->getMessage());
}
}
/**
* Удаляет факультет
*/
public function destroy(Faculty $faculty): RedirectResponse
{
try {
$this->deleteFacultyAction->run($faculty);
return redirect()->route('dashboard.faculties.index')
->with('success', 'Факультет успешно удален!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении факультета: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,102 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Faculties\AttachFacultyWorkerAction;
use App\Containers\Dashboard\Actions\Faculties\DetachFacultyWorkerAction;
use App\Containers\Dashboard\Actions\Faculties\ListFacultyWorkersAction;
use App\Containers\Dashboard\Actions\Faculties\UpdateFacultyWorkerAction;
use App\Containers\Dashboard\UI\WEB\Requests\AttachFacultyWorkerRequest;
use App\Containers\InstituteStructure\Models\Faculty;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class FacultyWorkerController extends Controller
{
public function __construct(
private readonly ListFacultyWorkersAction $listFacultyWorkersAction,
private readonly AttachFacultyWorkerAction $attachFacultyWorkerAction,
private readonly UpdateFacultyWorkerAction $updateFacultyWorkerAction,
private readonly DetachFacultyWorkerAction $detachFacultyWorkerAction,
) {}
/**
* Показывает список сотрудников факультета
*/
public function index(Faculty $faculty, Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'position']);
$data = $this->listFacultyWorkersAction->run($faculty, $filters);
// Получаем список доступных пользователей для прикрепления
$availableUsers = User::whereHas('userDetail')
->whereDoesntHave('faculties', fn($q) => $q->where('faculties.id', $faculty->id))
->orderBy('name')
->get(['id', 'name']);
return Inertia::render('Dashboard/Faculties/Workers/Index', [
'faculty' => $faculty,
'workers' => $data['workers'],
'availableUsers' => $availableUsers,
'filters' => $data['filters'],
]);
}
/**
* Прикрепляет сотрудника к факультету
*/
public function attach(Faculty $faculty, AttachFacultyWorkerRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$user = User::findOrFail($validated['user_id']);
$this->attachFacultyWorkerAction->run($faculty, $user, $validated);
return redirect()->route('dashboard.faculties.edit', $faculty->id)
->with('success', 'Сотрудник успешно добавлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при добавлении сотрудника: ' . $e->getMessage());
}
}
/**
* Обновляет данные сотрудника
*/
public function update(Faculty $faculty, User $worker, AttachFacultyWorkerRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateFacultyWorkerAction->run($faculty, $worker, $validated);
return redirect()->route('dashboard.faculties.edit', $faculty->id)
->with('success', 'Данные сотрудника обновлены!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении сотрудника: ' . $e->getMessage());
}
}
/**
* Открепляет сотрудника от факультета
*/
public function detach(Faculty $faculty, User $worker): RedirectResponse
{
try {
$this->detachFacultyWorkerAction->run($faculty, $worker);
return redirect()->route('dashboard.faculties.edit', $faculty->id)
->with('success', 'Сотрудник удален из факультета!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении сотрудника: ' . $e->getMessage());
}
}
}
@@ -2,22 +2,18 @@
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Tasks\GetAiPreparedPostsTask;
use App\Containers\Dashboard\Actions\LoadDashboardDataAction;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class IndexDashboardController extends Controller
{
public function __construct(
private readonly GetAiPreparedPostsTask $getAiPreparedPostsTask,
private readonly LoadDashboardDataAction $loadDashboardDataAction,
) {}
public function __invoke(Request $request): \Inertia\Response
{
$aiPreparedPosts = $this->getAiPreparedPostsTask->run();
return inertia()->render('Dashboard/Main', [
'aiPreparedPosts' => $aiPreparedPosts,
]);
return inertia()->render('Dashboard/Main', $this->loadDashboardDataAction->run());
}
}
@@ -0,0 +1,123 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\JournalIssues\CreateJournalIssueAction;
use App\Containers\Dashboard\Actions\JournalIssues\DeleteJournalIssueAction;
use App\Containers\Dashboard\Actions\JournalIssues\ListJournalIssuesAction;
use App\Containers\Dashboard\Actions\JournalIssues\UpdateJournalIssueAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreJournalIssueRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateJournalIssueRequest;
use App\Containers\Science\Models\AcademicJournal;
use App\Containers\Science\Models\JournalIssue;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
class JournalIssueController extends Controller
{
public function __construct(
private readonly ListJournalIssuesAction $listJournalIssuesAction,
private readonly CreateJournalIssueAction $createJournalIssueAction,
private readonly UpdateJournalIssueAction $updateJournalIssueAction,
private readonly DeleteJournalIssueAction $deleteJournalIssueAction,
) {}
/**
* Display a listing of journal issues for a journal
*/
public function index(AcademicJournal $academicJournal, Request $request): Response
{
$filters = $request->only(['search', 'year_publication', 'is_active']);
$data = $this->listJournalIssuesAction->run($academicJournal->id, $filters);
return Inertia::render('Dashboard/AcademicJournals/JournalIssues/Index', array_merge($data, [
'journal' => $academicJournal->only(['id', 'title', 'slug']),
]));
}
/**
* Show the form for creating a new journal issue
*/
public function create(AcademicJournal $academicJournal): Response
{
return Inertia::render('Dashboard/AcademicJournals/JournalIssues/Create', [
'journal' => $academicJournal->only(['id', 'title', 'slug']),
]);
}
/**
* Store a newly created journal issue
*/
public function store(StoreJournalIssueRequest $request, AcademicJournal $academicJournal): RedirectResponse
{
try {
$validated = $request->validated();
$validated['academic_journal_id'] = $academicJournal->id;
$this->createJournalIssueAction->run($validated);
return redirect()->route('dashboard.academic-journals.issues.index', $academicJournal->id)
->with('success', 'Выпуск журнала успешно создан!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании выпуска: ' . $e->getMessage());
}
}
/**
* Show the form for editing the specified journal issue
*/
public function edit(AcademicJournal $academicJournal, int $issue): Response
{
$issue = $academicJournal->journals()->findOrFail($issue);
return Inertia::render('Dashboard/AcademicJournals/JournalIssues/Edit', [
'journal' => $academicJournal->only(['id', 'title', 'slug']),
'issue' => $issue,
]);
}
/**
* Update the specified journal issue
*/
public function update(UpdateJournalIssueRequest $request, AcademicJournal $academicJournal, int $issue): RedirectResponse
{
$issue = $academicJournal->journals()->findOrFail($issue);
try {
$validated = $request->validated();
$this->updateJournalIssueAction->run($issue, $validated);
return redirect()->route('dashboard.academic-journals.issues.index', $academicJournal->id)
->with('success', 'Выпуск журнала успешно обновлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении выпуска: ' . $e->getMessage());
}
}
/**
* Remove the specified journal issue
*/
public function destroy(AcademicJournal $academicJournal, int $issue): RedirectResponse
{
$issue = $academicJournal->journals()->findOrFail($issue);
try {
$this->deleteJournalIssueAction->run($issue);
return redirect()->route('dashboard.academic-journals.issues.index', $academicJournal->id)
->with('success', 'Выпуск журнала успешно удален!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении выпуска: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,111 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\AppStructure\Models\MainSection;
use App\Containers\Dashboard\Actions\MainSections\CreateMainSectionAction;
use App\Containers\Dashboard\Actions\MainSections\DeleteMainSectionAction;
use App\Containers\Dashboard\Actions\MainSections\ListMainSectionsAction;
use App\Containers\Dashboard\Actions\MainSections\UpdateMainSectionAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreMainSectionRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateMainSectionRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class MainSectionController extends Controller
{
public function __construct(
private readonly ListMainSectionsAction $listMainSectionsAction,
private readonly CreateMainSectionAction $createMainSectionAction,
private readonly UpdateMainSectionAction $updateMainSectionAction,
private readonly DeleteMainSectionAction $deleteMainSectionAction,
) {}
/**
* Показывает список главных разделов
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search']);
$data = $this->listMainSectionsAction->run($filters);
return Inertia::render('Dashboard/MainSections/Index', $data);
}
/**
* Показывает форму создания раздела
*/
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/MainSections/Create');
}
/**
* Создает новый главный раздел
*/
public function store(StoreMainSectionRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createMainSectionAction->run($validated);
return redirect()->route('dashboard.main-sections.index')
->with('success', 'Главный раздел успешно создан!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании главного раздела: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования раздела
*/
public function edit(MainSection $mainSection): \Inertia\Response
{
$mainSection->load(['subSections']);
return Inertia::render('Dashboard/MainSections/Edit', [
'mainSection' => $mainSection,
]);
}
/**
* Обновляет существующий главный раздел
*/
public function update(UpdateMainSectionRequest $request, MainSection $mainSection): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateMainSectionAction->run($mainSection, $validated);
return redirect()->route('dashboard.main-sections.index')
->with('success', 'Главный раздел успешно обновлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении главного раздела: ' . $e->getMessage());
}
}
/**
* Удаляет главный раздел
*/
public function destroy(MainSection $mainSection): RedirectResponse
{
try {
$this->deleteMainSectionAction->run($mainSection);
return redirect()->route('dashboard.main-sections.index')
->with('success', 'Главный раздел успешно удален!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении главного раздела: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,118 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\AppStructure\Models\Page;
use App\Containers\Dashboard\Actions\Pages\CreatePageAction;
use App\Containers\Dashboard\Actions\Pages\DeletePageAction;
use App\Containers\Dashboard\Actions\Pages\ListPagesAction;
use App\Containers\Dashboard\Actions\Pages\UpdatePageAction;
use App\Containers\Dashboard\UI\WEB\Requests\StorePageRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdatePageRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class PageController extends Controller
{
public function __construct(
private readonly ListPagesAction $listPagesAction,
private readonly CreatePageAction $createPageAction,
private readonly UpdatePageAction $updatePageAction,
private readonly DeletePageAction $deletePageAction,
) {}
/**
* Показывает список страниц
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'tab', 'sub_section_id']);
$data = $this->listPagesAction->run($filters);
return Inertia::render('Dashboard/Pages/Index', $data);
}
/**
* Показывает форму создания страницы
*/
public function create(): \Inertia\Response
{
$data = $this->listPagesAction->run([]);
return Inertia::render('Dashboard/Pages/Create', [
'subSections' => $data['subSections'],
]);
}
/**
* Создает новую страницу
*/
public function store(StorePageRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createPageAction->run($validated);
return redirect()->route('dashboard.pages.index')
->with('success', 'Страница успешно создана!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании страницы: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования страницы
*/
public function edit(Page $page): \Inertia\Response
{
$page->load(['section.mainSection']);
$data = $this->listPagesAction->run([]);
return Inertia::render('Dashboard/Pages/Edit', [
'page' => $page,
'subSections' => $data['subSections'],
]);
}
/**
* Обновляет существующую страницу
*/
public function update(UpdatePageRequest $request, Page $page): RedirectResponse
{
try {
$validated = $request->validated();
$this->updatePageAction->run($page, $validated);
return redirect()->route('dashboard.pages.index')
->with('success', 'Страница успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении страницы: ' . $e->getMessage());
}
}
/**
* Удаляет страницу
*/
public function destroy(Page $page): RedirectResponse
{
try {
$this->deletePageAction->run($page);
return redirect()->route('dashboard.pages.index')
->with('success', 'Страница успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении страницы: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,83 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\PageReferenceLists\CreatePageReferenceListAction;
use App\Containers\Dashboard\Actions\PageReferenceLists\DeletePageReferenceListAction;
use App\Containers\Dashboard\Actions\PageReferenceLists\ListPageReferenceListsAction;
use App\Containers\Dashboard\Actions\PageReferenceLists\UpdatePageReferenceListAction;
use App\Containers\Dashboard\UI\WEB\Requests\StorePageReferenceListRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdatePageReferenceListRequest;
use App\Containers\Widget\Models\PageReferenceList;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class PageReferenceListController extends Controller
{
public function __construct(
private readonly ListPageReferenceListsAction $listPageReferenceListsAction,
private readonly CreatePageReferenceListAction $createPageReferenceListAction,
private readonly UpdatePageReferenceListAction $updatePageReferenceListAction,
private readonly DeletePageReferenceListAction $deletePageReferenceListAction,
) {}
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'is_active']);
$data = $this->listPageReferenceListsAction->run($filters);
return Inertia::render('Dashboard/PageReferenceLists/Index', $data);
}
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/PageReferenceLists/Create');
}
public function store(StorePageReferenceListRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createPageReferenceListAction->run($validated);
return redirect()->route('dashboard.page-reference-lists.index')
->with('success', 'Список ресурсов успешно создан!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при создании: ' . $e->getMessage());
}
}
public function edit(PageReferenceList $pageReferenceList): \Inertia\Response
{
return Inertia::render('Dashboard/PageReferenceLists/Edit', [
'list' => $pageReferenceList,
]);
}
public function update(UpdatePageReferenceListRequest $request, PageReferenceList $pageReferenceList): RedirectResponse
{
try {
$validated = $request->validated();
$this->updatePageReferenceListAction->run($pageReferenceList, $validated);
return redirect()->route('dashboard.page-reference-lists.index')
->with('success', 'Список ресурсов успешно обновлён!');
} catch (\Exception $e) {
return back()->withInput()->with('error', 'Ошибка при обновлении: ' . $e->getMessage());
}
}
public function destroy(PageReferenceList $pageReferenceList): RedirectResponse
{
try {
$this->deletePageReferenceListAction->run($pageReferenceList);
return redirect()->route('dashboard.page-reference-lists.index')
->with('success', 'Список ресурсов успешно удалён!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при удалении: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,55 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\EmailNews\FetchEmailNewsAction;
use App\Containers\Dashboard\Exceptions\EmailFetchException;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class ParseEmailNewsController extends Controller
{
public function __construct(
private readonly FetchEmailNewsAction $fetchEmailNewsAction,
) {}
public function __invoke(Request $request): RedirectResponse
{
try {
Log::info('[ParseEmailNewsController] Принудительный запуск парсинга email');
$result = $this->fetchEmailNewsAction->run();
if ($result['created_posts'] > 0) {
return redirect()->back()->with('success',
"Успешно обработано писем: {$result['processed_emails']}. Создано новостей: {$result['created_posts']}"
);
}
if ($result['processed_emails'] === 0) {
return redirect()->back()->with('info',
'Нет непрочитанных писем для обработки'
);
}
return redirect()->back()->with('warning',
"Обработано писем: {$result['processed_emails']}, но новостей не создано"
);
} catch (EmailFetchException $e) {
Log::error('[ParseEmailNewsController] EmailFetchException', [
'error' => $e->getMessage(),
]);
return redirect()->back()->with('error', $e->getMessage());
} catch (\Exception $e) {
Log::error('[ParseEmailNewsController] Критическая ошибка', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);
return redirect()->back()->with('error', 'Ошибка при парсинге email: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,218 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Article\Enums\PostStatus;
use App\Containers\Article\Models\Post;
use App\Containers\Dashboard\Actions\Posts\BulkDeletePostsAction;
use App\Containers\Dashboard\Actions\Posts\BulkPublishPostsAction;
use App\Containers\Dashboard\Actions\Posts\BulkVerificationPostsAction;
use App\Containers\Dashboard\Actions\Posts\CreatePostAction;
use App\Containers\Dashboard\Actions\Posts\DeletePostAction;
use App\Containers\Dashboard\Actions\Posts\GetPostFormDataAction;
use App\Containers\Dashboard\Actions\Posts\ListAiPreparedPostsAction;
use App\Containers\Dashboard\Actions\Posts\ListPostsAction;
use App\Containers\Dashboard\Actions\Posts\UpdatePostAction;
use App\Containers\Dashboard\UI\WEB\Requests\StorePostRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class PostController extends Controller
{
public function __construct(
private readonly CreatePostAction $createPostAction,
private readonly UpdatePostAction $updatePostAction,
private readonly DeletePostAction $deletePostAction,
private readonly ListPostsAction $listPostsAction,
private readonly ListAiPreparedPostsAction $listAiPreparedPostsAction,
private readonly GetPostFormDataAction $getPostFormDataAction,
private readonly BulkDeletePostsAction $bulkDeletePostsAction,
private readonly BulkPublishPostsAction $bulkPublishPostsAction,
private readonly BulkVerificationPostsAction $bulkVerificationPostsAction,
) {}
/**
* Показывает форму создания поста
*/
public function create(Request $request): \Inertia\Response
{
$formData = $this->getPostFormDataAction->run();
return Inertia::render('Dashboard/Posts/Create', $formData);
}
/**
* Создает новый пост
*/
public function store(StorePostRequest $request): RedirectResponse
{
try {
$this->createPostAction->run($request->validated());
return redirect()->route('dashboard.posts.index')
->with('success', 'Новость успешно создана!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании новости: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования поста
*/
public function edit(Post $post): \Inertia\Response
{
$post->load(['category', 'seo']);
$formData = $this->getPostFormDataAction->run();
return Inertia::render('Dashboard/Posts/Edit', [
'post' => [
...$post->toArray(),
'publish_setting' => [
'publish_after' => $post->publish_at !== null,
'publish_at' => $post->publish_at,
],
'publication' => [
'vk' => true,
'telegram' => true,
],
],
...$formData,
]);
}
/**
* Обновляет существующий пост
*/
public function update(StorePostRequest $request, Post $post): RedirectResponse
{
try {
$this->updatePostAction->run($post, $request->validated());
return redirect()->route('dashboard.posts.index')
->with('success', 'Новость успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении новости: ' . $e->getMessage());
}
}
/**
* Показывает список постов
*/
public function index(Request $request): \Inertia\Response
{
$filters = [
'status' => $request->status,
'search' => $request->search,
];
$posts = $this->listPostsAction->run($filters, 20);
return Inertia::render('Dashboard/Posts/Index', [
'posts' => $posts->withQueryString(),
'filters' => $filters,
]);
}
/**
* Показывает AI подготовленные посты для модерации
*/
public function aiPrepared(Request $request): \Inertia\Response
{
$aiPreparedPosts = $this->listAiPreparedPostsAction->run();
return Inertia::render('Dashboard/Posts/AiPrepared', [
'aiPreparedPosts' => $aiPreparedPosts,
]);
}
/**
* Показывает просмотр поста
*/
public function show(Post $post): \Inertia\Response
{
$post->load(['category', 'author', 'slide', 'tags']);
return Inertia::render('Dashboard/Posts/Show', [
'post' => [
...$post->toArray(),
'slide' => $post->slide?->toArray(),
],
]);
}
/**
* Удаляет пост
*/
public function destroy(Post $post): RedirectResponse
{
try {
$this->deletePostAction->run($post);
return redirect()->route('dashboard.posts.index')
->with('success', 'Новость успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении новости: ' . $e->getMessage());
}
}
/**
* Массовое удаление постов
*/
public function bulkDestroy(Request $request): RedirectResponse
{
$request->validate(['ids' => 'required|array', 'ids.*' => 'integer|exists:posts,id']);
try {
$count = $this->bulkDeletePostsAction->run($request->ids);
return redirect()->back()
->with('success', "Удалено {$count} новостей");
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении: ' . $e->getMessage());
}
}
/**
* Массовая публикация постов
*/
public function bulkPublish(Request $request): RedirectResponse
{
$request->validate(['ids' => 'required|array', 'ids.*' => 'integer|exists:posts,id']);
try {
$count = $this->bulkPublishPostsAction->run($request->ids);
return redirect()->back()
->with('success', "Опубликовано {$count} новостей");
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при публикации: ' . $e->getMessage());
}
}
/**
* Массовая установка статуса "На модерации"
*/
public function bulkVerification(Request $request): RedirectResponse
{
$request->validate(['ids' => 'required|array', 'ids.*' => 'integer|exists:posts,id']);
try {
$count = $this->bulkVerificationPostsAction->run($request->ids);
return redirect()->back()
->with('success', "{$count} новостей переведено на модерацию");
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка: ' . $e->getMessage());
}
}
}
@@ -2,7 +2,7 @@
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\ProcessMixedFilesAction;
use App\Containers\Dashboard\Actions\EmailNews\ProcessMixedFilesAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreFilesRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
@@ -3,7 +3,7 @@
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Article\Models\Post;
use App\Containers\Dashboard\Actions\PublishPostAction;
use App\Containers\Dashboard\Actions\Posts\PublishPostAction;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
@@ -0,0 +1,43 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Posts\QuickUploadFileAction;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
class QuickUploadController extends Controller
{
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/QuickUpload');
}
public function store(Request $request, QuickUploadFileAction $quickUploadFileAction): \Illuminate\Http\JsonResponse
{
$request->validate([
'file' => ['required', 'file', 'max:20000'],
]);
try {
$result = $quickUploadFileAction->run($request->file('file'));
return response()->json([
'success' => true,
'data' => [
'url' => url($result['url']),
'path' => $result['path'],
'original_name' => $result['original_name'],
],
]);
} catch (\Throwable $e) {
report($e);
return response()->json([
'success' => false,
'message' => 'Ошибка при загрузке файла: ' . $e->getMessage(),
], 500);
}
}
}
@@ -0,0 +1,153 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Schedules\CreateScheduleAction;
use App\Containers\Dashboard\Actions\Schedules\UpdateScheduleAction;
use App\Containers\Dashboard\Actions\Schedules\DeleteScheduleAction;
use App\Containers\Dashboard\Actions\Schedules\ListSchedulesAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreScheduleRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateScheduleRequest;
use App\Containers\Schedule\Models\Schedule;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Illuminate\Support\Str;
use Illuminate\Support\Carbon;
class ScheduleController extends Controller
{
public function __construct(
private readonly ListSchedulesAction $listSchedulesAction,
private readonly CreateScheduleAction $createScheduleAction,
private readonly UpdateScheduleAction $updateScheduleAction,
private readonly DeleteScheduleAction $deleteScheduleAction,
) {}
/**
* Показывает список расписаний
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'educational_group_id', 'education_form_id']);
$data = $this->listSchedulesAction->run($filters);
return Inertia::render('Dashboard/Schedules/Index', $data);
}
/**
* Показывает форму создания расписания
*/
public function create(): \Inertia\Response
{
$data = $this->listSchedulesAction->run([]);
return Inertia::render('Dashboard/Schedules/Create', [
'educationalGroups' => $data['educationalGroups'],
'educationForms' => $data['educationForms'],
]);
}
/**
* Создает новое расписание
*/
public function store(StoreScheduleRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
// Обработка файла
if (!empty($validated['file'][0]['path'])) {
$file = $validated['file'][0]['path'];
$filename = Str::slug(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) . '-' . Carbon::now()->timestamp) . '.' . $file->getClientOriginalExtension();
$path = $file->storeAs('schedules', $filename, 'public');
$validated['file'] = [
[
'title' => $validated['file'][0]['title'],
'path' => $path,
],
];
}
$this->createScheduleAction->run($validated);
return redirect()->route('dashboard.schedules.index')
->with('success', 'Расписание успешно создано!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании расписания: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования расписания
*/
public function edit(Schedule $schedule): \Inertia\Response
{
$schedule->load(['educationalGroup.faculty']);
$data = $this->listSchedulesAction->run([]);
return Inertia::render('Dashboard/Schedules/Edit', [
'schedule' => $schedule,
'educationalGroups' => $data['educationalGroups'],
'educationForms' => $data['educationForms'],
]);
}
/**
* Обновляет существующее расписание
*/
public function update(UpdateScheduleRequest $request, Schedule $schedule): RedirectResponse
{
try {
$validated = $request->validated();
// Обработка нового файла если загружен
if (!empty($validated['file'][0]['path'])) {
$file = $validated['file'][0]['path'];
$filename = Str::slug(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) . '-' . Carbon::now()->timestamp) . '.' . $file->getClientOriginalExtension();
$path = $file->storeAs('schedules', $filename, 'public');
$validated['file'] = [
[
'title' => $validated['file'][0]['title'],
'path' => $path,
],
];
} else {
// Оставляем старый файл
unset($validated['file']);
}
$this->updateScheduleAction->run($schedule, $validated);
return redirect()->route('dashboard.schedules.index')
->with('success', 'Расписание успешно обновлено!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении расписания: ' . $e->getMessage());
}
}
/**
* Удаляет расписание
*/
public function destroy(Schedule $schedule): RedirectResponse
{
try {
$this->deleteScheduleAction->run($schedule);
return redirect()->route('dashboard.schedules.index')
->with('success', 'Расписание успешно удалено!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении расписания: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,25 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\ListSlidersAction;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class SliderController extends Controller
{
public function __construct(
private readonly ListSlidersAction $listSlidersAction,
) {}
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'is_active']);
$sliders = $this->listSlidersAction->run($filters);
return inertia()->render('Dashboard/Sliders/Index', [
'sliders' => $sliders,
'filters' => $filters,
]);
}
}
@@ -2,7 +2,7 @@
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\ProcessUploadedFilesAction;
use App\Containers\Dashboard\Actions\EmailNews\ProcessUploadedFilesAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreFilesRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\CreateSlideAction;
use App\Containers\Widget\Models\Slider;
use App\Containers\Dashboard\UI\WEB\Requests\StoreSlideRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
class StoreSlideController extends Controller
{
public function __construct(
private readonly CreateSlideAction $createSlideAction,
) {}
public function __invoke(StoreSlideRequest $request, Slider $slider): JsonResponse
{
$slide = $this->createSlideAction->run($slider, $request->validated());
return response()->json([
'success' => true,
'slide' => $slide,
]);
}
}
@@ -0,0 +1,23 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\CreateSliderAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreSliderRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
class StoreSliderController extends Controller
{
public function __construct(
private readonly CreateSliderAction $createSliderAction,
) {}
public function __invoke(StoreSliderRequest $request): RedirectResponse
{
$slider = $this->createSliderAction->run($request->validated());
return redirect()->route('dashboard.sliders.edit', $slider->id)
->with('success', 'Слайдер успешно создан');
}
}
@@ -0,0 +1,203 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\AppStructure\Models\Page;
use App\Containers\AppStructure\Models\SubSection;
use App\Containers\Dashboard\Actions\Pages\AttachPageToSubSectionAction;
use App\Containers\Dashboard\Actions\Pages\DetachPageFromSubSectionAction;
use App\Containers\Dashboard\Actions\SubSections\AttachSubSectionToMainSectionAction;
use App\Containers\Dashboard\Actions\SubSections\CreateSubSectionAction;
use App\Containers\Dashboard\Actions\SubSections\DeleteSubSectionAction;
use App\Containers\Dashboard\Actions\SubSections\DetachSubSectionFromMainSectionAction;
use App\Containers\Dashboard\Actions\SubSections\ListSubSectionsAction;
use App\Containers\Dashboard\Actions\SubSections\UpdateSubSectionAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreSubSectionRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateSubSectionRequest;
use App\Containers\AppStructure\Models\MainSection;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
class SubSectionController extends Controller
{
public function __construct(
private readonly ListSubSectionsAction $listSubSectionsAction,
private readonly CreateSubSectionAction $createSubSectionAction,
private readonly UpdateSubSectionAction $updateSubSectionAction,
private readonly DeleteSubSectionAction $deleteSubSectionAction,
private readonly AttachSubSectionToMainSectionAction $attachSubSectionAction,
private readonly DetachSubSectionFromMainSectionAction $detachSubSectionAction,
private readonly AttachPageToSubSectionAction $attachPageAction,
private readonly DetachPageFromSubSectionAction $detachPageAction,
) {}
/**
* Показывает список подразделов
*/
public function index(Request $request): \Inertia\Response
{
$filters = $request->only(['search', 'main_section_id']);
$data = $this->listSubSectionsAction->run($filters);
$data['mainSections'] = MainSection::pluck('title', 'id');
return Inertia::render('Dashboard/SubSections/Index', $data);
}
/**
* Показывает форму создания подраздела
*/
public function create(): \Inertia\Response
{
$mainSections = MainSection::pluck('title', 'id');
return Inertia::render('Dashboard/SubSections/Create', [
'mainSections' => $mainSections,
]);
}
/**
* Создает новый подраздел
*/
public function store(StoreSubSectionRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createSubSectionAction->run($validated);
return redirect()->route('dashboard.sub-sections.index')
->with('success', 'Подраздел успешно создан!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании подраздела: ' . $e->getMessage());
}
}
/**
* Показывает форму редактирования подраздела
*/
public function edit(SubSection $subSection): \Inertia\Response
{
$subSection->load(['mainSection', 'pages']);
$mainSections = MainSection::pluck('title', 'id');
$availablePages = Page::whereNull('sub_section_id')
->whereNotNull('title')
->pluck('title', 'id');
return Inertia::render('Dashboard/SubSections/Edit', [
'subSection' => $subSection,
'mainSections' => $mainSections,
'availablePages' => $availablePages,
]);
}
/**
* Обновляет существующий подраздел
*/
public function update(UpdateSubSectionRequest $request, SubSection $subSection): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateSubSectionAction->run($subSection, $validated);
return redirect()->route('dashboard.sub-sections.index')
->with('success', 'Подраздел успешно обновлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении подраздела: ' . $e->getMessage());
}
}
/**
* Удаляет подраздел
*/
public function destroy(SubSection $subSection): RedirectResponse
{
try {
$this->deleteSubSectionAction->run($subSection);
return redirect()->route('dashboard.sub-sections.index')
->with('success', 'Подраздел успешно удален!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении подраздела: ' . $e->getMessage());
}
}
/**
* Прикрепляет подраздел к главному разделу
*/
public function attachToMainSection(Request $request, SubSection $subSection): RedirectResponse
{
$request->validate([
'main_section_id' => ['required', 'exists:main_sections,id'],
]);
try {
$mainSection = MainSection::findOrFail($request->main_section_id);
$this->attachSubSectionAction->run($subSection, $mainSection);
return back()->with('success', 'Подраздел прикреплен к главному разделу!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при прикреплении подраздела: ' . $e->getMessage());
}
}
/**
* Открепляет подраздел от главного раздела
*/
public function detachFromMainSection(SubSection $subSection): RedirectResponse
{
try {
$this->detachSubSectionAction->run($subSection);
return back()->with('success', 'Подраздел откреплен от главного раздела!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при откреплении подраздела: ' . $e->getMessage());
}
}
/**
* Прикрепляет страницу к подразделу
*/
public function attachPage(Request $request, SubSection $subSection): RedirectResponse
{
$request->validate([
'page_id' => ['required', 'exists:pages,id'],
]);
try {
$page = Page::findOrFail($request->page_id);
$this->attachPageAction->run($page, $subSection);
return back()->with('success', 'Страница прикреплена к подразделу!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при прикреплении страницы: ' . $e->getMessage());
}
}
/**
* Открепляет страницу от подраздела
*/
public function detachPage(SubSection $subSection, Page $page): RedirectResponse
{
try {
if ($page->sub_section_id !== $subSection->id) {
abort(403, 'Страница не принадлежит этому подразделу');
}
$this->detachPageAction->run($page);
return back()->with('success', 'Страница откреплена от подраздела!');
} catch (\Exception $e) {
return back()->with('error', 'Ошибка при откреплении страницы: ' . $e->getMessage());
}
}
}
@@ -0,0 +1,26 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\UpdateSlideAction;
use App\Containers\Widget\Models\Slide;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateSlideRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;
class UpdateSlideController extends Controller
{
public function __construct(
private readonly UpdateSlideAction $updateSlideAction,
) {}
public function __invoke(UpdateSlideRequest $request, Slide $slide): JsonResponse
{
$slide = $this->updateSlideAction->run($slide, $request->validated());
return response()->json([
'success' => true,
'slide' => $slide,
]);
}
}
@@ -0,0 +1,24 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\UpdateSliderAction;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateSliderRequest;
use App\Containers\Widget\Models\Slider;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
class UpdateSliderController extends Controller
{
public function __construct(
private readonly UpdateSliderAction $updateSliderAction,
) {}
public function __invoke(UpdateSliderRequest $request, Slider $slider): RedirectResponse
{
$this->updateSliderAction->run($slider, $request->validated());
return redirect()->back()
->with('success', 'Слайдер успешно обновлен');
}
}
@@ -0,0 +1,30 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Sliders\UpdateSlidesOrderAction;
use App\Containers\Widget\Models\Slider;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
class UpdateSlidesOrderController extends Controller
{
public function __construct(
private readonly UpdateSlidesOrderAction $updateSlidesOrderAction,
) {}
public function __invoke(Request $request, Slider $slider): JsonResponse
{
$request->validate([
'slide_ids' => 'required|array',
'slide_ids.*' => 'required|integer|exists:slides,id',
]);
$this->updateSlidesOrderAction->run($slider, $request->input('slide_ids'));
return response()->json([
'success' => true,
]);
}
}
@@ -0,0 +1,96 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Schedules\UploadMultipleSchedulesAction;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Inertia\Inertia;
class UploadSchedulesController extends Controller
{
public function __construct(
private readonly UploadMultipleSchedulesAction $uploadMultipleSchedulesAction,
) {}
/**
* Показывает страницу загрузки расписаний
*/
public function create(): \Inertia\Response
{
return Inertia::render('Dashboard/Schedules/Upload');
}
/**
* Обрабатывает загрузку файлов
*/
public function store(Request $request): \Inertia\Response
{
// Получаем файлы из request (FormData с files[])
$files = $request->file('files', []);
// Если files - это один файл (не массив), преобразуем в массив
if (!is_array($files)) {
$files = [$files];
}
// Валидация каждого файла
$validator = \Illuminate\Support\Facades\Validator::make(
['files' => $files],
[
'files' => 'required|array',
'files.*' => 'required|file|mimes:pdf|max:10000',
],
[
'files.required' => 'Выберите файлы для загрузки',
'files.*.mimes' => 'Разрешены только PDF файлы',
'files.*.max' => 'Размер файла не должен превышать 10MB',
]
);
if ($validator->fails()) {
return Inertia::render('Dashboard/Schedules/Upload', [
'flash' => [
'message' => $validator->errors()->first(),
'type' => 'error',
],
])->withInput();
}
if (empty($files)) {
return Inertia::render('Dashboard/Schedules/Upload', [
'flash' => [
'message' => 'Нет файлов для обработки',
'type' => 'error',
],
]);
}
$result = $this->uploadMultipleSchedulesAction->run($files);
$hasProcessed = $result['processed_count'] > 0;
$hasFailed = $result['failed_count'] > 0;
$message = '';
$messageType = 'success';
if ($hasProcessed && $hasFailed) {
$message = "Успешно: {$result['processed_count']}. Ошибки: {$result['failed_count']}.";
$messageType = 'warning';
} elseif ($hasProcessed) {
$message = "Успешно загружено: {$result['processed_count']} файл(ов)";
$messageType = 'success';
} elseif ($hasFailed) {
$message = "Ошибки при обработке: {$result['failed_count']} файл(ов)";
$messageType = 'error';
}
return Inertia::render('Dashboard/Schedules/Upload', [
'flash' => [
'message' => $message,
'type' => $messageType,
],
'data' => $result,
]);
}
}
@@ -0,0 +1,160 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\Users\CreateUserAction;
use App\Containers\Dashboard\Actions\Users\DeleteUserAction;
use App\Containers\Dashboard\Actions\Users\InviteUserAction;
use App\Containers\Dashboard\Actions\Users\ListUsersAction;
use App\Containers\Dashboard\Actions\Users\UpdateUserAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreUserRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateUserRequest;
use App\Containers\User\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
class UserController extends Controller
{
public function __construct(
private readonly ListUsersAction $listUsersAction,
private readonly CreateUserAction $createUserAction,
private readonly UpdateUserAction $updateUserAction,
private readonly DeleteUserAction $deleteUserAction,
private readonly InviteUserAction $inviteUserAction,
) {}
/**
* Display a listing of users
*/
public function index(Request $request): Response
{
$filters = $request->only(['search', 'role_id']);
$data = $this->listUsersAction->run($filters);
return Inertia::render('Dashboard/Users/Index', $data);
}
/**
* Show the form for creating a new user
*/
public function create(): Response
{
$data = $this->listUsersAction->run([]);
return Inertia::render('Dashboard/Users/Create', [
'roles' => $data['roles'],
]);
}
/**
* Store a newly created user
*/
public function store(StoreUserRequest $request): RedirectResponse
{
try {
$validated = $request->validated();
$this->createUserAction->run($validated);
return redirect()->route('dashboard.users.index')
->with('success', 'Пользователь успешно создан!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при создании пользователя: ' . $e->getMessage());
}
}
/**
* Show the form for editing the specified user
*/
public function edit(User $user): Response
{
$user->load(['roles', 'permissions', 'userDetail']);
$data = $this->listUsersAction->run([]);
return Inertia::render('Dashboard/Users/Edit', [
'user' => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
'slug' => $user->slug,
'roles' => $user->roles->map(fn($role) => [
'id' => $role->id,
'name' => $role->name,
]),
'permissions' => $user->permissions->map(fn($perm) => [
'name' => $perm->name,
]),
'user_detail' => $user->userDetail,
'created_at' => $user->created_at,
'updated_at' => $user->updated_at,
],
'roles' => $data['roles']->map(fn($role) => [
'id' => $role->id,
'name' => $role->name,
]),
'permissions' => $data['roles']->flatMap(function ($role) {
return $role->permissions;
})->unique('name')->values(),
]);
}
/**
* Update the specified user
*/
public function update(UpdateUserRequest $request, User $user): RedirectResponse
{
try {
$validated = $request->validated();
$this->updateUserAction->run($user, $validated);
return redirect()->route('dashboard.users.edit', $user->id)
->with('success', 'Пользователь успешно обновлен!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении пользователя: ' . $e->getMessage());
}
}
/**
* Remove the specified user
*/
public function destroy(User $user): RedirectResponse
{
try {
$this->deleteUserAction->run($user);
return redirect()->route('dashboard.users.index')
->with('success', 'Пользователь успешно удален!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении пользователя: ' . $e->getMessage());
}
}
/**
* Invite a new user via email
*/
public function invite(Request $request): RedirectResponse
{
$request->validate([
'email' => ['required', 'email', 'max:255'],
]);
$result = $this->inviteUserAction->run($request->email, auth()->id());
if ($result['success']) {
return back()->with('success', $result['message']);
}
return back()->with('error', $result['message']);
}
}
@@ -0,0 +1,165 @@
<?php
namespace App\Containers\Dashboard\UI\WEB\Controllers;
use App\Containers\Dashboard\Actions\UserDetails\CreateUserDetailAction;
use App\Containers\Dashboard\Actions\UserDetails\DeleteUserDetailAction;
use App\Containers\Dashboard\Actions\UserDetails\UpdateUserDetailAction;
use App\Containers\Dashboard\UI\WEB\Requests\StoreUserDetailRequest;
use App\Containers\Dashboard\UI\WEB\Requests\UpdateUserDetailRequest;
use App\Containers\User\Models\User;
use App\Containers\User\Models\UserDetail;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;
class UserDetailController extends Controller
{
public function __construct(
private readonly CreateUserDetailAction $createUserDetailAction,
private readonly UpdateUserDetailAction $updateUserDetailAction,
private readonly DeleteUserDetailAction $deleteUserDetailAction,
) {}
/**
* Show the form for creating user detail
*/
public function create(User $user): Response
{
return Inertia::render('Dashboard/Users/UserDetail/Create', [
'user' => $user->only(['id', 'name', 'email']),
]);
}
/**
* Store a newly created user detail
*/
public function store(StoreUserDetailRequest $request, User $user): RedirectResponse
{
try {
$validated = $request->validated();
// Обработка загруженного фото
if ($request->hasFile('photo')) {
$validated['photo'] = $this->handlePhotoUpload($request->file('photo'));
}
// Декодирование JSON полей
$validated = $this->decodeJsonFields($validated);
$this->createUserDetailAction->run($user->id, $validated);
return redirect()->route('dashboard.users.edit', $user->id)
->with('success', 'Детальная информация успешно добавлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при добавлении информации: ' . $e->getMessage());
}
}
/**
* Show the form for editing user detail
*/
public function edit(User $user, UserDetail $userDetail): Response
{
// Проверяем принадлежность userDetail к user
if ($userDetail->user_id !== $user->id) {
abort(403, 'Unauthorized access.');
}
return Inertia::render('Dashboard/Users/UserDetail/Edit', [
'user' => $user->only(['id', 'name', 'email']),
'userDetail' => $userDetail,
]);
}
/**
* Update the specified user detail
*/
public function update(UpdateUserDetailRequest $request, User $user, UserDetail $userDetail): RedirectResponse
{
// Проверяем принадлежность userDetail к user
if ($userDetail->user_id !== $user->id) {
abort(403, 'Unauthorized access.');
}
try {
$validated = $request->validated();
// Обработка загруженного фото
if ($request->hasFile('photo')) {
$validated['photo'] = $this->handlePhotoUpload($request->file('photo'));
}
// Декодирование JSON полей
$validated = $this->decodeJsonFields($validated);
$this->updateUserDetailAction->run($userDetail, $validated);
return redirect()->route('dashboard.users.edit', $user->id)
->with('success', 'Детальная информация успешно обновлена!');
} catch (\Exception $e) {
return back()
->withInput()
->with('error', 'Ошибка при обновлении информации: ' . $e->getMessage());
}
}
/**
* Remove the specified user detail
*/
public function destroy(User $user, UserDetail $userDetail): RedirectResponse
{
// Проверяем принадлежность userDetail к user
if ($userDetail->user_id !== $user->id) {
abort(403, 'Unauthorized access.');
}
try {
$this->deleteUserDetailAction->run($userDetail);
return redirect()->route('dashboard.users.edit', $user->id)
->with('success', 'Детальная информация успешно удалена!');
} catch (\Exception $e) {
return back()
->with('error', 'Ошибка при удалении информации: ' . $e->getMessage());
}
}
/**
* Handle photo upload and return file path
*/
private function handlePhotoUpload($file): string
{
$path = $file->store('images', 'public');
return $path;
}
/**
* Decode JSON fields from request data
*/
private function decodeJsonFields(array $data): array
{
$jsonFields = [
'workExperience',
'education',
'professionalRetraining',
'professionalDevelopment',
'awards',
'professDisciplines',
'attendedConferences',
'publications',
'other',
];
foreach ($jsonFields as $field) {
if (isset($data[$field]) && is_string($data[$field])) {
$data[$field] = json_decode($data[$field], true);
}
}
return $data;
}
}