feat: wrap game in centered card, style abandon button, abandon anonymous game on login
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -487,19 +487,34 @@ body {
|
|||||||
color: #16a34a;
|
color: #16a34a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── Game card ── */
|
||||||
|
|
||||||
|
.game-container {
|
||||||
|
max-width: fit-content;
|
||||||
|
margin: 56px auto;
|
||||||
|
padding: 24px 32px 32px;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
box-shadow: 0 4px 32px var(--shadow-warm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.game-container #actors {
|
||||||
|
margin: 16px auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Game actions ── */
|
/* ── Game actions ── */
|
||||||
|
|
||||||
.game-actions {
|
.game-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-start;
|
||||||
padding: 12px 40px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-abandon {
|
.btn-abandon {
|
||||||
padding: 7px 16px;
|
padding: 7px 16px;
|
||||||
background: none;
|
background: none;
|
||||||
color: var(--text-muted);
|
color: #dc2626;
|
||||||
border: 1.5px solid var(--border);
|
border: 1.5px solid #dc2626;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
font-family: 'Inter', sans-serif;
|
font-family: 'Inter', sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|||||||
39
src/EventListener/AbandonAnonymousGameOnLoginListener.php
Normal file
39
src/EventListener/AbandonAnonymousGameOnLoginListener.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\EventListener;
|
||||||
|
|
||||||
|
use App\Entity\Game;
|
||||||
|
use App\Repository\GameRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
|
||||||
|
use Symfony\Component\Security\Http\Event\LoginSuccessEvent;
|
||||||
|
|
||||||
|
#[AsEventListener]
|
||||||
|
class AbandonAnonymousGameOnLoginListener
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly GameRepository $gameRepository,
|
||||||
|
private readonly EntityManagerInterface $em,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function __invoke(LoginSuccessEvent $event): void
|
||||||
|
{
|
||||||
|
$session = $event->getRequest()->getSession();
|
||||||
|
$gameId = $session->get('current_game_id');
|
||||||
|
|
||||||
|
if (!$gameId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$game = $this->gameRepository->find($gameId);
|
||||||
|
|
||||||
|
if ($game && $game->getStatus() === Game::STATUS_IN_PROGRESS) {
|
||||||
|
$game->abandon();
|
||||||
|
$this->em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
$session->remove('current_game_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% if game %}
|
{% if game %}
|
||||||
|
<div class="game-container">
|
||||||
<div class="game-actions">
|
<div class="game-actions">
|
||||||
<form method="post" action="{{ path('app_game_abandon', {id: game.id}) }}">
|
<form method="post" action="{{ path('app_game_abandon', {id: game.id}) }}">
|
||||||
<input type="hidden" name="_token" value="{{ csrf_token('game_abandon') }}">
|
<input type="hidden" name="_token" value="{{ csrf_token('game_abandon') }}">
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
width: width,
|
width: width,
|
||||||
middle: middle,
|
middle: middle,
|
||||||
}) }}></div>
|
}) }}></div>
|
||||||
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="game-start-container">
|
<div class="game-start-container">
|
||||||
<form method="post" action="{{ path('app_game_start') }}">
|
<form method="post" action="{{ path('app_game_start') }}">
|
||||||
|
|||||||
Reference in New Issue
Block a user