feat: button to add movie monitor

This commit is contained in:
2025-05-03 11:53:23 -05:00
parent babcb00440
commit 5688b3a0df
9 changed files with 166 additions and 7 deletions

View File

@@ -0,0 +1,24 @@
import { Controller } from '@hotwired/stimulus';
/*
* The following line makes this controller "lazy": it won't be downloaded until needed
* See https://github.com/symfony/stimulus-bridge#lazy-controllers
*/
/* stimulusFetch: 'lazy' */
export default class extends Controller {
static values = {
title: String,
tmdbId: String,
imdbId: String,
mediaType: String,
}
addMovieMonitor() {
console.log(`/monitor/movies/${this.tmdbIdValue}/${this.imdbIdValue}/${encodeURI(this.titleValue)}`)
fetch(`/monitor/movies/${this.tmdbIdValue}/${this.imdbIdValue}/${encodeURI(this.titleValue)}`)
.then(res => res.json())
.then(json => {
console.log(json)
})
}
}

View File

@@ -2,6 +2,9 @@
namespace App\Controller;
use App\Download\Action\Command\AddMovieMonitorCommand;
use App\Download\Action\Handler\AddMovieMonitorHandler;
use App\Download\Action\Input\AddMovieMonitorInput;
use App\Download\Action\Input\DownloadMediaInput;
use App\Download\Framework\Repository\DownloadRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
@@ -37,4 +40,16 @@ class DownloadController extends AbstractController
return $this->json(['status' => 200, 'message' => 'Added to Queue']);
}
#[Route('/monitor/movies/{tmdbId}/{imdbId}/{title}', name: 'app_add_movie_monitor', methods: ['GET', 'POST'])]
public function addMonitor(
AddMovieMonitorInput $input,
AddMovieMonitorHandler $handler,
) {
$handler->handle($input->toCommand());
return $this->json([
'status' => 200,
'message' => $input
]);
}
}

View File

@@ -37,8 +37,8 @@ final class SearchController extends AbstractController
): Response {
$cacheId = sprintf("page.%s.%s", $input->mediaType, $input->tmdbId);
return $cache->get($cacheId, function (ItemInterface $item) use ($input) {
$item->expiresAt(new \DateTimeImmutable("today 11:59 pm"));
// return $cache->get($cacheId, function (ItemInterface $item) use ($input) {
// $item->expiresAt(new \DateTimeImmutable("today 11:59 pm"));
$result = $this->getMediaInfoHandler->handle($input->toCommand());
return $this->render('search/result.html.twig', [
'results' => $result,
@@ -51,6 +51,6 @@ final class SearchController extends AbstractController
'episode' => ''
]
]);
});
// });
}
}

View File

@@ -0,0 +1,16 @@
<?php
namespace App\Download\Action\Command;
use App\Download\Framework\Entity\MovieMonitor;
use OneToMany\RichBundle\Contract\CommandInterface;
class AddMovieMonitorCommand implements CommandInterface
{
public function __construct(
public string $userEmail,
public string $title,
public string $imdbId,
public string $tmdbId,
) {}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Download\Action\Handler;
use App\Download\Action\Command\AddMovieMonitorCommand;
use App\Download\Action\Result\MonitorMovieResult;
use App\Download\Framework\Entity\MovieMonitor;
use App\Download\Framework\Repository\MovieMonitorRepository;
use App\User\Framework\Repository\UserRepository;
use DateTimeImmutable;
use OneToMany\RichBundle\Contract\CommandInterface;
use OneToMany\RichBundle\Contract\HandlerInterface;
use OneToMany\RichBundle\Contract\ResultInterface;
/** @implements HandlerInterface<AddMovieMonitorCommand> */
readonly class AddMovieMonitorHandler implements HandlerInterface
{
public function __construct(
private MovieMonitorRepository $movieMonitorRepository,
private UserRepository $userRepository,
) {}
public function handle(CommandInterface $command): ResultInterface
{
$user = $this->userRepository->findOneBy(['email' => $command->userEmail]);
$monitor = new MovieMonitor();
$monitor->setTmdbId($command->tmdbId);
$monitor->setImdbId($command->imdbId);
$monitor->setTitle($command->title);
$monitor->setUser($user);
$monitor->setCreatedAt(new DateTimeImmutable());
$monitor->setSearchCount(0);
$monitor->setStatus('New');
$this->movieMonitorRepository->getEntityManager()->persist($monitor);
$this->movieMonitorRepository->getEntityManager()->flush();
return new MonitorMovieResult(
status: 'OK',
result: [
'monitor' => $monitor,
]
);
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Download\Action\Input;
use App\Download\Action\Command\AddMovieMonitorCommand;
use OneToMany\RichBundle\Attribute\SourceRoute;
use OneToMany\RichBundle\Attribute\SourceSecurity;
use OneToMany\RichBundle\Contract\CommandInterface;
use OneToMany\RichBundle\Contract\InputInterface;
class AddMovieMonitorInput implements InputInterface
{
public function __construct(
#[SourceSecurity]
public string $userEmail,
#[SourceRoute('title')]
public string $title,
#[SourceRoute('tmdbId')]
public string $tmdbId,
#[SourceRoute('imdbId')]
public string $imdbId,
) {}
public function toCommand(): CommandInterface
{
return new AddMovieMonitorCommand($this->userEmail, $this->title, $this->tmdbId, $this->imdbId);
}
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Download\Action\Result;
use OneToMany\RichBundle\Contract\ResultInterface;
class AddMovieMonitorResult implements ResultInterface
{
public function __construct(
public string $status,
public array $result,
) {}
}

View File

@@ -17,7 +17,7 @@
</div>
</div>
</div>
<div {{ turbo_stream_listen('alerts') }} class="absolute top-10 right-10 size-96">
<div {{ turbo_stream_listen('alerts') }} class="absolute top-10 right-10">
<div >
<ul id="alert_list">
</ul>

View File

@@ -10,9 +10,24 @@
<div class="p-4 flex flex-row gap-6">
<img class="w-40" src="{{ results.media.poster }}" />
<div class="w-full flex flex-col">
<h3 class="mb-4 text-xl font-medium leading-tight font-bold text-gray-50">
{{ results.media.title }} - {{ results.media.year }}
</h3>
<div class="mb-4 flex flex-row gap-2 justify-between">
<h3 class="text-xl font-medium leading-tight font-bold text-gray-50">
{{ results.media.title }} - {{ results.media.year }}
</h3>
<button class="px-1.5 py-1 bg-green-600 text-white rounded-md cursor-pointer"
{{ stimulus_controller('monitor', {
mediaType: results.media.mediaType,
imdbId: results.media.imdbId,
tmdbId: results.media.tmdbId,
title: results.media.title
}) }}
{% if results.media.mediaType == "movies" %}
{{ stimulus_action('monitor', 'addMovieMonitor', 'click') }}
{% endif %}
>
Monitor
</button>
</div>
<p class="text-gray-50">
{{ results.media.description }}
</p>