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;
|
||||
}
|
||||
|
||||
/* ── 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 {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 12px 40px 0;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.btn-abandon {
|
||||
padding: 7px 16px;
|
||||
background: none;
|
||||
color: var(--text-muted);
|
||||
border: 1.5px solid var(--border);
|
||||
color: #dc2626;
|
||||
border: 1.5px solid #dc2626;
|
||||
border-radius: 100px;
|
||||
font-family: 'Inter', sans-serif;
|
||||
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,18 +2,20 @@
|
||||
|
||||
{% block body %}
|
||||
{% if game %}
|
||||
<div class="game-actions">
|
||||
<form method="post" action="{{ path('app_game_abandon', {id: game.id}) }}">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('game_abandon') }}">
|
||||
<button type="submit" class="btn btn-abandon">Abandonner</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="game-container">
|
||||
<div class="game-actions">
|
||||
<form method="post" action="{{ path('app_game_abandon', {id: game.id}) }}">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('game_abandon') }}">
|
||||
<button type="submit" class="btn btn-abandon">Abandonner</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div {{ react_component('GameGrid', {
|
||||
grid: grid,
|
||||
width: width,
|
||||
middle: middle,
|
||||
}) }}></div>
|
||||
<div {{ react_component('GameGrid', {
|
||||
grid: grid,
|
||||
width: width,
|
||||
middle: middle,
|
||||
}) }}></div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="game-start-container">
|
||||
<form method="post" action="{{ path('app_game_start') }}">
|
||||
|
||||
Reference in New Issue
Block a user