added feature for binding form to page and fixing bugs

This commit is contained in:
F4ilji
2025-04-22 21:15:03 +05:00
parent aea6304ac4
commit 45c84e7ffb
12 changed files with 107 additions and 9 deletions
@@ -5,6 +5,7 @@ namespace App\Filament\Components\Forms;
use App\Enums\CustomFormStatus; use App\Enums\CustomFormStatus;
use App\Enums\PostStatus; use App\Enums\PostStatus;
use App\Filament\Components\Forms\ItemForm\Pages\ContentBuilderItem; use App\Filament\Components\Forms\ItemForm\Pages\ContentBuilderItem;
use App\Models\CustomForm;
use Filament\Forms; use Filament\Forms;
use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\Section; use Filament\Forms\Components\Section;
@@ -142,6 +143,12 @@ class PageForm
->label('Скрыть хлебные крошки') ->label('Скрыть хлебные крошки')
->helperText('Скрывает навигационную цепочку вверху страницы') ->helperText('Скрывает навигационную цепочку вверху страницы')
->columnSpan(1), ->columnSpan(1),
Select::make('settings.custom_form')->label('Прикрепить форму для страницы')
->searchable()
->preload()
->options(CustomForm::query()
->where('status', CustomFormStatus::PUBLISHED)->pluck('title', 'form_id'))
->columnSpanFull()
]) ])
->columns(2), ->columns(2),
]), ]),
@@ -88,7 +88,6 @@ class AdditionalEducationResource extends Resource
TextInput::make('qualification') TextInput::make('qualification')
->label('Выдаваемый документ') ->label('Выдаваемый документ')
->required()
->maxLength(255) ->maxLength(255)
->placeholder('Например: "Удостоверение о повышении квалификации"') ->placeholder('Например: "Удостоверение о повышении квалификации"')
->columnSpanFull() ->columnSpanFull()
@@ -141,11 +141,18 @@ class ClientAdditionalEducationController extends Controller
fn() => $this->seoPageProvider->getSeoForModel($additionalEducationModel) fn() => $this->seoPageProvider->getSeoForModel($additionalEducationModel)
); );
if (array_key_exists('custom_form', request()->input('settings_page'))) {
$form = request()->input('settings_page')['custom_form'];
} else {
$form = null;
}
$additionalEducation = new AdditionalEducationResource($additionalEducationModel); $additionalEducation = new AdditionalEducationResource($additionalEducationModel);
return Inertia::render('Client/Additional-educations/Show', compact( return Inertia::render('Client/Additional-educations/Show', compact(
'additionalEducation', 'additionalEducation',
'seo' 'seo',
'form',
)); ));
}} }}
+1 -1
View File
@@ -49,7 +49,7 @@ class MainController extends Controller
$educations = $this->getEducationsData(); $educations = $this->getEducationsData();
$posts = Cache::remember('recent_posts', now()->addHour(), function () { $posts = Cache::remember('posts_recent', now()->addHour(), function () {
return $this->getRecentPosts(); return $this->getRecentPosts();
}); });
+2
View File
@@ -37,6 +37,7 @@ class PageController extends Controller
->first(); ->first();
}); });
if ($page === null) { if ($page === null) {
abort(404); abort(404);
} }
@@ -51,6 +52,7 @@ class PageController extends Controller
abort($page->code); abort($page->code);
} }
return Inertia::render('Page', compact('page', 'subSectionPages', 'seo')); return Inertia::render('Page', compact('page', 'subSectionPages', 'seo'));
} }
} }
+2
View File
@@ -32,6 +32,8 @@ class AccessCheck
abort($registeredRoute->code); abort($registeredRoute->code);
} }
$request->merge(['settings_page' => $registeredRoute->settings]);
// Если все проверки пройдены, продолжаем выполнение запроса // Если все проверки пройдены, продолжаем выполнение запроса
return $next($request); return $next($request);
} }
@@ -23,8 +23,9 @@ class FormTimePeriodMiddleware
abort(Response::HTTP_NOT_FOUND, 'Form not found'); abort(Response::HTTP_NOT_FOUND, 'Form not found');
} }
if (!isset($form->settings['period'])) { if (!isset($form->settings['period'])) {
abort(Response::HTTP_BAD_REQUEST, 'Invalid form settings'); return $next($request);
} }
$period = $form->settings['period']; $period = $form->settings['period'];
@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('additional_education', function (Blueprint $table) {
$table->string('qualification')->change()->nullable();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('additional_education', function (Blueprint $table) {
$table->string('qualification')->nullable(false)->change();
});
}
};
@@ -13,11 +13,15 @@ import AdditionalProgramItemBreadcrumbs
import BasicPageContainer from "@/componentss/ui/templates/BasicPageContainer.vue"; import BasicPageContainer from "@/componentss/ui/templates/BasicPageContainer.vue";
import BasicPageWrapper from "@/componentss/ui/wrappers/BasicPageWrapper.vue"; import BasicPageWrapper from "@/componentss/ui/wrappers/BasicPageWrapper.vue";
import ProgramItemBreadcrumbs from "@/componentss/features/educationalPrograms/components/ProgramItemBreadcrumbs.vue"; import ProgramItemBreadcrumbs from "@/componentss/features/educationalPrograms/components/ProgramItemBreadcrumbs.vue";
import FormBlock from "@/componentss/shared/builder/pageBuilder/blocks/FormBlock.vue";
import FormBuilder from "@/componentss/shared/builder/formBuilder/FormBuilder.vue";
export default { export default {
name: "Show", name: "Show",
components: { components: {
FormBuilder,
FormBlock,
ProgramItemBreadcrumbs, BasicPageWrapper, BasicPageContainer, ProgramItemBreadcrumbs, BasicPageWrapper, BasicPageContainer,
AdditionalProgramItemBreadcrumbs, AdditionalProgramItemBreadcrumbs,
BasicFooter, BasicFooter,
@@ -42,7 +46,10 @@ export default {
}, },
seo: { seo: {
type: Object, type: Object,
} },
form: {
type: String
}
}, },
methods: { methods: {
getFormOfStudy(contests) { getFormOfStudy(contests) {
@@ -106,7 +113,7 @@ export default {
</div> </div>
<!-- End Icon Block --> <!-- End Icon Block -->
<div class="text-center"> <div v-if="additionalEducation.data.qualification" class="text-center">
<div class="flex justify-center items-center size-12 bg-gray-50 border border-gray-200 rounded-full mx-auto"> <div class="flex justify-center items-center size-12 bg-gray-50 border border-gray-200 rounded-full mx-auto">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 size-6 text-gray-600"> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="flex-shrink-0 size-6 text-gray-600">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 0 1-1.043 3.296 3.745 3.745 0 0 1-3.296 1.043A3.745 3.745 0 0 1 12 21c-1.268 0-2.39-.63-3.068-1.593a3.746 3.746 0 0 1-3.296-1.043 3.745 3.745 0 0 1-1.043-3.296A3.745 3.745 0 0 1 3 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 0 1 1.043-3.296 3.746 3.746 0 0 1 3.296-1.043A3.746 3.746 0 0 1 12 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 0 1 3.296 1.043 3.746 3.746 0 0 1 1.043 3.296A3.745 3.745 0 0 1 21 12Z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75 11.25 15 15 9.75M21 12c0 1.268-.63 2.39-1.593 3.068a3.745 3.745 0 0 1-1.043 3.296 3.745 3.745 0 0 1-3.296 1.043A3.745 3.745 0 0 1 12 21c-1.268 0-2.39-.63-3.068-1.593a3.746 3.746 0 0 1-3.296-1.043 3.745 3.745 0 0 1-1.043-3.296A3.745 3.745 0 0 1 3 12c0-1.268.63-2.39 1.593-3.068a3.745 3.745 0 0 1 1.043-3.296 3.746 3.746 0 0 1 3.296-1.043A3.746 3.746 0 0 1 12 3c1.268 0 2.39.63 3.068 1.593a3.746 3.746 0 0 1 3.296 1.043 3.746 3.746 0 0 1 1.043 3.296A3.745 3.745 0 0 1 21 12Z" />
@@ -169,11 +176,56 @@ export default {
<Builder :blocks="additionalEducation.data.content" /> <Builder :blocks="additionalEducation.data.content" />
</div> </div>
</div> </div>
</BasicPageContainer> </BasicPageContainer>
<BasicFooter /> <BasicFooter />
</BasicPageWrapper> </BasicPageWrapper>
<div class="fixed bottom-0 end-0 z-60 sm:max-w-xl w-full mx-auto p-6">
<!-- Card -->
<div class="p-4 bg-white border border-gray-200 rounded-xl shadow-2xs dark:bg-neutral-900 dark:border-neutral-800">
<div class="flex flex-col sm:flex-row sm:items-center gap-y-3 sm:gap-y-0 sm:gap-x-5">
<div class="grow">
<h2 class="text-gray-500 dark:text-neutral-500">
Оставить заявку на курс <span class="font-semibold text-gray-800 dark:text-neutral-200">{{ additionalEducation.data.title }}</span>
</h2>
</div>
<div class="inline-flex gap-x-2">
<div>
<button type="button" class="py-2 px-3 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-600 text-white hover:bg-blue-700 focus:outline-hidden focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" aria-haspopup="dialog" aria-expanded="false" aria-controls="hs-vertically-centered-scrollable-modal" data-hs-overlay="#hs-vertically-centered-scrollable-modal">
Записаться
</button>
</div>
</div>
</div>
</div>
<!-- End Card -->
</div>
<div id="hs-vertically-centered-scrollable-modal" class="hs-overlay hidden size-full fixed top-0 start-0 z-[1000000] overflow-x-hidden overflow-y-auto pointer-events-none" role="dialog" tabindex="-1" aria-labelledby="hs-vertically-centered-scrollable-modal-label">
<div class="hs-overlay-open:mt-7 hs-overlay-open:opacity-100 hs-overlay-open:duration-500 mt-0 opacity-0 ease-out transition-all sm:max-w-3xl sm:w-full m-3 sm:mx-auto h-[calc(100%-56px)] min-h-[calc(100%-56px)] flex items-center">
<div class="w-full max-h-full overflow-hidden flex flex-col bg-white border border-gray-200 shadow-2xs rounded-xl pointer-events-auto dark:bg-neutral-800 dark:border-neutral-700 dark:shadow-neutral-700/70">
<div class="flex justify-between items-center py-3 px-4 border-gray-200 dark:border-neutral-700">
<h3 id="hs-vertically-centered-scrollable-modal-label" class="font-bold text-gray-800 dark:text-white">
</h3>
<button type="button" class="size-8 inline-flex justify-center items-center gap-x-2 rounded-full border border-transparent bg-gray-100 text-gray-800 hover:bg-gray-200 focus:outline-hidden focus:bg-gray-200 disabled:opacity-50 disabled:pointer-events-none dark:bg-neutral-700 dark:hover:bg-neutral-600 dark:text-neutral-400 dark:focus:bg-neutral-600" aria-label="Close" data-hs-overlay="#hs-vertically-centered-scrollable-modal">
<span class="sr-only">Close</span>
<svg class="shrink-0 size-4" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 6 6 18"></path>
<path d="m6 6 12 12"></path>
</svg>
</button>
</div>
<div class="p-2 overflow-y-auto">
<FormBlock :form-id="form" />
</div>
</div>
</div>
</div>
</template> </template>
<style> <style>
@@ -1,6 +1,6 @@
<template> <template>
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<div class="flex w-full sm:items-center gap-x-5 sm:gap-x-3"> <div class="flex w-full sm:items-center truncate text-ellipsis gap-x-5 sm:gap-x-3">
<div class="grow"> <div class="grow">
<div class="grid sm:flex sm:justify-between sm:items-center gap-2"> <div class="grid sm:flex sm:justify-between sm:items-center gap-2">
<BreadcrumbsWrapper v-if="breadcrumbs"> <BreadcrumbsWrapper v-if="breadcrumbs">
@@ -29,7 +29,7 @@
</h2> </h2>
</div> </div>
<!-- Card --> <!-- Card -->
<div class="mt-5 p-4 relative z-1000 bg-white border rounded-xl sm:mt-10 md:p-10"> <div class="mt-5 p-4 relative z-1000 bg-white md:border rounded-xl sm:mt-10 md:p-10">
<form @submit="submitForm"> <form @submit="submitForm">
<component <component
v-for="(block, index) in blocks.data.columns" v-for="(block, index) in blocks.data.columns"
@@ -7,7 +7,7 @@
</div> </div>
</div> </div>
<div v-else> <div v-else>
<div v-if="block.data.settings.in_modal"> <div v-if="block?.data.settings.in_modal">
<button type="button" class="w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-primary text-white hover:bg-primary-light focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" aria-haspopup="dialog" aria-expanded="false" aria-controls="hs-vertically-centered-scrollable-modal" data-hs-overlay="#hs-vertically-centered-scrollable-modal"> <button type="button" class="w-full py-3 px-4 inline-flex justify-center items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-primary text-white hover:bg-primary-light focus:outline-none focus:bg-blue-700 disabled:opacity-50 disabled:pointer-events-none" aria-haspopup="dialog" aria-expanded="false" aria-controls="hs-vertically-centered-scrollable-modal" data-hs-overlay="#hs-vertically-centered-scrollable-modal">
{{ form.data.title }} {{ form.data.title }}
</button> </button>