From 12441517f68f379f52c4a11d3d4ca0f627520d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Cmit=20Tun=C3=A7?= Date: Thu, 1 Jan 2026 10:54:38 +0300 Subject: [PATCH] Add Custom Header and Footer Blade Selection: Implemented options for selecting custom Blade files for header and footer templates in the Page settings. Enhanced the PageController to render these templates dynamically, improving modularity and user experience. Updated relevant views to support this new functionality, ensuring better localization and flexibility in template management. --- .../Sections/FooterTemplateSection.php | 28 ++ .../Sections/HeaderTemplateSection.php | 28 ++ .../Schemas/Sections/PageSettingsSection.php | 7 +- .../Tables/ProductCategoriesTable.php | 6 +- .../Products/Schemas/ProductForm.php | 14 + .../Products/Tables/ProductsTable.php | 4 +- app/Http/Controllers/PageController.php | 257 ++++++++++-------- app/Http/Controllers/ProductController.php | 62 ++++- app/Models/Page.php | 2 + config/livewire.php | 2 +- ...tom_header_footer_blade_to_pages_table.php | 29 ++ .../views/components/custom/menu.blade.php | 100 +------ .../views/components/front/footer.blade.php | 79 ++++++ .../views/components/front/header.blade.php | 93 +++++++ .../components/front/menu-item.blade.php | 55 ++-- resources/views/front/products/show.blade.php | 2 +- resources/views/layouts/site.blade.php | 9 +- resources/views/partials/header.blade.php | 18 +- resources/views/templates/home.blade.php | 5 + .../views/templates/home/carousel.blade.php | 43 +++ 20 files changed, 587 insertions(+), 256 deletions(-) create mode 100644 database/migrations/2026_01_01_065719_add_custom_header_footer_blade_to_pages_table.php create mode 100644 resources/views/components/front/footer.blade.php create mode 100644 resources/views/components/front/header.blade.php create mode 100644 resources/views/templates/home/carousel.blade.php diff --git a/app/Filament/Admin/Resources/Pages/Schemas/Sections/FooterTemplateSection.php b/app/Filament/Admin/Resources/Pages/Schemas/Sections/FooterTemplateSection.php index 150fb23..91f9a50 100644 --- a/app/Filament/Admin/Resources/Pages/Schemas/Sections/FooterTemplateSection.php +++ b/app/Filament/Admin/Resources/Pages/Schemas/Sections/FooterTemplateSection.php @@ -10,6 +10,8 @@ use Filament\Schemas\Components\Section; use Filament\Schemas\Components\Utilities\Get; use Filament\Schemas\Components\Utilities\Set; +use Illuminate\Support\Facades\File; + class FooterTemplateSection { public static function make(): Section @@ -17,9 +19,35 @@ class FooterTemplateSection return Section::make(__('pages.form_section_footer_template')) ->description(__('pages.form_section_footer_template_desc')) ->schema([ + Select::make('custom_footer_blade') + ->label('Custom Footer Blade') + ->options(function () { + $files = File::glob(resource_path('views/partials/*.blade.php')); + $options = []; + foreach ($files as $file) { + $name = basename($file, '.blade.php'); + $options["partials.{$name}"] = "Partial: {$name}"; + } + + // Add other directories if needed + $componentFiles = File::glob(resource_path('views/components/front/*.blade.php')); + foreach ($componentFiles as $file) { + $name = basename($file, '.blade.php'); + $options["components.front.{$name}"] = "Component: {$name}"; + } + + return $options; + }) + ->searchable() + ->preload() + ->helperText('Select a physical Blade file to use as footer instead of a database template.') + ->live() + ->columnSpanFull(), + Select::make('footer_template_id') ->label(__('pages.footer_template_field')) ->options(FooterTemplate::where('is_active', true)->pluck('title', 'id')) + ->visible(fn (Get $get) => empty($get('custom_footer_blade'))) ->searchable() ->live() ->afterStateUpdated(function ($state, Set $set, Get $get) { diff --git a/app/Filament/Admin/Resources/Pages/Schemas/Sections/HeaderTemplateSection.php b/app/Filament/Admin/Resources/Pages/Schemas/Sections/HeaderTemplateSection.php index 4c2ec67..4d62140 100644 --- a/app/Filament/Admin/Resources/Pages/Schemas/Sections/HeaderTemplateSection.php +++ b/app/Filament/Admin/Resources/Pages/Schemas/Sections/HeaderTemplateSection.php @@ -10,6 +10,8 @@ use Filament\Schemas\Components\Section; use Filament\Schemas\Components\Utilities\Get; use Filament\Schemas\Components\Utilities\Set; +use Illuminate\Support\Facades\File; + class HeaderTemplateSection { public static function make(): Section @@ -17,9 +19,35 @@ class HeaderTemplateSection return Section::make(__('pages.form_section_header_template')) ->description(__('pages.form_section_header_template_desc')) ->schema([ + Select::make('custom_header_blade') + ->label('Custom Header Blade') + ->options(function () { + $files = File::glob(resource_path('views/partials/*.blade.php')); + $options = []; + foreach ($files as $file) { + $name = basename($file, '.blade.php'); + $options["partials.{$name}"] = "Partial: {$name}"; + } + + // Add other directories if needed + $componentFiles = File::glob(resource_path('views/components/front/*.blade.php')); + foreach ($componentFiles as $file) { + $name = basename($file, '.blade.php'); + $options["components.front.{$name}"] = "Component: {$name}"; + } + + return $options; + }) + ->searchable() + ->preload() + ->helperText('Select a physical Blade file to use as header instead of a database template.') + ->live() + ->columnSpanFull(), + Select::make('header_template_id') ->label(__('pages.header_template_field')) ->options(HeaderTemplate::where('is_active', true)->pluck('title', 'id')) + ->visible(fn (Get $get) => empty($get('custom_header_blade'))) ->searchable() ->live() ->afterStateUpdated(function ($state, Set $set, Get $get) { diff --git a/app/Filament/Admin/Resources/Pages/Schemas/Sections/PageSettingsSection.php b/app/Filament/Admin/Resources/Pages/Schemas/Sections/PageSettingsSection.php index d6ccec4..fadba52 100644 --- a/app/Filament/Admin/Resources/Pages/Schemas/Sections/PageSettingsSection.php +++ b/app/Filament/Admin/Resources/Pages/Schemas/Sections/PageSettingsSection.php @@ -69,13 +69,14 @@ class PageSettingsSection 'landing' => __('pages.template_landing'), 'blog' => __('pages.template_blog'), 'contact' => __('pages.template_contact'), + 'home' => 'Home', ]) ->default('default') ->columnSpanFull(), - TextInput::make('sort_order') - ->label(__('pages.sort_order_field')) - ->numeric() + TextInput::make('sort_order') + ->label(__('pages.sort_order_field')) + ->numeric() ->default(0) ->helperText(__('pages.sort_order_helper_text')) ->columnSpanFull(), diff --git a/app/Filament/Admin/Resources/ProductCategories/Tables/ProductCategoriesTable.php b/app/Filament/Admin/Resources/ProductCategories/Tables/ProductCategoriesTable.php index ca4299a..05f81dd 100644 --- a/app/Filament/Admin/Resources/ProductCategories/Tables/ProductCategoriesTable.php +++ b/app/Filament/Admin/Resources/ProductCategories/Tables/ProductCategoriesTable.php @@ -18,14 +18,14 @@ class ProductCategoriesTable ->columns([ TextColumn::make('title') ->label(__('product_categories.title')) - ->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state) + ->formatStateUsing(fn ($state, $record) => $record->translate('title')) ->searchable() ->sortable(), TextColumn::make('slug') ->label(__('product_categories.slug')) ->searchable(), - TextColumn::make('parent.title') // This might fail if parent title is JSON - ->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state) + TextColumn::make('parent.title') + ->formatStateUsing(fn ($state, $record) => $record->parent?->translate('title')) ->label(__('product_categories.parent')), TextColumn::make('sort_order') ->label(__('product_categories.sort_order')) diff --git a/app/Filament/Admin/Resources/Products/Schemas/ProductForm.php b/app/Filament/Admin/Resources/Products/Schemas/ProductForm.php index d593e84..2af3c63 100644 --- a/app/Filament/Admin/Resources/Products/Schemas/ProductForm.php +++ b/app/Filament/Admin/Resources/Products/Schemas/ProductForm.php @@ -10,6 +10,9 @@ use Filament\Forms\Components\FileUpload; use Filament\Schemas\Components\Section; use App\Filament\Admin\Resources\Components\TranslationTabs; use App\Models\ProductCategory; +use Illuminate\Support\Str; +use Filament\Forms\Get; +use Filament\Forms\Set; class ProductForm { @@ -19,6 +22,16 @@ class ProductForm ->schema([ Section::make(__('products.general_section')) ->schema([ + TextInput::make('title') + ->label(__('products.title')) + ->required() + ->live(onBlur: true) + ->afterStateUpdated(function (Get $get, Set $set, ?string $state) { + $set('slug', Str::slug($state)); + $set('translations.' . app()->getLocale() . '.title', $state); + }) + ->formatStateUsing(fn ($record) => $record?->translate('title')) + ->dehydrated(false), TextInput::make('slug') ->label(__('products.slug')) ->required() @@ -41,6 +54,7 @@ class ProductForm FileUpload::make('hero_image') ->label(__('products.hero_image')) ->image() + ->disk('public') ->directory('products'), TextInput::make('view_template') ->label(__('products.view_template')) diff --git a/app/Filament/Admin/Resources/Products/Tables/ProductsTable.php b/app/Filament/Admin/Resources/Products/Tables/ProductsTable.php index 94e5645..76f2d8e 100644 --- a/app/Filament/Admin/Resources/Products/Tables/ProductsTable.php +++ b/app/Filament/Admin/Resources/Products/Tables/ProductsTable.php @@ -21,7 +21,7 @@ class ProductsTable ->label(__('products.hero_image')), TextColumn::make('title') ->label(__('products.title')) - ->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state) + ->formatStateUsing(fn ($state, $record) => $record->translate('title')) ->searchable() ->sortable(), TextColumn::make('type') @@ -38,7 +38,7 @@ class ProductsTable default => $state, }), TextColumn::make('category.title') - ->formatStateUsing(fn ($state) => is_array($state) ? ($state[app()->getLocale()] ?? reset($state)) : $state) + ->formatStateUsing(fn ($state, $record) => $record->category?->translate('title')) ->label(__('products.category')), ToggleColumn::make('is_active') ->label(__('products.is_active')), diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index 9621edd..3b81bdb 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -143,52 +143,66 @@ class PageController extends Controller // Render Header Template $renderedHeader = null; - $headerTemplate = $page->headerTemplate; - - // Eğer sayfa için header seçilmemişse, en son aktif header template'i kullan - if (!$headerTemplate) { - $defaultHeaderId = $settings->default_header ?? null; - if ($defaultHeaderId) { - $headerTemplate = HeaderTemplate::find($defaultHeaderId); - } - } - - if ($headerTemplate) { - // Merge template defaults with page data (page data overrides defaults) - $templateDefaults = $headerTemplate->default_data ?? []; - $pageData = $page->header_data ?? []; - $mergedHeaderData = array_merge($templateDefaults, $pageData); + + // 1. Önce özel blade dosyası var mı kontrol et + if (!empty($page->custom_header_blade) && view()->exists($page->custom_header_blade)) { + $renderedHeader = view($page->custom_header_blade, ['page' => $page])->render(); + } else { + // 2. Yoksa Header Template sistemini kullan + $headerTemplate = $page->headerTemplate; - $renderedHeader = TemplateService::replacePlaceholders( - $headerTemplate->html_content, - $mergedHeaderData, - $page - ); + // Eğer sayfa için header seçilmemişse, en son aktif header template'i kullan + if (!$headerTemplate) { + $defaultHeaderId = $settings->default_header ?? null; + if ($defaultHeaderId) { + $headerTemplate = HeaderTemplate::find($defaultHeaderId); + } + } + + if ($headerTemplate) { + // Merge template defaults with page data (page data overrides defaults) + $templateDefaults = $headerTemplate->default_data ?? []; + $pageData = $page->header_data ?? []; + $mergedHeaderData = array_merge($templateDefaults, $pageData); + + $renderedHeader = TemplateService::replacePlaceholders( + $headerTemplate->html_content, + $mergedHeaderData, + $page + ); + } } // Render Footer Template $renderedFooter = null; - $footerTemplate = $page->footerTemplate; - - // Eğer sayfa için footer seçilmemişse, en son aktif footer template'i kullan - if (!$footerTemplate) { - $defaultFooterId = $settings->default_footer ?? null; - if ($defaultFooterId) { - $footerTemplate = FooterTemplate::find($defaultFooterId); - } - } - - if ($footerTemplate) { - // Merge template defaults with page data (page data overrides defaults) - $templateDefaults = $footerTemplate->default_data ?? []; - $pageData = $page->footer_data ?? []; - $mergedFooterData = array_merge($templateDefaults, $pageData); + + // 1. Önce özel blade dosyası var mı kontrol et + if (!empty($page->custom_footer_blade) && view()->exists($page->custom_footer_blade)) { + $renderedFooter = view($page->custom_footer_blade, ['page' => $page])->render(); + } else { + // 2. Yoksa Footer Template sistemini kullan + $footerTemplate = $page->footerTemplate; - $renderedFooter = TemplateService::replacePlaceholders( - $footerTemplate->html_content, - $mergedFooterData, - $page - ); + // Eğer sayfa için footer seçilmemişse, en son aktif footer template'i kullan + if (!$footerTemplate) { + $defaultFooterId = $settings->default_footer ?? null; + if ($defaultFooterId) { + $footerTemplate = FooterTemplate::find($defaultFooterId); + } + } + + if ($footerTemplate) { + // Merge template defaults with page data (page data overrides defaults) + $templateDefaults = $footerTemplate->default_data ?? []; + $pageData = $page->footer_data ?? []; + $mergedFooterData = array_merge($templateDefaults, $pageData); + + $renderedFooter = TemplateService::replacePlaceholders( + $footerTemplate->html_content, + $mergedFooterData, + $page + ); + } } return view($view, [ @@ -240,37 +254,48 @@ class PageController extends Controller $renderedFooter = null; if ($page) { - // Render Header Template - $headerTemplate = $page->headerTemplate; - if (!$headerTemplate) { - $defaultHeaderId = $settings->default_header ?? null; - if ($defaultHeaderId) { - $headerTemplate = HeaderTemplate::find($defaultHeaderId); - } - } - - if ($headerTemplate) { - $templateDefaults = $headerTemplate->default_data ?? []; - $pageData = $page->header_data ?? []; - $mergedHeaderData = array_merge($templateDefaults, $pageData); - $renderedHeader = TemplateService::replacePlaceholders($headerTemplate->html_content, $mergedHeaderData, $page); + // 1. Önce özel blade dosyası var mı kontrol et + if (!empty($page->custom_header_blade) && view()->exists($page->custom_header_blade)) { + $renderedHeader = view($page->custom_header_blade, ['page' => $page])->render(); + } else { + // 2. Yoksa Header Template sistemini kullan + $headerTemplate = $page->headerTemplate; + if (!$headerTemplate) { + $defaultHeaderId = $settings->default_header ?? null; + if ($defaultHeaderId) { + $headerTemplate = HeaderTemplate::find($defaultHeaderId); + } + } + + if ($headerTemplate) { + $templateDefaults = $headerTemplate->default_data ?? []; + $pageData = $page->header_data ?? []; + $mergedHeaderData = array_merge($templateDefaults, $pageData); + $renderedHeader = TemplateService::replacePlaceholders($headerTemplate->html_content, $mergedHeaderData, $page); + } } - // Render Footer Template - $footerTemplate = $page->footerTemplate; - - if (!$footerTemplate) { - $defaultFooterId = $settings->default_footer ?? null; - if ($defaultFooterId) { - $footerTemplate = FooterTemplate::find($defaultFooterId); - } - } - - if ($footerTemplate) { - $templateDefaults = $footerTemplate->default_data ?? []; - $pageData = $page->footer_data ?? []; - $mergedFooterData = array_merge($templateDefaults, $pageData); - $renderedFooter = TemplateService::replacePlaceholders($footerTemplate->html_content, $mergedFooterData, $page); + // Footer Render + // 1. Önce özel blade dosyası var mı kontrol et + if (!empty($page->custom_footer_blade) && view()->exists($page->custom_footer_blade)) { + $renderedFooter = view($page->custom_footer_blade, ['page' => $page])->render(); + } else { + // 2. Yoksa Footer Template sistemini kullan + $footerTemplate = $page->footerTemplate; + + if (!$footerTemplate) { + $defaultFooterId = $settings->default_footer ?? null; + if ($defaultFooterId) { + $footerTemplate = FooterTemplate::find($defaultFooterId); + } + } + + if ($footerTemplate) { + $templateDefaults = $footerTemplate->default_data ?? []; + $pageData = $page->footer_data ?? []; + $mergedFooterData = array_merge($templateDefaults, $pageData); + $renderedFooter = TemplateService::replacePlaceholders($footerTemplate->html_content, $mergedFooterData, $page); + } } } @@ -324,52 +349,66 @@ class PageController extends Controller // Render Header Template $renderedHeader = null; - $headerTemplate = $page->headerTemplate; - - // Eğer sayfa için header seçilmemişse, en son aktif header template'i kullan - if (!$headerTemplate) { - $defaultHeaderId = $settings->default_header ?? null; - if ($defaultHeaderId) { - $headerTemplate = HeaderTemplate::find($defaultHeaderId); - } - } - - if ($headerTemplate) { - // Merge template defaults with page data (page data overrides defaults) - $templateDefaults = $headerTemplate->default_data ?? []; - $pageData = $page->header_data ?? []; - $mergedHeaderData = array_merge($templateDefaults, $pageData); + + // 1. Önce özel blade dosyası var mı kontrol et + if (!empty($page->custom_header_blade) && view()->exists($page->custom_header_blade)) { + $renderedHeader = view($page->custom_header_blade, ['page' => $page])->render(); + } else { + // 2. Yoksa Header Template sistemini kullan + $headerTemplate = $page->headerTemplate; - $renderedHeader = TemplateService::replacePlaceholders( - $headerTemplate->html_content, - $mergedHeaderData, - $page - ); + // Eğer sayfa için header seçilmemişse, en son aktif header template'i kullan + if (!$headerTemplate) { + $defaultHeaderId = $settings->default_header ?? null; + if ($defaultHeaderId) { + $headerTemplate = HeaderTemplate::find($defaultHeaderId); + } + } + + if ($headerTemplate) { + // Merge template defaults with page data (page data overrides defaults) + $templateDefaults = $headerTemplate->default_data ?? []; + $pageData = $page->header_data ?? []; + $mergedHeaderData = array_merge($templateDefaults, $pageData); + + $renderedHeader = TemplateService::replacePlaceholders( + $headerTemplate->html_content, + $mergedHeaderData, + $page + ); + } } // Render Footer Template $renderedFooter = null; - $footerTemplate = $page->footerTemplate; - - // Eğer sayfa için footer seçilmemişse, en son aktif footer template'i kullan - if (!$footerTemplate) { - $defaultFooterId = $settings->default_footer ?? null; - if ($defaultFooterId) { - $footerTemplate = FooterTemplate::find($defaultFooterId); - } - } - - if ($footerTemplate) { - // Merge template defaults with page data (page data overrides defaults) - $templateDefaults = $footerTemplate->default_data ?? []; - $pageData = $page->footer_data ?? []; - $mergedFooterData = array_merge($templateDefaults, $pageData); + + // 1. Önce özel blade dosyası var mı kontrol et + if (!empty($page->custom_footer_blade) && view()->exists($page->custom_footer_blade)) { + $renderedFooter = view($page->custom_footer_blade, ['page' => $page])->render(); + } else { + // 2. Yoksa Footer Template sistemini kullan + $footerTemplate = $page->footerTemplate; - $renderedFooter = TemplateService::replacePlaceholders( - $footerTemplate->html_content, - $mergedFooterData, - $page - ); + // Eğer sayfa için footer seçilmemişse, en son aktif footer template'i kullan + if (!$footerTemplate) { + $defaultFooterId = $settings->default_footer ?? null; + if ($defaultFooterId) { + $footerTemplate = FooterTemplate::find($defaultFooterId); + } + } + + if ($footerTemplate) { + // Merge template defaults with page data (page data overrides defaults) + $templateDefaults = $footerTemplate->default_data ?? []; + $pageData = $page->footer_data ?? []; + $mergedFooterData = array_merge($templateDefaults, $pageData); + + $renderedFooter = TemplateService::replacePlaceholders( + $footerTemplate->html_content, + $mergedFooterData, + $page + ); + } } return view($view, [ diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 66f8c8b..f878c34 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -3,6 +3,10 @@ namespace App\Http\Controllers; use App\Models\Product; +use App\Models\Setting; +use App\Models\HeaderTemplate; +use App\Models\FooterTemplate; +use App\Services\TemplateService; use Illuminate\Http\Request; class ProductController extends Controller @@ -13,11 +17,61 @@ class ProductController extends Controller ->where('is_active', true) ->with('category') ->firstOrFail(); - - if ($product->view_template && view()->exists($product->view_template)) { - return view($product->view_template, compact('product')); + + // Get Settings + $settings = new \stdClass(); + $allSettings = Setting::where('is_active', true)->get(); + foreach ($allSettings as $setting) { + $settings->{$setting->key} = $setting->value; } - return view('front.products.show', compact('product')); + // --- Header Logic --- + $renderedHeader = null; + $defaultHeaderId = $settings->default_header ?? null; + + if ($defaultHeaderId) { + $headerTemplate = HeaderTemplate::find($defaultHeaderId); + if ($headerTemplate) { + $templateDefaults = $headerTemplate->default_data ?? []; + $productData = []; // Ürünlere özel header datası eklenebilir + $mergedHeaderData = array_merge($templateDefaults, $productData); + + $renderedHeader = TemplateService::replacePlaceholders( + $headerTemplate->html_content, + $mergedHeaderData, + $product // Model context + ); + } + } + + // --- Footer Logic --- + $renderedFooter = null; + $defaultFooterId = $settings->default_footer ?? null; + + if ($defaultFooterId) { + $footerTemplate = FooterTemplate::find($defaultFooterId); + if ($footerTemplate) { + $templateDefaults = $footerTemplate->default_data ?? []; + $productData = []; // Ürünlere özel footer datası eklenebilir + $mergedFooterData = array_merge($templateDefaults, $productData); + + $renderedFooter = TemplateService::replacePlaceholders( + $footerTemplate->html_content, + $mergedFooterData, + $product // Model context + ); + } + } + + $meta = [ + 'title' => $product->translate('title'), + 'description' => \Str::limit(strip_tags($product->translate('content')), 160), + ]; + + if ($product->view_template && view()->exists($product->view_template)) { + return view($product->view_template, compact('product', 'settings', 'renderedHeader', 'renderedFooter', 'meta')); + } + + return view('front.products.show', compact('product', 'settings', 'renderedHeader', 'renderedFooter', 'meta')); } } diff --git a/app/Models/Page.php b/app/Models/Page.php index 983657f..eec6984 100644 --- a/app/Models/Page.php +++ b/app/Models/Page.php @@ -34,8 +34,10 @@ class Page extends Model // Template System 'header_template_id', 'header_data', + 'custom_header_blade', 'footer_template_id', 'footer_data', + 'custom_footer_blade', 'sections_data', ]; diff --git a/config/livewire.php b/config/livewire.php index f52ed46..908b9e6 100644 --- a/config/livewire.php +++ b/config/livewire.php @@ -64,7 +64,7 @@ return [ */ 'temporary_file_upload' => [ - 'disk' => 'uploads', // Example: 'local', 's3' | Default: 'default' + 'disk' => 'public', // Example: 'local', 's3' | Default: 'default' 'rules' => null, // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB) 'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp' 'middleware' => null, // Example: 'throttle:5,1' | Default: 'throttle:60,1' diff --git a/database/migrations/2026_01_01_065719_add_custom_header_footer_blade_to_pages_table.php b/database/migrations/2026_01_01_065719_add_custom_header_footer_blade_to_pages_table.php new file mode 100644 index 0000000..95c9d7e --- /dev/null +++ b/database/migrations/2026_01_01_065719_add_custom_header_footer_blade_to_pages_table.php @@ -0,0 +1,29 @@ +string('custom_header_blade')->nullable()->after('header_data'); + $table->string('custom_footer_blade')->nullable()->after('footer_data'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('pages', function (Blueprint $table) { + $table->dropColumn(['custom_header_blade', 'custom_footer_blade']); + }); + } +}; diff --git a/resources/views/components/custom/menu.blade.php b/resources/views/components/custom/menu.blade.php index 17e213d..42c6bad 100644 --- a/resources/views/components/custom/menu.blade.php +++ b/resources/views/components/custom/menu.blade.php @@ -22,105 +22,7 @@ $menuItems = \App\Models\Page::with(['children' => function ($query) { @if($menuItems->isNotEmpty()) @endif diff --git a/resources/views/components/front/footer.blade.php b/resources/views/components/front/footer.blade.php new file mode 100644 index 0000000..16941cd --- /dev/null +++ b/resources/views/components/front/footer.blade.php @@ -0,0 +1,79 @@ + diff --git a/resources/views/components/front/header.blade.php b/resources/views/components/front/header.blade.php new file mode 100644 index 0000000..76a85b0 --- /dev/null +++ b/resources/views/components/front/header.blade.php @@ -0,0 +1,93 @@ +@php +// Get menu items from Pages with nested children +$menuItems = \App\Models\Page::with(['children' => function ($query) { + $query->where('status', 'published') + ->where('show_in_menu', true) + ->orderBy('sort_order', 'asc') + ->orderBy('title', 'asc'); + }, 'children.children' => function ($query) { + $query->where('status', 'published') + ->where('show_in_menu', true) + ->orderBy('sort_order', 'asc') + ->orderBy('title', 'asc'); + }]) + ->whereNull('parent_id') + ->where('status', 'published') + ->where('show_in_menu', true) + ->orderBy('sort_order', 'asc') + ->orderBy('title', 'asc') + ->get(); + +$midPoint = ceil($menuItems->count() / 2); +$leftMenuItems = $menuItems->slice(0, $midPoint); +$rightMenuItems = $menuItems->slice($midPoint); +@endphp +
+ + +
diff --git a/resources/views/components/front/menu-item.blade.php b/resources/views/components/front/menu-item.blade.php index 2f21a45..c007895 100644 --- a/resources/views/components/front/menu-item.blade.php +++ b/resources/views/components/front/menu-item.blade.php @@ -4,11 +4,11 @@ $hasChildren = $item->children->isNotEmpty(); $isMegaMenu = $item->slug === 'urunlerimiz'; - $productCategories = []; + $categories = []; + $services = []; if($isMegaMenu) { - $productCategories = \App\Models\ProductCategory::with(['products' => function($q) { - $q->where('is_active', true)->orderBy('sort_order'); - }])->where('is_active', true)->orderBy('sort_order')->get(); + $categories = \App\Models\ProductCategory::where('is_active', true)->orderBy('sort_order')->get(); + $services = \App\Models\Product::where('is_active', true)->orderBy('sort_order')->limit(10)->get(); } @endphp @@ -18,27 +18,38 @@