*/ public array $expandedFeeds = []; public function setTab(string $tab): void { $this->tab = $tab; $this->search = ''; $this->expandedFeeds = []; $this->resetPage(); } public function updatedFeedId(): void { $this->expandedFeeds = []; $this->resetPage(); } public function toggleFeed(int $feedId): void { if (isset($this->expandedFeeds[$feedId])) { unset($this->expandedFeeds[$feedId]); return; } $this->expandedFeeds[$feedId] = true; } public function updatedSearch(): void { $this->resetPage(); } public function approve(int $routeArticleId): void { RouteArticle::findOrFail($routeArticleId)->approve(); } public function reject(int $routeArticleId): void { RouteArticle::findOrFail($routeArticleId)->reject(); } public function restore(int $routeArticleId): void { $routeArticle = RouteArticle::findOrFail($routeArticleId); $routeArticle->update(['approval_status' => ApprovalStatusEnum::PENDING]); } public function clear(): void { $this->clearableQuery()->update(['approval_status' => ApprovalStatusEnum::REJECTED]); $this->expandedFeeds = []; } /** * @return Builder */ private function clearableQuery(): Builder { return RouteArticle::query() ->where('approval_status', ApprovalStatusEnum::PENDING) ->when($this->feedId !== null, fn (Builder $q) => $q->where('feed_id', $this->feedId)); } public function refresh(): void { $this->isRefreshing = true; ArticleDiscoveryJob::dispatch(); $this->dispatch('refresh-started'); } public function render(): View { $pendingCount = RouteArticle::where('approval_status', ApprovalStatusEnum::PENDING)->count(); if ($this->tab === 'pending') { return view('livewire.articles', [ 'routeArticles' => null, 'pendingFeeds' => $this->pendingFeeds(), 'feedOptions' => $this->feedOptions(), 'pendingCount' => $pendingCount, 'clearableCount' => $this->clearableQuery()->count(), ])->layout('layouts.app'); } $query = RouteArticle::with(['article.feed', 'feed', 'platformChannel']) ->orderBy('created_at', 'desc'); if ($this->feedId !== null) { $query->where('feed_id', $this->feedId); } if ($this->search !== '') { $search = $this->search; $query->whereHas('article', function ($q) use ($search) { $q->where('title', 'like', "%{$search}%") ->orWhere('description', 'like', "%{$search}%"); }); } return view('livewire.articles', [ 'routeArticles' => $query->paginate(15), 'pendingFeeds' => null, 'feedOptions' => $this->feedOptions(), 'pendingCount' => $pendingCount, 'clearableCount' => 0, ])->layout('layouts.app'); } /** * @return Collection */ private function pendingFeeds(): Collection { $counts = RouteArticle::query() ->selectRaw('feed_id, COUNT(*) as aggregate') ->where('approval_status', ApprovalStatusEnum::PENDING) ->when($this->feedId !== null, fn ($q) => $q->where('feed_id', $this->feedId)) ->groupBy('feed_id') ->pluck('aggregate', 'feed_id'); return Feed::whereIn('id', $counts->keys())->get() ->map(fn (Feed $feed): PendingFeedGroup => new PendingFeedGroup( $feed, (int) $counts->get($feed->id, 0), isset($this->expandedFeeds[$feed->id]) ? $this->routeArticlesForFeed($feed->id) : null, )) ->sortByDesc('count') ->values(); } /** * @return EloquentCollection */ private function feedOptions(): EloquentCollection { return Feed::whereIn('id', RouteArticle::query()->select('feed_id')->distinct()) ->orderBy('name') ->get(); } /** * @return EloquentCollection */ private function routeArticlesForFeed(int $feedId): EloquentCollection { return RouteArticle::with(['article.feed', 'feed', 'platformChannel']) ->where('approval_status', ApprovalStatusEnum::PENDING) ->where('feed_id', $feedId) ->orderBy('created_at', 'desc') ->get(); } }