Soldan sağa taşınan item'lar arama yapılınca kayboluyor
Sorun nedir?
Admin panelde radyo, playlist, sektör gibi yerlerde "soldan sağa seçim yapma" sistemi var.
Kullanıcı sol taraftan bir şey seçip sağ tarafa taşıyor. Sonra başka bir şey aramak için
arama kutusuna yazıyor. O anda daha önce seçtiği şeyler
kayboluyor!
Örnek senaryo:
Radyo oluştururken 5 tane playlist seçtin → Sağ tarafa taşıdın → Tamam güzel!
Sonra 6. playlist'i bulmak için arama yaptın →
İlk 5 playlist kayboldu!
Neden önemli?
Kullanıcı radyo oluştururken 20 tane playlist seçmiş olabilir. Aramak istediğinde
hepsi uçuyor ve baştan seçmek zorunda kalıyor. Bu kullanılamaz bir deneyim.
Etkilenen Sayfalar:
admin/muzibu/radio/manage - Radyo yönetimi (playlist seçimi)admin/muzibu/playlist/manage - Playlist yönetimi (sektör, radyo, tür, kurum seçimi)admin/muzibu/song/manage - Şarkı yönetimi (muhtemelen varsa)admin/muzibu/sector/manage - Sektör yönetimi (muhtemelen varsa)Dual listbox sistemi hybrid bir yapı:
1️⃣ Kullanıcı "Playlist A" seçti
→ JavaScript: DOM'da soldan sağa taşıdı ✅
→ JavaScript: @this.set('inputs.playlist_ids', [1]) gönderdi ✅
→ Livewire: $inputs['playlist_ids'] = [1] ✅
2️⃣ Kullanıcı "Playlist B"yi aramak için "search" yazdı
→ Livewire: $playlistSearch = "search" değişti
→ Livewire: activePlaylists() computed property tetiklendi
→ Livewire: Sadece "search" içeren playlist'leri getir
→ Livewire: RENDER! (Blade yeniden render edildi)
3️⃣ Blade Render Sırasında:
@foreach($this->activePlaylists as $playlist)
// activePlaylists() sadece arama sonuçlarını döndürüyor
// "Playlist A" arama sonucunda YOK!
// Blade "Playlist A"yı görmüyor
// Sağ tarafta render edilemiyor
@endforeach
4️⃣ SONUÇ:
❌ "Playlist A" kayboldu! (Arama sonucunda olmadığı için render edilmedi)
❌ Kullanıcı "Playlist A"yı görmüyor
❌ Tekrar aramak zorunda kalıyor
Dosya: RadioManageComponent.php
#[Computed]
public function activePlaylists()
{
$query = \Modules\Muzibu\App\Models\Playlist::where('is_active', true);
// ❌ SORUN: Sadece arama sonuçlarını döndürüyor
if (!empty($this->playlistSearch)) {
$locale = app()->getLocale();
$search = strtolower($this->playlistSearch);
$query->where(function($q) use ($search, $locale) {
$q->whereRaw("LOWER(JSON_UNQUOTE(JSON_EXTRACT(title, ?))) LIKE ?",
["$.{$locale}", "%{$search}%"]);
});
}
return $query->orderBy('title->tr')->get();
// ❌ Seçili item'lar arama sonucunda yoksa render edilmiyor!
}
Dosya: radio-manage-component.blade.php
<!-- Sol Taraf: Mevcut Listeler -->
<div class="listbox" id="available-playlists">
@foreach($this->activePlaylists as $playlist)
@if(!in_array($playlist->playlist_id, $inputs['playlist_ids'] ?? []))
<div class="listbox-item">{{ $playlist->title }}</div>
@endif
@endforeach
</div>
<!-- Sağ Taraf: Seçilen Listeler -->
<div class="listbox" id="selected-playlists">
@foreach($this->activePlaylists as $playlist)
@if(in_array($playlist->playlist_id, $inputs['playlist_ids'] ?? []))
<!-- ❌ SORUN: activePlaylists'te yoksa burası boş kalıyor! -->
<div class="listbox-item">{{ $playlist->title }}</div>
@endif
@endforeach
</div>
activePlaylists() computed property'sini iki ayrı property'ye böl:
availablePlaylists() → Arama sonuçları (seçilmemiş olanlar)selectedPlaylists() → Seçili olanlar (her zaman render et)
Backend: RadioManageComponent.php
// ✅ ÇÖZÜM 1: Seçilmemiş olanlar (arama sonuçları)
#[Computed]
public function availablePlaylists()
{
$query = \Modules\Muzibu\App\Models\Playlist::where('is_active', true);
// Seçilenleri hariç tut
if (!empty($this->inputs['playlist_ids'])) {
$query->whereNotIn('playlist_id', $this->inputs['playlist_ids']);
}
// Arama filtresi
if (!empty($this->playlistSearch)) {
$locale = app()->getLocale();
$search = strtolower($this->playlistSearch);
$query->where(function($q) use ($search, $locale) {
$q->whereRaw("LOWER(JSON_UNQUOTE(JSON_EXTRACT(title, ?))) LIKE ?",
["$.{$locale}", "%{$search}%"]);
});
}
return $query->orderBy('title->tr')->get();
}
// ✅ ÇÖZÜM 2: Seçili olanlar (her zaman göster)
#[Computed]
public function selectedPlaylists()
{
if (empty($this->inputs['playlist_ids'])) {
return collect([]);
}
// Seçili playlist'leri ID'ye göre getir
return \Modules\Muzibu\App\Models\Playlist::whereIn('playlist_id', $this->inputs['playlist_ids'])
->orderBy('title->tr')
->get();
}
Frontend: radio-manage-component.blade.php
<!-- Sol Taraf: Mevcut Listeler (Seçilmemiş + Arama Sonuçları) -->
<div class="listbox" id="available-playlists">
@foreach($this->availablePlaylists as $playlist)
<div class="listbox-item"
data-value="{{ $playlist->playlist_id }}">
{{ $playlist->getTranslated('title', app()->getLocale()) }}
</div>
@endforeach
</div>
<!-- Sağ Taraf: Seçilen Listeler (Her Zaman Göster) -->
<div class="listbox" id="selected-playlists">
@foreach($this->selectedPlaylists as $playlist)
<!-- ✅ ÇÖZÜM: Seçililer her zaman render ediliyor -->
<div class="listbox-item"
data-value="{{ $playlist->playlist_id }}">
{{ $playlist->getTranslated('title', app()->getLocale()) }}
</div>
@endforeach
</div>
Modules/Muzibu/App/Http/Livewire/Admin/RadioManageComponent.php
activePlaylists() → availablePlaylists() + selectedPlaylists()Modules/Muzibu/resources/views/admin/livewire/radio-manage-component.blade.php
$this->activePlaylists → $this->availablePlaylists ve $this->selectedPlaylistsModules/Muzibu/App/Http/Livewire/Admin/PlaylistManageComponent.php
activeSectors() → availableSectors() + selectedSectors()activeRadios() → availableRadios() + selectedRadios()activeGenres() → availableGenres() + selectedGenres()activeCorporates() → availableCorporates() + selectedCorporates()Modules/Muzibu/resources/views/admin/livewire/playlist-manage-component.blade.php
$this->active* referanslarını $this->available* ve $this->selected* olarak ayırSongManageComponent.php
(varsa playlist/album/artist seçimi)
SectorManageComponent.php
(varsa playlist seçimi)
AlbumManageComponent.php
(varsa song seçimi)
💡 Tüm dual listbox kullanan component'lerde aynı pattern uygulanmalı!
muzibu.com/admin/muzibu/radio/managemuzibu.com/admin/muzibu/playlist/managemuzibu.com/admin/muzibu/song/manage (varsa)