Refactor Blog and Page Controllers: Updated BlogController and PageController to utilize the new Blog model and integrated dynamic header and footer templates. Removed the DatabaseSeeder file as it is no longer needed. Enhanced the TemplateService to support dynamic content rendering for both blog and page templates, improving the overall template management system.
This commit is contained in:
-29
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Seed the application's database.
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// Settings seed
|
||||
$this->call([
|
||||
SettingSeeder::class,
|
||||
]);
|
||||
|
||||
// User::factory(10)->create();
|
||||
|
||||
User::factory()->create([
|
||||
'name' => 'Test User',
|
||||
'email' => 'test@example.com',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,20 +3,57 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Setting;
|
||||
use App\Models\Post;
|
||||
use App\Models\Blog;
|
||||
use App\Models\HeaderTemplate;
|
||||
use App\Models\FooterTemplate;
|
||||
use App\Services\TemplateService;
|
||||
|
||||
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)
|
||||
$posts = class_exists(Blog::class)
|
||||
? Blog::with(['category', 'author'])
|
||||
->withCount('comments')
|
||||
->published()
|
||||
->latest('published_at')
|
||||
->paginate(12)
|
||||
: collect();
|
||||
|
||||
// Render Header Template - En son aktif olan header template'i kullan
|
||||
$renderedHeader = null;
|
||||
$headerTemplate = HeaderTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
|
||||
if ($headerTemplate) {
|
||||
$templateDefaults = $headerTemplate->default_data ?? [];
|
||||
$renderedHeader = TemplateService::replacePlaceholders(
|
||||
$headerTemplate->html_content,
|
||||
$templateDefaults
|
||||
);
|
||||
}
|
||||
|
||||
// Render Footer Template - En son aktif olan footer template'i kullan
|
||||
$renderedFooter = null;
|
||||
$footerTemplate = FooterTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
|
||||
if ($footerTemplate) {
|
||||
$templateDefaults = $footerTemplate->default_data ?? [];
|
||||
$renderedFooter = TemplateService::replacePlaceholders(
|
||||
$footerTemplate->html_content,
|
||||
$templateDefaults
|
||||
);
|
||||
}
|
||||
|
||||
return view('blog.index', [
|
||||
'settings' => $settings,
|
||||
'posts' => $posts,
|
||||
'renderedHeader' => $renderedHeader,
|
||||
'renderedFooter' => $renderedFooter,
|
||||
'meta' => [
|
||||
'title' => __('blog.meta-index-title'),
|
||||
'description' => __('blog.meta-index-description'),
|
||||
@@ -27,18 +64,54 @@ class BlogController extends Controller
|
||||
public function show(string $slug)
|
||||
{
|
||||
$settings = class_exists(Setting::class) ? (Setting::query()->first()) : null;
|
||||
if (!class_exists(Post::class)) {
|
||||
if (!class_exists(Blog::class)) {
|
||||
abort(404);
|
||||
}
|
||||
$post = Post::query()->where('slug', $slug)->where('status', 'published')->firstOrFail();
|
||||
$post = Blog::with(['category', 'author'])
|
||||
->withCount('comments')
|
||||
->published()
|
||||
->where('slug', $slug)
|
||||
->firstOrFail();
|
||||
|
||||
// Render Header Template - En son aktif olan header template'i kullan
|
||||
$renderedHeader = null;
|
||||
$headerTemplate = HeaderTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
|
||||
if ($headerTemplate) {
|
||||
$templateDefaults = $headerTemplate->default_data ?? [];
|
||||
$renderedHeader = TemplateService::replacePlaceholders(
|
||||
$headerTemplate->html_content,
|
||||
$templateDefaults,
|
||||
$post
|
||||
);
|
||||
}
|
||||
|
||||
// Render Footer Template - En son aktif olan footer template'i kullan
|
||||
$renderedFooter = null;
|
||||
$footerTemplate = FooterTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
|
||||
if ($footerTemplate) {
|
||||
$templateDefaults = $footerTemplate->default_data ?? [];
|
||||
$renderedFooter = TemplateService::replacePlaceholders(
|
||||
$footerTemplate->html_content,
|
||||
$templateDefaults,
|
||||
$post
|
||||
);
|
||||
}
|
||||
|
||||
return view('blog.show', [
|
||||
'settings' => $settings,
|
||||
'post' => $post,
|
||||
'renderedHeader' => $renderedHeader,
|
||||
'renderedFooter' => $renderedFooter,
|
||||
'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,
|
||||
'image' => $post->featured_image ? asset('storage/' . $post->featured_image) : null,
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Page;
|
||||
use App\Models\Setting;
|
||||
use App\Models\HeaderTemplate;
|
||||
use App\Models\FooterTemplate;
|
||||
use App\Services\TemplateService;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@@ -66,14 +68,23 @@ class PageController extends Controller
|
||||
|
||||
// Render Header Template
|
||||
$renderedHeader = null;
|
||||
if ($page->headerTemplate) {
|
||||
$headerTemplate = $page->headerTemplate;
|
||||
|
||||
// Eğer sayfa için header seçilmemişse, en son aktif header template'i kullan
|
||||
if (!$headerTemplate) {
|
||||
$headerTemplate = HeaderTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($headerTemplate) {
|
||||
// Merge template defaults with page data (page data overrides defaults)
|
||||
$templateDefaults = $page->headerTemplate->default_data ?? [];
|
||||
$templateDefaults = $headerTemplate->default_data ?? [];
|
||||
$pageData = $page->header_data ?? [];
|
||||
$mergedHeaderData = array_merge($templateDefaults, $pageData);
|
||||
|
||||
$renderedHeader = TemplateService::replacePlaceholders(
|
||||
$page->headerTemplate->html_content,
|
||||
$headerTemplate->html_content,
|
||||
$mergedHeaderData,
|
||||
$page
|
||||
);
|
||||
@@ -81,14 +92,23 @@ class PageController extends Controller
|
||||
|
||||
// Render Footer Template
|
||||
$renderedFooter = null;
|
||||
if ($page->footerTemplate) {
|
||||
$footerTemplate = $page->footerTemplate;
|
||||
|
||||
// Eğer sayfa için footer seçilmemişse, en son aktif footer template'i kullan
|
||||
if (!$footerTemplate) {
|
||||
$footerTemplate = FooterTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($footerTemplate) {
|
||||
// Merge template defaults with page data (page data overrides defaults)
|
||||
$templateDefaults = $page->footerTemplate->default_data ?? [];
|
||||
$templateDefaults = $footerTemplate->default_data ?? [];
|
||||
$pageData = $page->footer_data ?? [];
|
||||
$mergedFooterData = array_merge($templateDefaults, $pageData);
|
||||
|
||||
$renderedFooter = TemplateService::replacePlaceholders(
|
||||
$page->footerTemplate->html_content,
|
||||
$footerTemplate->html_content,
|
||||
$mergedFooterData,
|
||||
$page
|
||||
);
|
||||
@@ -148,14 +168,23 @@ public function show($slug)
|
||||
|
||||
// Render Header Template
|
||||
$renderedHeader = null;
|
||||
if ($page->headerTemplate) {
|
||||
$headerTemplate = $page->headerTemplate;
|
||||
|
||||
// Eğer sayfa için header seçilmemişse, en son aktif header template'i kullan
|
||||
if (!$headerTemplate) {
|
||||
$headerTemplate = HeaderTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($headerTemplate) {
|
||||
// Merge template defaults with page data (page data overrides defaults)
|
||||
$templateDefaults = $page->headerTemplate->default_data ?? [];
|
||||
$templateDefaults = $headerTemplate->default_data ?? [];
|
||||
$pageData = $page->header_data ?? [];
|
||||
$mergedHeaderData = array_merge($templateDefaults, $pageData);
|
||||
|
||||
$renderedHeader = TemplateService::replacePlaceholders(
|
||||
$page->headerTemplate->html_content,
|
||||
$headerTemplate->html_content,
|
||||
$mergedHeaderData,
|
||||
$page
|
||||
);
|
||||
@@ -163,14 +192,23 @@ public function show($slug)
|
||||
|
||||
// Render Footer Template
|
||||
$renderedFooter = null;
|
||||
if ($page->footerTemplate) {
|
||||
$footerTemplate = $page->footerTemplate;
|
||||
|
||||
// Eğer sayfa için footer seçilmemişse, en son aktif footer template'i kullan
|
||||
if (!$footerTemplate) {
|
||||
$footerTemplate = FooterTemplate::where('is_active', true)
|
||||
->latest('updated_at')
|
||||
->first();
|
||||
}
|
||||
|
||||
if ($footerTemplate) {
|
||||
// Merge template defaults with page data (page data overrides defaults)
|
||||
$templateDefaults = $page->footerTemplate->default_data ?? [];
|
||||
$templateDefaults = $footerTemplate->default_data ?? [];
|
||||
$pageData = $page->footer_data ?? [];
|
||||
$mergedFooterData = array_merge($templateDefaults, $pageData);
|
||||
|
||||
$renderedFooter = TemplateService::replacePlaceholders(
|
||||
$page->footerTemplate->html_content,
|
||||
$footerTemplate->html_content,
|
||||
$mergedFooterData,
|
||||
$page
|
||||
);
|
||||
|
||||
+4
-1
@@ -94,7 +94,10 @@ class Blog extends Model
|
||||
public function scopePublished($query)
|
||||
{
|
||||
return $query->where('status', 'published')
|
||||
->where('published_at', '<=', now());
|
||||
->where(function($q) {
|
||||
$q->whereNull('published_at')
|
||||
->orWhere('published_at', '<=', now());
|
||||
});
|
||||
}
|
||||
|
||||
public function scopeFeatured($query)
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Services;
|
||||
use App\Models\HeaderTemplate;
|
||||
use App\Models\SectionTemplate;
|
||||
use App\Models\FooterTemplate;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Filament\Forms\Components\{
|
||||
TextInput, Textarea, Select, Checkbox, CheckboxList,
|
||||
Radio, Toggle, ToggleButtons, DateTimePicker, DatePicker,
|
||||
@@ -31,19 +32,47 @@ class TemplateService
|
||||
$fields = [];
|
||||
|
||||
foreach ($placeholders as $placeholder) {
|
||||
$parts = explode('.', $placeholder);
|
||||
// Handle special.* prefix - remove it for processing
|
||||
$normalizedPlaceholder = $placeholder;
|
||||
if (str_starts_with($placeholder, 'special.')) {
|
||||
$normalizedPlaceholder = substr($placeholder, 8); // Remove 'special.' prefix
|
||||
}
|
||||
|
||||
if (count($parts) !== 2) {
|
||||
$parts = explode('.', $normalizedPlaceholder);
|
||||
|
||||
if (count($parts) < 2) {
|
||||
continue; // Skip invalid placeholders
|
||||
}
|
||||
|
||||
[$type, $name] = $parts;
|
||||
$type = $parts[0];
|
||||
|
||||
// Skip special.* placeholders - they are special placeholders (page.*, menu, staticMenu), not form fields
|
||||
if (str_starts_with($placeholder, 'special.')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip custom.* placeholders - they are blade components, not form fields
|
||||
if ($type === 'custom') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip page.* placeholders - they are special placeholders, not form fields
|
||||
if ($type === 'page') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip menu and staticMenu placeholders - they are special placeholders, not form fields
|
||||
if ($normalizedPlaceholder === 'menu' || $normalizedPlaceholder === 'staticMenu') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// For form fields, we expect type.field format (2 parts)
|
||||
if (count($parts) !== 2) {
|
||||
continue; // Skip invalid placeholders
|
||||
}
|
||||
|
||||
[$type, $name] = $parts;
|
||||
|
||||
$label = str($name)->title()->replace('_', ' ')->toString();
|
||||
|
||||
// Get existing value from existingData if provided
|
||||
@@ -248,11 +277,12 @@ class TemplateService
|
||||
|
||||
/**
|
||||
* Parse placeholders from HTML content
|
||||
* Format: {type.field_name} or {type.field-name}
|
||||
* Format: {type.field_name} or {type.field-name} or {special.type.field}
|
||||
*/
|
||||
public static function parsePlaceholders(string $html): array
|
||||
{
|
||||
preg_match_all('/\{([a-z]+\.[a-z][a-z_-]*)\}/i', $html, $matches);
|
||||
// Pattern: {type.field} or {special.type.field} or {type.field.field2} etc.
|
||||
preg_match_all('/\{([a-z]+(?:\.[a-z][a-z_-]*)+)\}/i', $html, $matches);
|
||||
return array_unique($matches[1] ?? []);
|
||||
}
|
||||
|
||||
@@ -275,44 +305,48 @@ class TemplateService
|
||||
* Also supports {menu} and {staticMenu} placeholders for menu rendering
|
||||
* Also supports {custom.component_name} for custom blade components
|
||||
* Also supports {page.content}, {page.title}, {page.excerpt} for page data
|
||||
*
|
||||
* @param string $html HTML content with placeholders
|
||||
* @param array $data Data array for placeholders
|
||||
* @param Model|null $model Optional model instance (Page, Blog, etc.) for dynamic data
|
||||
*/
|
||||
public static function replacePlaceholders(string $html, array $data, ?\App\Models\Page $page = null): string
|
||||
public static function replacePlaceholders(string $html, array $data, ?Model $model = null): string
|
||||
{
|
||||
// Handle special {page.content} placeholder - Sayfa içeriğini gösterir
|
||||
// Handle special {page.content} placeholder - Sayfa/model içeriğini gösterir
|
||||
if (str_contains($html, '{page.content}')) {
|
||||
$pageContent = '';
|
||||
if ($page) {
|
||||
if ($model) {
|
||||
// Translation desteği varsa çeviriyi kullan
|
||||
if (method_exists($page, 'translate')) {
|
||||
$pageContent = $page->translate('content') ?: $page->content;
|
||||
if (method_exists($model, 'translate')) {
|
||||
$pageContent = $model->translate('content') ?: ($model->content ?? '');
|
||||
} else {
|
||||
$pageContent = $page->content;
|
||||
$pageContent = $model->content ?? '';
|
||||
}
|
||||
}
|
||||
$html = str_replace('{page.content}', $pageContent ?? '', $html);
|
||||
}
|
||||
|
||||
// Handle special {page.title} placeholder - Sayfa başlığını gösterir
|
||||
// Handle special {page.title} placeholder - Sayfa/model başlığını gösterir
|
||||
if (str_contains($html, '{page.title}')) {
|
||||
$pageTitle = '';
|
||||
if ($page) {
|
||||
if (method_exists($page, 'translate')) {
|
||||
$pageTitle = $page->translate('title') ?: $page->title;
|
||||
if ($model) {
|
||||
if (method_exists($model, 'translate')) {
|
||||
$pageTitle = $model->translate('title') ?: ($model->title ?? '');
|
||||
} else {
|
||||
$pageTitle = $page->title;
|
||||
$pageTitle = $model->title ?? '';
|
||||
}
|
||||
}
|
||||
$html = str_replace('{page.title}', $pageTitle ?? '', $html);
|
||||
}
|
||||
|
||||
// Handle special {page.excerpt} placeholder - Sayfa özetini gösterir
|
||||
// Handle special {page.excerpt} placeholder - Sayfa/model özetini gösterir
|
||||
if (str_contains($html, '{page.excerpt}')) {
|
||||
$pageExcerpt = '';
|
||||
if ($page) {
|
||||
if (method_exists($page, 'translate')) {
|
||||
$pageExcerpt = $page->translate('excerpt') ?: $page->excerpt;
|
||||
if ($model) {
|
||||
if (method_exists($model, 'translate')) {
|
||||
$pageExcerpt = $model->translate('excerpt') ?: ($model->excerpt ?? '');
|
||||
} else {
|
||||
$pageExcerpt = $page->excerpt;
|
||||
$pageExcerpt = $model->excerpt ?? '';
|
||||
}
|
||||
}
|
||||
$html = str_replace('{page.excerpt}', $pageExcerpt ?? '', $html);
|
||||
@@ -373,8 +407,10 @@ class TemplateService
|
||||
}
|
||||
|
||||
// First, parse all placeholders in the format {type.field_name} or {type.field-name}
|
||||
// Also supports {special.page.title} format (special.* prefix)
|
||||
// Exclude custom.* from this regex to avoid double processing
|
||||
preg_match_all('/\{([a-z]+\.[a-z][a-z_-]*)\}/i', $html, $matches);
|
||||
// Pattern: {type.field} or {special.type.field} or {type.field.field2} etc.
|
||||
preg_match_all('/\{([a-z]+(?:\.[a-z][a-z_-]*)+)\}/i', $html, $matches);
|
||||
$placeholders = array_unique($matches[1] ?? []);
|
||||
|
||||
// Filter out custom.* placeholders as they're already handled above
|
||||
@@ -384,11 +420,74 @@ class TemplateService
|
||||
|
||||
// Replace each placeholder
|
||||
foreach ($placeholders as $placeholder) {
|
||||
// Handle special.* prefix - remove it and process as normal placeholder
|
||||
// e.g., {special.page.title} -> {page.title}, {special.menu} -> {menu}
|
||||
$originalPlaceholder = $placeholder;
|
||||
if (str_starts_with($placeholder, 'special.')) {
|
||||
$placeholder = substr($placeholder, 8); // Remove 'special.' prefix (8 characters)
|
||||
}
|
||||
|
||||
// Extract type from placeholder
|
||||
$parts = explode('.', $placeholder);
|
||||
$type = $parts[0] ?? null;
|
||||
$field = $parts[1] ?? null;
|
||||
|
||||
// Handle special placeholders that were prefixed with special.*
|
||||
// These are page data placeholders: page.content, page.title, page.excerpt
|
||||
if ($type === 'page') {
|
||||
if ($field === 'content' && str_contains($html, '{' . $originalPlaceholder . '}')) {
|
||||
$pageContent = '';
|
||||
if ($page) {
|
||||
if (method_exists($page, 'translate')) {
|
||||
$pageContent = $page->translate('content') ?: $page->content;
|
||||
} else {
|
||||
$pageContent = $page->content;
|
||||
}
|
||||
}
|
||||
$html = str_replace('{' . $originalPlaceholder . '}', $pageContent ?? '', $html);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($field === 'title' && str_contains($html, '{' . $originalPlaceholder . '}')) {
|
||||
$pageTitle = '';
|
||||
if ($page) {
|
||||
if (method_exists($page, 'translate')) {
|
||||
$pageTitle = $page->translate('title') ?: $page->title;
|
||||
} else {
|
||||
$pageTitle = $page->title;
|
||||
}
|
||||
}
|
||||
$html = str_replace('{' . $originalPlaceholder . '}', $pageTitle ?? '', $html);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($field === 'excerpt' && str_contains($html, '{' . $originalPlaceholder . '}')) {
|
||||
$pageExcerpt = '';
|
||||
if ($page) {
|
||||
if (method_exists($page, 'translate')) {
|
||||
$pageExcerpt = $page->translate('excerpt') ?: $page->excerpt;
|
||||
} else {
|
||||
$pageExcerpt = $page->excerpt;
|
||||
}
|
||||
}
|
||||
$html = str_replace('{' . $originalPlaceholder . '}', $pageExcerpt ?? '', $html);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle special menu placeholders that were prefixed with special.*
|
||||
if ($placeholder === 'menu' && str_contains($html, '{' . $originalPlaceholder . '}')) {
|
||||
$renderedMenu = \App\Services\MenuService::render();
|
||||
$html = str_replace('{' . $originalPlaceholder . '}', $renderedMenu, $html);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($placeholder === 'staticMenu' && str_contains($html, '{' . $originalPlaceholder . '}')) {
|
||||
$renderedStaticMenu = view('components.static-menu')->render();
|
||||
$html = str_replace('{' . $originalPlaceholder . '}', $renderedStaticMenu, $html);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle setting.* placeholders - get value from Setting model
|
||||
if ($type === 'setting' && $field) {
|
||||
$value = setting($field, '');
|
||||
@@ -444,11 +543,19 @@ class TemplateService
|
||||
}
|
||||
|
||||
// Replace both {text.title} and {{text.title}} formats
|
||||
$html = str_replace(
|
||||
["{{$placeholder}}", "{{{$placeholder}}}"],
|
||||
[$value, $value],
|
||||
$html
|
||||
);
|
||||
// Also replace original placeholder if it was prefixed with special.*
|
||||
$replacements = [
|
||||
"{{$placeholder}}",
|
||||
"{{{$placeholder}}}"
|
||||
];
|
||||
|
||||
if ($originalPlaceholder !== $placeholder) {
|
||||
// Original placeholder had special.* prefix, replace it too
|
||||
$replacements[] = "{{$originalPlaceholder}}";
|
||||
$replacements[] = "{{{$originalPlaceholder}}}";
|
||||
}
|
||||
|
||||
$html = str_replace($replacements, array_fill(0, count($replacements), $value), $html);
|
||||
}
|
||||
|
||||
return $html;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
@php
|
||||
// Blog modelinden published içerikleri çek
|
||||
$blogs = \App\Models\Blog::with(['category', 'author'])
|
||||
->withCount('comments')
|
||||
->published()
|
||||
->latest('published_at')
|
||||
->limit(6)
|
||||
->get();
|
||||
@endphp
|
||||
|
||||
<section class="wrapper !bg-[#ffffff] ">
|
||||
<div class="container pt-20 xl:pt-28 lg:pt-28 md:pt-28 pb-16 xl:pb-20 lg:pb-20 md:pb-20">
|
||||
|
||||
@if($blogs->count() > 0)
|
||||
<div class="swiper-container blog grid-view !mb-6" data-margin="30" data-dots="true" data-items-xl="3" data-items-md="2" data-items-xs="1">
|
||||
<div class="swiper">
|
||||
<div class="swiper-wrapper">
|
||||
@foreach($blogs as $blog)
|
||||
@php
|
||||
$title = method_exists($blog, 'translate') ? $blog->translate('title') : $blog->title;
|
||||
$excerpt = method_exists($blog, 'translate') ? $blog->translate('excerpt') : ($blog->excerpt ?? '');
|
||||
$categoryName = $blog->category ? ($blog->category->name ?? '') : '';
|
||||
$publishedDate = $blog->published_at ? $blog->published_at->format('d M Y') : '';
|
||||
$imageUrl = $blog->featured_image ? asset('storage/' . $blog->featured_image) : asset('assets/img/photos/b4.jpg');
|
||||
$blogUrl = route('blog.show', $blog->slug);
|
||||
$commentCount = $blog->comments_count ?? 0;
|
||||
@endphp
|
||||
|
||||
<div class="swiper-slide">
|
||||
<article>
|
||||
<figure class="overlay overlay-1 hover-scale group rounded !mb-5">
|
||||
<a href="{{ $blogUrl }}">
|
||||
<img class="!transition-all !duration-[0.35s] !ease-in-out group-hover:scale-105" src="{{ $imageUrl }}" alt="{{ $title }}">
|
||||
</a>
|
||||
<figcaption class="group-hover:opacity-100 absolute w-full h-full opacity-0 text-center px-4 py-3 inset-0 z-[5] pointer-events-none p-2">
|
||||
<h5 class="from-top !mb-0 absolute w-full translate-y-[-80%] p-[.75rem_1rem] left-0 top-2/4">{{ __('blog.read_more', ['default' => 'Read More']) }}</h5>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<div class="post-header">
|
||||
@if($categoryName)
|
||||
<div class="inline-flex !mb-[.4rem] uppercase !tracking-[0.02rem] text-[0.7rem] font-bold !text-[#aab0bc] relative align-top !pl-[1.4rem] before:content-[''] before:absolute before:inline-block before:translate-y-[-60%] before:w-3 before:h-[0.05rem] before:left-0 before:top-2/4 before:bg-[#3f78e0]">
|
||||
<a href="{{ route('blog.index', ['category' => $blog->category->slug ?? '']) }}" class="hover" rel="category">{{ $categoryName }}</a>
|
||||
</div>
|
||||
@endif
|
||||
<!-- /.post-category -->
|
||||
<h2 class="post-title h3 !mt-1 !mb-3">
|
||||
<a class="!text-[#343f52] hover:!text-[#3f78e0]" href="{{ $blogUrl }}">{{ $title }}</a>
|
||||
</h2>
|
||||
</div>
|
||||
<!-- /.post-header -->
|
||||
<div class="post-footer">
|
||||
<ul class="!text-[0.7rem] !text-[#aab0bc] m-0 p-0 list-none !mb-0">
|
||||
@if($publishedDate)
|
||||
<li class="post-date inline-block">
|
||||
<i class="uil uil-calendar-alt pr-[0.2rem] align-[-.05rem] before:content-['\e9ba']"></i>
|
||||
<span>{{ $publishedDate }}</span>
|
||||
</li>
|
||||
@endif
|
||||
@if($blog->allow_comments)
|
||||
<li class="post-comments inline-block before:content-[''] before:inline-block before:w-[0.2rem] before:h-[0.2rem] before:opacity-50 before:m-[0_.6rem_0] before:rounded-[100%] before:align-[.15rem] before:bg-[#aab0bc]">
|
||||
<a class="!text-[#aab0bc] hover:!text-[#3f78e0] hover:!border-[#3f78e0]" href="{{ $blogUrl }}#comments">
|
||||
<i class="uil uil-comment pr-[0.2rem] align-[-.05rem] before:content-['\ea54']"></i>{{ $commentCount }}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
<!-- /.post-meta -->
|
||||
</div>
|
||||
<!-- /.post-footer -->
|
||||
</article>
|
||||
<!-- /article -->
|
||||
</div>
|
||||
<!--/.swiper-slide -->
|
||||
@endforeach
|
||||
</div>
|
||||
<!--/.swiper-wrapper -->
|
||||
</div>
|
||||
<!-- /.swiper -->
|
||||
</div>
|
||||
<!-- /.swiper-container -->
|
||||
@else
|
||||
<div class="text-center py-12">
|
||||
<p class="text-[#aab0bc]">{{ __('blog.empty', ['default' => 'No blog posts available at the moment.']) }}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</section>
|
||||
<!-- /section -->
|
||||
Reference in New Issue
Block a user