Add city and date filters on /evenements page

- City filter: LIKE search on event.city
- Date filter: events starting on selected date
- Combines with Meilisearch text search
- Labels on filter inputs, clear button when any filter active

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Serreau Jovann
2026-03-22 20:32:51 +01:00
parent 830e3359d9
commit 44845b6313
3 changed files with 55 additions and 8 deletions

View File

@@ -32,7 +32,7 @@
### UX & Pages
- [ ] Page /tarifs : détailler les 3 offres (free/basic/custom) avec les prix
- [ ] Ajouter la recherche d'événements sur la homepage
- [ ] Ajouter le filtrage par date/ville sur /evenements
- [x] Ajouter le filtrage par date/ville sur /evenements
- [x] Responsive : pages publiques OK à 320px (flex-wrap, overflow-x-auto, breakpoints)
- [x] Ajouter les métadonnées OpenGraph sur toutes les pages publiques (og:title, og:description, og:type, og:url, og:image, twitter:card)
- [x] Ajouter le sitemap dynamique avec les événements en ligne

View File

@@ -53,15 +53,53 @@ class HomeController extends AbstractController
}
#[Route('/evenements', name: 'app_events')]
public function events(Request $request, PaginatorInterface $paginator, EventIndexService $eventIndex): Response
public function events(Request $request, PaginatorInterface $paginator, EventIndexService $eventIndex, EntityManagerInterface $em): Response
{
$searchQuery = $request->query->getString('q', '');
$eventsQuery = $eventIndex->searchEvents('event_global', $searchQuery, ['isOnline' => true, 'isSecret' => false]);
$city = $request->query->getString('city', '');
$date = $request->query->getString('date', '');
$hasFilters = '' !== $city || '' !== $date;
if ($hasFilters) {
$qb = $em->createQueryBuilder()
->select('e')
->from(Event::class, 'e')
->where('e.isOnline = true')
->andWhere('e.isSecret = false')
->orderBy('e.startAt', 'ASC');
if ('' !== $searchQuery) {
$searchResults = $eventIndex->searchEvents('event_global', $searchQuery, ['isOnline' => true, 'isSecret' => false]);
$ids = array_map(fn ($e) => $e->getId(), $searchResults);
if ($ids) {
$qb->andWhere('e.id IN (:ids)')->setParameter('ids', $ids);
} else {
$qb->andWhere('1 = 0');
}
}
if ('' !== $city) {
$qb->andWhere('LOWER(e.city) LIKE LOWER(:city)')->setParameter('city', '%'.$city.'%');
}
if ('' !== $date) {
$dateObj = new \DateTimeImmutable($date);
$qb->andWhere('e.startAt >= :dateStart')->setParameter('dateStart', $dateObj->setTime(0, 0));
$qb->andWhere('e.startAt <= :dateEnd')->setParameter('dateEnd', $dateObj->setTime(23, 59, 59));
}
$eventsQuery = $qb->getQuery()->getResult();
} else {
$eventsQuery = $eventIndex->searchEvents('event_global', $searchQuery, ['isOnline' => true, 'isSecret' => false]);
}
$events = $paginator->paginate($eventsQuery, $request->query->getInt('page', 1), 12);
return $this->render('home/events.html.twig', [
'events' => $events,
'searchQuery' => $searchQuery,
'city' => $city,
'date' => $date,
'breadcrumbs' => [
self::BREADCRUMB_HOME,
['name' => 'Evenements', 'url' => '/evenements'],

View File

@@ -25,10 +25,19 @@
<div class="max-w-7xl mx-auto">
<form method="get" action="{{ path('app_events') }}" class="flex flex-wrap gap-3 items-end">
<div class="flex-1 min-w-[200px]">
<input type="text" name="q" value="{{ searchQuery }}" class="form-input" placeholder="Rechercher un evenement, une ville...">
<label class="text-[10px] font-black uppercase tracking-widest text-gray-400 mb-1 block">Recherche</label>
<input type="text" name="q" value="{{ searchQuery }}" class="form-input" placeholder="Nom, organisateur...">
</div>
<button type="submit" class="btn-brutal font-black uppercase text-xs tracking-widest hover:bg-indigo-600 hover:text-white transition-all">Rechercher</button>
{% if searchQuery %}
<div class="w-full sm:w-auto">
<label class="text-[10px] font-black uppercase tracking-widest text-gray-400 mb-1 block">Ville</label>
<input type="text" name="city" value="{{ city }}" class="form-input" placeholder="Paris, Lyon...">
</div>
<div class="w-full sm:w-auto">
<label class="text-[10px] font-black uppercase tracking-widest text-gray-400 mb-1 block">Date</label>
<input type="date" name="date" value="{{ date }}" class="form-input">
</div>
<button type="submit" class="btn-brutal font-black uppercase text-xs tracking-widest hover:bg-indigo-600 hover:text-white transition-all">Filtrer</button>
{% if searchQuery or city or date %}
<a href="{{ path('app_events') }}" class="px-4 py-3 border-3 border-gray-900 bg-white font-black uppercase text-xs tracking-widest hover:bg-gray-100 transition-all">Effacer</a>
{% endif %}
</form>
@@ -68,8 +77,8 @@
<div class="text-center py-16">
<div class="border-4 border-gray-900 bg-white shadow-[6px_6px_0px_rgba(0,0,0,1)] p-12 max-w-lg mx-auto">
<p class="text-gray-400 font-black text-lg uppercase">
{% if searchQuery %}
Aucun evenement trouve pour "{{ searchQuery }}"
{% if searchQuery or city or date %}
Aucun evenement trouve{% if searchQuery %} pour "{{ searchQuery }}"{% endif %}{% if city %} a {{ city }}{% endif %}{% if date %} le {{ date }}{% endif %}
{% else %}
Aucun evenement pour le moment
{% endif %}