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:
@@ -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
|
||||
|
||||
@@ -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'],
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
Reference in New Issue
Block a user