Fix SSE listeners type cast, replace Blade tab component with Alpine.js tabs in DjModeration, use wire:confirm instead of onclick
This commit is contained in:
1 parent
0c6c558a59
commit
261a5e63c6
27 files changed
+142
-136
No files matched your search
@@ -1 +1 @@
|
|||||||
{"version":"pest_4.4.3","defects":{"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_returns_default_value_when_setting_not_found":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_returns_existing_setting_value":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_returns_default_for_non_existent_key":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_install_helper_creates_basic_settings":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_cache_works_correctly":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_can_be_updated_and_retrieved":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_handles_empty_string_default":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_handles_numeric_defaults":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_can_be_created_with_factory":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_factory_creates_proper_defaults":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_can_be_updated":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_can_be_deleted":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_password_is_hashed":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_multiple_users_can_be_created":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_articles_index_page_loads":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_published_article_can_be_viewed":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_unpublished_article_can_be_viewed":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_multiple_articles_appear_on_index":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_with_special_characters_in_title":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_with_long_content":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_non_existent_article_returns_404":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_url_contains_correct_slug":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_articles_can_be_filtered_or_sorted":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_page_has_proper_meta_tags":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_users_can_authenticate_using_the_login_screen":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_users_can_not_authenticate_with_invalid_password":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_requires_csrf_token":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_requires_username":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_requires_password":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_with_non_existent_user_fails":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_authenticated_user_is_redirected_from_login_page":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_user_can_logout":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_applications_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_guest_cannot_access_staff_applications":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_photos_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_leaderboard_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_community_pages_have_proper_structure":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_authenticated_user_can_access_community_pages":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_applications_requires_authentication":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_page_shows_team_members":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_photos_page_has_proper_layout":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_leaderboard_shows_rankings":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_community_routes_return_correct_status_codes":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_community_pages_load_within_reasonable_time":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_applications_page_shows_form_elements":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_help_center_page_loads_for_authenticated_user":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_help_center_page_loads_for_guest_user":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_user_can_create_help_ticket":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_guest_cannot_create_help_ticket":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_rules_page_loads":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_help_center_pages_are_accessible_to_all":8,"P\\TestLine truncated
|
{"version":"pest_4.7.0","defects":{"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_returns_default_value_when_setting_not_found":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_returns_existing_setting_value":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_returns_default_for_non_existent_key":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_install_helper_creates_basic_settings":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_cache_works_correctly":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_can_be_updated_and_retrieved":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_handles_empty_string_default":8,"P\\Tests\\Unit\\SettingsServiceTest::__pest_evaluable_settings_service_handles_numeric_defaults":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_can_be_created_with_factory":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_factory_creates_proper_defaults":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_can_be_updated":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_can_be_deleted":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_user_password_is_hashed":8,"P\\Tests\\Unit\\UserTest::__pest_evaluable_multiple_users_can_be_created":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_articles_index_page_loads":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_published_article_can_be_viewed":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_unpublished_article_can_be_viewed":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_multiple_articles_appear_on_index":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_with_special_characters_in_title":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_with_long_content":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_non_existent_article_returns_404":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_url_contains_correct_slug":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_articles_can_be_filtered_or_sorted":8,"P\\Tests\\Feature\\Articles\\ArticleTest::__pest_evaluable_article_page_has_proper_meta_tags":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_users_can_authenticate_using_the_login_screen":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_users_can_not_authenticate_with_invalid_password":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_requires_csrf_token":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_requires_username":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_requires_password":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_login_with_non_existent_user_fails":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_authenticated_user_is_redirected_from_login_page":8,"P\\Tests\\Feature\\AuthenticationTest::__pest_evaluable_user_can_logout":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_applications_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_guest_cannot_access_staff_applications":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_photos_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_leaderboard_page_loads":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_community_pages_have_proper_structure":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_authenticated_user_can_access_community_pages":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_applications_requires_authentication":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_page_shows_team_members":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_photos_page_has_proper_layout":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_leaderboard_shows_rankings":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_community_routes_return_correct_status_codes":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_community_pages_load_within_reasonable_time":8,"P\\Tests\\Feature\\Community\\CommunityTest::__pest_evaluable_staff_applications_page_shows_form_elements":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_help_center_page_loads_for_authenticated_user":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_help_center_page_loads_for_guest_user":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_user_can_create_help_ticket":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_guest_cannot_create_help_ticket":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_rules_page_loads":8,"P\\Tests\\Feature\\Help\\HelpCenterTest::__pest_evaluable_help_center_pages_are_accessible_to_all":8,"P\\TestLine truncated
|
||||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+1
-1
@@ -134,7 +134,7 @@ class SseController extends Controller
|
|||||||
|
|
||||||
private function getListeners(): int
|
private function getListeners(): int
|
||||||
{
|
{
|
||||||
return Cache::remember('radio_listeners', 30, function () {
|
return (int) Cache::remember('radio_listeners', 30, function () {
|
||||||
$apiUrl = $this->getSetting(RadioSettings::ListenersEnabled)
|
$apiUrl = $this->getSetting(RadioSettings::ListenersEnabled)
|
||||||
? ($this->getSetting(RadioSettings::ListenersApiUrl) ?: $this->getAzureCastApiUrl())
|
? ($this->getSetting(RadioSettings::ListenersApiUrl) ?: $this->getAzureCastApiUrl())
|
||||||
: null;
|
: null;
|
||||||
|
|||||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
Regular → Executable
+136
-130
@@ -7,145 +7,151 @@ use App\Models\RadioSongRequest;
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<x-filament-panels::page>
|
<x-filament-panels::page>
|
||||||
<x-filament::tabs>
|
<div x-data="{ tab: 'shouts' }">
|
||||||
|
<div class="flex gap-1 mb-6 border-b border-gray-200 dark:border-gray-700">
|
||||||
|
<button @click="tab = 'shouts'" :class="{ 'border-primary-600 text-primary-600': tab === 'shouts', 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300': tab !== 'shouts' }" class="px-4 py-2 text-sm font-medium border-b-2 transition flex items-center gap-2">
|
||||||
|
<x-filament::icon name="heroicon-o-chat-bubble-oval-left" class="w-4 h-4" />
|
||||||
|
Shouts
|
||||||
|
<span class="inline-flex items-center justify-center px-2 py-0.5 text-xs font-medium rounded-full bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400">{{ RadioShout::where('approved', false)->count() }}</span>
|
||||||
|
</button>
|
||||||
|
<button @click="tab = 'requests'" :class="{ 'border-primary-600 text-primary-600': tab === 'requests', 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300': tab !== 'requests' }" class="px-4 py-2 text-sm font-medium border-b-2 transition flex items-center gap-2">
|
||||||
|
<x-filament::icon name="heroicon-o-musical-note" class="w-4 h-4" />
|
||||||
|
Verzoeken
|
||||||
|
<span class="inline-flex items-center justify-center px-2 py-0.5 text-xs font-medium rounded-full bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400">{{ RadioSongRequest::where('is_approved', false)->where('is_played', false)->count() }}</span>
|
||||||
|
</button>
|
||||||
|
<button @click="tab = 'applications'" :class="{ 'border-primary-600 text-primary-600': tab === 'applications', 'border-transparent text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300': tab !== 'applications' }" class="px-4 py-2 text-sm font-medium border-b-2 transition flex items-center gap-2">
|
||||||
|
<x-filament::icon name="heroicon-o-user-group" class="w-4 h-4" />
|
||||||
|
Aanmeldingen
|
||||||
|
<span class="inline-flex items-center justify-center px-2 py-0.5 text-xs font-medium rounded-full bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400">{{ RadioApplication::where('status', 'pending')->count() }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- Shouts Tab --}}
|
{{-- Shouts Tab --}}
|
||||||
<x-filament::tabs.tab
|
<div x-show="tab === 'shouts'">
|
||||||
icon="heroicon-o-chat-bubble-oval-left"
|
@php $pendingShouts = $this->getPendingShouts(); @endphp
|
||||||
label="Shouts ({{ RadioShout::where('approved', false)->count() }} wachtend, {{ RadioShout::where('reported', true)->count() }} gerapporteerd)"
|
@php $reportedShouts = $this->getReportedShouts(); @endphp
|
||||||
>
|
|
||||||
<div class="space-y-4">
|
|
||||||
@php $pendingShouts = $this->getPendingShouts(); @endphp
|
|
||||||
@if($pendingShouts->count() > 0)
|
|
||||||
<h3 class="text-lg font-semibold">Wachtend op goedkeuring</h3>
|
|
||||||
<div class="space-y-2">
|
|
||||||
@foreach($pendingShouts as $shout)
|
|
||||||
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 flex items-start justify-between gap-4">
|
|
||||||
<div class="flex-1 min-w-0">
|
|
||||||
<p class="font-medium text-sm">{{ $shout->user?->username ?? 'Onbekend' }}</p>
|
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-400 truncate">{{ $shout->message }}</p>
|
|
||||||
<p class="text-xs text-gray-400 mt-1">{{ $shout->created_at->diffForHumans() }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2 shrink-0">
|
|
||||||
<x-filament::button wire:click="approveShout({{ $shout->id }})" color="success" size="xs" icon="heroicon-o-check">
|
|
||||||
Goedkeuren
|
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button wire:click="deleteShout({{ $shout->id }})" color="danger" size="xs" icon="heroicon-o-trash" onclick="return confirm('Zeker weten?')">
|
|
||||||
Verwijderen
|
|
||||||
</x-filament::button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
{{ $pendingShouts->links() }}
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
@php $reportedShouts = $this->getReportedShouts(); @endphp
|
@if($pendingShouts->count() > 0)
|
||||||
@if($reportedShouts->count() > 0)
|
<h3 class="text-lg font-semibold mb-3">Wachtend op goedkeuring</h3>
|
||||||
<h3 class="text-lg font-semibold mt-6">Gerapporteerde shouts</h3>
|
<div class="space-y-2 mb-6">
|
||||||
<div class="space-y-2">
|
@foreach($pendingShouts as $shout)
|
||||||
@foreach($reportedShouts as $shout)
|
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 flex items-start justify-between gap-4">
|
||||||
<div class="bg-red-50 dark:bg-red-950 rounded-lg p-4 flex items-start justify-between gap-4">
|
<div class="flex-1 min-w-0">
|
||||||
<div class="flex-1 min-w-0">
|
<p class="font-medium text-sm">{{ $shout->user?->username ?? 'Onbekend' }}</p>
|
||||||
<p class="font-medium text-sm">{{ $shout->user?->username ?? 'Onbekend' }}</p>
|
<p class="text-sm text-gray-600 dark:text-gray-400 truncate">{{ $shout->message }}</p>
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-400 truncate">{{ $shout->message }}</p>
|
<p class="text-xs text-gray-400 mt-1">{{ $shout->created_at->diffForHumans() }}</p>
|
||||||
<p class="text-xs text-gray-400 mt-1">{{ $shout->created_at->diffForHumans() }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2 shrink-0">
|
|
||||||
<x-filament::button wire:click="dismissShoutReport({{ $shout->id }})" color="info" size="xs" icon="heroicon-o-flag">
|
|
||||||
Negeren
|
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button wire:click="deleteShout({{ $shout->id }})" color="danger" size="xs" icon="heroicon-o-trash" onclick="return confirm('Zeker weten?')">
|
|
||||||
Verwijderen
|
|
||||||
</x-filament::button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
<div class="flex gap-2 shrink-0">
|
||||||
{{ $reportedShouts->links() }}
|
<x-filament::button wire:click="approveShout({{ $shout->id }})" color="success" size="xs" icon="heroicon-o-check">
|
||||||
</div>
|
Goedkeuren
|
||||||
@endif
|
</x-filament::button>
|
||||||
|
<x-filament::button wire:click="deleteShout({{ $shout->id }})" color="danger" size="xs" icon="heroicon-o-trash" wire:confirm="Zeker weten?">
|
||||||
|
Verwijderen
|
||||||
|
</x-filament::button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
{{ $pendingShouts->links() }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
@if($pendingShouts->count() === 0 && $reportedShouts->count() === 0)
|
@if($reportedShouts->count() > 0)
|
||||||
<p class="text-gray-500 text-center py-8">Geen shouts wachtend op moderatie</p>
|
<h3 class="text-lg font-semibold mb-3">Gerapporteerde shouts</h3>
|
||||||
@endif
|
<div class="space-y-2">
|
||||||
</div>
|
@foreach($reportedShouts as $shout)
|
||||||
</x-filament::tabs.tab>
|
<div class="bg-red-50 dark:bg-red-950 rounded-lg p-4 flex items-start justify-between gap-4">
|
||||||
|
<div class="flex-1 min-w-0">
|
||||||
|
<p class="font-medium text-sm">{{ $shout->user?->username ?? 'Onbekend' }}</p>
|
||||||
|
<p class="text-sm text-gray-600 dark:text-gray-400 truncate">{{ $shout->message }}</p>
|
||||||
|
<p class="text-xs text-gray-400 mt-1">{{ $shout->created_at->diffForHumans() }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="flex gap-2 shrink-0">
|
||||||
|
<x-filament::button wire:click="dismissShoutReport({{ $shout->id }})" color="info" size="xs" icon="heroicon-o-flag">
|
||||||
|
Negeren
|
||||||
|
</x-filament::button>
|
||||||
|
<x-filament::button wire:click="deleteShout({{ $shout->id }})" color="danger" size="xs" icon="heroicon-o-trash" wire:confirm="Zeker weten?">
|
||||||
|
Verwijderen
|
||||||
|
</x-filament::button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
{{ $reportedShouts->links() }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($pendingShouts->count() === 0 && $reportedShouts->count() === 0)
|
||||||
|
<p class="text-gray-500 text-center py-8">Geen shouts wachtend op moderatie</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- Song Requests Tab --}}
|
{{-- Song Requests Tab --}}
|
||||||
<x-filament::tabs.tab
|
<div x-show="tab === 'requests'">
|
||||||
icon="heroicon-o-musical-note"
|
@php $requests = $this->getPendingRequests(); @endphp
|
||||||
label="Verzoeken ({{ RadioSongRequest::where('is_approved', false)->where('is_played', false)->count() }} wachtend)"
|
@if($requests->count() > 0)
|
||||||
>
|
<div class="space-y-2">
|
||||||
<div class="space-y-4">
|
@foreach($requests as $request)
|
||||||
@php $requests = $this->getPendingRequests(); @endphp
|
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 flex items-start justify-between gap-4">
|
||||||
@if($requests->count() > 0)
|
<div class="flex-1 min-w-0">
|
||||||
<div class="space-y-2">
|
<p class="font-medium text-sm">{{ $request->user?->username ?? 'Onbekend' }}</p>
|
||||||
@foreach($requests as $request)
|
<p class="text-sm font-semibold">{{ $request->song_title }}</p>
|
||||||
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 flex items-start justify-between gap-4">
|
@if($request->song_artist)
|
||||||
<div class="flex-1 min-w-0">
|
<p class="text-sm text-gray-500">{{ $request->song_artist }}</p>
|
||||||
<p class="font-medium text-sm">{{ $request->user?->username ?? 'Onbekend' }}</p>
|
@endif
|
||||||
<p class="text-sm font-semibold">{{ $request->song_title }}</p>
|
<div class="flex items-center gap-3 mt-1">
|
||||||
<p class="text-sm text-gray-500" x-show="{{ $request->song_artist }}">{{ $request->song_artist }}</p>
|
<span class="text-xs text-gray-400">{{ $request->submitted_at->diffForHumans() }}</span>
|
||||||
<div class="flex items-center gap-3 mt-1">
|
<span class="text-xs text-amber-500">{{ $request->votes }} stemmen</span>
|
||||||
<span class="text-xs text-gray-400">{{ $request->submitted_at->diffForHumans() }}</span>
|
|
||||||
<span class="text-xs text-amber-500">{{ $request->votes }} stemmen</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2 shrink-0">
|
|
||||||
<x-filament::button wire:click="approveRequest({{ $request->id }})" color="success" size="xs" icon="heroicon-o-check">
|
|
||||||
Goedkeuren
|
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button wire:click="rejectRequest({{ $request->id }})" color="danger" size="xs" icon="heroicon-o-x-mark" onclick="return confirm('Zeker weten?')">
|
|
||||||
Afwijzen
|
|
||||||
</x-filament::button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
<div class="flex gap-2 shrink-0">
|
||||||
{{ $requests->links() }}
|
<x-filament::button wire:click="approveRequest({{ $request->id }})" color="success" size="xs" icon="heroicon-o-check">
|
||||||
</div>
|
Goedkeuren
|
||||||
@else
|
</x-filament::button>
|
||||||
<p class="text-gray-500 text-center py-8">Geen verzoeken wachtend op goedkeuring</p>
|
<x-filament::button wire:click="rejectRequest({{ $request->id }})" color="danger" size="xs" icon="heroicon-o-x-mark" wire:confirm="Zeker weten?">
|
||||||
@endif
|
Afwijzen
|
||||||
</div>
|
</x-filament::button>
|
||||||
</x-filament::tabs.tab>
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
{{ $requests->links() }}
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<p class="text-gray-500 text-center py-8">Geen verzoeken wachtend op goedkeuring</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- Applications Tab --}}
|
{{-- Applications Tab --}}
|
||||||
<x-filament::tabs.tab
|
<div x-show="tab === 'applications'">
|
||||||
icon="heroicon-o-user-group"
|
@php $applications = $this->getPendingApplications(); @endphp
|
||||||
label="Aanmeldingen ({{ RadioApplication::where('status', 'pending')->count() }} wachtend)"
|
@if($applications->count() > 0)
|
||||||
>
|
<div class="space-y-2">
|
||||||
<div class="space-y-4">
|
@foreach($applications as $app)
|
||||||
@php $applications = $this->getPendingApplications(); @endphp
|
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 flex items-start justify-between gap-4">
|
||||||
@if($applications->count() > 0)
|
<div class="flex-1 min-w-0">
|
||||||
<div class="space-y-2">
|
<p class="font-medium">{{ $app->user?->username ?? 'Onbekend' }}</p>
|
||||||
@foreach($applications as $app)
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
||||||
<div class="bg-gray-50 dark:bg-gray-900 rounded-lg p-4 flex items-start justify-between gap-4">
|
{{ $app->rank?->name ?? 'Geen functie' }} · {{ $app->age }} jaar
|
||||||
<div class="flex-1 min-w-0">
|
</p>
|
||||||
<p class="font-medium">{{ $app->user?->username ?? 'Onbekend' }}</p>
|
<p class="text-sm mt-2">{{ $app->motivation }}</p>
|
||||||
<p class="text-sm text-gray-600 dark:text-gray-400">
|
@if($app->experience)
|
||||||
{{ $app->rank?->name ?? 'Geen functie' }} · {{ $app->age }} jaar
|
<p class="text-xs text-gray-400 mt-1">Ervaring: {{ $app->experience }}</p>
|
||||||
</p>
|
@endif
|
||||||
<p class="text-sm mt-2">{{ $app->motivation }}</p>
|
<p class="text-xs text-gray-400 mt-1">{{ $app->created_at->diffForHumans() }}</p>
|
||||||
@if($app->experience)
|
|
||||||
<p class="text-xs text-gray-400 mt-1">Ervaring: {{ $app->experience }}</p>
|
|
||||||
@endif
|
|
||||||
<p class="text-xs text-gray-400 mt-1">{{ $app->created_at->diffForHumans() }}</p>
|
|
||||||
</div>
|
|
||||||
<div class="flex gap-2 shrink-0">
|
|
||||||
<x-filament::button wire:click="approveApplication({{ $app->id }})" color="success" size="xs" icon="heroicon-o-check" onclick="return confirm('Aanmelding goedkeuren?')">
|
|
||||||
Goedkeuren
|
|
||||||
</x-filament::button>
|
|
||||||
<x-filament::button wire:click="rejectApplication({{ $app->id }})" color="danger" size="xs" icon="heroicon-o-x-mark" onclick="return confirm('Aanmelding afwijzen?')">
|
|
||||||
Afwijzen
|
|
||||||
</x-filament::button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
<div class="flex gap-2 shrink-0">
|
||||||
{{ $applications->links() }}
|
<x-filament::button wire:click="approveApplication({{ $app->id }})" color="success" size="xs" icon="heroicon-o-check" wire:confirm="Aanmelding goedkeuren?">
|
||||||
</div>
|
Goedkeuren
|
||||||
@else
|
</x-filament::button>
|
||||||
<p class="text-gray-500 text-center py-8">Geen aanmeldingen wachtend</p>
|
<x-filament::button wire:click="rejectApplication({{ $app->id }})" color="danger" size="xs" icon="heroicon-o-x-mark" wire:confirm="Aanmelding afwijzen?">
|
||||||
@endif
|
Afwijzen
|
||||||
</div>
|
</x-filament::button>
|
||||||
</x-filament::tabs.tab>
|
</div>
|
||||||
</x-filament::tabs>
|
</div>
|
||||||
|
@endforeach
|
||||||
|
{{ $applications->links() }}
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<p class="text-gray-500 text-center py-8">Geen aanmeldingen wachtend</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</x-filament-panels::page>
|
</x-filament-panels::page>
|
||||||
Regular → Executable
File mode changed.
Regular → Executable
File mode changed.
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"exported_at": "2026-05-22 18:56:37",
|
"exported_at": "2026-05-23 17:57:11",
|
||||||
"settings": {
|
"settings": {
|
||||||
"preset": "atom_original",
|
"preset": "atom_original",
|
||||||
"color_primary": "#eeb425",
|
"color_primary": "#eeb425",
|
||||||
@@ -102,15 +102,15 @@
|
|||||||
"card_border_width": "1",
|
"card_border_width": "1",
|
||||||
"card_border_radius": "12",
|
"card_border_radius": "12",
|
||||||
"page_transition": true,
|
"page_transition": true,
|
||||||
"login_effect_enabled": true,
|
"login_effect_enabled": false,
|
||||||
"login_effect_animation": "fire",
|
"login_effect_animation": "fire",
|
||||||
"login_effect_background": "#0088ff",
|
"login_effect_background": "#0088ff",
|
||||||
"login_effect_icon_color": "#eeb425",
|
"login_effect_icon_color": "#eeb425",
|
||||||
"login_effect_text_color": "#ffffff",
|
"login_effect_text_color": "#ffffff",
|
||||||
"login_effect_bar_color": "#eeb425",
|
"login_effect_bar_color": "#eeb425",
|
||||||
"login_effect_bar_style": "dots",
|
"login_effect_bar_style": "dots",
|
||||||
"login_effect_show_logo": true,
|
"login_effect_show_logo": false,
|
||||||
"login_effect_show_name": true,
|
"login_effect_show_name": false,
|
||||||
"login_effect_icon_size": "120",
|
"login_effect_icon_size": "120",
|
||||||
"login_effect_custom_text": "",
|
"login_effect_custom_text": "",
|
||||||
"header_background": "#2d2d44",
|
"header_background": "#2d2d44",
|
||||||
|
|||||||
Reference in new issue
Block a user