showCreateModal = true; $this->newFeedId = null; $this->newChannelId = null; $this->newPriority = 50; } public function closeCreateModal(): void { $this->showCreateModal = false; } public function createRoute(): void { $this->validate([ 'newFeedId' => 'required|exists:feeds,id', 'newChannelId' => 'required|exists:platform_channels,id', 'newPriority' => 'required|integer|min:0', ]); $exists = Route::where('feed_id', $this->newFeedId) ->where('platform_channel_id', $this->newChannelId) ->exists(); if ($exists) { $this->addError('newFeedId', 'This route already exists.'); return; } Route::create([ 'feed_id' => $this->newFeedId, 'platform_channel_id' => $this->newChannelId, 'priority' => $this->newPriority, 'is_active' => true, ]); $this->closeCreateModal(); } public function openEditModal(int $feedId, int $channelId): void { $route = Route::where('feed_id', $feedId) ->where('platform_channel_id', $channelId) ->firstOrFail(); $this->editingFeedId = $feedId; $this->editingChannelId = $channelId; $this->editPriority = $route->priority; $this->newKeyword = ''; $this->showKeywordInput = false; } public function closeEditModal(): void { $this->editingFeedId = null; $this->editingChannelId = null; } public function updateRoute(): void { if (!$this->editingFeedId || !$this->editingChannelId) { return; } $this->validate([ 'editPriority' => 'required|integer|min:0', ]); Route::where('feed_id', $this->editingFeedId) ->where('platform_channel_id', $this->editingChannelId) ->update(['priority' => $this->editPriority]); $this->closeEditModal(); } public function toggle(int $feedId, int $channelId): void { $route = Route::where('feed_id', $feedId) ->where('platform_channel_id', $channelId) ->firstOrFail(); $route->is_active = !$route->is_active; $route->save(); } public function delete(int $feedId, int $channelId): void { // Delete associated keywords first Keyword::where('feed_id', $feedId) ->where('platform_channel_id', $channelId) ->delete(); Route::where('feed_id', $feedId) ->where('platform_channel_id', $channelId) ->delete(); } public function addKeyword(): void { if (!$this->editingFeedId || !$this->editingChannelId || empty(trim($this->newKeyword))) { return; } Keyword::create([ 'feed_id' => $this->editingFeedId, 'platform_channel_id' => $this->editingChannelId, 'keyword' => trim($this->newKeyword), 'is_active' => true, ]); $this->newKeyword = ''; $this->showKeywordInput = false; } public function toggleKeyword(int $keywordId): void { $keyword = Keyword::findOrFail($keywordId); $keyword->is_active = !$keyword->is_active; $keyword->save(); } public function deleteKeyword(int $keywordId): void { Keyword::destroy($keywordId); } public function render() { $routes = Route::with(['feed', 'platformChannel']) ->orderBy('priority', 'desc') ->get(); // Batch load keywords for all routes to avoid N+1 queries $routeKeys = $routes->map(fn($r) => $r->feed_id . '-' . $r->platform_channel_id); $allKeywords = Keyword::whereIn('feed_id', $routes->pluck('feed_id')) ->whereIn('platform_channel_id', $routes->pluck('platform_channel_id')) ->get() ->groupBy(fn($k) => $k->feed_id . '-' . $k->platform_channel_id); $routes = $routes->map(function ($route) use ($allKeywords) { $key = $route->feed_id . '-' . $route->platform_channel_id; $route->keywords = $allKeywords->get($key, collect()); return $route; }); $feeds = Feed::where('is_active', true)->orderBy('name')->get(); $channels = PlatformChannel::where('is_active', true)->orderBy('name')->get(); $editingRoute = null; $editingKeywords = collect(); if ($this->editingFeedId && $this->editingChannelId) { $editingRoute = Route::with(['feed', 'platformChannel']) ->where('feed_id', $this->editingFeedId) ->where('platform_channel_id', $this->editingChannelId) ->first(); $editingKeywords = Keyword::where('feed_id', $this->editingFeedId) ->where('platform_channel_id', $this->editingChannelId) ->get(); } return view('livewire.routes', [ 'routes' => $routes, 'feeds' => $feeds, 'channels' => $channels, 'editingRoute' => $editingRoute, 'editingKeywords' => $editingKeywords, ])->layout('layouts.app'); } }