feat: implement premium blog search and filter UI with improved layout and dynamic post loading.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
<!-- Carousel Section -->
|
||||
@if(isset($carouselPosts) && $carouselPosts->count() > 0)
|
||||
<div class="swiper-container blog grid-view !mb-24 relative z-10" data-margin="30" data-dots="true" data-items-lg="2" data-items-md="1" data-items-xs="1">
|
||||
<div class="swiper-container blog grid-view !mb-10 relative z-10" data-margin="30" data-dots="true" data-items-lg="2" data-items-md="1" data-items-xs="1">
|
||||
<div class="swiper">
|
||||
<div class="swiper-wrapper">
|
||||
@foreach($carouselPosts as $cPost)
|
||||
@@ -21,9 +21,9 @@
|
||||
$cUrl = route('blog.show', $cPost->slug);
|
||||
@endphp
|
||||
<div class="swiper-slide">
|
||||
<figure class="overlay caption caption-overlay rounded !mb-0">
|
||||
<a href="{{ $cUrl }}">
|
||||
<img src="{{ $cImage }}" alt="{{ $cTitle }}" style="height: 380px; object-fit: cover; width: 100%;" loading="lazy">
|
||||
<figure class="overlay caption caption-overlay rounded !mb-0" style="height: 380px !important; overflow: hidden;">
|
||||
<a href="{{ $cUrl }}" class="block w-full h-full">
|
||||
<img src="{{ $cImage }}" alt="{{ $cTitle }}" style="height: 380px !important; object-fit: cover !important; width: 100% !important;" loading="lazy">
|
||||
</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">
|
||||
@if($cCategoryName)
|
||||
@@ -58,7 +58,7 @@
|
||||
<!-- Welcome Banner Section -->
|
||||
<div class="flex flex-wrap mx-[-15px]">
|
||||
<div class="lg:w-full xl:w-10/12 xxl:w-8/12 w-full flex-[0_0_auto] !px-[15px] max-w-full !mx-auto !text-center">
|
||||
<h2 class="xl:!text-[1.7rem] !text-[calc(1.295rem_+_0.54vw)] !leading-[1.25] font-semibold !text-center !mt-4 !mb-10">
|
||||
<h2 class="xl:!text-[1.7rem] !text-[calc(1.295rem_+_0.54vw)] !leading-[1.25] font-semibold !text-center !mt-0 !mb-4">
|
||||
Merhaba! Biz Trunçgil. Blogumuza hoş geldiniz. Burada web tasarım, yazılım geliştirme ve teknolojik yeniliklere dair ipuçlarını ve deneyimlerimizi paylaşıyoruz.
|
||||
</h2>
|
||||
</div>
|
||||
@@ -71,7 +71,7 @@
|
||||
// Dynamically select column width based on category count
|
||||
$gridClass = $catCount >= 4 ? 'md:w-6/12 lg:w-3/12 xl:w-3/12' : 'md:w-6/12 lg:w-4/12 xl:w-4/12';
|
||||
@endphp
|
||||
<div class="flex flex-wrap mx-[-15px] grid-view md:mx-[-20px] lg:mx-[-20px] xl:mx-[-25px] !mt-[-40px] xl:!mt-0 lg:!mt-0 !text-center !mb-16">
|
||||
<div class="flex flex-wrap mx-[-15px] grid-view md:mx-[-20px] lg:mx-[-20px] xl:mx-[-25px] !mt-[-40px] xl:!mt-0 lg:!mt-0 !text-center !mb-8">
|
||||
@foreach($highlightCategories as $index => $hCat)
|
||||
@php
|
||||
$images = [
|
||||
@@ -104,26 +104,40 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Main Content & Sidebar Layout -->
|
||||
<div class="flex flex-wrap mx-[-15px] xl:mx-[-35px] lg:mx-[-20px] !mt-[4rem]">
|
||||
|
||||
<!-- Left Column: Posts Feed (8/12) -->
|
||||
<div class="xl:w-8/12 lg:w-8/12 w-full flex-[0_0_auto] !px-[15px] max-w-full lg:!px-[20px] xl:!px-[35px] xl:!mt-0 lg:!mt-0">
|
||||
|
||||
<!-- Category Filter -->
|
||||
<!-- Category Filter & Search Bar Wrapper -->
|
||||
<div class="flex flex-wrap justify-between items-center gap-4 !mb-8 blog-filter-search-wrapper">
|
||||
@if(isset($categories) && $categories->count() > 0)
|
||||
<div class="flex flex-wrap justify-start !mb-10 gap-2 blog-filter-menu">
|
||||
<a href="#" class="category-filter-btn active !text-[0.75rem] !font-bold !uppercase !tracking-[0.02rem] !px-4 !py-2 !rounded-full !border !border-[#e31e24] !bg-[#e31e24] !text-white hover:!bg-[#c8191f] hover:!border-[#c8191f] transition-colors" data-category="">
|
||||
<div class="blog-filter-menu !mb-0">
|
||||
<a href="#" class="category-filter-btn active" data-category="">
|
||||
Tümü
|
||||
</a>
|
||||
@foreach($categories as $category)
|
||||
<a href="#" class="category-filter-btn !text-[0.75rem] !font-bold !uppercase !tracking-[0.02rem] !px-4 !py-2 !rounded-full !border !border-[#eef2f6] !bg-[#eef2f6] !text-[#343f52] hover:!bg-[#e31e24] hover:!text-white hover:!border-[#e31e24] transition-colors" data-category="{{ $category->slug }}">
|
||||
<a href="#" class="category-filter-btn" data-category="{{ $category->slug }}">
|
||||
{{ $category->name }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Premium Search Box -->
|
||||
<div class="blog-search-box">
|
||||
<form action="#" class="blog-search-form" id="blog-search-form">
|
||||
<input type="text" name="search" id="blog-search-input" placeholder="Yazılarda ara..." autocomplete="off">
|
||||
<button type="submit" class="blog-search-submit-btn">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-search" viewBox="0 0 16 16" style="width: 14px; height: 14px; display: block; color: white;">
|
||||
<path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001q.044.06.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1 1 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0"/>
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content & Sidebar Layout -->
|
||||
<div class="flex flex-wrap mx-[-15px] xl:mx-[-35px] lg:mx-[-20px] !mt-[1.5rem]">
|
||||
|
||||
<!-- Left Column: Posts Feed (8/12) -->
|
||||
<div class="xl:w-8/12 lg:w-8/12 w-full flex-[0_0_auto] !px-[15px] max-w-full lg:!px-[20px] xl:!px-[35px] xl:!mt-0 lg:!mt-0">
|
||||
|
||||
<div id="blog-posts-container" class="relative min-h-[400px]">
|
||||
@include('blog.partials.posts')
|
||||
</div>
|
||||
@@ -219,6 +233,131 @@
|
||||
|
||||
@push('styles')
|
||||
<style>
|
||||
/* Premium Blog Filter Menu */
|
||||
.blog-filter-menu {
|
||||
display: inline-flex !important;
|
||||
flex-wrap: wrap !important;
|
||||
gap: 8px !important;
|
||||
background: #ffffff !important;
|
||||
padding: 8px 12px !important;
|
||||
border-radius: 50px !important;
|
||||
border: 1px solid #eef2f6 !important;
|
||||
box-shadow: 0 4px 20px rgba(30, 34, 40, 0.05) !important;
|
||||
margin-bottom: 0 !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.category-filter-btn {
|
||||
font-size: 0.75rem !important;
|
||||
font-weight: 700 !important;
|
||||
padding: 8px 20px !important;
|
||||
border-radius: 50px !important;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
border: 1px solid transparent !important;
|
||||
color: #60697b !important;
|
||||
background: transparent !important;
|
||||
text-transform: uppercase !important;
|
||||
letter-spacing: 0.03em !important;
|
||||
text-decoration: none !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.category-filter-btn:hover {
|
||||
color: #e31e24 !important;
|
||||
background: rgba(227, 30, 36, 0.05) !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.category-filter-btn.active {
|
||||
color: #ffffff !important;
|
||||
background: #e31e24 !important;
|
||||
border-color: #e31e24 !important;
|
||||
box-shadow: 0 4px 12px rgba(227, 30, 36, 0.25) !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
/* Premium Blog Search Box */
|
||||
.blog-search-box {
|
||||
background: #ffffff !important;
|
||||
border-radius: 50px !important;
|
||||
border: 1px solid #eef2f6 !important;
|
||||
box-shadow: 0 4px 20px rgba(30, 34, 40, 0.05) !important;
|
||||
padding: 4px 6px 4px 18px !important;
|
||||
display: inline-flex !important;
|
||||
align-items: center !important;
|
||||
width: 280px !important;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
}
|
||||
|
||||
.blog-search-box:focus-within {
|
||||
border-color: #e31e24 !important;
|
||||
box-shadow: 0 4px 20px rgba(227, 30, 36, 0.1) !important;
|
||||
width: 320px !important;
|
||||
}
|
||||
|
||||
.blog-search-form {
|
||||
display: flex !important;
|
||||
width: 100% !important;
|
||||
align-items: center !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
#blog-search-input {
|
||||
border: none !important;
|
||||
background: transparent !important;
|
||||
outline: none !important;
|
||||
font-size: 0.8rem !important;
|
||||
font-weight: 500 !important;
|
||||
color: #343f52 !important;
|
||||
width: 100% !important;
|
||||
padding: 6px 0 !important;
|
||||
}
|
||||
|
||||
#blog-search-input::placeholder {
|
||||
color: #aab0bc !important;
|
||||
}
|
||||
|
||||
.blog-search-submit-btn {
|
||||
border: none !important;
|
||||
background: #e31e24 !important;
|
||||
color: #ffffff !important;
|
||||
width: 32px !important;
|
||||
height: 32px !important;
|
||||
border-radius: 50% !important;
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
justify-content: center !important;
|
||||
cursor: pointer !important;
|
||||
transition: all 0.25s ease !important;
|
||||
box-shadow: 0 4px 10px rgba(227, 30, 36, 0.2) !important;
|
||||
flex-shrink: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.blog-search-submit-btn:hover {
|
||||
background: #c8191f !important;
|
||||
transform: scale(1.05) !important;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.blog-filter-search-wrapper {
|
||||
flex-direction: column !important;
|
||||
align-items: stretch !important;
|
||||
gap: 15px !important;
|
||||
}
|
||||
.blog-filter-menu {
|
||||
justify-content: center !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.blog-search-box {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loading Overlay for AJAX Requests */
|
||||
.blog-loading-overlay {
|
||||
position: absolute;
|
||||
@@ -285,7 +424,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
window.history.pushState({html: html}, '', url);
|
||||
|
||||
document.querySelector('.blog-filter-menu').scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
const scrollTarget = document.querySelector('.blog-filter-search-wrapper') || document.querySelector('.blog-filter-menu');
|
||||
if (scrollTarget) {
|
||||
scrollTarget.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
overlay.classList.remove('active');
|
||||
@@ -314,11 +456,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
e.preventDefault();
|
||||
|
||||
filterBtns.forEach(b => {
|
||||
b.classList.remove('!text-white', '!bg-[#e31e24]', '!border-[#e31e24]');
|
||||
b.classList.add('!text-[#343f52]', '!bg-[#eef2f6]', '!border-[#eef2f6]');
|
||||
b.classList.remove('active');
|
||||
});
|
||||
this.classList.remove('!text-[#343f52]', '!bg-[#eef2f6]', '!border-[#eef2f6]');
|
||||
this.classList.add('!text-white', '!bg-[#e31e24]', '!border-[#e31e24]');
|
||||
this.classList.add('active');
|
||||
|
||||
const category = this.getAttribute('data-category');
|
||||
const url = new URL(window.location.href);
|
||||
@@ -333,6 +473,45 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
});
|
||||
});
|
||||
|
||||
// Bind Search Form
|
||||
const searchForm = document.getElementById('blog-search-form');
|
||||
const searchInput = document.getElementById('blog-search-input');
|
||||
if (searchForm && searchInput) {
|
||||
searchForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const query = searchInput.value.trim();
|
||||
const url = new URL(window.location.href);
|
||||
|
||||
if (query) {
|
||||
url.searchParams.set('search', query);
|
||||
} else {
|
||||
url.searchParams.delete('search');
|
||||
}
|
||||
url.searchParams.delete('page');
|
||||
|
||||
fetchPosts(url.toString());
|
||||
});
|
||||
|
||||
// Clear search automatically when input is empty
|
||||
searchInput.addEventListener('input', function() {
|
||||
if (this.value.trim() === '') {
|
||||
const url = new URL(window.location.href);
|
||||
if (url.searchParams.has('search')) {
|
||||
url.searchParams.delete('search');
|
||||
url.searchParams.delete('page');
|
||||
fetchPosts(url.toString());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Prepopulate search parameter from URL
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const initialSearch = urlParams.get('search') || '';
|
||||
if (initialSearch) {
|
||||
searchInput.value = initialSearch;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('popstate', function(e) {
|
||||
if (e.state && e.state.html) {
|
||||
container.innerHTML = e.state.html;
|
||||
@@ -341,15 +520,18 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const currentCategory = urlParams.get('category') || '';
|
||||
const currentSearch = urlParams.get('search') || '';
|
||||
|
||||
filterBtns.forEach(b => {
|
||||
b.classList.remove('!text-white', '!bg-[#e31e24]', '!border-[#e31e24]');
|
||||
b.classList.add('!text-[#343f52]', '!bg-[#eef2f6]', '!border-[#eef2f6]');
|
||||
b.classList.remove('active');
|
||||
if (b.getAttribute('data-category') === currentCategory) {
|
||||
b.classList.remove('!text-[#343f52]', '!bg-[#eef2f6]', '!border-[#eef2f6]');
|
||||
b.classList.add('!text-white', '!bg-[#e31e24]', '!border-[#e31e24]');
|
||||
b.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
if (searchInput) {
|
||||
searchInput.value = currentSearch;
|
||||
}
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
@@ -363,11 +545,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const activeBtn = Array.from(filterBtns).find(btn => btn.getAttribute('data-category') === initialCategory);
|
||||
if (activeBtn) {
|
||||
filterBtns.forEach(b => {
|
||||
b.classList.remove('!text-white', '!bg-[#e31e24]', '!border-[#e31e24]');
|
||||
b.classList.add('!text-[#343f52]', '!bg-[#eef2f6]', '!border-[#eef2f6]');
|
||||
b.classList.remove('active');
|
||||
});
|
||||
activeBtn.classList.remove('!text-[#343f52]', '!bg-[#eef2f6]', '!border-[#eef2f6]');
|
||||
activeBtn.classList.add('!text-white', '!bg-[#e31e24]', '!border-[#e31e24]');
|
||||
activeBtn.classList.add('active');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user