191 lines
5.8 KiB
PHP
191 lines
5.8 KiB
PHP
<?php
|
||
|
||
namespace App\Livewire\Partials;
|
||
|
||
use App\Models\Blog;
|
||
use App\Models\Category;
|
||
use Livewire\Component;
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Collection;
|
||
use Illuminate\Support\Str;
|
||
|
||
class Header extends Component
|
||
{
|
||
public $search = '';
|
||
public $showMenu = false;
|
||
public $activeTab = 'posts';
|
||
public $selectedCategory = null;
|
||
public $blogsSearchs = [];
|
||
public $expandedCategory = null;
|
||
public $categoryBlogs = [];
|
||
public $loadedCategories = [];
|
||
public $loadingStates = [];
|
||
public $dynamicBlogs = [];
|
||
public $lastNewsPosts2 = [];
|
||
|
||
// دادههای اصلی
|
||
public $blogs;
|
||
public $categories;
|
||
|
||
protected $cacheKey = 'header_all_data_v4';
|
||
protected $cacheExpiration = 60; // 1 دقیقه
|
||
|
||
public function mount()
|
||
{
|
||
$this->loadAllData();
|
||
}
|
||
|
||
protected function loadAllData()
|
||
{
|
||
$data = Cache::remember($this->cacheKey, $this->cacheExpiration, function () {
|
||
return $this->fetchAllData();
|
||
});
|
||
|
||
$this->blogs = $data['blogs'];
|
||
$this->categories = $data['categories_full'];
|
||
$this->lastNewsPosts2 = $data['lastNewsPosts2'];
|
||
}
|
||
|
||
protected function fetchAllData(): array
|
||
{
|
||
// فقط 10 پست کافی است
|
||
$blogs = Blog::where('status', 1)
|
||
->select('id', 'subject', 'slug', 'image', 'published_at', 'category_id', 'notBlog', 'category_array')
|
||
->orderByDesc('published_at')
|
||
->take(10)
|
||
->get();
|
||
|
||
$categories = Category::where('status', 1)
|
||
->with(['children' => fn($q) => $q->orderByDesc('priority')])
|
||
->orderByDesc('priority')
|
||
->get();
|
||
|
||
$posts = $blogs->whereNull('notBlog');
|
||
$articles = $blogs->where('notBlog', 1);
|
||
|
||
return [
|
||
'blogs' => $blogs,
|
||
'lastNewsPosts2' => $posts->take(10),
|
||
'categories_full' => $categories,
|
||
'categoriesNotBlog' => $categories->whereNotNull('parent_id')->whereNull('parent'),
|
||
'categoriesNotBlogM' => $categories->where('is_news', 1)->whereNull('parent_below')->whereNotNull('parent_id'),
|
||
];
|
||
}
|
||
|
||
public function loadCategoryData($categoryId)
|
||
{
|
||
if (isset($this->categoryBlogs[$categoryId])) {
|
||
$this->expandedCategory = $categoryId;
|
||
return;
|
||
}
|
||
|
||
$this->expandedCategory = $categoryId;
|
||
$this->loadingStates[$categoryId] = true;
|
||
$this->dynamicBlogs[$categoryId] = [];
|
||
|
||
if (!in_array($categoryId, $this->loadedCategories)) {
|
||
$this->loadedCategories[] = $categoryId;
|
||
}
|
||
|
||
$blogs = Cache::remember("category_blogs_{$categoryId}", 300, function () use ($categoryId) {
|
||
return Blog::where('status', 1)
|
||
->select('id', 'subject', 'slug', 'image', 'published_at')
|
||
->where(function ($q) use ($categoryId) {
|
||
$q->where('category_id', $categoryId)
|
||
->orWhereJsonContains('category_array', (string)$categoryId);
|
||
})
|
||
->orderByDesc('published_at')
|
||
->take(4)
|
||
->get();
|
||
});
|
||
|
||
$this->categoryBlogs[$categoryId] = $blogs;
|
||
$this->dynamicBlogs[$categoryId] = $blogs->toArray();
|
||
$this->loadingStates[$categoryId] = false;
|
||
}
|
||
|
||
public function getLastNewsPosts($notBlog)
|
||
{
|
||
$this->activeTab = $notBlog ? 'news' : 'posts';
|
||
$this->selectedCategory = null;
|
||
|
||
$source = $notBlog
|
||
? $this->blogs->where('notBlog', 1)
|
||
: $this->blogs->whereNull('notBlog');
|
||
|
||
$this->lastNewsPosts2 = $source->take(10);
|
||
}
|
||
|
||
public function searchBox()
|
||
{
|
||
if (empty($this->search)) {
|
||
$this->showMenu = false;
|
||
$this->blogsSearchs = [];
|
||
return;
|
||
}
|
||
|
||
$search = str_replace(['', ' '], ' ', $this->search);
|
||
$searchVariants = [$search, str_replace(' ', '***', $search)];
|
||
|
||
$source = $this->activeTab === 'posts'
|
||
? $this->blogs->whereNull('notBlog')
|
||
: $this->blogs->where('notBlog', 1);
|
||
|
||
if ($this->selectedCategory) {
|
||
$source = $source->filter(fn($b) =>
|
||
$b->category_id == $this->selectedCategory ||
|
||
in_array($this->selectedCategory, $b->category_array ?? [])
|
||
);
|
||
}
|
||
|
||
$this->blogsSearchs = $source->filter(function ($blog) use ($searchVariants) {
|
||
$subject = $blog->subject;
|
||
$excerpt = $blog->excerpt ?? '';
|
||
|
||
foreach ($searchVariants as $variant) {
|
||
if (str_contains($subject, $variant) || str_contains($excerpt, $variant)) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
})
|
||
->sortByDesc(function ($blog) use ($searchVariants) {
|
||
foreach ($searchVariants as $i => $variant) {
|
||
if (str_contains($blog->subject, $variant)) {
|
||
return $i;
|
||
}
|
||
}
|
||
return 10;
|
||
})
|
||
->take(10)
|
||
->values();
|
||
|
||
$this->showMenu = $this->blogsSearchs->isNotEmpty();
|
||
}
|
||
|
||
public function selectCategory($categoryId = null)
|
||
{
|
||
$this->selectedCategory = $categoryId;
|
||
$this->searchBox();
|
||
}
|
||
|
||
public function resetCategory()
|
||
{
|
||
$this->selectedCategory = null;
|
||
$this->searchBox();
|
||
}
|
||
|
||
public function refreshsearch()
|
||
{
|
||
$this->reset('blogsSearchs');
|
||
$this->searchBox();
|
||
}
|
||
|
||
public function render()
|
||
{
|
||
return view('livewire.partials.header', [
|
||
'rootCategories' => $this->categories->whereNull('parent_id')->whereNull('parent_below')->where('is_news', 0),
|
||
'lastNewsPosts' => $this->blogs->whereNull('notBlog')->take(10),
|
||
]);
|
||
}
|
||
} |