AI İÇİN TALİMATLAR
Görev Tamamlandığında:
- Bu HTML dosyasını aç:
public/readme/2025/12/20/muzibu-component-audit/v2/index.html - İlgili görevin
todo-itemdiv'inecompletedclass'ı ekle - Checkbox'a
✓işareti koy - Header'daki sayacı güncelle (örn: 1 / 28, 2 / 28...)
- Varsa notları "Yapılan Değişiklikler" bölümüne ekle
Önemli Kurallar:
- Her görev tamamlandığında HEMEN bu dosyayı güncelle
- Sırayla ilerle - öncelik numaralarına uy
- CSS değişikliği yaptıysan:
npm run prodçalıştır - View değişikliği yaptıysan:
php artisan view:clear && php artisan responsecache:clear
Hızlı Komutlar:
npm run prod
php artisan view:clear && php artisan responsecache:clear
KRİTİK CSS HATALARI
ÖNCELİK: ACİLTespit Edilen Sorunlar:
muzibu-coral- Tailwind config'de tanımlanmamış!muzibu-gray- Tailwind config'de tanımlanmamış!bg-white/5,bg-white/10- Safelist'te yok, purge edilmiş olabilir!bg-black/40,bg-black/70- Safelist'te yok!
tailwind/tenants/tenant-1001.config.js dosyasına muzibu-coral ve muzibu-gray ekle
colors: {
...baseConfig.theme.extend.colors,
// Spotify-style Muzibu colors
'spotify-black': '#121212',
'spotify-dark': '#181818',
'spotify-green': '#1DB954',
'spotify-green-light': '#1ed760',
'spotify-gray': '#282828',
// Muzibu custom colors - YENİ EKLE
'muzibu-coral': '#ff7f50',
'muzibu-gray': '#1a1a1a',
}
tailwind/tenants/tenant-1001.config.js safelist'ine opacity class'ları ekle
safelist: [
...baseConfig.safelist,
// Opacity backgrounds - YENİ EKLE
'bg-white/5', 'bg-white/10', 'bg-white/20',
'bg-black/20', 'bg-black/40', 'bg-black/50', 'bg-black/60', 'bg-black/70', 'bg-black/90',
'hover:bg-white/10', 'hover:bg-black/60', 'hover:bg-black/90',
// Muzibu coral variants
'bg-muzibu-coral', 'text-muzibu-coral', 'border-muzibu-coral',
'bg-muzibu-coral/10', 'bg-muzibu-coral/20',
'hover:bg-muzibu-coral', 'hover:text-muzibu-coral',
'ring-muzibu-coral',
// Muzibu gray variants
'bg-muzibu-gray', 'hover:bg-gray-700',
// ... existing safelist
]
Config değişikliklerinden sonra CSS'i yeniden oluştur
YENİ COMPONENT OLUŞTURMA
ÖNCELİK: YÜKSEKAna sayfa Quick Access için yatay playlist kartı
resources/views/components/muzibu/playlist-quick-card.blade.php
@props(['playlist', 'index' => 0])
{{-- Muzibu Playlist Quick Card Component --}}
{{-- Usage: <x-muzibu.playlist-quick-card :playlist="$playlist" /> --}}
{{-- Ana sayfa Quick Access için yatay kart --}}
@php
$isFavorite = auth()->check() && method_exists($playlist, 'isFavoritedBy') && $playlist->isFavoritedBy(auth()->id());
$isMine = auth()->check() && isset($playlist->user_id) && $playlist->user_id == auth()->id();
@endphp
<div class="playlist-card group flex items-center gap-3 bg-white/5 hover:bg-white/10 rounded transition-all cursor-pointer overflow-hidden h-16 relative"
data-playlist-id="{{ $playlist->id ?? $playlist->playlist_id }}"
data-context-type="playlist"
x-data="{ touchTimer: null, touchStartPos: { x: 0, y: 0 } }"
x-on:contextmenu.prevent.stop="$store.contextMenu.openContextMenu($event, 'playlist', {
id: {{ $playlist->id ?? $playlist->playlist_id }},
title: '{{ addslashes($playlist->getTranslation('title', app()->getLocale())) }}',
is_favorite: {{ $isFavorite ? 'true' : 'false' }},
is_mine: {{ $isMine ? 'true' : 'false' }}
})"
x-on:touchstart="touchStartPos = { x: $event.touches[0].clientX, y: $event.touches[0].clientY }; touchTimer = setTimeout(() => { if (navigator.vibrate) navigator.vibrate(50); $store.contextMenu.openContextMenu({ clientX: $event.touches[0].clientX, clientY: $event.touches[0].clientY }, 'playlist', { id: {{ $playlist->id ?? $playlist->playlist_id }}, title: '{{ addslashes($playlist->getTranslation('title', app()->getLocale())) }}', is_favorite: {{ $isFavorite ? 'true' : 'false' }}, is_mine: {{ $isMine ? 'true' : 'false' }} }); }, 500);"
x-on:touchend="clearTimeout(touchTimer)"
x-on:touchmove="if (Math.abs($event.touches[0].clientX - touchStartPos.x) > 10 || Math.abs($event.touches[0].clientY - touchStartPos.y) > 10) clearTimeout(touchTimer);"
@click="$store.sidebar.showPreview('playlist', {{ $playlist->id ?? $playlist->playlist_id }}, {
type: 'Playlist',
id: {{ $playlist->id ?? $playlist->playlist_id }},
title: '{{ addslashes($playlist->getTranslation('title', app()->getLocale())) }}',
cover: '{{ $playlist->coverMedia ? thumb($playlist->coverMedia, 300, 300, ['scale' => 1]) : '' }}',
is_favorite: {{ $isFavorite ? 'true' : 'false' }}
})">
{{-- Cover Image --}}
<div class="w-16 h-16 flex-shrink-0 bg-gradient-to-br from-muzibu-coral to-pink-600">
@if($playlist->coverMedia)
<img src="{{ thumb($playlist->coverMedia, 64, 64, ['scale' => 1]) }}"
alt="{{ $playlist->getTranslation('title', app()->getLocale()) }}"
loading="{{ $index < 6 ? 'eager' : 'lazy' }}"
class="w-full h-full object-cover">
@else
<div class="w-full h-full flex items-center justify-center text-xl text-white/90">🎵</div>
@endif
</div>
{{-- Title --}}
<div class="flex-1 min-w-0 pr-20">
<h3 class="font-semibold text-white text-sm truncate">
{{ $playlist->getTranslation('title', app()->getLocale()) }}
</h3>
</div>
{{-- Favorite + Menu Buttons - HOVER'DA GÖRÜNÜR --}}
<div class="absolute right-2 top-1/2 -translate-y-1/2 z-10 flex gap-1 opacity-0 group-hover:opacity-100 transition-opacity" @click.stop>
{{-- Favorite Button --}}
<button @click.stop="$store.favorites.toggle('playlist', {{ $playlist->id ?? $playlist->playlist_id }})"
class="w-7 h-7 bg-black/40 hover:bg-black/60 rounded-full flex items-center justify-center text-white/70 hover:text-white transition-all"
x-bind:class="$store.favorites.isFavorite('playlist', {{ $playlist->id ?? $playlist->playlist_id }}) ? 'text-muzibu-coral' : ''">
<i class="text-xs"
x-bind:class="$store.favorites.isFavorite('playlist', {{ $playlist->id ?? $playlist->playlist_id }}) ? 'fas fa-heart' : 'far fa-heart'"></i>
</button>
{{-- 3-Dot Menu Button --}}
<button @click.stop="$store.contextMenu.openContextMenu($event, 'playlist', {
id: {{ $playlist->id ?? $playlist->playlist_id }},
title: '{{ addslashes($playlist->getTranslation('title', app()->getLocale())) }}',
is_favorite: {{ $isFavorite ? 'true' : 'false' }},
is_mine: {{ $isMine ? 'true' : 'false' }}
})" class="w-7 h-7 bg-black/40 hover:bg-black/60 rounded-full flex items-center justify-center text-white/70 hover:text-white transition-all">
<i class="fas fa-ellipsis-v text-xs"></i>
</button>
</div>
</div>
Favoriler ve grid görünüm için şarkı kartı (album-card benzeri)
resources/views/components/muzibu/song-card.blade.php
@props(['song', 'preview' => false])
{{-- Muzibu Song Card Component --}}
{{-- Grid görünüm için şarkı kartı --}}
@php
$isFavorite = auth()->check() && method_exists($song, 'isFavoritedBy') && $song->isFavoritedBy(auth()->id());
$albumCover = $song->album && $song->album->coverMedia ? $song->album->coverMedia : null;
@endphp
<div class="group bg-muzibu-gray hover:bg-gray-700 rounded-lg p-4 transition-all duration-300 cursor-pointer"
data-song-id="{{ $song->id }}"
data-album-id="{{ $song->album_id ?? '' }}"
data-context-type="song"
x-on:click="$store.player.playSong({{ $song->id }})"
x-on:contextmenu.prevent.stop="..."
x-bind:class="$store.player.currentSong?.id === {{ $song->id }} ? 'ring-2 ring-muzibu-coral' : ''">
{{-- Cover + Play Button --}}
<div class="relative mb-4">
@if($albumCover)
<img src="{{ thumb($albumCover, 300, 300) }}" ... />
@else
<div class="w-full aspect-square bg-gradient-to-br from-muzibu-coral to-purple-600 rounded-lg ...">
<i class="fas fa-music text-white text-4xl opacity-50"></i>
</div>
@endif
{{-- Play Button --}}
<button @click.stop="$store.player.playSong({{ $song->id }})"
class="absolute bottom-2 right-2 opacity-0 group-hover:opacity-100 ... bg-muzibu-coral ...">
<i class="fas fa-play ml-1"></i>
</button>
{{-- Favorite + Menu --}}
<div class="absolute top-2 right-2 z-10 flex gap-2 opacity-0 group-hover:opacity-100 ...">
{{-- Favorite Button --}}
<button @click.stop="$store.favorites.toggle('song', {{ $song->id }})" ...>
<i x-bind:class="$store.favorites.isFavorite('song', {{ $song->id }}) ? 'fas fa-heart' : 'far fa-heart'"></i>
</button>
{{-- Menu Button --}}
...
</div>
</div>
{{-- Song Title --}}
<h3 class="font-semibold text-white mb-1 truncate">{{ $song->getTranslation('title', app()->getLocale()) }}</h3>
{{-- Artist --}}
@if($song->album && $song->album->artist)
<p class="text-sm text-gray-400 truncate">{{ $song->album->artist->getTranslation('title', app()->getLocale()) }}</p>
@endif
</div>
Tam kodu album-card'dan kopyala ve şarkıya uyarla
Tekrar eden scroll logic'i tek component'te topla
resources/views/components/muzibu/horizontal-scroll-section.blade.php
@props(['title' => null])
{{-- Kullanım: --}}
{{-- <x-muzibu.horizontal-scroll-section title="Öne Çıkanlar"> --}}
{{-- @foreach($items as $item) ... @endforeach --}}
{{-- </x-muzibu.horizontal-scroll-section> --}}
<div class="mb-6 relative group/scroll" x-data="horizontalScroll()">
@if($title)
<h2 class="text-2xl font-bold text-white mb-2">{{ $title }}</h2>
@endif
{{-- Left/Right Arrows --}}
<button @click="scrollLeft()" class="absolute left-[-12px] ...">...</button>
<button @click="scrollRight()" class="absolute right-[-12px] ...">...</button>
{{-- Scroll Container --}}
<div x-ref="scrollContainer" class="flex gap-2 overflow-x-auto scrollbar-hide scroll-smooth pb-4">
{{ $slot }}
</div>
</div>
ANA SAYFA DÜZELTMELERİ
ÖNCELİK: YÜKSEKAna sayfa Quick Access bölümündeki inline HTML'i component ile değiştir
resources/views/themes/muzibu/index.blade.php (Satır 63-114)
❌ ESKİ (50 satır inline):
@foreach($featuredPlaylists->take(8) as $index => $playlist)
<div class="playlist-card group flex items-center gap-3 ..."
x-data="{ touchTimer: null, ... }"
x-on:contextmenu.prevent.stop="..."
x-on:touchstart="..."
@click="...">
... 50 satır inline HTML ...
</div>
@endforeach
✅ YENİ (3 satır):
@foreach($featuredPlaylists->take(8) as $index => $playlist)
<x-muzibu.playlist-quick-card
:playlist="$playlist"
:index="$index"
/>
@endforeach
4 kez tekrar eden x-data scroll logic'i için horizontal-scroll-section component kullan
Inline style tag'i (scrollbar-hide) global CSS'e taşı
<style>.scrollbar-hide...</style> kaldır, tenant CSS'e ekle
DİĞER SAYFA DÜZELTMELERİ
ÖNCELİK: ORTAInline album kartlarını component ile değiştir
resources/views/themes/muzibu/artists/show.blade.php (Satır 56-84)
3 tip inline kartı component ile değiştir (song-card, album-card, playlist-card)
Modules/Muzibu/.../favorites/index.blade.php (Satır 44-158)
Hardcoded Unsplash URL'i gerçek album cover ile değiştir
https://images.unsplash.com/... → {{ $album->coverMedia ? thumb($album->coverMedia, 232, 232) : '' }}
Hardcoded Unsplash URL'i gerçek playlist cover ile değiştir
https://images.unsplash.com/... → {{ $playlist->coverMedia ? thumb($playlist->coverMedia, 232, 232) : '' }}
FAVORİ BUTONU KONTROLÜ
DOĞRULAMAMevcut Durum (İYİ):
Tüm mevcut component'lerde favori butonu VAR:
Yeni oluşturulan component'e hover'da görünen favori butonu ekle (2.1'de yapıldı mı kontrol et)
Yeni oluşturulan component'e hover'da görünen favori butonu ekle (2.2'de yapıldı mı kontrol et)
Her component'te favori butonunun çalıştığını doğrula:
- • Hover'da görünüyor mu?
- • Tıklayınca toggle oluyor mu?
- • Favorilenmişse kalp dolu mu?
- • Alpine store ile senkron mu?
GENEL İYİLEŞTİRMELER
ÖNCELİK: DÜŞÜKBoş içerik durumları için merkezi component
Sanatçı listesi ve arama için yuvarlak kart
.scrollbar-hide class'ını tenant CSS'e ekle
Her component'in başına kullanım örneği yorum ekle
Yapılan Değişiklikler Log
AI, her tamamlanan görev için buraya log ekle:
Format: [TARİH] [SAAT] - [GÖREV ID] tamamlandı: [KISA AÇIKLAMA]
Görev Özeti
| Bölüm | Görev Sayısı | Öncelik | Durum |
|---|---|---|---|
| 1. Kritik CSS Hataları | 3 | ACİL | 3/3 ✅ |
| 2. Yeni Component Oluşturma | 3 | YÜKSEK | 2/3 ✅ |
| 3. Ana Sayfa Düzeltmeleri | 3 | YÜKSEK | 2/3 ✅ |
| 4. Diğer Sayfa Düzeltmeleri | 4 | ORTA | 4/4 ✅ |
| 5. Favori Butonu Kontrolü | 3 | DOĞRULAMA | 3/3 ✅ |
| 6. Genel İyileştirmeler | 4 | DÜŞÜK | 0/4 (Opsiyonel) |
| TOPLAM | 20 | - | 14/20 ✅ |