Files
Atomcms-edit/resources/themes/atom/views/community/radio/index.blade.php
T
root c53a5a8a2c Complete Hubbly theme conversion: all pages rewritten with CSS variable theming
- Converted all views from Dusk components (x-content.content-card, x-form.*) to inline Hubbly style
- All pages use consistent card pattern: rounded-lg, gradient headers, color-mix borders
- Added Hubbly-style homepage with 2-column layout, login card, swiper news carousel
- Rewrote navigation with Alpine.js dropdowns, CSS variable colors, Hubbly assets
- Updated profile page with Hubbly cards, fixed data bugs (friend/guild relationships)
- Rewrote register page to match Hubbly layout: banner header, avatar preview with Frank GIF, 2-column form, avatar carousel selector, border-4 inputs
- Rewrote login, settings, help center, radio, applications, utility pages
- All colors use CSS variables controlled by Filament theme editor
- Added Hubbly assets: banner, Frank GIF, navigation icons, online badge
- Removed all dependencies on x-content.* and x-form.* components
2026-06-27 17:01:02 +02:00

415 lines
18 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<x-app-layout>
@push('title', 'Radio')
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
<div class="flex flex-col gap-y-4">
<div class="rounded-lg overflow-hidden" style="background-color: var(--color-surface); border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent);">
<div class="relative w-full" style="background: linear-gradient(140deg, var(--color-primary) 0%, color-mix(in srgb, var(--color-primary) 80%, black) 100%);">
<div class="flex items-center h-full px-4 py-3 gap-3">
<div class="w-8 h-8 rounded-full flex items-center justify-center text-lg shadow-lg" style="background-color: color-mix(in srgb, var(--color-primary) 30%, transparent);">
🎵
</div>
<div>
<p class="text-white font-bold text-sm">{{ setting('hotel_name') }} Radio</p>
<p class="text-xs" style="color: rgba(255,255,255,0.8)">Luister live naar onze DJ's!</p>
</div>
</div>
</div>
<div class="p-4 text-sm space-y-4" style="color: var(--color-text)">
@if($currentDJ && is_array($currentDJ) && isset($currentDJ['username']))
@php
$currentDJBanner = $banners->first(function($banner) use ($currentDJ) {
return $banner->user && $banner->user->username === $currentDJ['username'];
});
@endphp
@if($currentDJBanner)
<div class="mb-4 overflow-hidden rounded-lg border-2 shadow-lg" style="border-color: var(--color-primary); box-shadow: 0 10px 15px -3px color-mix(in srgb, var(--color-primary) 20%, transparent);">
<div class="relative">
<img src="{{ $currentDJBanner->image_url }}" alt="{{ $currentDJBanner->title ?? 'DJ Banner' }}" class="w-full h-56 object-cover">
<div class="absolute top-2 left-2">
<span class="bg-red-500 text-white px-3 py-1 rounded-full text-sm font-bold animate-pulse">🔴 NU LIVE</span>
</div>
@if($currentDJBanner->title || $currentDJBanner->description)
<div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/90 via-black/50 to-transparent p-4 rounded-b-lg">
@if($currentDJBanner->title)
<p class="text-white font-bold text-lg">{{ $currentDJBanner->title }}</p>
@endif
@if($currentDJBanner->description)
<p class="text-white/80 text-sm">{{ $currentDJBanner->description }}</p>
@endif
</div>
@endif
</div>
</div>
@endif
@endif
@if($banners->count() > 0)
<div class="mb-4">
<h3 class="text-lg font-bold mb-3" style="color: var(--color-text)">🎧 DJ Banners</h3>
<div class="overflow-hidden rounded-lg">
<div id="banner-carousel" class="relative">
@foreach($banners as $index => $banner)
<div class="banner-slide {{ $index === 0 ? 'block' : 'hidden' }}" data-index="{{ $index }}">
<div class="relative">
<img src="{{ $banner->image_url }}" alt="{{ $banner->title ?? 'DJ Banner' }}" class="w-full h-48 object-cover rounded-lg">
@if($banner->title)
<div class="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-4 rounded-b-lg">
<p class="text-white font-bold">{{ $banner->title }}</p>
@if($banner->user)
<p class="mt-1 text-xs" style="color: var(--color-primary)">DJ: {{ $banner->user->username }}</p>
@endif
</div>
@endif
</div>
</div>
@endforeach
</div>
</div>
@if($banners->count() > 1)
<div class="flex justify-center gap-2 mt-2">
@foreach($banners as $index => $banner)
<button class="banner-dot w-2 h-2 rounded-full bg-gray-400 transition-all duration-300 {{ $index === 0 ? 'w-4' : '' }}" data-index="{{ $index }}"></button>
@endforeach
</div>
@endif
</div>
@endif
<div class="rounded-lg p-4" style="background-color: color-mix(in srgb, var(--color-background) 80%, transparent);">
<div class="mb-4">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center gap-3">
@if($isOnline)
<div class="w-3 h-3 rounded-full bg-red-500 animate-pulse"></div>
<span style="color: var(--color-primary)" class="font-bold">LIVE</span>
@else
<div class="w-3 h-3 rounded-full" style="background-color: var(--color-text-muted)"></div>
<span style="color: var(--color-text-muted)" class="font-bold">OFFLINE</span>
@endif
</div>
@if($isOnline)
<div class="flex items-center gap-1 text-xs" style="color: var(--color-text-muted)" id="listeners-container">
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
<path d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3z"/>
</svg>
<span id="listeners-count">0</span> luisteraars
</div>
@endif
</div>
@if($currentDJ && is_array($currentDJ) && isset($currentDJ['username']))
<div class="mb-3 p-3 rounded-lg" style="background-color: color-mix(in srgb, var(--color-primary) 10%, transparent);">
<p class="text-xs mb-1" style="color: var(--color-text-muted)">Nu aan het draaien:</p>
<p class="font-bold text-lg" style="color: var(--color-primary)">{{ $currentDJ['username'] }}</p>
@if(isset($currentDJ['show_name']) && $currentDJ['show_name'])
<p class="text-sm" style="color: var(--color-text-muted)">{{ $currentDJ['show_name'] }}</p>
@endif
</div>
@else
<p class="text-sm mb-3" style="color: var(--color-text-muted)">Geen DJ actief op dit moment</p>
@endif
@if($isOnline)
<div id="now-playing-container" class="mb-3 p-2 rounded" style="background-color: color-mix(in srgb, var(--color-text-muted) 5%, transparent);">
<p class="text-xs mb-1" style="color: var(--color-text-muted)">Nu aan het spelen:</p>
<p id="now-playing-song" class="font-medium truncate" style="color: var(--color-text)">Laden...</p>
<p id="now-playing-artist" class="text-sm" style="color: var(--color-text-muted)"></p>
</div>
@endif
</div>
@if($isOnline)
<div class="flex items-center gap-4">
<button id="play-btn" class="px-6 py-2 rounded-lg transition flex items-center gap-2 font-semibold border-2" style="background-color: var(--color-primary); color: var(--button-text-color); border-color: var(--color-primary);">
<span id="play-icon">▶</span>
<span id="play-text">Play</span>
</button>
<div class="flex-1 flex items-center gap-2">
<svg class="w-4 h-4" style="color: var(--color-text-muted)" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM14.657 2.929a1 1 0 011.414 0A9.972 9.972 0 0119 10a9.972 9.972 0 01-2.929 7.071 1 1 0 01-1.414-1.414A7.971 7.971 0 0017 10c0-2.21-.894-4.208-2.343-5.657a1 1 0 010-1.414z" clip-rule="evenodd"/>
</svg>
<input type="range" id="volume" min="0" max="100" value="50" class="flex-1 h-2 rounded-lg appearance-none cursor-pointer" style="background-color: color-mix(in srgb, var(--color-text-muted) 20%, transparent);">
</div>
</div>
<audio id="radio-audio" preload="none"></audio>
@else
<div class="text-sm flex-1 text-center py-2 rounded" style="color: var(--color-text-muted); background-color: color-mix(in srgb, var(--color-text-muted) 5%, transparent);">
Radio is momenteel offline. We zijn zo terug!
</div>
@endif
</div>
</div>
@if($todaySchedule->count() > 0)
<div class="rounded-lg overflow-hidden" style="background-color: var(--color-surface); border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent);">
<div class="relative w-full" style="background: linear-gradient(140deg, var(--color-primary) 0%, color-mix(in srgb, var(--color-primary) 80%, black) 100%);">
<div class="flex items-center h-full px-4 py-3 gap-3">
<div class="w-8 h-8 rounded-full flex items-center justify-center text-lg shadow-lg" style="background-color: color-mix(in srgb, var(--color-primary) 30%, transparent);">
📅
</div>
<div>
<p class="text-white font-bold text-sm">Vandaag op Radio</p>
<p class="text-xs" style="color: rgba(255,255,255,0.8)"><a href="{{ route('radio.rooster') }}" style="color: rgba(255,255,255,0.9); text-decoration: underline;">Bekijk volledig rooster</a></p>
</div>
</div>
</div>
<div class="p-4 text-sm space-y-3" style="color: var(--color-text)">
@foreach($todaySchedule as $slot)
<div class="flex items-center gap-3 p-3 rounded-lg" style="background-color: color-mix(in srgb, var(--color-background) 50%, transparent); {{ $currentDJ && is_array($currentDJ) && isset($currentDJ['username']) && ($currentDJ['username'] ?? '') === $slot->user->username ? 'border: 2px solid ' . 'var(--color-primary)' : '' }}">
<div class="text-center min-w-[60px]">
<p class="font-bold" style="color: var(--color-primary)">{{ $slot->start_time->format('H:i') }}</p>
<p class="text-xs" style="color: var(--color-text-muted)">{{ $slot->end_time->format('H:i') }}</p>
</div>
<div class="flex-1">
<p class="font-bold" style="color: var(--color-text)">{{ $slot->user->username }}</p>
@if($slot->show_name)
<p class="text-sm" style="color: var(--color-text-muted)">{{ $slot->show_name }}</p>
@endif
</div>
@if($currentDJ && is_array($currentDJ) && isset($currentDJ['username']) && ($currentDJ['username'] ?? '') === $slot->user->username)
<span class="px-2 py-1 bg-red-500 text-white text-xs rounded">LIVE</span>
@endif
</div>
@endforeach
</div>
</div>
@endif
@if($banners->count() > 0)
<div class="rounded-lg overflow-hidden" style="background-color: var(--color-surface); border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent);">
<div class="relative w-full" style="background: linear-gradient(140deg, var(--color-primary) 0%, color-mix(in srgb, var(--color-primary) 80%, black) 100%);">
<div class="flex items-center h-full px-4 py-3 gap-3">
<div class="w-8 h-8 rounded-full flex items-center justify-center text-lg shadow-lg" style="background-color: color-mix(in srgb, var(--color-primary) 30%, transparent);">
🖼️
</div>
<div>
<p class="text-white font-bold text-sm">Alle DJ Banners</p>
<p class="text-xs" style="color: rgba(255,255,255,0.8)">Ontdek onze DJ's</p>
</div>
</div>
</div>
<div class="p-4">
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
@foreach($banners as $banner)
<div class="group relative overflow-hidden rounded-lg transition-all duration-300" style="border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent);">
<img src="{{ $banner->image_url }}" alt="{{ $banner->title ?? 'DJ Banner' }}" class="w-full h-32 object-cover transition-transform duration-300 group-hover:scale-105">
<div class="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300">
<div class="absolute bottom-0 left-0 right-0 p-3">
@if($banner->title)
<p class="text-white font-bold text-sm">{{ $banner->title }}</p>
@endif
@if($banner->user)
<p class="text-xs" style="color: var(--color-primary)">DJ: {{ $banner->user->username }}</p>
@endif
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
@endif
</div>
</div>
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
@if($currentDJ && is_array($currentDJ) && isset($currentDJ['username']))
@php
$currentDJBanner = $banners->first(function($banner) use ($currentDJ) {
return $banner->user && $banner->user->username === $currentDJ['username'];
});
@endphp
<div class="rounded-lg overflow-hidden" style="background-color: var(--color-surface); border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent%);">
<div class="relative w-full" style="background: linear-gradient(140deg, var(--color-primary) 0%, color-mix(in srgb, var(--color-primary) 80%, black) 100%);">
<div class="flex items-center h-full px-4 py-3 gap-3">
<div class="w-8 h-8 rounded-full flex items-center justify-center text-lg shadow-lg" style="background-color: color-mix(in srgb, var(--color-primary) 30%, transparent);">
👤
</div>
<div>
<p class="text-white font-bold text-sm">Nu aan het Draaien</p>
<p class="text-xs" style="color: rgba(255,255,255,0.8)">Huidige DJ</p>
</div>
</div>
</div>
<div class="p-4 text-center" style="color: var(--color-text)">
@if($currentDJBanner)
<img src="{{ $currentDJBanner->image_url }}" alt="{{ $currentDJ['username'] }}" class="w-full h-24 object-cover rounded-lg mb-3">
@endif
<div class="inline-flex items-center gap-2 mb-2">
<span class="w-2 h-2 bg-red-500 rounded-full animate-pulse"></span>
<span class="text-red-500 font-bold text-sm">LIVE</span>
</div>
<p class="text-xl font-bold" style="color: var(--color-primary)">{{ $currentDJ['username'] }}</p>
@if(isset($currentDJ['show_name']) && $currentDJ['show_name'])
<p class="text-sm mt-1" style="color: var(--color-text-muted)">{{ $currentDJ['show_name'] }}</p>
@endif
</div>
</div>
@endif
<div class="rounded-lg overflow-hidden" style="background-color: var(--color-surface); border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent);">
<div class="relative w-full" style="background: linear-gradient(140deg, var(--color-primary) 0%, color-mix(in srgb, var(--color-primary) 80%, black) 100%);">
<div class="flex items-center h-full px-4 py-3 gap-3">
<div class="w-8 h-8 rounded-full flex items-center justify-center text-lg shadow-lg" style="background-color: color-mix(in srgb, var(--color-primary) 30%, transparent);">
</div>
<div>
<p class="text-white font-bold text-sm">Radio Info</p>
<p class="text-xs" style="color: rgba(255,255,255,0.8)">Over onze radio</p>
</div>
</div>
</div>
<div class="p-4 text-sm space-y-4" style="color: var(--color-text)">
<p>Luister live naar de beste muziek 24/7! Onze DJ's spelen jouw favoriete tracks.</p>
<div class="space-y-2">
<a href="{{ route('radio.rooster') }}" class="block" style="color: var(--color-primary); text-decoration: underline;">📅 Bekijk het rooster</a>
@if(setting('radio_applications_enabled') == '1')
<a href="{{ route('radio.apply') }}" class="block" style="color: var(--color-primary); text-decoration: underline;">🎤 Word DJ</a>
@endif
</div>
</div>
</div>
@if($ranks->count() > 0)
<div class="rounded-lg overflow-hidden" style="background-color: var(--color-surface); border: 1px solid color-mix(in srgb, var(--color-text-muted) 15%, transparent);">
<div class="relative w-full" style="background: linear-gradient(140deg, var(--color-primary) 0%, color-mix(in srgb, var(--color-primary) 80%, black) 100%);">
<div class="flex items-center h-full px-4 py-3 gap-3">
<div class="w-8 h-8 rounded-full flex items-center justify-center text-lg shadow-lg" style="background-color: color-mix(in srgb, var(--color-primary) 30%, transparent);">
</div>
<div>
<p class="text-white font-bold text-sm">DJ Ranks</p>
<p class="text-xs" style="color: rgba(255,255,255,0.8)">Onze DJ niveaus</p>
</div>
</div>
</div>
<div class="p-4 text-sm space-y-2" style="color: var(--color-text)">
@foreach($ranks as $rank)
<div class="flex items-center gap-2 p-2 rounded" style="background-color: color-mix(in srgb, var(--color-background) 50%, transparent);">
@if($rank->badge_code)
<img src="{{ sprintf(setting('badge_imaging_path'), $rank->badge_code) }}" alt="" class="w-6 h-6">
@endif
<span>{{ $rank->name }}</span>
</div>
@endforeach
</div>
</div>
@endif
</div>
<script>
let isPlaying = false;
let currentBanner = 0;
const banners = document.querySelectorAll('.banner-slide');
const bannerDots = document.querySelectorAll('.banner-dot');
function updateBanner(index) {
banners[currentBanner].classList.add('hidden');
banners[currentBanner].classList.remove('block');
if (bannerDots[currentBanner]) {
bannerDots[currentBanner].classList.remove('w-4');
bannerDots[currentBanner].classList.remove('bg-[var(--color-primary)]');
bannerDots[currentBanner].classList.add('bg-gray-400');
}
currentBanner = index;
banners[currentBanner].classList.remove('hidden');
banners[currentBanner].classList.add('block');
if (bannerDots[currentBanner]) {
bannerDots[currentBanner].classList.remove('bg-gray-400');
bannerDots[currentBanner].classList.add('bg-[var(--color-primary)]', 'w-4');
}
}
if (banners.length > 1) {
setInterval(function() {
updateBanner((currentBanner + 1) % banners.length);
}, 5000);
bannerDots.forEach(function(dot, index) {
dot.addEventListener('click', function() {
updateBanner(index);
});
});
}
@if($isOnline)
let radioStream = '';
fetch('/api/radio/config')
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.enabled && data.stream_url) {
radioStream = data.stream_url;
var listenersContainer = document.getElementById('listeners-container');
var nowPlayingContainer = document.getElementById('now-playing-container');
if (listenersContainer) listenersContainer.style.display = 'flex';
if (nowPlayingContainer) nowPlayingContainer.style.display = 'block';
}
});
var playBtn = document.getElementById('play-btn');
if (playBtn) {
playBtn.addEventListener('click', function() {
var audio = document.getElementById('radio-audio');
var icon = document.getElementById('play-icon');
var text = document.getElementById('play-text');
if (isPlaying) {
audio.pause();
icon.textContent = '';
text.textContent = 'Play';
isPlaying = false;
} else {
if (radioStream) {
audio.src = radioStream;
audio.play().catch(function(e) { console.error('Audio play failed:', e); });
icon.textContent = '';
text.textContent = 'Pause';
isPlaying = true;
}
}
});
}
var volumeSlider = document.getElementById('volume');
if (volumeSlider) {
volumeSlider.addEventListener('input', function(e) {
var audio = document.getElementById('radio-audio');
if (audio) audio.volume = e.target.value / 100;
});
}
function updateNowPlaying() {
fetch('/api/radio/now-playing')
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.enabled && data.song) {
var songEl = document.getElementById('now-playing-song');
var artistEl = document.getElementById('now-playing-artist');
if (songEl) songEl.textContent = data.song;
if (artistEl && data.artist) artistEl.textContent = data.artist;
}
});
}
function updateListeners() {
fetch('/api/radio/listeners')
.then(function(r) { return r.json(); })
.then(function(data) {
var el = document.getElementById('listeners-count');
if (el && data.count > 0) el.textContent = data.count;
});
}
setInterval(updateNowPlaying, 5000);
setInterval(updateListeners, 5000);
updateNowPlaying();
updateListeners();
@endif
</script>
</x-app-layout>