Add Blog functionality: Created BlogController with index and show methods, added blog views, and integrated localization for meta tags. Updated routes to include blog paths.

This commit is contained in:
Ümit Tunç
2025-10-30 15:26:11 -03:00
parent 1cd55f4a1d
commit 08e07a9e63
21 changed files with 732 additions and 27 deletions
+47
View File
@@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers;
use App\Models\Setting;
use App\Models\Post;
class BlogController extends Controller
{
public function index()
{
$settings = class_exists(Setting::class) ? (Setting::query()->first()) : null;
$posts = class_exists(Post::class)
? Post::query()->where('status', 'published')->latest('published_at')->paginate(12)
: collect();
return view('blog.index', [
'settings' => $settings,
'posts' => $posts,
'meta' => [
'title' => __('blog.meta-index-title'),
'description' => __('blog.meta-index-description'),
],
]);
}
public function show(string $slug)
{
$settings = class_exists(Setting::class) ? (Setting::query()->first()) : null;
if (!class_exists(Post::class)) {
abort(404);
}
$post = Post::query()->where('slug', $slug)->where('status', 'published')->firstOrFail();
return view('blog.show', [
'settings' => $settings,
'post' => $post,
'meta' => [
'title' => method_exists($post, 'translate') ? ($post->translate('meta_title') ?: $post->translate('title')) : ($post->meta_title ?? $post->title),
'description' => method_exists($post, 'translate') ? ($post->translate('meta_description') ?: $post->translate('excerpt')) : ($post->meta_description ?? $post->excerpt),
'image' => $post->featured_image ?? null,
],
]);
}
}
+72 -8
View File
@@ -3,6 +3,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Page; use App\Models\Page;
use App\Models\Setting;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class PageController extends Controller class PageController extends Controller
@@ -12,22 +13,63 @@ class PageController extends Controller
*/ */
public function index() public function index()
{ {
// Homepage'i bul // 1) is_homepage işaretli ve published
$page = Page::where('is_homepage', true) $page = Page::where('is_homepage', true)
->where('status', 'published') ->where('status', 'published')
->first(); ->first();
// 2) yoksa 'home' slug'ı
if (!$page) { if (!$page) {
// Homepage yoksa, view'e boş geçelim $page = Page::where('slug', 'home')
return view('home', [ ->where('status', 'published')
->first();
}
// 3) yoksa ilk published sayfa (fallback)
if (!$page) {
$page = Page::where('status', 'published')->orderByDesc('published_at')->first();
}
$settings = class_exists(Setting::class) ? (Setting::query()->first()) : null;
// Hiç sayfa yoksa: direkt home template'inin statik fallback'i ile render et
if (!$page) {
return view('templates.home', [
'page' => null, 'page' => null,
'menuItems' => $this->getMenuItems() 'settings' => $settings,
'meta' => [
'title' => $settings->default_meta_title ?? config('app.name'),
'description' => $settings->default_meta_description ?? null,
'image' => $settings->default_meta_image ?? null,
],
]); ]);
} }
return view('home', [ $metaTitle = method_exists($page, 'translate')
? ($page->translate('meta_title') ?: $page->translate('title'))
: ($page->meta_title ?? $page->title ?? null);
$metaDescription = method_exists($page, 'translate')
? ($page->translate('meta_description') ?: ($page->excerpt ?? null))
: ($page->meta_description ?? $page->excerpt ?? null);
$sections = $page->sections ?? $page->data ?? [];
$template = ($page->slug === 'home' || ($page->is_homepage ?? false))
? 'home'
: ($page->template ?? null);
$view = $template && view()->exists("templates.$template")
? "templates.$template"
: (($page->slug === 'home' || ($page->is_homepage ?? false)) ? 'templates.home' : 'templates.generic');
return view($view, [
'page' => $page, 'page' => $page,
'menuItems' => $this->getMenuItems() 'settings' => $settings,
'sections' => $sections,
'meta' => [
'title' => $metaTitle ?: ($settings->default_meta_title ?? config('app.name')),
'description' => $metaDescription ?: ($settings->default_meta_description ?? null),
'image' => $settings->default_meta_image ?? null,
],
]); ]);
} }
@@ -40,9 +82,31 @@ class PageController extends Controller
->where('status', 'published') ->where('status', 'published')
->firstOrFail(); ->firstOrFail();
return view('page', [ $settings = class_exists(Setting::class) ? (Setting::query()->first()) : null;
$metaTitle = method_exists($page, 'translate')
? ($page->translate('meta_title') ?: $page->translate('title'))
: ($page->meta_title ?? $page->title ?? null);
$metaDescription = method_exists($page, 'translate')
? ($page->translate('meta_description') ?: ($page->excerpt ?? null))
: ($page->meta_description ?? $page->excerpt ?? null);
$sections = $page->sections ?? $page->data ?? [];
$template = ($slug === 'home' || ($page->is_homepage ?? false))
? 'home'
: ($page->template ?? 'generic');
$view = view()->exists("templates.$template") ? "templates.$template" : (($slug === 'home') ? 'templates.home' : 'templates.generic');
return view($view, [
'page' => $page, 'page' => $page,
'menuItems' => $this->getMenuItems() 'settings' => $settings,
'sections' => $sections,
'meta' => [
'title' => $metaTitle ?: ($settings->default_meta_title ?? config('app.name')),
'description' => $metaDescription ?: ($settings->default_meta_description ?? null),
'image' => $settings->default_meta_image ?? null,
],
]); ]);
} }
+7
View File
@@ -1,6 +1,13 @@
<?php <?php
return [ return [
// Navigation & list
'nav-blog' => 'Blog',
'meta-index-title' => 'Blog',
'meta-index-description' => 'Latest posts',
'empty' => 'No posts yet.',
// Module labels
'title' => 'Blog Posts', 'title' => 'Blog Posts',
'navigation_label' => 'Blog', 'navigation_label' => 'Blog',
'model_label' => 'Blog Post', 'model_label' => 'Blog Post',
+7 -9
View File
@@ -1,6 +1,13 @@
<?php <?php
return [ return [
// Navigation
'nav-home' => 'Home',
'nav-about' => 'About',
'nav-services' => 'Services',
'nav-contact' => 'Contact',
// Module labels
'title' => 'Pages', 'title' => 'Pages',
'navigation_label' => 'Pages', 'navigation_label' => 'Pages',
'model_label' => 'Page', 'model_label' => 'Page',
@@ -13,15 +20,6 @@ return [
'restore' => 'Restore Page', 'restore' => 'Restore Page',
'force_delete' => 'Force Delete', 'force_delete' => 'Force Delete',
// Form fields
'title_field' => 'Title',
'slug_field' => 'URL Slug',
'content_field' => 'Content',
'meta_title_field' => 'Meta Title',
'meta_description_field' => 'Meta Description',
'status_field' => 'Status',
'published_at_field' => 'Published At',
// Form sections // Form sections
'form_section_content' => 'Content', 'form_section_content' => 'Content',
'form_section_page_settings' => 'Page Settings', 'form_section_page_settings' => 'Page Settings',
+7
View File
@@ -1,6 +1,13 @@
<?php <?php
return [ return [
// Navigation & list
'nav-blog' => 'Blog',
'meta-index-title' => 'Blog',
'meta-index-description' => 'Güncel paylaşımlarımız',
'empty' => 'Şu anda blog yazısı bulunmuyor.',
// Module labels
'title' => 'Blog Yazıları', 'title' => 'Blog Yazıları',
'navigation_label' => 'Blog', 'navigation_label' => 'Blog',
'model_label' => 'Blog Yazısı', 'model_label' => 'Blog Yazısı',
+8 -10
View File
@@ -1,6 +1,13 @@
<?php <?php
return [ return [
// Navigation
'nav-home' => 'Anasayfa',
'nav-about' => 'Hakkımızda',
'nav-services' => 'Hizmetler',
'nav-contact' => 'İletişim',
// Module labels
'title' => 'Sayfalar', 'title' => 'Sayfalar',
'navigation_label' => 'Sayfalar', 'navigation_label' => 'Sayfalar',
'model_label' => 'Sayfa', 'model_label' => 'Sayfa',
@@ -13,15 +20,6 @@ return [
'restore' => 'Sayfayı Geri Yükle', 'restore' => 'Sayfayı Geri Yükle',
'force_delete' => 'Kalıcı Olarak Sil', 'force_delete' => 'Kalıcı Olarak Sil',
// Form fields
'title_field' => 'Başlık',
'slug_field' => 'URL Yolu',
'content_field' => 'İçerik',
'meta_title_field' => 'Meta Başlık',
'meta_description_field' => 'Meta Açıklama',
'status_field' => 'Durum',
'published_at_field' => 'Yayın Tarihi',
// Form sections // Form sections
'form_section_content' => 'İçerik', 'form_section_content' => 'İçerik',
'form_section_page_settings' => 'Sayfa Ayarları', 'form_section_page_settings' => 'Sayfa Ayarları',
@@ -30,7 +28,7 @@ return [
// Form fields // Form fields
'title_field' => 'Başlık', 'title_field' => 'Başlık',
'slug_field' => 'URL Slug', 'slug_field' => 'URL Yolu',
'content_field' => 'İçerik', 'content_field' => 'İçerik',
'excerpt_field' => 'Özet', 'excerpt_field' => 'Özet',
'featured_image_field' => 'Öne Çıkan Görsel', 'featured_image_field' => 'Öne Çıkan Görsel',
+31
View File
@@ -0,0 +1,31 @@
@extends('layouts.site')
@section('content')
<section class="blog-list">
<div class="container">
<div class="grid">
@forelse($posts as $post)
<article class="card">
@if(!empty($post->featured_image))
<a href="{{ route('blog.show', $post->slug) }}">
<img src="{{ asset($post->featured_image) }}" alt="{{ method_exists($post, 'translate') ? $post->translate('title') : $post->title }}">
</a>
@endif
<h3>
<a href="{{ route('blog.show', $post->slug) }}">{{ method_exists($post, 'translate') ? $post->translate('title') : $post->title }}</a>
</h3>
<p>{{ method_exists($post, 'translate') ? $post->translate('excerpt') : ($post->excerpt ?? '') }}</p>
</article>
@empty
<p>{{ __('blog.empty') }}</p>
@endforelse
</div>
@if(method_exists($posts, 'links'))
{{ $posts->links() }}
@endif
</div>
</section>
@endsection
+17
View File
@@ -0,0 +1,17 @@
@extends('layouts.site')
@section('content')
<article class="post">
<div class="container">
<h1>{{ method_exists($post, 'translate') ? $post->translate('title') : $post->title }}</h1>
@if(!empty($post->featured_image))
<img src="{{ asset($post->featured_image) }}" alt="{{ method_exists($post, 'translate') ? $post->translate('title') : $post->title }}">
@endif
<div class="post-content">
{!! method_exists($post, 'translate') ? $post->translate('content') : ($post->content ?? '') !!}
</div>
</div>
</article>
@endsection
@@ -0,0 +1,54 @@
@props(['data' => []])
<section class="wrapper {{ $data['bg_class'] ?? 'overflow-hidden' }}">
<div class="container pt-24 xl:pt-32 lg:pt-32 md:pt-32 pb-24 xl:pb-32 lg:pb-32 md:pb-32 !text-center !relative">
@if(!empty($data['background_image']))
<div class="absolute" style="top: -7%; left: 50%; transform: translateX(-50%);">
<img src="{{ asset($data['background_image']) }}" alt="background">
</div>
@endif
<div class="flex flex-wrap mx-[-15px] !relative">
<div class="lg:w-10/12 xl:w-9/12 xxl:w-7/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
@if(!empty($data['icon']))
<div class="!mb-5">
<img class="m-[0_auto] !w-[4rem] !h-[4rem]" src="{{ asset($data['icon']) }}" alt="icon">
</div>
@endif
@if(!empty($data['title']))
<h1 class="font-semibold !leading-[1.15] xl:!text-[3.2rem] !text-[calc(1.445rem_+_2.34vw)] !mb-5">
{!! $data['title'] !!}
</h1>
@endif
@if(!empty($data['subtitle']))
<p class="lead !text-[1.2rem] !leading-[1.6] !mb-8 lg:!px-14 xl:!px-[4.5rem] xxl:!px-10">
{{ $data['subtitle'] }}
</p>
@endif
@if(!empty($data['button_text']))
<div class="flex justify-center">
<span>
<a href="{{ $data['button_url'] ?? '#' }}"
class="btn btn-lg btn-grape !text-white !bg-[#e31e24] border-[#e31e24] hover:text-white hover:bg-[#e31e24] hover:!border-[#e31e24] btn-icon btn-icon-end !rounded-[0.8rem]">
{{ $data['button_text'] }}
@if(!empty($data['button_icon']))
<i class="{{ $data['button_icon'] }}"></i>
@endif
</a>
</span>
</div>
@endif
</div>
</div>
@if(!empty($data['cta_image']))
<div class="container !text-center !mt-10">
<img class="max-w-full h-auto !relative m-[0_auto]" style="z-index: 2;" src="{{ asset($data['cta_image']) }}" alt="cta">
</div>
@endif
</div>
</section>
@@ -0,0 +1,50 @@
@props(['data' => []])
<section class="wrapper {{ $data['bg_class'] ?? '!bg-[#f0f0f8]' }}">
<div class="container py-24 xl:py-32 lg:py-32 md:py-32">
@if(!empty($data['section_title']) || !empty($data['section_subtitle']))
<div class="flex flex-wrap mx-[-15px] !mb-12 !text-center">
<div class="md:w-10/12 lg:w-9/12 xl:w-8/12 xxl:w-7/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
@if(!empty($data['section_badge']))
<h2 class="text-[0.8rem] tracking-[0.02rem] uppercase text-[#e31e24] !mb-3 !leading-[1.35]">{{ $data['section_badge'] }}</h2>
@endif
@if(!empty($data['section_title']))
<h2 class="!text-[calc(1.345rem_+_1.14vw)] font-bold !leading-[1.2] xl:!text-[2.2rem] !mb-3">
{{ $data['section_title'] }}
</h2>
@endif
@if(!empty($data['section_subtitle']))
<p class="lead text-[1.05rem] !leading-[1.6]">{{ $data['section_subtitle'] }}</p>
@endif
</div>
</div>
@endif
@if(!empty($data['features']))
<div class="flex flex-wrap mx-[-15px] xl:mx-[-20px] lg:mx-[-20px] md:mx-[-20px] !mt-[-50px]">
@foreach($data['features'] as $feature)
<div class="{{ $data['column_class'] ?? 'md:w-6/12 lg:w-4/12' }} w-full flex-[0_0_auto] xl:!px-[20px] lg:!px-[20px] md:!px-[20px] !px-[15px] max-w-full !mt-[50px]">
<div class="flex flex-row">
@if(!empty($feature['icon']))
<div>
<img src="{{ asset($feature['icon']) }}" class="!w-[2.2rem] !h-[2.2rem] !mr-4" alt="icon">
</div>
@endif
<div>
@if(!empty($feature['title']))
<h4 class="!mb-1">{{ $feature['title'] }}</h4>
@endif
@if(!empty($feature['description']))
<p class="!mb-0">{{ $feature['description'] }}</p>
@endif
</div>
</div>
</div>
@endforeach
</div>
@endif
</div>
</section>
@@ -0,0 +1,53 @@
@props(['data' => []])
<section class="wrapper {{ $data['bg_class'] ?? '!bg-[#f0f0f8]' }}">
<div class="container py-24 xl:py-32 lg:py-32 md:py-32">
@if(!empty($data['section_title']) || !empty($data['section_subtitle']))
<div class="flex flex-wrap mx-[-15px] !mb-12 !text-center">
<div class="md:w-10/12 lg:w-8/12 xl:w-7/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
@if(!empty($data['section_badge']))
<h2 class="text-[0.8rem] tracking-[0.02rem] uppercase text-[#e31e24] !mb-3 !leading-[1.35]">{{ $data['section_badge'] }}</h2>
@endif
@if(!empty($data['section_title']))
<h2 class="!text-[calc(1.345rem_+_1.14vw)] font-bold !leading-[1.2] xl:!text-[2.2rem] !mb-3">
{{ $data['section_title'] }}
</h2>
@endif
@if(!empty($data['section_subtitle']))
<p class="lead text-[1.05rem] !leading-[1.6]">{{ $data['section_subtitle'] }}</p>
@endif
</div>
</div>
@endif
@if(!empty($data['items']))
<div class="flex flex-wrap mx-[-15px] xl:mx-[-12px] lg:mx-[-12px] md:mx-[-12px] !mt-[-24px]">
@foreach($data['items'] as $item)
<div class="{{ $data['column_class'] ?? 'md:w-6/12 lg:w-4/12' }} w-full flex-[0_0_auto] xl:!px-[12px] lg:!px-[12px] md:!px-[12px] !px-[15px] max-w-full !mt-[24px]">
<figure class="!rounded-[0.8rem] !mb-6 group overflow-hidden">
<a href="{{ $item['link'] ?? '#' }}">
<img class="!rounded-[0.8rem] !transition-all !duration-[0.3s] !ease-in-out group-hover:!scale-105"
src="{{ asset($item['image']) }}"
alt="{{ $item['title'] ?? '' }}">
</a>
</figure>
@if(!empty($item['category']))
<span class="badge bg-[#e31e24] !rounded-[0.8rem] !mb-2 text-white text-[0.7rem]">{{ $item['category'] }}</span>
@endif
@if(!empty($item['title']))
<h4 class="!mb-1">
<a href="{{ $item['link'] ?? '#' }}" class="hover:text-[#e31e24]">{{ $item['title'] }}</a>
</h4>
@endif
@if(!empty($item['description']))
<p class="!mb-0">{{ $item['description'] }}</p>
@endif
</div>
@endforeach
</div>
@endif
</div>
</section>
@@ -0,0 +1,52 @@
@props(['data' => []])
<section class="wrapper overflow-hidden">
<div class="container pt-36 xl:pt-[12.5rem] lg:pt-[12.5rem] md:pt-[12.5rem] pb-24 xl:pb-32 lg:pb-32 md:pb-32 !text-center !relative">
@if(!empty($data['background_image']))
<div class="absolute" style="top: -12%; left: 50%; transform: translateX(-50%);" data-cue="fadeIn">
<img src="{{ asset($data['background_image']) }}" alt="background">
</div>
@endif
<div class="flex flex-wrap mx-[-15px] !relative">
<div class="lg:w-8/12 xl:w-8/12 xxl:w-7/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto !relative">
@if(!empty($data['badge']))
<h2 class="text-[0.8rem] tracking-[0.02rem] uppercase text-[#e31e24] !mb-3 !leading-[1.35]">{{ $data['badge'] }}</h2>
@endif
@if(!empty($data['title']))
<h1 class="!text-[calc(1.445rem_+_2.34vw)] font-semibold !leading-[1.15] xl:!text-[3.2rem] !mb-6">
{!! $data['title'] !!}
</h1>
@endif
@if(!empty($data['subtitle']))
<p class="lead text-[1.2rem] !leading-[1.6] !mb-8">{{ $data['subtitle'] }}</p>
@endif
<div class="flex justify-center flex-wrap gap-3">
@if(!empty($data['primary_button_text']))
<a href="{{ $data['primary_button_url'] ?? '#' }}"
class="btn btn-lg btn-grape !text-white !bg-[#e31e24] border-[#e31e24] hover:text-white hover:bg-[#e31e24] hover:!border-[#e31e24] !rounded-[0.8rem]">
{{ $data['primary_button_text'] }}
</a>
@endif
@if(!empty($data['secondary_button_text']))
<a href="{{ $data['secondary_button_url'] ?? '#' }}"
class="btn btn-lg btn-outline-grape !text-[#e31e24] !border-[#e31e24] hover:text-white hover:bg-[#e31e24] hover:!border-[#e31e24] !rounded-[0.8rem]">
{{ $data['secondary_button_text'] }}
</a>
@endif
</div>
</div>
</div>
@if(!empty($data['hero_image']))
<div class="!mt-10">
<img class="max-w-full h-auto !relative m-[0_auto]" src="{{ asset($data['hero_image']) }}" alt="hero">
</div>
@endif
</div>
</section>
@@ -0,0 +1,78 @@
@props(['data' => []])
<section class="wrapper {{ $data['bg_class'] ?? '!bg-[#ffffff]' }}">
<div class="container py-24 xl:py-32 lg:py-32 md:py-32">
@if(!empty($data['section_title']) || !empty($data['section_subtitle']))
<div class="flex flex-wrap mx-[-15px] !mb-12 !text-center">
<div class="md:w-10/12 lg:w-9/12 xl:w-7/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
@if(!empty($data['section_badge']))
<h2 class="text-[0.8rem] tracking-[0.02rem] uppercase text-[#e31e24] !mb-3 !leading-[1.35]">{{ $data['section_badge'] }}</h2>
@endif
@if(!empty($data['section_title']))
<h2 class="!text-[calc(1.345rem_+_1.14vw)] font-bold !leading-[1.2] xl:!text-[2.2rem] !mb-3">
{{ $data['section_title'] }}
</h2>
@endif
@if(!empty($data['section_subtitle']))
<p class="lead text-[1.05rem] !leading-[1.6]">{{ $data['section_subtitle'] }}</p>
@endif
</div>
</div>
@endif
@if(!empty($data['plans']))
<div class="flex flex-wrap mx-[-15px] xl:mx-[-20px] lg:mx-[-20px] md:mx-[-20px] !mt-[-50px] justify-center">
@foreach($data['plans'] as $plan)
<div class="{{ $data['column_class'] ?? 'md:w-6/12 lg:w-4/12' }} w-full flex-[0_0_auto] xl:!px-[20px] lg:!px-[20px] md:!px-[20px] !px-[15px] max-w-full !mt-[50px]">
<div class="pricing card {{ !empty($plan['featured']) ? '!shadow-[0_0.5rem_2rem_rgba(30,34,40,0.15)] !border-[#e31e24] !border-2' : '!shadow-[0_0.25rem_1.75rem_rgba(30,34,40,0.07)]' }} !rounded-[0.8rem]">
<div class="card-body p-10">
@if(!empty($plan['featured']))
<div class="!mb-3 !text-center">
<span class="badge bg-[#e31e24] !rounded-[0.8rem] !px-3 !py-1 text-white text-[0.75rem]">{{ $data['featured_label'] ?? 'Önerilen' }}</span>
</div>
@endif
@if(!empty($plan['name']))
<h4 class="!mb-2 !text-center">{{ $plan['name'] }}</h4>
@endif
<div class="!text-center !mb-6">
@if(!empty($plan['currency']))
<span class="text-[1.2rem] text-muted">{{ $plan['currency'] }}</span>
@endif
@if(!empty($plan['price']))
<span class="!text-[2.5rem] font-bold text-[#343f52]">{{ $plan['price'] }}</span>
@endif
@if(!empty($plan['period']))
<span class="text-[1rem] text-muted">/{{ $plan['period'] }}</span>
@endif
</div>
@if(!empty($plan['features']))
<ul class="list-none !pl-0 !mb-6">
@foreach($plan['features'] as $feature)
<li class="flex items-start !mb-3">
<i class="uil uil-check text-[#e31e24] text-[1.2rem] !mr-2 !mt-1"></i>
<span>{{ $feature }}</span>
</li>
@endforeach
</ul>
@endif
@if(!empty($plan['button_text']))
<a href="{{ $plan['button_url'] ?? '#' }}"
class="btn {{ !empty($plan['featured']) ? 'btn-grape !text-white !bg-[#e31e24]' : 'btn-outline-grape !text-[#e31e24]' }} !w-full !rounded-[0.8rem]">
{{ $plan['button_text'] }}
</a>
@endif
</div>
</div>
</div>
@endforeach
</div>
@endif
</div>
</section>
@@ -0,0 +1,30 @@
@props(['data' => []])
<section class="wrapper {{ $data['bg_class'] ?? '!bg-[#ffffff]' }}">
<div class="container py-16 xl:py-20 lg:py-20 md:py-20">
@if(!empty($data['stats']))
<div class="flex flex-wrap mx-[-15px] xl:mx-[-35px] lg:mx-[-35px] counter-wrapper !text-center">
@foreach($data['stats'] as $stat)
<div class="{{ $data['column_class'] ?? 'md:w-6/12 lg:w-3/12' }} xl:w-3/12 w-full flex-[0_0_auto] xl:!px-[35px] lg:!px-[35px] !px-[15px] max-w-full">
<div class="!mb-4">
@if(!empty($stat['icon']))
<img src="{{ asset($stat['icon']) }}" class="!w-[3rem] !h-[3rem] m-[0_auto] !mb-3" alt="icon">
@endif
@if(!empty($stat['number']))
<h3 class="counter xl:!text-[2.5rem] !text-[calc(1.375rem_+_1.5vw)] !leading-none !mb-2 text-[#e31e24]">
{{ $stat['number'] }}
</h3>
@endif
@if(!empty($stat['label']))
<p class="text-[0.9rem] font-medium !mb-0">{{ $stat['label'] }}</p>
@endif
</div>
</div>
@endforeach
</div>
@endif
</div>
</section>
@@ -0,0 +1,64 @@
@props(['data' => []])
<section class="wrapper {{ $data['bg_class'] ?? '!bg-[#f0f0f8]' }}">
<div class="container py-24 xl:py-32 lg:py-32 md:py-32">
@if(!empty($data['section_title']) || !empty($data['section_subtitle']))
<div class="flex flex-wrap mx-[-15px] !mb-12 !text-center">
<div class="md:w-10/12 lg:w-8/12 xl:w-7/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto">
@if(!empty($data['section_badge']))
<h2 class="text-[0.8rem] tracking-[0.02rem] uppercase text-[#e31e24] !mb-3 !leading-[1.35]">{{ $data['section_badge'] }}</h2>
@endif
@if(!empty($data['section_title']))
<h2 class="!text-[calc(1.345rem_+_1.14vw)] font-bold !leading-[1.2] xl:!text-[2.2rem] !mb-3">
{{ $data['section_title'] }}
</h2>
@endif
@if(!empty($data['section_subtitle']))
<p class="lead text-[1.05rem] !leading-[1.6]">{{ $data['section_subtitle'] }}</p>
@endif
</div>
</div>
@endif
@if(!empty($data['testimonials']))
<div class="flex flex-wrap mx-[-15px] xl:mx-[-20px] lg:mx-[-20px] md:mx-[-20px] !mt-[-50px]">
@foreach($data['testimonials'] as $testimonial)
<div class="{{ $data['column_class'] ?? 'md:w-6/12 lg:w-4/12' }} w-full flex-[0_0_auto] xl:!px-[20px] lg:!px-[20px] md:!px-[20px] !px-[15px] max-w-full !mt-[50px]">
<div class="card !shadow-[0_0.25rem_1.75rem_rgba(30,34,40,0.07)] !rounded-[0.8rem] !bg-white p-6">
@if(!empty($testimonial['rating']))
<div class="!mb-3">
@for($i = 0; $i < ($testimonial['rating'] ?? 5); $i++)
<i class="uil uil-star text-[#ffc107] text-[1rem]"></i>
@endfor
</div>
@endif
@if(!empty($testimonial['quote']))
<blockquote class="!border-0 !mb-4">
<p class="!mb-0">"{{ $testimonial['quote'] }}"</p>
</blockquote>
@endif
<div class="flex items-center">
@if(!empty($testimonial['avatar']))
<img class="!rounded-[50%] !w-12 !h-12 !mr-4" src="{{ asset($testimonial['avatar']) }}" alt="avatar">
@endif
<div>
@if(!empty($testimonial['name']))
<h6 class="!mb-0">{{ $testimonial['name'] }}</h6>
@endif
@if(!empty($testimonial['position']))
<p class="!mb-0 text-[0.85rem]">{{ $testimonial['position'] }}</p>
@endif
</div>
</div>
</div>
</div>
@endforeach
</div>
@endif
</div>
</section>
+21
View File
@@ -0,0 +1,21 @@
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ $meta['title'] ?? ($settings->default_meta_title ?? config('app.name')) }}</title>
<meta name="description" content="{{ $meta['description'] ?? ($settings->default_meta_description ?? '') }}">
<link rel="icon" href="{{ $settings?->favicon_path ? asset($settings->favicon_path) : asset('assets/img/favicon.ico') }}">
<link rel="stylesheet" href="{{ asset('html/style.css') }}">
</head>
<body>
@include('partials.navbar')
@yield('content')
@include('partials.footer')
{{-- İsteğe bağlı: tema JS dosyalarınız varsa buraya ekleyin --}}
{{-- <script src="{{ asset('assets/js/main.js') }}" defer></script> --}}
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
<footer class="site-footer">
<div class="container">
<p>{{ ($settings->site_name ?? config('app.name')) }} © {{ now()->year }}</p>
<div class="social">
@php $links = $settings->social_links ?? []; @endphp
@if(!empty($links['facebook'])) <a href="{{ $links['facebook'] }}" rel="nofollow">Facebook</a> @endif
@if(!empty($links['instagram'])) <a href="{{ $links['instagram'] }}" rel="nofollow">Instagram</a> @endif
@if(!empty($links['linkedin'])) <a href="{{ $links['linkedin'] }}" rel="nofollow">LinkedIn</a> @endif
@if(!empty($links['twitter'])) <a href="{{ $links['twitter'] }}" rel="nofollow">X</a> @endif
</div>
</div>
</footer>
+22
View File
@@ -0,0 +1,22 @@
<header class="site-header">
<div class="container">
<a href="{{ route('home') }}" class="logo">
@if(isset($settings) && !empty($settings->logo_path))
<img src="{{ asset($settings->logo_path) }}" alt="{{ $settings?->translate('site_name') ?? config('app.name') }}">
@else
<span>{{ $settings->site_name ?? config('app.name') }}</span>
@endif
</a>
<nav class="main-nav">
<ul>
<li><a href="{{ route('home') }}">{{ __('pages.nav-home') }}</a></li>
<li><a href="{{ url('/about') }}">{{ __('pages.nav-about') }}</a></li>
<li><a href="{{ url('/services') }}">{{ __('pages.nav-services') }}</a></li>
<li><a href="{{ url('/blog') }}">{{ __('blog.nav-blog') }}</a></li>
<li><a href="{{ url('/contact') }}">{{ __('pages.nav-contact') }}</a></li>
</ul>
</nav>
</div>
</header>
@@ -0,0 +1,15 @@
@extends('layouts.site')
@section('content')
@php $blocks = $sections ?? []; @endphp
@if(is_array($blocks))
@foreach($blocks as $block)
@php $type = $block['type'] ?? null; @endphp
@if($type && view()->exists("components.templates.$type"))
@include("components.templates.$type", ['data' => $block['props'] ?? $block])
@endif
@endforeach
@endif
@endsection
+77
View File
@@ -0,0 +1,77 @@
@extends('layouts.site')
@section('content')
@php
// Admin verisi varsa ve boş değilse dinamik render, yoksa statik HTML
$pageData = $page->data ?? [];
$hasDynamic = is_array($pageData) && count($pageData) > 0;
@endphp
@if($hasDynamic)
{{-- Dinamik (admin) veri ile render --}}
<section class="hero">
<div class="container">
<h1>{{ data_get($page->data ?? [], 'hero_title') }}</h1>
<p>{{ data_get($page->data ?? [], 'hero_subtitle') }}</p>
@if($img = data_get($page->data ?? [], 'hero_image'))
<img src="{{ asset($img) }}" alt="hero">
@endif
<div class="hero-actions">
@if($btn = data_get($page->data ?? [], 'hero_primary_url'))
<a href="{{ $btn }}" class="btn">{{ data_get($page->data ?? [], 'hero_primary_text') }}</a>
@endif
@if($btn2 = data_get($page->data ?? [], 'hero_secondary_url'))
<a href="{{ $btn2 }}" class="btn btn-outline">{{ data_get($page->data ?? [], 'hero_secondary_text') }}</a>
@endif
</div>
</div>
</section>
@if($features = data_get($page->data ?? [], 'features', []))
<section class="features">
<div class="container">
<div class="grid">
@foreach($features as $item)
<div class="feature-item">
@if(!empty($item['icon'])) <img src="{{ asset($item['icon']) }}" alt=""> @endif
<h3>{{ $item['title'] ?? '' }}</h3>
<p>{{ $item['text'] ?? '' }}</p>
</div>
@endforeach
</div>
</div>
</section>
@endif
@if(data_get($page->data ?? [], 'cta_title'))
<section class="cta">
<div class="container">
<h2>{{ data_get($page->data ?? [], 'cta_title') }}</h2>
<a class="btn" href="{{ data_get($page->data ?? [], 'cta_button_url', '#') }}">
{{ data_get($page->data ?? [], 'cta_button_text') }}
</a>
</div>
</section>
@endif
@else
{{-- Statik fallback: public/html/index.html içeriğinin <body> bölümü --}}
@php
$indexPath = public_path('html/index.html');
$bodyHtml = '';
if (file_exists($indexPath) && is_readable($indexPath)) {
$html = file_get_contents($indexPath);
// Body içeriğini çıkar
if (preg_match('/<body[^>]*>(.*?)<\/body>/is', $html, $m)) {
$bodyHtml = $m[1];
}
}
// Eğer body boşsa placeholder göster
if (empty(trim($bodyHtml))) {
$bodyHtml = '<div class="container py-20"><h1>Admin panelinden anasayfa içeriği ekleyin veya index.html kontrol edin.</h1></div>';
}
@endphp
{!! $bodyHtml !!}
@endif
@endsection
+6
View File
@@ -2,6 +2,12 @@
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PageController; use App\Http\Controllers\PageController;
use App\Http\Controllers\BlogController;
// Home -> admin'de işaretli anasayfayı (veya 'home' slug'ını) göster
Route::get('/', [PageController::class, 'index'])->name('home'); Route::get('/', [PageController::class, 'index'])->name('home');
Route::get('/{slug}', [PageController::class, 'show'])->name('page.show'); Route::get('/{slug}', [PageController::class, 'show'])->name('page.show');
// Blog
Route::get('/blog', [BlogController::class, 'index'])->name('blog.index');
Route::get('/blog/{slug}', [BlogController::class, 'show'])->name('blog.show');