Sistem Ozeti
2
Yeni Tablo
+4
Kolon
Media
Library
song_plays
Kopyasi
Tum Kararlar
Veritabani (2 Tablo + 4 Kolon)
1 muzibu_corporate_spots
| Kolon | Tip | Aciklama |
|---|---|---|
| id | BIGINT PK | |
| corporate_account_id | BIGINT FK | Hangi corporate'a ait |
| title | VARCHAR(255) | Spot basligi |
| slug | VARCHAR(255) | URL-friendly isim |
| duration | INT | Sure (saniye) |
| starts_at | TIMESTAMP NULL | Baslangic (NULL = her zaman) |
| ends_at | TIMESTAMP NULL | Bitis (NULL = suresiz) |
| position | INT DEFAULT 0 | Siralama |
| is_enabled | BOOLEAN DEFAULT TRUE | Aktif mi? |
| is_archived | BOOLEAN DEFAULT FALSE | Arsivlendi mi? |
| timestamps | TIMESTAMP | created_at, updated_at |
Dosya: MediaLibrary ile iliskilendirilir. spots->getFirstMedia('audio')
2 muzibu_corporate_spot_plays (song_plays kopyasi)
| Kolon | Tip | Aciklama |
|---|---|---|
| id | BIGINT PK | |
| spot_id | BIGINT FK | Hangi spot |
| corporate_account_id | BIGINT FK | Hangi sube |
| user_id | BIGINT FK NULL | Kim dinledi |
| ip_address | VARCHAR(45) NULL | IP adresi |
| user_agent | VARCHAR(255) NULL | Tarayici bilgisi |
| device_type | VARCHAR(255) NULL | mobile / desktop |
| browser | VARCHAR(50) NULL | Chrome, Safari, etc. |
| platform | VARCHAR(50) NULL | Windows, iOS, Android |
| listened_duration | INT UNSIGNED NULL | Kac saniye dinledi |
| was_skipped | BOOLEAN DEFAULT FALSE | Atlandi mi? |
| created_at | TIMESTAMP | Basladi |
| updated_at | TIMESTAMP | |
| ended_at | TIMESTAMP NULL | Bitti |
INDEX (corporate_account_id, created_at)
INDEX (user_id)
INDEX (ip_address)
INDEX (device_type)
GUNCELLEME: muzibu_corporate_accounts (+4 kolon)
spot_enabled BOOLEAN DEFAULT TRUE -- Ana sube: Sistem acik mi?
spot_songs_between INT DEFAULT 10 -- Ana sube: Kac sarkida bir?
spot_current_index INT DEFAULT 0 -- Rotation index
spot_is_paused BOOLEAN DEFAULT FALSE -- Her sube: Durduruldu mu?
Dosya Yukleme
Spatie MediaLibrary Kullanimi
Model Ayarlari
class CorporateSpot extends Model
implements HasMedia
{
use InteractsWithMedia;
public function registerMediaCollections(): void
{
$this->addMediaCollection('audio')
->singleFile()
->acceptsMimeTypes([
'audio/mpeg', // MP3
'audio/wav', // WAV
'audio/ogg', // OGG
'audio/aac', // AAC
'audio/mp4', // M4A
]);
}
}
Yukleme Islemi
// Yukleme
$spot->addMediaFromRequest('audio')
->usingFileName(Str::slug($title) . '.mp3')
->toMediaCollection('audio');
// Okuma
$url = $spot->getFirstMediaUrl('audio');
$path = $spot->getFirstMediaPath('audio');
// Duration almak
$media = $spot->getFirstMedia('audio');
$duration = $media->getCustomProperty('duration');
Dosya Ozellikleri
30 MB
MP3, WAV, OGG, AAC, M4A
(Tum ses formatlari)
Orijinal ismin slug'i
yilbasi-kampanyasi.mp3
Depolama Yolu
// MediaLibrary varsayilan yolu:
storage/app/public/media/{media_id}/{slug}.mp3
// Ornek:
storage/app/public/media/1234/yilbasi-kampanyasi.mp3
// Public URL:
https://muzibu.com/storage/media/1234/yilbasi-kampanyasi.mp3
Sistem Akisi
Corporate Spot Yukler
Ses dosyasi (MediaLibrary) + baslik + tarih + sira
Sube Kontrol Eder
Durdur/devam (spot_is_paused)
Player 30 sn Sayar
localStorage ile sayac tutar (performans)
10 Sarkida Spot Calar
Siradaki spot calar, kullanici atlayabilir
Dinlenme Loglanir
spot_plays tablosuna (song_plays gibi) detayli kayit
Spot Calmasi Icin Kosullar
SELECT s.*, m.file_name, m.disk
FROM muzibu_corporate_spots s
LEFT JOIN media m ON m.model_id = s.id
AND m.model_type = 'CorporateSpot'
AND m.collection_name = 'audio'
WHERE s.corporate_account_id = :main_corporate_id
AND s.is_enabled = TRUE
AND s.is_archived = FALSE
AND (s.starts_at IS NULL OR s.starts_at <= NOW())
AND (s.ends_at IS NULL OR s.ends_at >= NOW())
ORDER BY s.position ASC
Kurumsal Panel
Spot Yukleme
Dosya adi: yilbasi-kampanyasi.mp3
Dosyayi surukle veya tikla
Max 30 MB • MP3, WAV, OGG, AAC, M4A
Yilbasi Kampanyasi
yilbasi-kampanyasi.mp3
Spotlariniz
Yilbasi Kampanyasi
0:45 • 1.2 MB • yilbasi-kampanyasi.mp3
25 Ara - 05 Oca
152 dinlenme • 12 atlama
Player & 30 Saniye Kurali
Spot Calarken
Yilbasi Kampanyasi
30 Saniye Kurali & Loglama
// Sarki 30 sn dinlenince sayac artar
function onSongTimeUpdate(currentTime) {
if (currentTime >= 30 && !this.songCounted) {
this.songCounted = true;
let count = parseInt(localStorage.getItem('spot_count') || '0');
count++;
if (count >= this.spotSongsBetween) {
this.playNextSpot();
localStorage.setItem('spot_count', '0');
} else {
localStorage.setItem('spot_count', count.toString());
}
}
}
// Spot bitince veya atlaninca - DETAYLI LOG
async function logSpotPlay(spot, wasSkipped, listenedDuration) {
await fetch('/api/spot/played', {
method: 'POST',
body: JSON.stringify({
spot_id: spot.id,
was_skipped: wasSkipped,
listened_duration: listenedDuration,
// Backend otomatik ekler:
// user_id, ip_address, user_agent,
// device_type, browser, platform
})
});
}
API Endpoints
Corporate
Sube
Player
Gelistirme Sirasi
2 migration + 2 model + MediaLibrary
CRUD + upload + istatistik
Durdur/devam
30 sn kurali + spot calar + loglama
Migration + build + test