diff --git a/resources/views/components/layouts/app/header.blade.php b/resources/views/components/layouts/app/header.blade.php
index 18ff125..063ef41 100644
--- a/resources/views/components/layouts/app/header.blade.php
+++ b/resources/views/components/layouts/app/header.blade.php
@@ -24,6 +24,10 @@
:current="request()->routeIs(['plugins.index', 'plugins.markup', 'plugins.api', 'plugins.receipt'])">
Plugins
+
+ Playlists
+
@@ -100,6 +104,10 @@
:current="request()->routeIs('plugins.index')" class="m-2">
Plugins
+
+ Playlists
+
diff --git a/resources/views/livewire/playlists/index.blade.php b/resources/views/livewire/playlists/index.blade.php
new file mode 100644
index 0000000..3d34999
--- /dev/null
+++ b/resources/views/livewire/playlists/index.blade.php
@@ -0,0 +1,307 @@
+devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ return view('livewire.playlists.index');
+ }
+
+ public function togglePlaylistActive(Playlist $playlist)
+ {
+ abort_unless(auth()->user()->devices->contains($playlist->device), 403);
+ $playlist->update(['is_active' => !$playlist->is_active]);
+ $this->devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ }
+
+ public function movePlaylistItemUp(PlaylistItem $item)
+ {
+ abort_unless(auth()->user()->devices->contains($item->playlist->device), 403);
+ $previousItem = $item->playlist->items()
+ ->where('order', '<', $item->order)
+ ->orderBy('order', 'desc')
+ ->first();
+
+ if ($previousItem) {
+ $tempOrder = $previousItem->order;
+ $previousItem->update(['order' => $item->order]);
+ $item->update(['order' => $tempOrder]);
+ $this->devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ }
+ }
+
+ public function movePlaylistItemDown(PlaylistItem $item)
+ {
+ abort_unless(auth()->user()->devices->contains($item->playlist->device), 403);
+ $nextItem = $item->playlist->items()
+ ->where('order', '>', $item->order)
+ ->orderBy('order')
+ ->first();
+
+ if ($nextItem) {
+ $tempOrder = $nextItem->order;
+ $nextItem->update(['order' => $item->order]);
+ $item->update(['order' => $tempOrder]);
+ $this->devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ }
+ }
+
+ public function togglePlaylistItemActive(PlaylistItem $item)
+ {
+ abort_unless(auth()->user()->devices->contains($item->playlist->device), 403);
+ $item->update(['is_active' => !$item->is_active]);
+ $this->devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ }
+
+ public function deletePlaylist(Playlist $playlist)
+ {
+ abort_unless(auth()->user()->devices->contains($playlist->device), 403);
+ $playlist->delete();
+ $this->devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ Flux::modal('delete-playlist-' . $playlist->id)->close();
+ }
+
+ public function deletePlaylistItem(PlaylistItem $item)
+ {
+ abort_unless(auth()->user()->devices->contains($item->playlist->device), 403);
+ $item->delete();
+ $this->devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ Flux::modal('delete-playlist-item-' . $item->id)->close();
+ }
+
+ public function editPlaylist(Playlist $playlist)
+ {
+ abort_unless(auth()->user()->devices->contains($playlist->device), 403);
+
+ $this->validate([
+ 'playlist_name' => 'required|string|max:255',
+ 'selected_weekdays' => 'array',
+ 'active_from' => 'nullable|date_format:H:i',
+ 'active_until' => 'nullable|date_format:H:i',
+ ]);
+
+ $playlist->update([
+ 'name' => $this->playlist_name,
+ 'weekdays' => $this->selected_weekdays,
+ 'active_from' => $this->active_from,
+ 'active_until' => $this->active_until,
+ ]);
+
+ $this->devices = auth()->user()->devices()->with(['playlists.items.plugin'])->get();
+ $this->reset(['playlist_name', 'selected_weekdays', 'active_from', 'active_until']);
+ Flux::modal('edit-playlist-' . $playlist->id)->close();
+ }
+
+ public function preparePlaylistEdit(Playlist $playlist)
+ {
+ $this->playlist_name = $playlist->name;
+ $this->selected_weekdays = $playlist->weekdays ?? [];
+ $this->active_from = optional($playlist->active_from)->format('H:i');
+ $this->active_until = optional($playlist->active_until)->format('H:i');
+ }
+}; ?>
+
+
+
+
+
+
Playlists
+
+
+ @foreach($devices as $device)
+ @if($device->playlists->isNotEmpty())
+
+
+
{{ $device->name }}
+
+
+
+
+
+ @foreach($device->playlists as $playlist)
+
+
+
+
{{ $playlist->name }}
+
+
+
+
+ @if($playlist->weekdays)
+ {{ implode(', ', collect($playlist->weekdays)->map(fn($day) => ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][$day])->toArray()) }}
+ @endif
+ @if($playlist->active_from && $playlist->active_until)
+
+ {{ $playlist->active_from->format('H:i') }} - {{ $playlist->active_until->format('H:i') }}
+ @endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ |
+ Plugin
+ |
+
+ Status
+ |
+
+ Actions
+ |
+
+
+
+ @foreach($playlist->items->sortBy('order') as $item)
+
+ |
+ {{ $item->plugin->name }}
+ |
+
+
+ |
+
+
+ @if($playlist->items->count() > 1)
+ @if(!$loop->first)
+
+ @endif
+ @if(!$loop->last)
+
+ @endif
+ @endif
+
+
+
+
+
+
+
+ Delete {{ $item->plugin->name }}?
+ This will remove this item from the playlist.
+
+
+
+
+
+ Cancel
+
+ Delete item
+
+
+ |
+
+ @endforeach
+
+
+
+
+
+
+
+ Edit Playlist
+
+
+
+
+
+
+
+
+
Delete {{ $playlist->name }}?
+
This will permanently delete this playlist and all its items.
+
+
+
+
+
+ Cancel
+
+ Delete playlist
+
+
+ @endforeach
+
+
+ @endif
+ @endforeach
+
+ @if($devices->isEmpty() || $devices->every(fn($device) => $device->playlists->isEmpty()))
+
+
+
No playlists found
+
Add playlists to your devices to see them here.
+ @if($devices->isNotEmpty())
+
+ Go to Devices
+
+ @else
+
+ Add Device
+
+ @endif
+
+
+ @endif
+
+
+
diff --git a/routes/web.php b/routes/web.php
index 8738bb5..613945e 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -23,6 +23,7 @@ Route::middleware(['auth'])->group(function () {
Volt::route('plugins/receipt/{plugin}', 'plugins.receipt')->name('plugins.receipt');
Volt::route('plugins/markup', 'plugins.markup')->name('plugins.markup');
Volt::route('plugins/api', 'plugins.api')->name('plugins.api');
+ Volt::route('playlists', 'playlists.index')->name('playlists.index');
});
require __DIR__.'/auth.php';