219 lines
5.4 KiB
PHP
219 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace App\Livewire;
|
|
|
|
use App\Models\Episode;
|
|
use App\Models\Playlist;
|
|
use App\Models\PlaylistEpisode;
|
|
use App\Services\PlaylistService;
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Livewire\Attributes\Url;
|
|
use Livewire\Component;
|
|
use Livewire\WithPagination;
|
|
|
|
class PlaylistOverview extends Component
|
|
{
|
|
use WithPagination;
|
|
|
|
protected PlaylistService $playlistService;
|
|
|
|
#[Url(history: true)]
|
|
public string $search = '';
|
|
|
|
#[Url(history: true)]
|
|
public int $perPage = 25;
|
|
|
|
public Playlist $playlist;
|
|
|
|
public bool $editingName = false;
|
|
|
|
public string $editingPlaylistName = '';
|
|
|
|
public function boot(PlaylistService $playlistService)
|
|
{
|
|
$this->playlistService = $playlistService;
|
|
}
|
|
|
|
public function mount($playlist_id)
|
|
{
|
|
$this->playlist = Playlist::withCount('episodes')->with('user')->findOrFail($playlist_id);
|
|
|
|
$this->sanitizePerPage();
|
|
|
|
$this->repairNullPositions();
|
|
}
|
|
|
|
public function updatingSearch(): void
|
|
{
|
|
$this->resetPage();
|
|
}
|
|
|
|
public function updatingPerPage(): void
|
|
{
|
|
$this->resetPage();
|
|
}
|
|
|
|
public function getEpisodesProperty(): LengthAwarePaginator
|
|
{
|
|
$this->sanitizePerPage();
|
|
|
|
return PlaylistEpisode::query()
|
|
->where('playlist_id', $this->playlist->id)
|
|
->when($this->search !== '', fn ($query) => $query->whereHas('episode', fn ($episode) => $episode
|
|
->where('title', 'like', '%'.$this->search.'%')
|
|
->orWhere('title_jpn', 'like', '%'.$this->search.'%')))
|
|
->orderBy('position')
|
|
->with(['episode.gallery' => fn ($gallery) => $gallery->orderBy('id')->limit(1)])
|
|
->paginate($this->perPage);
|
|
}
|
|
|
|
public function getFirstEpisodeProperty(): ?Episode
|
|
{
|
|
return PlaylistEpisode::where('playlist_id', $this->playlist->id)
|
|
->orderBy('position')
|
|
->first()?->episode;
|
|
}
|
|
|
|
public function moveUp($episodeId)
|
|
{
|
|
if (! $this->isOwner()) {
|
|
return;
|
|
}
|
|
|
|
$episode = PlaylistEpisode::find($episodeId);
|
|
|
|
if (! $episode) {
|
|
return;
|
|
}
|
|
|
|
$above = PlaylistEpisode::where('playlist_id', $episode->playlist_id)
|
|
->where('position', '<', $episode->position)
|
|
->orderBy('position', 'desc')
|
|
->first();
|
|
|
|
if ($above) {
|
|
$this->playlistService->swapPositions($episode, $above);
|
|
}
|
|
}
|
|
|
|
public function moveDown($episodeId)
|
|
{
|
|
if (! $this->isOwner()) {
|
|
return;
|
|
}
|
|
|
|
$episode = PlaylistEpisode::find($episodeId);
|
|
|
|
if (! $episode) {
|
|
return;
|
|
}
|
|
|
|
$below = PlaylistEpisode::where('playlist_id', $episode->playlist_id)
|
|
->where('position', '>', $episode->position)
|
|
->orderBy('position')
|
|
->first();
|
|
|
|
if ($below) {
|
|
$this->playlistService->swapPositions($episode, $below);
|
|
}
|
|
}
|
|
|
|
public function remove($episodeId)
|
|
{
|
|
if (! $this->isOwner()) {
|
|
return;
|
|
}
|
|
|
|
PlaylistEpisode::find($episodeId)?->delete();
|
|
$this->playlistService->reorderPositions($this->playlist);
|
|
$this->playlist->loadCount('episodes');
|
|
|
|
$lastPage = max(1, (int) ceil(PlaylistEpisode::where('playlist_id', $this->playlist->id)->count() / $this->perPage));
|
|
|
|
if ($this->getPage() > $lastPage) {
|
|
$this->setPage($lastPage);
|
|
}
|
|
}
|
|
|
|
public function editName()
|
|
{
|
|
if (! $this->isOwner()) {
|
|
return;
|
|
}
|
|
|
|
$this->editingPlaylistName = $this->playlist->name;
|
|
$this->editingName = true;
|
|
}
|
|
|
|
public function cancelEditName()
|
|
{
|
|
$this->editingName = false;
|
|
$this->editingPlaylistName = '';
|
|
}
|
|
|
|
public function updateName()
|
|
{
|
|
if (! $this->isOwner()) {
|
|
return;
|
|
}
|
|
|
|
$this->validate([
|
|
'editingPlaylistName' => 'required|max:30',
|
|
]);
|
|
|
|
$this->playlist->update([
|
|
'name' => $this->editingPlaylistName,
|
|
]);
|
|
|
|
$this->editingName = false;
|
|
$this->editingPlaylistName = '';
|
|
}
|
|
|
|
public function toggleVisibility()
|
|
{
|
|
if (! $this->isOwner()) {
|
|
return;
|
|
}
|
|
|
|
$this->playlist->update([
|
|
'is_private' => ! $this->playlist->is_private,
|
|
]);
|
|
|
|
$this->playlist->loadCount('episodes');
|
|
}
|
|
|
|
public function render()
|
|
{
|
|
return view('livewire.playlist-overview', [
|
|
'episodes' => $this->episodes,
|
|
'firstEpisode' => $this->firstEpisode,
|
|
'isOwner' => $this->isOwner(),
|
|
]);
|
|
}
|
|
|
|
private function isOwner(): bool
|
|
{
|
|
return Auth::check() && Auth::user()->id === $this->playlist->user_id;
|
|
}
|
|
|
|
private function sanitizePerPage(): void
|
|
{
|
|
if (! in_array($this->perPage, [25, 50, 100], true)) {
|
|
$this->perPage = 25;
|
|
}
|
|
}
|
|
|
|
private function repairNullPositions(): void
|
|
{
|
|
if (! PlaylistEpisode::where('playlist_id', $this->playlist->id)->whereNull('position')->exists()) {
|
|
return;
|
|
}
|
|
|
|
PlaylistEpisode::where('playlist_id', $this->playlist->id)
|
|
->orderBy('position')->orderBy('id')
|
|
->get()
|
|
->each(fn ($playlistEpisode, $index) => $playlistEpisode->update(['position' => $index + 1]));
|
|
}
|
|
}
|