added feature for binding form to page and fixing bugs
This commit is contained in:
@@ -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',
|
||||||
));
|
));
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -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();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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'];
|
||||||
|
|||||||
+28
@@ -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,6 +46,9 @@ export default {
|
|||||||
},
|
},
|
||||||
seo: {
|
seo: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -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
-1
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user