From c6227ea8c119ab43e12de40237b7ec24e8d6c15e Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 23 Aug 2026 21:18:03 +0200 Subject: [PATCH] Add admin "create game" form; show total time on session-creation dropdown New game_admin_game_new route/form (reuses AdminGameType, same pattern as editing a game's total time) so games - including the 3 upcoming Easy/Medium/Hard difficulty options - can be created through the admin panel instead of needing a direct DB insert. Also show each game's total time (in minutes) next to the player count in the "Create New Session" dropdown, since that's the actual difficulty signal players are choosing between - number of players alone didn't convey it. Difficulty itself needs no new session-level concept: each difficulty is just a separate Game row with its own TOTAL_TIME setting, which checkAllPlayersReady() already reads when starting the session's timer. Hint timing depending on difficulty is separate, upcoming work. --- .../Controller/GameAdminGameController.php | 36 +++++++++++ templates/game/admin/games/index.html.twig | 13 +++- templates/game/admin/games/new.html.twig | 64 +++++++++++++++++++ templates/game/dashboard.html.twig | 9 ++- 4 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 templates/game/admin/games/new.html.twig diff --git a/src/Game/Controller/GameAdminGameController.php b/src/Game/Controller/GameAdminGameController.php index 55a5df3..c185aac 100644 --- a/src/Game/Controller/GameAdminGameController.php +++ b/src/Game/Controller/GameAdminGameController.php @@ -6,6 +6,7 @@ namespace App\Game\Controller; use App\Game\Entity\GameSetting; use App\Game\Enum\GameSettingType; +use App\Game\Enum\GameStatus; use App\Game\Form\AdminGameType; use App\Game\Entity\Game; use App\Game\Repository\GameRepository; @@ -29,6 +30,41 @@ final class GameAdminGameController extends AbstractController ]); } + #[Route('/new', name: 'game_admin_game_new', methods: ['GET', 'POST'])] + public function new( + Request $request, + EntityManagerInterface $em, + ): Response { + $game = new Game(); + $game->setStatus(GameStatus::IN_DEVELOPMENT); + + $form = $this->createForm(AdminGameType::class, $game); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + $totalTime = $form->get('totalTime')->getData(); + + $em->persist($game); + + if ($totalTime !== null) { + $totalTimeSetting = new GameSetting(); + $totalTimeSetting->setGame($game); + $totalTimeSetting->setName(GameSettingType::TOTAL_TIME); + $totalTimeSetting->setValue((string) $totalTime); + $em->persist($totalTimeSetting); + } + + $em->flush(); + $this->addFlash('success', sprintf('Game "%s" created.', $game->getName())); + + return $this->redirectToRoute('game_admin_games'); + } + + return $this->render('game/admin/games/new.html.twig', [ + 'form' => $form, + ]); + } + #[Route('/{id}/edit', name: 'game_admin_game_edit', methods: ['GET', 'POST'])] public function edit( Game $game, diff --git a/templates/game/admin/games/index.html.twig b/templates/game/admin/games/index.html.twig index 5262a4f..eac2c84 100644 --- a/templates/game/admin/games/index.html.twig +++ b/templates/game/admin/games/index.html.twig @@ -5,7 +5,18 @@ {% block admin_body %}

Games

- {{ games|length }} total +
+ {{ games|length }} total + + New Game +
diff --git a/templates/game/admin/games/new.html.twig b/templates/game/admin/games/new.html.twig new file mode 100644 index 0000000..4bd3ec8 --- /dev/null +++ b/templates/game/admin/games/new.html.twig @@ -0,0 +1,64 @@ +{% extends 'game/admin/base.html.twig' %} + +{% block title %}New Game — Admin{% endblock %} + +{% block admin_body %} +
+ ← Games +
+ +

New game

+ +
+ {{ form_start(form, {attr: {style: 'display: flex; flex-direction: column; gap: 1.25rem;'}}) }} + +
+ {{ form_label(form.name, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }} + {{ form_widget(form.name, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }} + {{ form_errors(form.name) }} +
+ +
+ {{ form_label(form.numberOfPlayers, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }} + {{ form_widget(form.numberOfPlayers, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }} + {{ form_errors(form.numberOfPlayers) }} +
+ +
+ {{ form_label(form.status, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }} + {{ form_widget(form.status, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }} + {{ form_errors(form.status) }} +
+ +
+ {{ form_label(form.totalTime, null, {label_attr: {style: 'display: block; font-weight: 600; margin-bottom: 0.35rem; color: #374151; font-size: 0.875rem;'}}) }} + {{ form_widget(form.totalTime, {attr: {style: 'width: 100%; padding: 0.5rem 0.75rem; border: 1px solid #d1d5db; border-radius: 6px; font-size: 0.9rem; box-sizing: border-box;'}}) }} + In seconds — e.g. 3600 = 1 hour + {{ form_errors(form.totalTime) }} +
+ +
+ + Cancel +
+ + {{ form_end(form) }} +
+{% endblock %} diff --git a/templates/game/dashboard.html.twig b/templates/game/dashboard.html.twig index c81804a..bf6e297 100644 --- a/templates/game/dashboard.html.twig +++ b/templates/game/dashboard.html.twig @@ -20,8 +20,15 @@