You've already forked Atomcms-edit
Initial commit
This commit is contained in:
+187
@@ -0,0 +1,187 @@
|
||||
<x-app-layout>
|
||||
@push('title', $article->title)
|
||||
|
||||
<div class="col-span-12 rounded space-y-3 md:col-span-3">
|
||||
<div
|
||||
class="relative mt-6 h-24 w-full overflow-hidden rounded border bg-white shadow-sm dark:border-gray-900 dark:bg-gray-800 md:mt-0">
|
||||
<div
|
||||
class="absolute top-1 right-1 rounded bg-white px-2 text-sm font-semibold dark:bg-gray-700 dark:text-gray-100">
|
||||
{{ $article->user && !$article->user->hidden_staff ? $article->user->permission->rank_name ?? 'Member' : 'Member' }}
|
||||
</div>
|
||||
|
||||
<div class="h-[65%] w-full staff-bg"
|
||||
style="background: rgba(0, 0, 0, 0.5) url({{ asset(sprintf('assets/images/%s', $article->user ? $article->user->permission->staff_background ?? 'staff-bg.png' : 'staff-bg.png')) }});">
|
||||
</div>
|
||||
|
||||
<a href="{{ route('profile.show', $article->user ?? \App\Models\User::first()) }}" class="absolute top-4 left-1 ">
|
||||
<img style="image-rendering: pixelated;" class="transition duration-300 ease-in-out hover:scale-105"
|
||||
src="{{ setting('avatar_imager') }}{{ $article->user?->look }}&direction=2&head_direction=3&gesture=sml&action=wav"
|
||||
alt="">
|
||||
</a>
|
||||
|
||||
<p class="text-2xl font-semibold ml-[70px] text-white -mt-[35px] ">
|
||||
{{ $article->user->username ?? setting('hotel_name') }}
|
||||
</p>
|
||||
|
||||
<div class="flex w-full items-center justify-between px-4">
|
||||
<p class="ml-[57px] text-sm mt-[10px] font-semibold text-gray-500 ">
|
||||
{{ $article->user->motto ?? setting('start_motto') }}
|
||||
</p>
|
||||
|
||||
@if($article->user)
|
||||
<div class="w-4 h-4 rounded-full mt-2 {{ $article->user->online ? 'bg-green-600' : 'bg-red-600' }}">
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<x-content.content-card icon="article-icon" classes="border dark:bg-gray-800 dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
{{ __('Other articles') }}
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
{{ __('Our most recent articles') }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="flex flex-col gap-y-2">
|
||||
@forelse($otherArticles as $art)
|
||||
<a href="{{ route('article.show', $art->slug) }}"
|
||||
style="background: rgba(0, 0, 0, 0.5) url({{ $art->image }}) center;"
|
||||
class="w-full rounded h-12 bg-blue-200 transition ease-in-out duration-200 hover:scale-[103%] text-white flex justify-center items-center font-bold recent-articles">
|
||||
{{ Str::limit($art->title, 20) }}
|
||||
</a>
|
||||
@empty
|
||||
<p class="dark:text-gray-400">
|
||||
{{ __('There is currently no other articles') }}
|
||||
</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 space-y-4 md:col-span-9">
|
||||
<div
|
||||
class="relative flex flex-col gap-y-8 overflow-hidden rounded bg-white p-3 shadow-sm dark:bg-gray-800 dark:text-gray-300">
|
||||
<div class="relative flex h-24 flex-col items-center justify-center gap-y-1 overflow-hidden rounded px-2"
|
||||
style="background: url(/storage/{{ $article->image }}) center; background-size: cover; color: var(--color-text);">
|
||||
<div class="absolute h-full w-full bg-black/50"></div>
|
||||
|
||||
<p class="relative w-full truncate text-center text-xl font-semibold lg:text-2xl xl:text-3xl " style="color: white;">
|
||||
{{ $article->title }}</p>
|
||||
<p class="relative w-full truncate text-center " style="color: rgba(255,255,255,0.9);">{{ $article->short_story }}</p>
|
||||
</div>
|
||||
|
||||
<div class="px-2" id="article-content">
|
||||
{!! $article->full_story !!}
|
||||
</div>
|
||||
|
||||
<div class="w-full h-10 lg:h-1/2 py-1 flex gap-1 items-center justify-start flex-wrap">
|
||||
@forelse ($article->tags as $tag)
|
||||
<span @class([
|
||||
"text-xs font-medium rounded-lg px-2",
|
||||
"text-slate-600" => $tag->background_color,
|
||||
"text-white" => $tag->background_color
|
||||
]) style="background-color: {{ $tag->background_color }}">{{ $tag->name }}</span>
|
||||
@empty
|
||||
<span @class([
|
||||
"text-xs font-medium rounded-lg px-2",
|
||||
"text-slate-600",
|
||||
"text-white"
|
||||
]) style="background-color: #000000">{{ __('No tags found.') }}</span>
|
||||
</span>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
@include('community.partials.article-reactions')
|
||||
</div>
|
||||
|
||||
@if ($article->can_comment)
|
||||
@if (auth()->check() && !$article->userHasReachedArticleCommentLimit())
|
||||
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
{{ __('Post a comment') }}
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
{{ __('Post a comment on the article, to let us know what you think about it') }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm dark:text-gray-200">
|
||||
<form action="{{ route('article.comment.store', $article) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<textarea name="comment"
|
||||
class="focus:ring-0 border-2 border-gray-200 rounded dark:bg-gray-800 dark:border-gray-700 dark:text-gray-200 focus:border-[var(--color-primary)] w-full min-h-[100px] max-h-[100px] @error('comment') border-red-600 ring-red-500 @enderror"></textarea>
|
||||
|
||||
<x-form.primary-button classes="mt-2">
|
||||
{{ __('Post comment') }}
|
||||
</x-form.primary-button>
|
||||
</form>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
@endif
|
||||
|
||||
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
{{ __('Comments') }}
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
{{ __('Below you will see all the comments, written on this article') }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-1 dark:text-gray-200 space-y-[13px]">
|
||||
@foreach ($article->comments as $comment)
|
||||
<div
|
||||
class="relative w-full rounded bg-[#f5f5f5] dark:bg-gray-700 p-4 h-[90px] overflow-hidden flex items-center shadow-sm">
|
||||
<a href="{{ route('profile.show', $comment->user) }}"
|
||||
class="absolute top-2 left-1 ">
|
||||
<img style="image-rendering: pixelated;"
|
||||
class="transition duration-300 ease-in-out hover:scale-105"
|
||||
src="{{ setting('avatar_imager') }}{{ $comment->user->look }}&direction=2&head_direction=3&gesture=sml&action=wav"
|
||||
alt="">
|
||||
</a>
|
||||
|
||||
<div class="flex justify-between ml-[60px] w-full">
|
||||
<div class="text-sm">
|
||||
<a href="{{ route('profile.show', $comment->user) }}"
|
||||
class="font-semibold text-[#89cdf0] dark:text-blue-300 hover:underline">
|
||||
{{ $comment->user->username }}
|
||||
</a>
|
||||
|
||||
<p class="block dark:text-gray-200">
|
||||
{{ $comment->comment }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-x-2">
|
||||
<p class="text-xs dark:text-gray-200">
|
||||
{{ $comment->created_at->diffForHumans() }}
|
||||
</p>
|
||||
|
||||
@if ($comment->canBeDeleted())
|
||||
<form action="{{ route('article.comment.destroy', $comment) }}" method="POST"
|
||||
class="cursor-pointer transition duration-200 ease-in-out hover:scale-105">
|
||||
@method('DELETE')
|
||||
@csrf
|
||||
|
||||
<button type="submit">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
|
||||
class="h-4 w-4">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
@endif
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,17 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Articles'))
|
||||
|
||||
<div class="col-span-12">
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
|
||||
@forelse($articles as $article)
|
||||
<x-article-card :article="$article" />
|
||||
@empty
|
||||
<x-filler-article-card />
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
{{ $articles->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,76 @@
|
||||
<x-modals.modal-wrapper>
|
||||
<div class="select-none"
|
||||
x-data='reactions(@json($myReactions), @json($articleReactions), "{{ route('article.toggle-reaction', $article->slug) }}")'>
|
||||
<div class="mt-4 flex w-full flex-wrap gap-2 rounded-lg bg-gray-100 p-2 dark:bg-gray-900">
|
||||
<div x-show="isAuthenticated"
|
||||
class="px-2 hover:scale-110 transition-all font-semibold h-8 flex items-center justify-center border-2 text-xs border-[var(--color-primary)] cursor-pointer bg-[var(--color-primary)] text-white rounded-lg"
|
||||
x-on:click="open = true">
|
||||
{{ __('Add') }}
|
||||
</div>
|
||||
|
||||
<template x-for="articleReaction in articleReactions">
|
||||
<div>
|
||||
<div class="flex h-8 w-12 items-center justify-center gap-2 rounded-lg border-2 border-gray-300 text-sm font-bold dark:border-gray-800"
|
||||
:class="{
|
||||
'bg-gray-300 dark:bg-gray-800 dark:border-gray-700': userHasReaction(
|
||||
articleReaction),
|
||||
'cursor-pointer hover:bg-gray-200 hover:scale-110 transition-all dark:hover:bg-gray-700': isAuthenticated
|
||||
}"
|
||||
@click="toggleReaction(articleReaction.name)" :data-popover-target="articleReaction.id">
|
||||
<img :src="'/assets/images/icons/reactions/' + articleReaction.name + '.png'"
|
||||
:alt="articleReaction.name">
|
||||
<span x-text="articleReaction.count"></span>
|
||||
</div>
|
||||
|
||||
<div data-popover :id="articleReaction.id" role="tooltip"
|
||||
class="invisible absolute z-10 inline-block w-64 rounded-lg border border-gray-200 bg-white text-sm font-light text-gray-500 opacity-0 shadow-xs transition-opacity duration-300 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400">
|
||||
<div
|
||||
class="rounded-t-lg border-b border-gray-200 bg-gray-100 px-3 py-2 dark:border-gray-600 dark:bg-gray-700">
|
||||
<div
|
||||
class="flex w-full items-center justify-center font-semibold text-gray-900 dark:text-white">
|
||||
{{ __('Reactions with') }} <img
|
||||
:src="'/assets/images/icons/reactions/' + articleReaction.name + '.png'"
|
||||
class="ml-1" :alt="articleReaction.name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-y-auto px-3 py-2" style="max-height: 200px">
|
||||
<template x-for="user in articleReaction.users">
|
||||
<p class="w-full text-center" x-text="user"></p>
|
||||
</template>
|
||||
</div>
|
||||
<div data-popper-arrow></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div x-show="isAuthenticated">
|
||||
<x-modals.regular-modal>
|
||||
<x-slot name="title">
|
||||
<h2 class="text-2xl">
|
||||
{{ __('Insert Reaction') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div class="flex w-full flex-wrap justify-center gap-3 p-2">
|
||||
<template x-for="defaultReaction in allReactions">
|
||||
<div class="cursor-pointer rounded-lg border-2 border-gray-300 px-3 py-2 hover:bg-gray-200 dark:hover:bg-gray-700 dark:hover:border-g dark:border-gray-800"
|
||||
x-show="canAddReactionFromModal(defaultReaction)" @click="toggleReaction(defaultReaction)">
|
||||
<img :src="'/assets/images/icons/reactions/' + defaultReaction + '.png'"
|
||||
:alt="defaultReaction">
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</x-modals.regular-modal>
|
||||
</div>
|
||||
</div>
|
||||
</x-modals.modal-wrapper>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
window.App = {
|
||||
defaultReactions: @json(config('habbo.reactions')),
|
||||
isAuthenticated: @json(auth()->check())
|
||||
}
|
||||
</script>
|
||||
@endpush
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Photos'))
|
||||
|
||||
<div class="col-span-12">
|
||||
<div class="mb-6 p-6 rounded-xl border-2">
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="w-14 h-14 rounded-full flex items-center justify-center shadow-lg" style="background-color: var(--color-primary);">
|
||||
<svg class="w-8 h-8" style="color: var(--button-text-color);" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 9a2 2 0 012-2h.93a2 2 0 001.664-.89l.812-1.22A2 2 0 0110.07 4h3.86a2 2 0 011.664.89l.812 1.22A2 2 0 0018.07 7H19a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2V9z"></path>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 13a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-2xl font-bold" style="color: var(--color-text)">{{ __('Photos') }}</h1>
|
||||
<p style="color: var(--color-text-muted)">Bekijk de beste momenten vastgelegd door gebruikers</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<x-content.content-card icon="camera-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
{{ __('Photo Gallery') }}
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
{{ __('Klik op een foto om deze te vergroten') }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<x-photos :photos="$photos" />
|
||||
</x-content.content-card>
|
||||
|
||||
<div class="mt-6">
|
||||
{{ $photos->links() }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('javascript')
|
||||
<script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js"></script>
|
||||
@endpush
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css" />
|
||||
</x-app-layout>
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
<x-app-layout>
|
||||
@push('title', 'Word DJ')
|
||||
|
||||
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<x-content.content-card icon="star-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
Word DJ
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Solliciteer als DJ bij {{ setting('hotel_name') }} Radio!
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
@if (session('success'))
|
||||
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if (session('error'))
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
|
||||
<ul class="list-disc list-inside">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($hasPendingApplication)
|
||||
<div class="bg-yellow-100 border border-yellow-400 text-yellow-700 px-4 py-3 rounded mb-4">
|
||||
<p class="font-bold">Je hebt al een openstaande aanmelding!</p>
|
||||
<p>Je kunt pas een nieuwe aanmelding doen als je huidige aanmelding is beoordeeld.</p>
|
||||
</div>
|
||||
@else
|
||||
<p>Heb je passie voor muziek en wil je onze community entertainen? Solliciteer dan nu als DJ!</p>
|
||||
|
||||
<form action="{{ route('radio.apply.store') }}" method="POST" class="space-y-4">
|
||||
@csrf
|
||||
|
||||
<!-- Persoonlijke Gegevens -->
|
||||
<div class="bg-gray-100 dark:bg-gray-800 p-4 rounded">
|
||||
<h3 class="font-bold text-[var(--color-primary)] mb-3 text-lg">Persoonlijke Gegevens</h3>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label for="real_name" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Echte Naam <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="real_name"
|
||||
name="real_name"
|
||||
required
|
||||
value="{{ old('real_name') }}"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
placeholder="Je echte naam">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="age" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Leeftijd <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="age"
|
||||
name="age"
|
||||
required
|
||||
min="13"
|
||||
max="100"
|
||||
value="{{ old('age') }}"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
placeholder="Je leeftijd">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DJ Gegevens -->
|
||||
<div class="bg-gray-100 dark:bg-gray-800 p-4 rounded">
|
||||
<h3 class="font-bold text-[var(--color-primary)] mb-3 text-lg">DJ Gegevens</h3>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<label for="availability" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Beschikbaarheid <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="availability"
|
||||
name="availability"
|
||||
rows="3"
|
||||
required
|
||||
minlength="10"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
placeholder="Wanneer kan je draaien? (bijv. maandag 20:00-22:00, woensdag 19:00-21:00)">{{ old('availability') }}</textarea>
|
||||
<p class="text-xs text-gray-500 mt-1">Geef aan op welke dagen en tijden je beschikbaar bent om te draaien.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="experience" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Ervaring
|
||||
</label>
|
||||
<textarea
|
||||
id="experience"
|
||||
name="experience"
|
||||
rows="3"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
placeholder="Heb je ervaring als DJ? Zo ja, vertel erover...">{{ old('experience') }}</textarea>
|
||||
<p class="text-xs text-gray-500 mt-1">Heb je eerder als DJ gewerkt? Bijvoorbeeld op andere hotels of radio stations.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="motivation" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Motivatie <span class="text-red-500">*</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="motivation"
|
||||
name="motivation"
|
||||
rows="5"
|
||||
required
|
||||
minlength="50"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
placeholder="Waarom wil je DJ worden bij ons? Vertel ons waarom we jou moeten kiezen...">{{ old('motivation') }}</textarea>
|
||||
<p class="text-xs text-gray-500 mt-1">Minimaal 50 karakters. Wees zo uitgebreid mogelijk!</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="music_style" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Muziekstijl
|
||||
</label>
|
||||
<textarea
|
||||
id="music_style"
|
||||
name="music_style"
|
||||
rows="2"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
placeholder="Welke muziekstijl draai je graag? (bijv. Pop, EDM, Hip-Hop, etc.)">{{ old('music_style') }}</textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="discord_username" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Discord Gebruikersnaam
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="discord_username"
|
||||
name="discord_username"
|
||||
value="{{ old('discord_username') }}"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white"
|
||||
placeholder="bijv. gebruiker#1234">
|
||||
<p class="text-xs text-gray-500 mt-1">Voor contact over je aanmelding.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="rank_id" class="block text-sm font-medium dark:text-gray-300 mb-1">
|
||||
Gewenste DJ Rank
|
||||
</label>
|
||||
<select
|
||||
id="rank_id"
|
||||
name="rank_id"
|
||||
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-700 dark:border-gray-600 dark:text-white">
|
||||
<option value="">-- Kies een rank (optioneel) --</option>
|
||||
@foreach ($ranks as $rank)
|
||||
<option value="{{ $rank->id }}" {{ old('rank_id') == $rank->id ? 'selected' : '' }}>
|
||||
{{ $rank->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<button type="submit" class="flex-1 bg-[var(--color-primary)] hover:bg-[var(--color-primary)] text-white px-6 py-3 rounded transition font-bold">
|
||||
Verstuur Aanmelding
|
||||
</button>
|
||||
<a href="{{ route('radio.index') }}" class="bg-gray-300 hover:bg-gray-400 text-gray-800 px-6 py-3 rounded transition">
|
||||
Annuleren
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="info-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
DJ Info
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Waarom word DJ?
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>Als DJ bij {{ setting('hotel_name') }} Radio krijg je de kans om je favoriete muziek te delen met de community.</p>
|
||||
|
||||
<div class="space-y-2 text-xs">
|
||||
<p><strong class="text-[var(--color-primary)]">Voordelen:</strong></p>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<li>Eigen radioshow</li>
|
||||
<li>Leuke community</li>
|
||||
<li>Ervaring opdoen</li>
|
||||
<li>Events draaien</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="text-xs text-gray-500">We zoeken naar gepassioneerde muziekliefhebbers!</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
|
||||
<x-content.content-card icon="musical-note-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
Beschikbare Ranks
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
DJ Ranks
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-2 dark:text-gray-200">
|
||||
@forelse ($ranks as $rank)
|
||||
<div class="flex items-center gap-2 p-2 bg-gray-100 dark:bg-gray-800 rounded">
|
||||
@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>
|
||||
@empty
|
||||
<p class="text-gray-500">Momenteel geen ranks beschikbaar.</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,54 @@
|
||||
<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">
|
||||
<x-content.content-card icon="music-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
{{ setting('hotel_name') }} Radio
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Radio is momenteel offline
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<div class="bg-gray-100 dark:bg-gray-800 rounded-lg p-8 text-center">
|
||||
<div class="text-6xl mb-4">📻</div>
|
||||
<h2 class="text-xl font-bold text-[var(--color-primary)] mb-2">Radio is Offline</h2>
|
||||
<p class="text-gray-500">Onze radio is momenteel niet beschikbaar.</p>
|
||||
<p class="text-sm text-gray-400 mt-2">Kom later terug om te luisteren naar onze geweldige DJ's!</p>
|
||||
|
||||
<div class="mt-6 space-y-2">
|
||||
<a href="{{ route('radio.rooster') }}" class="block text-[var(--color-primary)] hover:underline">
|
||||
Bekijk het rooster
|
||||
</a>
|
||||
@if(setting('radio_applications_enabled') == '1')
|
||||
<a href="{{ route('radio.apply') }}" class="block text-[var(--color-primary)] hover:underline">
|
||||
Word DJ
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="info-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
Radio Info
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Over onze radio
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>Onze radio is normaal gesproken 24/7 online met de beste muziek!</p>
|
||||
<p class="text-xs text-gray-500">De radio kan tijdelijk offline zijn voor onderhoud.</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
+367
@@ -0,0 +1,367 @@
|
||||
<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">
|
||||
<x-content.content-card icon="music-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
{{ setting('hotel_name') }} Radio
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Luister live naar onze DJ's!
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
@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 border-[var(--color-primary)] shadow-lg shadow-[var(--color-primary)]/20">
|
||||
<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="text-[var(--color-primary)] text-xs mt-1 ">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 ? 'bg-[var(--color-primary)] w-4' : '' }}" data-index="{{ $index }}"></button>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="bg-black/80 rounded-lg p-4">
|
||||
<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 class="text-[var(--color-primary)] font-bold">LIVE</span>
|
||||
@else
|
||||
<div class="w-3 h-3 rounded-full bg-gray-500"></div>
|
||||
<span class="text-gray-500 font-bold" style="color: var(--color-text-muted)">OFFLINE</span>
|
||||
@endif
|
||||
</div>
|
||||
@if($isOnline)
|
||||
<div class="flex items-center gap-1 text-xs text-gray-400" 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 bg-white/10 rounded-lg">
|
||||
<p class="text-xs text-gray-400 mb-1">Nu aan het draaien:</p>
|
||||
<p class="text-[var(--color-primary)] font-bold text-lg">{{ $currentDJ['username'] }}</p>
|
||||
@if(isset($currentDJ['show_name']) && $currentDJ['show_name'])
|
||||
<p class="text-white text-sm ">{{ $currentDJ['show_name'] }}</p>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<p class="text-gray-400 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 bg-white/5 rounded">
|
||||
<p class="text-xs text-gray-400 mb-1">Nu aan het spelen:</p>
|
||||
<p id="now-playing-song" class="text-white font-medium truncate ">Laden...</p>
|
||||
<p id="now-playing-artist" class="text-gray-400 text-sm"></p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if($isOnline)
|
||||
<div class="flex items-center gap-4">
|
||||
<button id="play-btn" class="bg-[var(--color-primary)] hover:bg-[var(--color-primary)] text-white px-6 py-2 rounded-lg transition flex items-center gap-2">
|
||||
<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 text-gray-400" 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 bg-gray-600 rounded-lg appearance-none cursor-pointer">
|
||||
</div>
|
||||
</div>
|
||||
<audio id="radio-audio" preload="none"></audio>
|
||||
@else
|
||||
<div class="text-gray-400 text-sm flex-1 text-center py-2 bg-white/5 rounded">
|
||||
Radio is momenteel offline. We zijn zo terug!
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
|
||||
@if($todaySchedule->count() > 0)
|
||||
<x-content.content-card icon="calendar-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>Vandaag op Radio</x-slot:title>
|
||||
<x-slot:under-title>
|
||||
<a href="{{ route('radio.rooster') }}" class="text-[var(--color-primary)] hover:underline">Bekijk volledig rooster</a>
|
||||
</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-3 dark:text-gray-200">
|
||||
@foreach($todaySchedule as $slot)
|
||||
<div class="flex items-center gap-3 p-3 bg-gray-100 dark:bg-gray-800 rounded-lg {{ $currentDJ && is_array($currentDJ) && isset($currentDJ['username']) && ($currentDJ['username'] ?? '') === $slot->user->username ? 'ring-2 ring-[var(--color-primary)]' : '' }}">
|
||||
<div class="text-center min-w-[60px]">
|
||||
<p class="font-bold text-[var(--color-primary)]">{{ $slot->start_time->format('H:i') }}</p>
|
||||
<p class="text-xs text-gray-500">{{ $slot->end_time->format('H:i') }}</p>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="font-bold">{{ $slot->user->username }}</p>
|
||||
@if($slot->show_name)
|
||||
<p class="text-sm text-gray-400">{{ $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>
|
||||
</x-content.content-card>
|
||||
@endif
|
||||
|
||||
@if($banners->count() > 0)
|
||||
<x-content.content-card icon="photo-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>Alle DJ Banners</x-slot:title>
|
||||
<x-slot:under-title>Ontdek onze DJ's</x-slot:under-title>
|
||||
<div class="px-2">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
@foreach($banners as $banner)
|
||||
<div class="group relative overflow-hidden rounded-lg border border-gray-200 dark:border-gray-700 hover:border-[var(--color-primary)] transition-all duration-300">
|
||||
<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-[var(--color-primary)] text-xs">DJ: {{ $banner->user->username }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
@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
|
||||
<x-content.content-card icon="user-icon" classes="border dark:border-gray-900 bg-gradient-to-br from-[var(--color-primary)]/10 to-transparent">
|
||||
<x-slot:title>Nu aan het Draaien</x-slot:title>
|
||||
<x-slot:under-title>Huidige DJ</x-slot:under-title>
|
||||
<div class="px-2 text-center">
|
||||
@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 text-[var(--color-primary)]">{{ $currentDJ['username'] }}</p>
|
||||
@if(isset($currentDJ['show_name']) && $currentDJ['show_name'])
|
||||
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">{{ $currentDJ['show_name'] }}</p>
|
||||
@endif
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
@endif
|
||||
|
||||
<x-content.content-card icon="info-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>Radio Info</x-slot:title>
|
||||
<x-slot:under-title>Over onze radio</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<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 text-[var(--color-primary)] hover:underline">📅 Bekijk het rooster</a>
|
||||
@if(setting('radio_applications_enabled') == '1')
|
||||
<a href="{{ route('radio.apply') }}" class="block text-[var(--color-primary)] hover:underline">🎤 Word DJ</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
|
||||
@if($ranks->count() > 0)
|
||||
<x-content.content-card icon="star-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>DJ Ranks</x-slot:title>
|
||||
<x-slot:under-title>Onze DJ niveaus</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-2 dark:text-gray-200">
|
||||
@foreach($ranks as $rank)
|
||||
<div class="flex items-center gap-2 p-2 bg-gray-100 dark:bg-gray-800 rounded">
|
||||
@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>
|
||||
</x-content.content-card>
|
||||
@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('bg-[var(--color-primary)]', 'w-4');
|
||||
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>
|
||||
@@ -0,0 +1,275 @@
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', $title ?? '')
|
||||
|
||||
@push('styles')
|
||||
@stack('styles')
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="radio-container text-white">
|
||||
@if(!$enabled)
|
||||
<!-- Radio Disabled State -->
|
||||
<div class="min-h-screen flex items-center justify-center p-6">
|
||||
<div class="text-center max-w-md">
|
||||
<div class="mb-6">
|
||||
<svg class="w-24 h-24 mx-auto text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1 class="text-3xl font-bold mb-4">Radio is Offline</h1>
|
||||
<p class="text-gray-400 mb-6">De radio is momenteel uitgeschakeld. Kom later terug!</p>
|
||||
@if($offlineMessage)
|
||||
<div class="bg-gray-800 rounded-lg p-4">
|
||||
<p class="text-gray-300">{{ $offlineMessage }}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<!-- Radio Player Section -->
|
||||
<div class="max-w-6xl mx-auto px-4 py-8">
|
||||
<!-- Header -->
|
||||
<div class="flex items-center justify-between mb-8">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold flex items-center gap-3">
|
||||
<span class="live-badge inline-flex items-center px-3 py-1 rounded-full text-xs font-bold">
|
||||
<span class="w-2 h-2 bg-white rounded-full mr-2"></span>
|
||||
LIVE
|
||||
</span>
|
||||
Radio
|
||||
</h1>
|
||||
<p class="text-gray-400 mt-1">Luister nu naar de beste muziek</p>
|
||||
</div>
|
||||
|
||||
<!-- Stats -->
|
||||
<div class="flex gap-6">
|
||||
@if($showListeners)
|
||||
<div class="stat-card rounded-lg px-4 py-2 flex items-center gap-2">
|
||||
<svg class="w-5 h-5 text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/>
|
||||
</svg>
|
||||
<span id="listenerCount" class="font-semibold">--</span>
|
||||
<span class="text-gray-400 text-sm">luisteraars</span>
|
||||
</div>
|
||||
@endif
|
||||
<a href="{{ route('radio.leaderboard') }}" class="stat-card rounded-lg px-4 py-2 flex items-center gap-2 hover:bg-white/10 transition">
|
||||
<svg class="w-5 h-5 text-yellow-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z"/>
|
||||
</svg>
|
||||
<span class="font-semibold">Top 100</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Player -->
|
||||
<div class="radio-player rounded-2xl p-6 mb-8">
|
||||
<div class="grid md:grid-cols-3 gap-6 items-center">
|
||||
<!-- Album Art / DJ Avatar -->
|
||||
<div class="flex justify-center">
|
||||
<div id="djAvatar" class="w-32 h-32 rounded-full bg-gradient-to-br from-amber-400 to-amber-600 flex items-center justify-center text-4xl">
|
||||
@if($currentDJ && $currentDJ->user)
|
||||
<img src="{{ $currentDJ->user->avatar_url ?? asset('images/default-avatar.png') }}" alt="{{ $currentDJ->user->username }}" class="w-full h-full rounded-full object-cover">
|
||||
@else
|
||||
🎵
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Track Info -->
|
||||
<div class="text-center">
|
||||
<div id="nowPlayingInfo">
|
||||
<p class="text-gray-400 text-sm mb-1">Nu draait</p>
|
||||
<h2 id="trackTitle" class="text-xl font-bold mb-2">
|
||||
@if($nowPlaying && $nowPlaying['title'])
|
||||
{{ $nowPlaying['title'] }}
|
||||
@else
|
||||
--
|
||||
@endif
|
||||
</h2>
|
||||
@if($nowPlaying && $nowPlaying['artist'])
|
||||
<p id="trackArtist" class="text-gray-400">{{ $nowPlaying['artist'] }}</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- DJ Info -->
|
||||
@if($showCurrentDJ && $currentDJ && $currentDJ->user)
|
||||
<div class="mt-4 pt-4 border-t border-white/10">
|
||||
<p class="text-gray-400 text-sm mb-1">Presentator</p>
|
||||
<p class="font-semibold text-amber-400">{{ $currentDJ->user->username }}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<!-- Player Controls -->
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<!-- Audio Player -->
|
||||
<audio id="radioPlayer" preload="none">
|
||||
<source src="{{ $streamUrl }}" type="audio/mpeg">
|
||||
</audio>
|
||||
|
||||
<!-- Play/Pause Button -->
|
||||
<button id="playPauseBtn" class="w-20 h-20 rounded-full bg-amber-500 hover:bg-amber-400 flex items-center justify-center transition-all transform hover:scale-105 shadow-lg shadow-amber-500/30">
|
||||
<svg id="playIcon" class="w-10 h-10 ml-1" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M8 5v14l11-7z"/>
|
||||
</svg>
|
||||
<svg id="pauseIcon" class="w-10 h-10 hidden" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- Volume Control -->
|
||||
<div class="flex items-center gap-3 w-full max-w-xs">
|
||||
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15H4a1 1 0 01-1-1v-4a1 1 0 011-1h1.586l4.707-4.707C10.923 3.663 12 4.109 12 5v14c0 .891-1.077 1.337-1.707.707L5.586 15z"/>
|
||||
</svg>
|
||||
<input type="range" id="volumeSlider" min="0" max="100" value="80" class="flex-1 h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Song History -->
|
||||
@if($showHistory && !empty($songHistory))
|
||||
<div class="now-playing-card rounded-xl p-6 mb-8">
|
||||
<h3 class="text-lg font-semibold mb-4">Recent Gedraaid</h3>
|
||||
<div class="space-y-3" id="songHistory">
|
||||
@foreach($songHistory as $song)
|
||||
<div class="flex items-center justify-between py-2 border-b border-white/5 last:border-0">
|
||||
<div>
|
||||
<p class="font-medium">{{ $song['title'] }}</p>
|
||||
@if($song['artist'])
|
||||
<p class="text-sm text-gray-400">{{ $song['artist'] }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<span class="text-sm text-gray-500">{{ $song['time'] }}</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Schedule Preview -->
|
||||
@if($showSchedule && $todaySchedule->isNotEmpty())
|
||||
<div class="now-playing-card rounded-xl p-6">
|
||||
<h3 class="text-lg font-semibold mb-4">Vandaag op Radio</h3>
|
||||
<div class="space-y-3">
|
||||
@foreach($todaySchedule as $slot)
|
||||
<div class="flex items-center justify-between py-2 border-b border-white/5 last:border-0">
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-amber-400 font-mono">{{ date('H:i', strtotime($slot->start_time)) }}</span>
|
||||
<span class="font-medium">{{ $slot->user->username ?? 'Onbekend' }}</span>
|
||||
</div>
|
||||
<span class="text-gray-400 text-sm">{{ $slot->description ?? $slot->name }}</span>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Social Links -->
|
||||
@if(!empty($socialLinks))
|
||||
<div class="flex justify-center gap-6 mt-8">
|
||||
@foreach($socialLinks as $platform => $url)
|
||||
@if($url)
|
||||
<a href="{{ $url }}" target="_blank" class="w-10 h-10 rounded-full bg-white/10 hover:bg-white/20 flex items-center justify-center transition">
|
||||
@switch($platform)
|
||||
@case('facebook')
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>
|
||||
@break
|
||||
@case('twitter')
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
||||
@break
|
||||
@case('instagram')
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
|
||||
@break
|
||||
@case('discord')
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
|
||||
@break
|
||||
@case('youtube')
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>
|
||||
@break
|
||||
@case('twitch')
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714z"/></svg>
|
||||
@break
|
||||
@endswitch
|
||||
</a>
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const player = document.getElementById('radioPlayer');
|
||||
const playBtn = document.getElementById('playPauseBtn');
|
||||
const playIcon = document.getElementById('playIcon');
|
||||
const pauseIcon = document.getElementById('pauseIcon');
|
||||
const volumeSlider = document.getElementById('volumeSlider');
|
||||
const listenerCount = document.getElementById('listenerCount');
|
||||
|
||||
// Play/Pause
|
||||
playBtn.addEventListener('click', function() {
|
||||
if (player.paused) {
|
||||
player.play().catch(function(e) {
|
||||
console.log('Autoplay blocked:', e);
|
||||
});
|
||||
playIcon.classList.add('hidden');
|
||||
pauseIcon.classList.remove('hidden');
|
||||
} else {
|
||||
player.pause();
|
||||
playIcon.classList.remove('hidden');
|
||||
pauseIcon.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
// Volume
|
||||
volumeSlider.addEventListener('input', function() {
|
||||
player.volume = this.value / 100;
|
||||
});
|
||||
|
||||
// Initial volume
|
||||
player.volume = volumeSlider.value / 100;
|
||||
|
||||
// Update listeners count
|
||||
function updateListeners() {
|
||||
fetch('/api/radio/listeners')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (listenerCount) {
|
||||
listenerCount.textContent = data.count.toLocaleString();
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
if (listenerCount) listenerCount.textContent = '--';
|
||||
});
|
||||
}
|
||||
|
||||
// Update now playing
|
||||
function updateNowPlaying() {
|
||||
fetch('/api/radio/now-playing')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
const titleEl = document.getElementById('trackTitle');
|
||||
const artistEl = document.getElementById('trackArtist');
|
||||
if (titleEl && data.title) titleEl.textContent = data.title;
|
||||
if (artistEl && data.artist) artistEl.textContent = data.artist;
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
// Auto-update listeners every 30 seconds
|
||||
updateListeners();
|
||||
setInterval(updateListeners, 30000);
|
||||
|
||||
// Auto-update now playing every 15 seconds
|
||||
updateNowPlaying();
|
||||
setInterval(updateNowPlaying, 15000);
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@endsection
|
||||
@@ -0,0 +1,128 @@
|
||||
<x-app-layout>
|
||||
@push('title', 'DJ Rooster')
|
||||
|
||||
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<x-content.content-card icon="calendar-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
DJ Rooster
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Wanneer is de volgende show?
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-6 dark:text-gray-200">
|
||||
@php
|
||||
$days = [
|
||||
'monday' => 'Maandag',
|
||||
'tuesday' => 'Dinsdag',
|
||||
'wednesday' => 'Woensdag',
|
||||
'thursday' => 'Donderdag',
|
||||
'friday' => 'Vrijdag',
|
||||
'saturday' => 'Zaterdag',
|
||||
'sunday' => 'Zondag',
|
||||
];
|
||||
$currentDay = strtolower(now()->format('l'));
|
||||
@endphp
|
||||
|
||||
@foreach($days as $dayKey => $dayName)
|
||||
@if(isset($schedule[$dayKey]) && $schedule[$dayKey]->count() > 0)
|
||||
<div class="border-b border-gray-200 dark:border-gray-700 pb-4 last:border-0">
|
||||
<h3 class="text-lg font-bold text-[var(--color-primary)] mb-3 {{ $dayKey === $currentDay ? 'ring-2 ring-[var(--color-primary)] rounded-lg p-2' : '' }}">
|
||||
{{ $dayName }}
|
||||
@if($dayKey === $currentDay)
|
||||
<span class="text-xs bg-red-500 text-white px-2 py-1 rounded ml-2">Vandaag</span>
|
||||
@endif
|
||||
</h3>
|
||||
|
||||
<div class="space-y-2">
|
||||
@foreach($schedule[$dayKey] as $slot)
|
||||
<div class="flex items-center gap-4 p-3 bg-gray-100 dark:bg-gray-800 rounded-lg {{ $dayKey === $currentDay && now()->format('H:i') >= $slot->start_time->format('H:i') && now()->format('H:i') <= $slot->end_time->format('H:i') ? 'ring-2 ring-green-500' : '' }}">
|
||||
<div class="text-center min-w-[80px]">
|
||||
<p class="font-bold">{{ $slot->start_time->format('H:i') }}</p>
|
||||
<p class="text-xs text-gray-500">{{ $slot->end_time->format('H:i') }}</p>
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="font-bold">{{ $slot->user->username }}</span>
|
||||
@if($slot->show_name)
|
||||
<span class="text-sm text-gray-400">- {{ $slot->show_name }}</span>
|
||||
@endif
|
||||
</div>
|
||||
@if($slot->description)
|
||||
<p class="text-xs text-gray-500 mt-1">{{ $slot->description }}</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if($dayKey === $currentDay && now()->format('H:i') >= $slot->start_time->format('H:i') && now()->format('H:i') <= $slot->end_time->format('H:i'))
|
||||
<span class="px-2 py-1 bg-green-500 text-white text-xs rounded animate-pulse">NU LIVE</span>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
@if($schedule->isEmpty())
|
||||
<div class="text-center py-8">
|
||||
<p class="text-gray-500">Er zijn momenteel geen shows gepland.</p>
|
||||
<p class="text-sm text-gray-400 mt-2">Kom later terug voor updates!</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="info-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
Rooster Info
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Houd ons in de gaten!
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>Al onze DJ's staan klaar om je te entertainen met de beste muziek!</p>
|
||||
|
||||
<div class="space-y-2 text-xs">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-3 h-3 bg-green-500 rounded animate-pulse"></span>
|
||||
<span>NU LIVE</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="w-3 h-3 bg-[var(--color-primary)] rounded"></span>
|
||||
<span>Vandaag</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-xs text-gray-500 mt-4">Tijden kunnen wijzigen zonder voorafgaande kennisgeving.</p>
|
||||
|
||||
<a href="{{ route('radio.index') }}" class="block text-[var(--color-primary)] hover:underline mt-4">
|
||||
← Terug naar Radio
|
||||
</a>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
|
||||
<x-content.content-card icon="music-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
Nu op Radio
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Luister mee!
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm dark:text-gray-200">
|
||||
<a href="{{ route('radio.index') }}" class="block bg-[var(--color-primary)] hover:bg-[var(--color-primary)] text-white text-center py-3 rounded-lg transition">
|
||||
▶ Luister Live
|
||||
</a>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,76 @@
|
||||
<x-app-layout>
|
||||
@push('title', 'Stuur een Shout')
|
||||
|
||||
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
|
||||
<div class="flex flex-col gap-y-4">
|
||||
<x-content.content-card icon="chat-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
Stuur een Shout naar de DJ
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Stuur een bericht naar de DJ!
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
@if (auth()->check())
|
||||
@if (session('success'))
|
||||
<div class="bg-green-100 dark:bg-green-900/30 border border-green-400 dark:border-green-600 text-green-700 dark:text-green-300 px-4 py-3 rounded mb-4">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form action="{{ route('radio.shouts.store') }}" method="POST" class="mb-4">
|
||||
@csrf
|
||||
<div>
|
||||
<label class="block text-sm font-medium dark:text-gray-300 mb-2">Jouw bericht (max 280 karakters)</label>
|
||||
<div class="flex gap-2">
|
||||
<input
|
||||
type="text"
|
||||
name="message"
|
||||
required
|
||||
maxlength="280"
|
||||
class="flex-1 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[var(--color-primary)] dark:bg-gray-800 dark:border-gray-700 dark:text-gray-200"
|
||||
placeholder="Plaats je shout voor de DJ...">
|
||||
<button type="submit" class="bg-[var(--color-primary)] hover:bg-[var(--color-primary)] text-white px-4 py-2 rounded transition whitespace-nowrap">
|
||||
📤 Stuur
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 p-4 rounded-lg">
|
||||
<p class="text-blue-800 dark:text-blue-300">
|
||||
<span class="font-semibold">✅ Je shout is verstuurd!</span><br>
|
||||
De DJ kan je bericht lezen in het admin paneel. Bedankt voor je bericht!
|
||||
</p>
|
||||
</div>
|
||||
@else
|
||||
<div class="bg-gray-100 dark:bg-gray-800 p-3 rounded text-center">
|
||||
<p class="text-gray-500 mb-2">
|
||||
<a href="/login" class="text-[var(--color-primary)] hover:underline">Log in</a> om een shout te sturen
|
||||
</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="info-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
Shout Info
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
Hoe werkt het?
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>Stuur shouts die de DJ live kan lezen tijdens de show!</p>
|
||||
<p class="text-xs text-gray-500">Houd het vriendelijk en respectvol.</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,73 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Staff'))
|
||||
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-2">
|
||||
@forelse($positions as $position)
|
||||
@continue(!$position->permission) {{-- skip if the rank relation is missing --}}
|
||||
|
||||
<x-content.staff-content-section :badge="$position->permission->badge" :color="$position->permission->staff_color">
|
||||
<x-slot:title>
|
||||
{{ $position->permission->rank_name }}
|
||||
</x-slot:title>
|
||||
<x-slot:under-title>
|
||||
{{ $position->permission->job_description }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="text-center dark:text-gray-400">
|
||||
<div class="mb-4 text-sm">
|
||||
{!! $position->description !!}
|
||||
</div>
|
||||
<div class="mb-4 text-sm font-semibold">
|
||||
{{ __('Application Deadline :date', [
|
||||
'date' => $position->apply_to ? $position->apply_to->format('F j, Y, g:i A') : __('No deadline set')
|
||||
]) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
@if (auth()->check() && auth()->user()->hasAppliedForPosition($position->permission->id))
|
||||
<x-form.danger-button>
|
||||
{{ __('You have already applied for :position', ['position' => $position->permission->rank_name]) }}
|
||||
</x-form.danger-button>
|
||||
@else
|
||||
<a href="{{ route('staff-applications.show', $position) }}" class="w-full">
|
||||
<x-form.secondary-button>
|
||||
{{ __('Apply for :position', ['position' => $position->permission->rank_name]) }}
|
||||
</x-form.secondary-button>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</x-content.staff-content-section>
|
||||
@empty
|
||||
<x-content.content-card icon="lighthouse-icon" classes="border dark:border-gray-900 col-span-full">
|
||||
<x-slot:title>
|
||||
{{ __('No positions open') }}
|
||||
</x-slot:title>
|
||||
<x-slot:under-title>
|
||||
{{ __('There is currently no positions open') }}
|
||||
</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>
|
||||
{{ __('Please come back at a later time to check if we have any positions open by then! Thank you for your interest.', ['hotel' => setting('hotel_name')]) }}
|
||||
</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="chat-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>
|
||||
{{ __('Apply for :hotel staff', ['hotel' => setting('hotel_name')]) }}
|
||||
</x-slot:title>
|
||||
<x-slot:under-title>
|
||||
{{ __('Select position to get started', ['hotel' => setting('hotel_name')]) }}
|
||||
</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>
|
||||
{{ __('Here at :hotel we open up for staff applications every now and then. Sometimes you will find this page empty other times it might be filled with positions, if you ever come across a position you feel you would fit perfectly into, then do not hesitate to apply for it.', ['hotel' => setting('hotel_name')]) }}
|
||||
</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,56 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Staff'))
|
||||
|
||||
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
|
||||
<x-content.staff-content-section :badge="$position->permission->badge" :color="$position->permission->staff_color">
|
||||
<x-slot:title>
|
||||
{{ __('You are applying for :position', ['position' => $position->permission->rank_name]) }}
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
{{ __('Please fill out the fields below to apply for :position', ['position' => $position->permission->rank_name]) }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<form class="flex flex-col gap-y-3" action="{{ route('staff-applications.store', $position) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div>
|
||||
<x-form.label for="username" disabled>{{ __('Username') }}</x-form.label>
|
||||
<x-form.input name="username" value="{{ auth()->user()->username }}" :readonly="true" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-form.label for="content" disabled>{{ __('About you') }}</x-form.label>
|
||||
<textarea name="content" class="focus:ring-0 border-4 border-gray-200 rounded dark:bg-gray-800 dark:border-gray-700 dark:text-gray-200 focus:border-[var(--color-primary)] w-full min-h-[180px]">{{ old('content') }}</textarea>
|
||||
@error('content')
|
||||
<p class="text-red-600 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if (setting('google_recaptcha_enabled'))
|
||||
<div class="g-recaptcha" data-sitekey="{{ config('habbo.site.recaptcha_site_key') }}"></div>
|
||||
@endif
|
||||
|
||||
@if (setting('cloudflare_turnstile_enabled'))
|
||||
<x-turnstile />
|
||||
@endif
|
||||
|
||||
<x-form.primary-button>
|
||||
{{ __('Apply for :position', ['position' => $position->permission->rank_name]) }}
|
||||
</x-form.primary-button>
|
||||
</form>
|
||||
</x-content.staff-content-section>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>{{ __('Applying for :position', ['position' => $position->permission->rank_name]) }}</x-slot:title>
|
||||
<x-slot:under-title>{{ __('Read before applying') }}</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>
|
||||
{{ __('Please fill out all the fields to apply for :position. Be honest and transparent. Providing incorrect information may lead to removal if hired.', ['position' => $position->permission->rank_name]) }}
|
||||
</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Staff'))
|
||||
|
||||
<div class="col-span-12 lg:col-span-9 space-y-8">
|
||||
@foreach ($employees as $employee)
|
||||
@php
|
||||
$sectionColor = $employee->staff_color ?? '#eeb425';
|
||||
@endphp
|
||||
<div class="bg-white dark:bg-gray-800 rounded-2xl border-2 overflow-hidden transition-all duration-300"
|
||||
style="border-color: {{ $sectionColor }}30; box-shadow: 0 8px 32px {{ $sectionColor }}10;">
|
||||
<div class="px-6 py-5 border-b flex items-center gap-4 transition-all duration-300"
|
||||
style="background: linear-gradient(135deg, {{ $sectionColor }}12 0%, transparent 100%); border-color: {{ $sectionColor }}30;">
|
||||
@if($employee->badge)
|
||||
<div class="relative">
|
||||
<img src="{{ asset(setting('badges_path') . $employee->badge . '.gif') }}"
|
||||
alt="{{ $employee->rank_name }}"
|
||||
class="w-14 h-14 -lg">
|
||||
</div>
|
||||
@endif
|
||||
<div class="flex-1">
|
||||
<div class="flex items-center gap-3">
|
||||
<h2 class="text-2xl font-extrabold tracking-tight"
|
||||
style="color: {{ $sectionColor }};">
|
||||
{{ $employee->rank_name }}
|
||||
</h2>
|
||||
</div>
|
||||
@if($employee->job_description)
|
||||
<p class="text-sm text-gray-500 dark:text-gray-400 mt-0.5">{{ $employee->job_description }}</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="px-4 py-1.5 rounded-full text-sm font-bold"
|
||||
style="background-color: {{ $sectionColor }}20; color: {{ $sectionColor }}; border: 1px solid {{ $sectionColor }}40;">
|
||||
{{ count($employee->users) }} {{ count($employee->users) == 1 ? __('member') : __('members') }}
|
||||
</span>
|
||||
<span class="text-4xl font-black tracking-tighter"
|
||||
style="color: {{ $sectionColor }}; text-shadow: 0 0 20px {{ $sectionColor }}60;">
|
||||
>>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-6">
|
||||
@if(count($employee->users) > 0)
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-5">
|
||||
@foreach ($employee->users as $staff)
|
||||
<x-community.staff-card :user="$staff" />
|
||||
@endforeach
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center py-16">
|
||||
<div class="w-20 h-20 mx-auto mb-4 rounded-full bg-gray-100 dark:bg-gray-700 flex items-center justify-center">
|
||||
<svg class="w-10 h-10 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
<p class="text-lg text-gray-500 dark:text-gray-400 font-medium">{{ __('No staff members in this position') }}</p>
|
||||
<p class="text-sm text-gray-400 dark:text-gray-500 mt-1">{{ __('Check back later for updates') }}</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 space-y-4">
|
||||
<div class="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden">
|
||||
<div class="absolute left-0 top-0 bottom-0 w-1.5 bg-gradient-to-b from-amber-400 to-amber-500"></div>
|
||||
<div class="p-5">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<h3 class="text-lg font-bold" style="color: var(--color-text)">
|
||||
{{ setting('hotel_name') }} {{ __('Staff') }}
|
||||
</h3>
|
||||
<span style="color: var(--color-primary);" class="text-2xl font-black">>></span>
|
||||
</div>
|
||||
<p class="text-xs uppercase tracking-wider mb-4" style="color: var(--color-text-muted)">{{ __('About our team') }}</p>
|
||||
<div class="space-y-3 text-sm" style="color: var(--color-text)">
|
||||
<p>{{ __('The :hotel staff team is one big happy family, each staff member has a different role and duties to fulfill.', ['hotel' => setting('hotel_name')]) }}</p>
|
||||
<p>{{ __('Most of our team usually consists of players that have been around :hotel for quite a while, but this does not mean we only recruit old & known players, we recruit those who shine out to us!', ['hotel' => setting('hotel_name')]) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border overflow-hidden" style="background-color: var(--color-surface); border-color: var(--color-text-muted);">
|
||||
<div class="absolute left-0 top-0 bottom-0 w-1.5" style="background: linear-gradient(to bottom, var(--color-primary), var(--color-primary));"></div>
|
||||
<div class="p-5">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<h3 class="text-lg font-bold" style="color: var(--color-text)">
|
||||
{{ __('Join the Team') }}
|
||||
</h3>
|
||||
<span style="color: var(--color-primary);" class="text-2xl font-black">>></span>
|
||||
</div>
|
||||
<p class="text-xs uppercase tracking-wider mb-4" style="color: var(--color-text-muted)">{{ __('Become a staff member') }}</p>
|
||||
<div class="space-y-3 text-sm" style="color: var(--color-text)">
|
||||
<p>{{ __('Every now and then staff applications may open up. Once they do we always make sure to post a news article explaining the process - So make sure you keep an eye out for those in you are interested in joining the :hotel staff team.', ['hotel' => setting('hotel_name')]) }}</p>
|
||||
<a href="/community/staff-applications" class="inline-flex items-center gap-2 mt-2 px-4 py-2 rounded-lg font-semibold text-sm transition-all hover:scale-105"
|
||||
style="background: var(--color-primary); color: var(--button-text-color);">
|
||||
{{ __('View Open Positions') }}
|
||||
<span class="text-lg">>></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,105 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Staff'))
|
||||
|
||||
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-2">
|
||||
@forelse($positions as $position)
|
||||
@continue(!$position->team)
|
||||
@php
|
||||
$status = auth()->check()
|
||||
? ($userAppStatuses[$position->team->id] ?? null) // 'pending'|'approved'|'rejected'|null
|
||||
: null;
|
||||
|
||||
$statusLabel = $status ? ucfirst($status) : null;
|
||||
$statusColorClasses = match ($status) {
|
||||
'approved' => 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300 border-green-200 dark:border-green-800',
|
||||
'pending' => 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300 border-yellow-200 dark:border-yellow-800',
|
||||
'rejected' => 'bg-red-100 text-red-800 dark:bg-red-900/40 dark:text-red-300 border-red-200 dark:border-red-800',
|
||||
default => '',
|
||||
};
|
||||
@endphp
|
||||
|
||||
<x-content.staff-content-section :badge="$position->team->badge" :color="$position->team->staff_color">
|
||||
<x-slot:title>
|
||||
<span class="inline-flex items-center gap-2">
|
||||
{{ $position->team->rank_name }}
|
||||
|
||||
@if ($statusLabel)
|
||||
<span class="inline-flex items-center rounded-full border px-2 py-0.5 text-xs font-medium {{ $statusColorClasses }}">
|
||||
{{ $statusLabel }}
|
||||
</span>
|
||||
@endif
|
||||
</span>
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
{{ $position->team?->job_description }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<div class="text-center dark:text-gray-400">
|
||||
<div class="mb-4 text-sm">
|
||||
{!! $position->description !!}
|
||||
</div>
|
||||
<div class="mb-4 text-sm font-semibold">
|
||||
{{ __('Application Deadline :date', ['date' => $position->apply_to ? $position->apply_to->format('F j, Y, g:i A') : __('No deadline set')]) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between">
|
||||
@auth
|
||||
@if ($status)
|
||||
{{-- Already applied: show a disabled button indicating status --}}
|
||||
<x-form.secondary-button class="w-full justify-center" disabled>
|
||||
@switch($status)
|
||||
@case('pending')
|
||||
{{ __('Your application is pending') }}
|
||||
@break
|
||||
@case('approved')
|
||||
{{ __('You have been approved') }}
|
||||
@break
|
||||
@case('rejected')
|
||||
{{ __('Your application was rejected') }}
|
||||
@break
|
||||
@default
|
||||
{{ __('Application submitted') }}
|
||||
@endswitch
|
||||
</x-form.secondary-button>
|
||||
@else
|
||||
{{-- No application yet: show Apply --}}
|
||||
<a href="{{ route('team-applications.show', $position) }}" class="w-full">
|
||||
<x-form.primary-button class="w-full justify-center">
|
||||
{{ __('Apply for :position', ['position' => $position->team->rank_name]) }}
|
||||
</x-form.primary-button>
|
||||
</a>
|
||||
@endif
|
||||
@else
|
||||
<a href="{{ route('login') }}" class="w-full">
|
||||
<x-form.secondary-button class="w-full justify-center">
|
||||
{{ __('Login to apply') }}
|
||||
</x-form.secondary-button>
|
||||
</a>
|
||||
@endauth
|
||||
</div>
|
||||
</x-content.staff-content-section>
|
||||
@empty
|
||||
<x-content.content-card icon="lighthouse-icon" classes="border dark:border-gray-900 col-span-full">
|
||||
<x-slot:title>{{ __('No team positions open') }}</x-slot:title>
|
||||
<x-slot:under-title>{{ __('There are currently no open team positions') }}</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>{{ __('Please come back later to check for new openings. Thank you!') }}</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="chat-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>{{ __('Apply for :hotel Team', ['hotel' => setting('hotel_name')]) }}</x-slot:title>
|
||||
<x-slot:under-title>{{ __('Select a team to get started') }}</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>{{ __('We open team applications periodically. If you see a team you fit, do not hesitate to apply!') }}</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@@ -0,0 +1,56 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Staff'))
|
||||
|
||||
<div class="col-span-12 lg:col-span-9 lg:w-[96%]">
|
||||
<x-content.staff-content-section :badge="$position->team->badge" :color="$position->team->staff_color">
|
||||
<x-slot:title>
|
||||
{{ __('You are applying for :position', ['position' => $position->team->rank_name]) }}
|
||||
</x-slot:title>
|
||||
|
||||
<x-slot:under-title>
|
||||
{{ __('Please fill out the fields below to apply for :position', ['position' => $position->team->rank_name]) }}
|
||||
</x-slot:under-title>
|
||||
|
||||
<form class="flex flex-col gap-y-3" action="{{ route('team-applications.store', $position) }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div>
|
||||
<x-form.label for="username" disabled>{{ __('Username') }}</x-form.label>
|
||||
<x-form.input classes="bg-gray-100" name="username" value="{{ auth()->user()->username }}" :readonly="true" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<x-form.label for="content" disabled>{{ __('About you') }}</x-form.label>
|
||||
<textarea name="content" class="focus:ring-0 border-4 border-gray-200 rounded dark:bg-gray-800 dark:border-gray-700 dark:text-gray-200 focus:border-[var(--color-primary)] w-full min-h-[180px]">{{ old('content') }}</textarea>
|
||||
@error('content')
|
||||
<span class="text-red-500 text-sm">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
@if (setting('google_recaptcha_enabled'))
|
||||
<div class="g-recaptcha" data-sitekey="{{ config('habbo.site.recaptcha_site_key') }}"></div>
|
||||
@endif
|
||||
|
||||
@if (setting('cloudflare_turnstile_enabled'))
|
||||
<x-turnstile />
|
||||
@endif
|
||||
|
||||
<x-form.primary-button>
|
||||
{{ __('Apply for :position', ['position' => $position->team->rank_name]) }}
|
||||
</x-form.primary-button>
|
||||
</form>
|
||||
</x-content.staff-content-section>
|
||||
</div>
|
||||
|
||||
<div class="col-span-12 lg:col-span-3 lg:w-[110%] space-y-4 lg:-ml-[32px]">
|
||||
<x-content.content-card icon="hotel-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>{{ __('Applying for :position', ['position' => $position->team->rank_name]) }}</x-slot:title>
|
||||
<x-slot:under-title>{{ __('Read before applying') }}</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>
|
||||
{{ __('Please fill out all the fields to apply for :position. Be honest and transparent. Providing incorrect information may lead to removal if hired.', ['position' => $position->team->rank_name]) }}
|
||||
</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
<x-app-layout>
|
||||
@push('title', __('Staff'))
|
||||
|
||||
<div
|
||||
x-data="{ q: '', hideEmpty: false }"
|
||||
class="col-span-12 space-y-4"
|
||||
>
|
||||
{{-- Toolbar --}}
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
||||
<h1 class="text-2xl font-semibold tracking-tight" style="color: var(--color-text)">{{ __('Teams') }}</h1>
|
||||
|
||||
<div class="flex w-full flex-col items-stretch gap-3 sm:w-auto sm:flex-row sm:items-center">
|
||||
<div class="relative sm:w-80">
|
||||
<input
|
||||
x-model="q"
|
||||
type="text"
|
||||
placeholder="{{ __('Search teams…') }}"
|
||||
class="w-full rounded-xl border px-4 py-2.5 pr-10 text-sm focus:outline-none focus:ring-0"
|
||||
style="background-color: var(--color-background); color: var(--color-text); border-color: var(--input-border-color);"
|
||||
/>
|
||||
<svg class="pointer-events-none absolute right-3 top-1/2 h-5 w-5 -translate-y-1/2 opacity-60"
|
||||
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="m21 21-4.35-4.35M10 18a8 8 0 1 1 0-16 8 8 0 0 1 0 16z" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<label class="inline-flex items-center gap-2 text-sm" style="color: var(--color-text)">
|
||||
<input type="checkbox" x-model="hideEmpty"
|
||||
class="rounded border-gray-300 text-[var(--color-primary)] focus:ring-[var(--color-primary)]" />
|
||||
<span class="select-none">{{ __('Hide empty teams') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Teams --}}
|
||||
<div class="flex flex-col gap-y-4">
|
||||
@forelse ($employees as $employee)
|
||||
@php
|
||||
/** @var \Illuminate\Support\Collection $users */
|
||||
$users = $employee->users ?? collect();
|
||||
$memberCount = $users->count();
|
||||
$searchText = trim(($employee->rank_name ?? '') . ' ' . ($employee->job_description ?? ''));
|
||||
@endphp
|
||||
|
||||
<section
|
||||
x-data="{
|
||||
name: @js($searchText),
|
||||
hasMembers: {{ $memberCount > 0 ? 'true' : 'false' }}
|
||||
}"
|
||||
x-show="(name.toLowerCase().includes(q.toLowerCase())) && (!hideEmpty || hasMembers)"
|
||||
x-cloak
|
||||
>
|
||||
<x-content.staff-content-section
|
||||
:badge="$employee->badge"
|
||||
:color="$employee->staff_color"
|
||||
class="overflow-hidden rounded-2xl border border-gray-100 shadow-sm dark:border-gray-800"
|
||||
>
|
||||
{{-- Header --}}
|
||||
<div class="flex items-start justify-between">
|
||||
<div>
|
||||
<x-slot:title>
|
||||
{{ $employee->rank_name }}
|
||||
</x-slot:title>
|
||||
<x-slot:under-title>
|
||||
{{ $employee?->job_description }}
|
||||
</x-slot:under-title>
|
||||
</div>
|
||||
|
||||
{{-- Member count chip --}}
|
||||
<span class="ml-4 shrink-0 rounded-full border px-3 py-1 text-xs font-medium" style="border-color: var(--color-text-muted); color: var(--color-text);">
|
||||
{{ $memberCount }} {{ \Illuminate\Support\Str::plural(__('member'), $memberCount) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{{-- Members grid --}}
|
||||
<div class="mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
@forelse ($users as $staff)
|
||||
<x-community.staff-card :user="$staff" />
|
||||
@empty
|
||||
<div class="col-span-full">
|
||||
<div class="rounded-xl border border-dashed p-6 text-center text-sm" style="border-color: var(--color-text-muted); color: var(--color-text-muted);">
|
||||
{{ __('We currently have no staff in this team') }}
|
||||
</div>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</x-content.staff-content-section>
|
||||
</section>
|
||||
@empty
|
||||
<x-content.content-card icon="lighthouse-icon" classes="border dark:border-gray-900">
|
||||
<x-slot:title>{{ __('No teams found') }}</x-slot:title>
|
||||
<x-slot:under-title>{{ __('Please check back later.') }}</x-slot:under-title>
|
||||
<div class="px-2 text-sm space-y-4 dark:text-gray-200">
|
||||
<p>{{ __('There are no teams to display right now.') }}</p>
|
||||
</div>
|
||||
</x-content.content-card>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
Reference in New Issue
Block a user