Browse Source

optimisation des requêtes du planning, correctifs visuels sur le planning et préparation espace gestionnaire

garthh 4 weeks ago
parent
commit
0486454afd

+ 9 - 0
assets/styles/app.css

@@ -135,6 +135,7 @@
 .planning-cell-free {
   border-bottom: 1px solid #ccc;
   z-index: 0;
+  justify-content: center;
 }
 
 
@@ -142,6 +143,7 @@
 .planning-cell-locked {
   border-bottom: 1px solid #ccc;
   z-index: 0;
+  justify-content: center;
 }
 
 /* Hidden slot */
@@ -157,6 +159,7 @@
   overflow: visible;
   border: none !important;
   z-index: 0 !important;
+  pointer-events: none;
 }
 
 .planning-cell-game {
@@ -171,6 +174,12 @@
   white-space: normal;
   text-overflow: clip;
   overflow: hidden;
+  pointer-events: all;
+  cursor: zoom-in;
+}
+
+.planning-cell-game-isfull {
+  filter: grayscale(1) opacity(0.3);
 }
 
 /* Optional: highlight on hover globally */

+ 2 - 2
src/Controller/ManageController.php

@@ -18,7 +18,7 @@ final class ManageController extends AbstractController
     {
 
         // Récupérer la liste des événements visibles
-        $events = $repository->findEventsToCome();
+        $events = $repository->findEventsToCome(false);
         if (!$events) {
             $this->addFlash('info', 'Aucun d\'événement n\'est plannifié pour le moment.');
             return $this->redirectToRoute('app_main');
@@ -41,7 +41,7 @@ final class ManageController extends AbstractController
         }
 
         // Récupérer la liste des événements visibles
-        $events = $repository->findEventsToCome();
+        $events = $repository->findEventsToCome(false);
 
         return $this->render('manage/manage.html.twig', [
             'event' => $event,

+ 1 - 0
src/Repository/SlotRepository.php

@@ -3,6 +3,7 @@
 namespace App\Repository;
 
 use App\Entity\Slot;
+use App\Entity\Event;
 use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 use Doctrine\Persistence\ManagerRegistry;
 

+ 30 - 0
src/Service/SlotFinder.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Service;
+
+use App\Entity\Slot;
+
+class SlotFinder
+{
+    /** @var array<string, Slot> */
+    private array $index = [];
+
+    public function __construct(iterable $slots)
+    {
+        foreach ($slots as $slot) {
+            $this->index[$this->makeKey($slot->getStartOn(), $slot->getSpace()->getId())] = $slot;
+        }
+    }
+
+    public function find(\DateTimeInterface $dateRef, $space): ?Slot
+    {
+        $key = $this->makeKey($dateRef, $space->getId());
+        $found = $this->index[$key] ?? null;
+        return $found;
+    }
+
+    private function makeKey(\DateTimeInterface $startOn, $spaceId): string
+    {
+        return $startOn->format('Y-m-d H:i:s') . '|' . $spaceId;
+    }
+}

+ 16 - 9
src/Twig/Components/Planning.php

@@ -8,6 +8,7 @@ use App\Entity\Period;
 use App\Entity\Space;
 use App\Entity\Slot;
 use App\Service\DateTimeHelper;
+use App\Service\SlotFinder;
 use App\Repository\SlotRepository;
 
 #[AsTwigComponent]
@@ -24,6 +25,7 @@ class Planning
 
     private DateTimeHelper $dateTimeHelper;
     private SlotRepository $repository;
+    private SlotFinder $finder;
 
     public function __construct(DateTimeHelper $dateTimeHelper, SlotRepository $repository)
     {
@@ -31,11 +33,17 @@ class Planning
         $this->repository = $repository;
     }
 
+    public function mount(Event $event): void
+    {
+        $this->event = $event;
+        $this->finder = new SlotFinder($this->event->getSlots());
+    }
+
     public function getDateOrdered(Period $period): array
     {
-        $dates = array();
+        $dates = [];
         $cursorDate = $this->dateTimeHelper->roundUpToNextSlot($period->getStartOn());
-        // Première date
+
         while ($cursorDate < $period->getEndOn()) {
             $dates[] = clone $cursorDate;
             $cursorDate->add(new \DateInterval('PT30M'));
@@ -44,16 +52,15 @@ class Planning
         return $dates;
     }
 
-    public function getThisSlot(\Datetime $dateRef, Space $space, Period $period): ?Slot
+    public function getThisSlotInfo(\DateTimeInterface $dateRef, Space $space): ?Slot
     {
-        $slot = $this->repository->findASlot($dateRef, $space, $period);
-        return $slot;
+        $found = $this->finder->find($dateRef, $space);
+        return $found;
     }
 
-    public function timeTag(): bool
+    // Si tu veux garder la recherche SQL (moins efficace)
+    public function getThisSlot(\DateTimeInterface $dateRef, Space $space, Period $period): ?Slot
     {
-        
-        return $timeTag;
+        return $this->repository->findASlot($dateRef, $space, $period);
     }
-
 }

+ 1 - 1
templates/admin/event/config/slot.html.twig

@@ -83,7 +83,7 @@
         <div class="block">
           <div class="content">
           <h3 class="title is-3">Aperçu du planning</h3>
-          <p>Cliquez sur les <strong>slots</strong> pour les basculer <span class="icon-text"><span class="icon"><twig:ux:icon name="bi:lock-fill"/></span><span><em>indisponible</em></span></span> (aucune partie ne pourra être organisé sur ce slot) ou <em>disponible</em>. <em class="has-text-danger">Fonctionnalité en cours de développement.</em></p>
+          <p>Cliquez sur les <strong>slots</strong> pour les basculer <span class="icon-text"><span class="icon"><twig:ux:icon name="bi:lock-fill"/></span><span><em>indisponible</em></span></span> (aucune partie ne pourra être organisé sur ce slot) ou  <span class="icon-text"><span class="icon"><twig:ux:icon name="bi:unlock-fill"/></span><span><em>disponible</em></span></span>. <em class="has-text-danger">Fonctionnalité en cours de développement.</em></p>
           </div>
         </div>
         {% if event.getSlots()|length > 0 %}

+ 18 - 13
templates/components/Planning.html.twig

@@ -9,11 +9,11 @@
         <div class="grid is-gap-0">
 
             {# en-tête avec les noms des espaces #}
-            <div class="cell planning-cell planning-cell-heading has-background-primary-light">
+            <div class="cell is-coll-start planning-cell planning-cell-heading">
                 Espaces
             </div>
             {% for space in event.getSpaces() %}
-            <div class="cell planning-cell planning-cell-heading has-background-primary-light">
+            <div class="cell planning-cell planning-cell-heading">
                 {{ space.name }}
             </div>
             {% endfor %}
@@ -26,17 +26,18 @@
 
                 {# On affiche tous les slots de la période, space par space #}
                 {% for dateRef in this.getDateOrdered(period) %}
-                    <div class="cell planning-cell planning-cell-heading has-background-primary-light">
+                    <div class="cell planning-cell planning-cell-heading">
                         {{ dateRef|date('H:i', app_timezone) }}
                     </div>
                     {% for space in event.getSpaces() %}
                         {# extraction du slot de cet espace, ce moment et cette période #}
-                        {% set thisSlot = this.getThisSlot(dateRef, space, period) %}
-                        
+                        {# set thisSlot = this.getThisSlot(dateRef, space, period) #}
+                        {% set thisSlot = this.getThisSlotInfo(dateRef, space) %}
+
                         {# si le slot est Indisponible #}
                         {% if thisSlot.unavailable %}
                             {% if displayLocked %}
-                            <div class="cell planning-cell planning-cell-locked" data-id="{{ thisSlot.id }}">
+                            <div class="cell planning-cell planning-cell-locked  has-text-centered" data-id="{{ thisSlot.id }}">
                                 <div class="icon"><twig:ux:icon name="bi:lock-fill" /></div>
                             </div>
                             {% else %}
@@ -50,27 +51,27 @@
                                 {% if thisSlot == thisSlot.party.slots[0] %}
                                 {# Premier slot d'une partie ou partie non validée #}
                                 <div class="cell planning-cell planning-cell-game-parent">
-                                    <div class="planning-cell-game" style="height: {{ thisSlot.party.slots|length * 4 }}rem !important">
+                                    <div class="planning-cell-game {% if thisSlot.party.getSeatsLeft < 1 %}planning-cell-game-isfull {% endif %}{% if pathFullSlot %} open-modal" href="{{ path(pathFullSlot, {id: thisSlot.id}) }}"{% else %}"{% endif %} style="height: {{ thisSlot.party.slots|length * 4 * app_hmult }}rem !important">
                                       {# Carte "jeu" DEBUT #}
-                                        <div class="card" style="height: {{ thisSlot.party.slots|length * 4 - 0.7 }}rem !important {% if not thisSlot.party.isValidated %}; filter:grayscale(1) opacity(0.3);{% endif %}">
+                                        <div class="card" style="height: {{ thisSlot.party.slots|length * 4 * app_hmult - 0.7 }}rem !important {% if not thisSlot.party.isValidated %}; filter:grayscale(1) opacity(0.3);{% endif %}">
                                             
                                                 <div class="card-header">
                                                     <div class="media">
                                                         <div class="media-left">
                                                             <figure class="image is-48x48">
-                                                                {% if pathFullSlot %}<a href="{{ path(pathFullSlot, {id: thisSlot.id}) }}" class="open-modal">{% endif %}
+                                                                
                                                                 {% if thisSlot.party.gamemaster.picture %}
                                                                 <img class="is-rounded" src="/images/gamemasters/{{ thisSlot.party.gamemaster.picture }}"  />
                                                                 {% else %}
                                                                 <twig:ux:icon name="bi:person-fill"/>
                                                                 {% endif %}
-                                                                {% if pathFullSlot %}</a>{% endif %}
+                                                                
                                                             </figure>
                                                         </div>
                                                     </div>
                                                         <div class="media-content">
                                                             <small class="hax-text-grey-light">@{{ thisSlot.party.gamemaster.preferedName }}</small><br/>
-                                                            {% if pathFullSlot %}<a href="{{ path(pathFullSlot, {id: thisSlot.id}) }}" class="open-modal">{% endif %}<span class="title is-6">{{ thisSlot.party.game.name }}</span>{% if pathFullSlot %}</a>{% endif %}<br/>
+                                                            <span class="title is-6">{{ thisSlot.party.game.name }}</span>
                                                             {% if thisSlot.party.gamemasterIsAuthor %}<br/><span class="tag is-info">animée par l'auteur</span>{% endif %}
                                                         </div>
 
@@ -79,7 +80,7 @@
                                                     <small>Places : {{ thisSlot.party.getSeatsLeft }} / {{ thisSlot.party.getMaxParticipants }}</small>
                                                 </div>
 
-                                            
+                                            {% if pathFullSlot %}</a>{% endif %}
                                         </div>                             
                                       {# Carte "jeu" FIN #}
                                     </div>
@@ -99,10 +100,14 @@
                         {% if not thisSlot.unavailable and not thisSlot.party %}
                             {% if pathEmptySlot %}
                             <a href="{{ path(pathEmptySlot, {id: thisSlot.id}) }}"  class="open-modal">
-                            <div class="cell planning-cell planning-cell-free" data-id="{{ thisSlot.id }}">
+                            <div class="cell planning-cell planning-cell-free has-text-centered" data-id="{{ thisSlot.id }}">
                                 <div class="icon"><twig:ux:icon name="bi:plus-circle" /></div>
                             </div>
                             </a>
+                            {% elseif displayLocked %}
+                            <div class="cell planning-cell planning-cell-free has-text-centered" data-id="{{ thisSlot.id }}">
+                                <div class="icon"><twig:ux:icon name="bi:unlock-fill" /></div>
+                            </div>
                             {% else %}
                             <div class="cell planning-cell planning-cell-free" data-id="{{ thisSlot.id }}">
                                 

+ 11 - 6
templates/manage/manage.html.twig

@@ -56,20 +56,25 @@
         {% endfor %}
       </p>
     </div>
-    {% if event.isEveryoneCanAskForGame %}
-    <div class="column">
-      <a href="#" class="button is-primary open-modal">Demander une partie</a>
-    </div>
-    {% endif %}
   </div>
 
 </div>
 
+    <div class="tabs is-boxed">
+        <ul>
+            <li class="is-active"><a>Planning</a></li>
+            <li><a>Liste des parties</a></li>
+            <li><a>Liste des participants</a></li>
+            <li><a>Liste des demandes</a></li>
+
+
+        </ul>
+    </div>
 
 
 <section>
   <div id="planning">
-    {{ component('Planning', {event: event,pathFullSlot: 'app_participation'}) }}
+              {{ component('Planning', {event: event, pathEmptySlot: 'app_party_add', pathFullSlot: 'app_party_modify', displayUnvalidates: true}) }}
   </div>
 </section>