map(fn($tag) => [ 'title' => $tag->name, 'tag' => $tag->slug, 'category' => $category, ]) ->values(); $enumYears = collect(YearsEnum::toArray()) ->map(fn($year) => YearsEnum::make((int) $year->value)) ->map(fn($year) => [ 'title' => trans($year->label()), 'tag' => Str::replace('/', '-', $year->label()), 'value' => $type === "news" ? explode('/', $year->label())[1] : $year->value, 'category' => $category, ]) ->sortDesc() ->values(); $orders = collect(OrdersEnum::toArray()) ->map(fn($order) => OrdersEnum::make((int) $order->value)) ->filter(fn($orderLocal) => $orderLocal->ordersWithLocal()) ->map(fn($orderLocal) => [ 'title' => ucfirst(trans($orderLocal->label())), 'tag' => Str::slug($orderLocal->name), 'category' => $category, ]) ->values(); /** Sort displayed years */ $years = $collectionHelper->getMatchingValues( $collectionHelper->getUniqueYearsFromQuery($query, 'published_at'), $enumYears, 'value' ); if ($type === "documents") { $filters[] = [ 'title' => ucfirst(__('front.news.order')), 'name' => 'order', 'fields' => $orders, ]; } $filters[] = [ 'title' => $type === "documents" ? ucfirst(__('front.news.document')) : ucfirst(__('front.news.theme')), 'name' => 'tags', 'fields' => $tags, ]; $filters[] = [ 'title' => $type === "documents" ? ucfirst(__('front.news.exercise')) : ucfirst(__('front.news.year')), 'name' => 'years', 'fields' => $years, ]; return $filters; } /** * Returns news in JSON format filtered by category and language * Optionally, the results can be further filtered by tags, and years * * @param \App\Http\Requests\Front\PostsRequest $request * @return \Illuminate\Http\JsonResponse */ public function ajaxLoadNews(PostsRequest $request): \Illuminate\Http\JsonResponse { $data = $request->validated(); $perPage = 9; $selectedFilters = []; $category = $data['category']; app()->setLocale($data['locale']); $locale = app()->getLocale(); $publishedNewsTags = NewsTag::getTagsByCategoryInCurrentLocale($category); /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\News> $query */ $query = News::getPublishedNewsByCategoryInCurrentLocale($category); $requestedTags = collect($data['filters']['tags'] ?? '') ->filter() ->unique() ->values(); $selectedTags = $publishedNewsTags->filter(fn ($tag) => $requestedTags->contains($tag->slug ?? null)) ->map(fn ($tag) => [ 'id' => $tag->id, 'title' => $tag->name, 'tag' => $tag->slug, 'color' => $tag->color, 'category' => $category, ]) ->values(); if ($selectedTags->isNotEmpty()) { $query->whereHas('tags', function ($q) use ($selectedTags) { $q->whereIn('newsable_id', $selectedTags->map->id->all()); }); $selectedFilters['tags'] = $selectedTags; } $selectedYears = collect($data['filters']['years'] ?? '') ->map(fn (string $label) => YearsEnum::makeFromLabel(Str::replace('-', '/', $label))) ->filter() ->map(fn($year) => [ 'title' => $year->label(), 'tag' => Str::replace('/', '-', $year->label()), 'value' => explode('/', $year->label())[1], 'category' => $category, ]) ->values(); if ($selectedYears->isNotEmpty()) { foreach ($selectedYears->map->value->all() as $value) { $query->whereYear('published_at', $value); } $selectedFilters['years'] = $selectedYears; } /** Sort columns with a query */ $this->sortQuery($query); $filters = $this->getFilters('news', $category, $publishedNewsTags, $query); /** Custom pagination */ $newsModel = $query->paginate($perPage, ['*'], 'page', $data['page'] ?? 1); return response()->json([ 'pagination' => [ 'total' => $newsModel->total(), 'nbItems' => count($newsModel->items()), 'currentPage' => $newsModel->currentPage(), 'lastPage' => $newsModel->lastPage(), 'hasMore' => $newsModel->currentPage() < $newsModel->lastPage(), ], 'filters' => view('components.front.posts.filters-dropdowns', ['filters' => $filters])->render(), 'selectedFilters' => view('components.front.posts.selected-filters', ['selectedFilters' => $selectedFilters])->render(), 'news' => view('components.front.posts.news', ['newsList' => $newsModel->items()])->render() ]); } /** * Returns documents in JSON format filtered by category and language * Optionally, the results can be further filtered by order, tags, and years * * @param \App\Http\Requests\Front\PostsRequest $request * @return \Illuminate\Http\JsonResponse */ public function ajaxLoadDocuments(PostsRequest $request): \Illuminate\Http\JsonResponse { $data = $request->validated(); $perPage = 3; $selectedFilters = []; $category = $data['category']; app()->setLocale($data['locale']); $locale = app()->getLocale(); $publishedDocumentsTags = DocumentTag::getTagsByCategoryInCurrentLocale($category); /** @var \Illuminate\Database\Eloquent\Builder<\App\Models\Document> $query */ $query = Document::getPublishedDocumentsByCategoryInCurrentLocale($category); $requestedTags = collect($data['filters']['tags'] ?? '') ->filter() ->unique() ->values(); $selectedTags = $publishedDocumentsTags->filter(fn ($tag) => $requestedTags->contains($tag->slug ?? null)) ->map(fn ($tag) => [ 'id' => $tag->id, 'title' => $tag->name, 'tag' => $tag->slug, 'color' => $tag->color, 'category' => $category, ]) ->values(); if ($selectedTags->isNotEmpty()) { $query->whereHas('tags', function ($q) use ($selectedTags) { $q->whereIn('documentable_id', $selectedTags->map->id->all()); }); $selectedFilters['tags'] = $selectedTags; } $selectedYears = collect($data['filters']['years'] ?? '') ->map(fn (string $label) => YearsEnum::makeFromLabel(Str::replace('-', '/', $label))) ->filter() ->map(fn($year) => [ 'title' => $year->label(), 'tag' => Str::replace('/', '-', $year->label()), 'value' => $year->value, 'category' => $category, ]) ->values(); if ($selectedYears->isNotEmpty()) { foreach ($selectedYears->map->value->all() as $value) { $query->where('exercice', $value); } $selectedFilters['years'] = $selectedYears; } $selectedOrder = collect($data['filters']['order'] ?? '') ->map(fn (string $label) => OrdersEnum::makeFromLabel($label)) ->filter() ->map(fn($order) => [ 'title' => trans($order->label()), 'tag' => $order->name(), 'category' => $category, ]) ->values(); if ($selectedOrder->isNotEmpty()) { $query->orderBy('published_at', $selectedOrder->map->tag->first()); $selectedFilters['order'] = $selectedOrder->all(); } /** Sort columns with a query */ $this->sortQuery($query); $filters = $this->getFilters('documents', $category, $publishedDocumentsTags, $query); /** Custom pagination */ $documentsModel = $query->paginate($perPage, ['*'], 'page', $data['page'] ?? 1); return response()->json([ 'pagination' => [ 'total' => $documentsModel->total(), 'nbItems' => count($documentsModel->items()), 'currentPage' => $documentsModel->currentPage(), 'lastPage' => $documentsModel->lastPage(), 'hasMore' => $documentsModel->currentPage() < $documentsModel->lastPage(), ], 'filters' => view('components.front.posts.filters-dropdowns', ['filters' => $filters])->render(), 'selectedFilters' => view('components.front.posts.selected-filters', ['selectedFilters' => $selectedFilters])->render(), 'news' => view('components.front.posts.documents', ['documentsList' => $documentsModel->items()])->render() ]); } }