Redesign edit event page: two-column layout, action buttons, poster display
- Left column: edit form (title, description, dates, address, image upload)
- Right column: sticky poster preview card with image or placeholder
- Top action bar: toggle online/offline, toggle secret/public, status badges
- Add routes: /mon-compte/evenement/{id}/en-ligne and /mon-compte/evenement/{id}/secret
- Remove is_online checkbox from form (replaced by dedicated toggle buttons)
- Meilisearch re-indexed on toggle actions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -396,6 +396,48 @@ class AccountController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/mon-compte/evenement/{id}/en-ligne', name: 'app_account_toggle_event_online', methods: ['POST'])]
|
||||
public function toggleEventOnline(\App\Entity\Event $event, EntityManagerInterface $em, EventIndexService $eventIndex): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_ORGANIZER');
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
if ($event->getAccount()->getId() !== $user->getId()) {
|
||||
throw $this->createAccessDeniedException();
|
||||
}
|
||||
|
||||
$event->setIsOnline(!$event->isOnline());
|
||||
$em->flush();
|
||||
|
||||
$eventIndex->indexEvent($event);
|
||||
|
||||
$this->addFlash('success', $event->isOnline() ? 'Evenement mis en ligne.' : 'Evenement passe hors ligne.');
|
||||
|
||||
return $this->redirectToRoute('app_account_edit_event', ['id' => $event->getId()]);
|
||||
}
|
||||
|
||||
#[Route('/mon-compte/evenement/{id}/secret', name: 'app_account_toggle_event_secret', methods: ['POST'])]
|
||||
public function toggleEventSecret(\App\Entity\Event $event, EntityManagerInterface $em, EventIndexService $eventIndex): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('ROLE_ORGANIZER');
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->getUser();
|
||||
if ($event->getAccount()->getId() !== $user->getId()) {
|
||||
throw $this->createAccessDeniedException();
|
||||
}
|
||||
|
||||
$event->setIsSecret(!$event->isSecret());
|
||||
$em->flush();
|
||||
|
||||
$eventIndex->indexEvent($event);
|
||||
|
||||
$this->addFlash('success', $event->isSecret() ? 'Evenement marque comme secret.' : 'Evenement rendu public.');
|
||||
|
||||
return $this->redirectToRoute('app_account_edit_event', ['id' => $event->getId()]);
|
||||
}
|
||||
|
||||
#[Route('/mon-compte/evenement/{id}/supprimer', name: 'app_account_delete_event', methods: ['POST'])]
|
||||
public function deleteEvent(\App\Entity\Event $event, EntityManagerInterface $em, EventIndexService $eventIndex): Response
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
{% block title %}Modifier un evenement - E-Ticket{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="page-container">
|
||||
<div class="max-w-6xl mx-auto py-12 px-4">
|
||||
<a href="{{ path('app_account', {tab: 'events'}) }}" class="inline-flex items-center gap-2 text-sm font-black uppercase tracking-widest text-gray-500 hover:text-gray-900 transition-colors mb-8">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M15 19l-7-7 7-7"/></svg>
|
||||
Retour aux evenements
|
||||
@@ -12,68 +12,125 @@
|
||||
<h1 class="text-3xl font-black uppercase tracking-tighter italic heading-page">Modifier un evenement</h1>
|
||||
<p class="font-bold text-gray-600 italic mb-8">Modifiez les informations de votre evenement.</p>
|
||||
|
||||
{% for message in app.flashes('success') %}
|
||||
<div class="flash-success"><p class="font-black text-sm">{{ message }}</p></div>
|
||||
{% endfor %}
|
||||
{% for message in app.flashes('error') %}
|
||||
<div class="flash-error"><p class="font-black text-sm">{{ message }}</p></div>
|
||||
{% endfor %}
|
||||
|
||||
<form method="post" action="{{ path('app_account_edit_event', {id: event.id}) }}" enctype="multipart/form-data" class="form-col">
|
||||
<div>
|
||||
<label for="event_title" class="text-xs font-black uppercase tracking-widest form-label">Titre de l'evenement</label>
|
||||
<input type="text" id="event_title" name="title" required class="form-input focus:border-indigo-600" value="{{ event.title }}">
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-4 mb-8">
|
||||
{% if event.online %}
|
||||
<form method="post" action="{{ path('app_account_toggle_event_online', {id: event.id}) }}">
|
||||
<button type="submit" class="px-4 py-2 border-2 border-red-800 bg-red-600 text-white font-black uppercase text-xs tracking-widest cursor-pointer hover:bg-red-800 transition-all">
|
||||
Passer hors ligne
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form method="post" action="{{ path('app_account_toggle_event_online', {id: event.id}) }}">
|
||||
<button type="submit" class="px-4 py-2 border-2 border-gray-900 bg-green-500 text-white font-black uppercase text-xs tracking-widest cursor-pointer hover:bg-green-700 transition-all">
|
||||
Mettre en ligne
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<div>
|
||||
<label for="event_description" class="text-xs font-black uppercase tracking-widest form-label">Description</label>
|
||||
<e-ticket-editor>
|
||||
<textarea id="event_description" name="description" rows="5" placeholder="Decrivez votre evenement...">{{ event.description }}</textarea>
|
||||
</e-ticket-editor>
|
||||
</div>
|
||||
{% if event.secret %}
|
||||
<form method="post" action="{{ path('app_account_toggle_event_secret', {id: event.id}) }}">
|
||||
<button type="submit" class="px-4 py-2 border-2 border-gray-900 bg-[#fabf04] font-black uppercase text-xs tracking-widest cursor-pointer hover:bg-yellow-500 transition-all">
|
||||
Rendre public
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<form method="post" action="{{ path('app_account_toggle_event_secret', {id: event.id}) }}">
|
||||
<button type="submit" class="px-4 py-2 border-2 border-gray-900 bg-gray-200 font-black uppercase text-xs tracking-widest cursor-pointer hover:bg-gray-300 transition-all">
|
||||
Rendre secret
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="event_start_at" class="text-xs font-black uppercase tracking-widest form-label">Date et heure de debut</label>
|
||||
<input type="datetime-local" id="event_start_at" name="start_at" required class="form-input focus:border-indigo-600" value="{{ event.startAt|date('Y-m-d\\TH:i') }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="event_end_at" class="text-xs font-black uppercase tracking-widest form-label">Date et heure de fin</label>
|
||||
<input type="datetime-local" id="event_end_at" name="end_at" required class="form-input focus:border-indigo-600" value="{{ event.endAt|date('Y-m-d\\TH:i') }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="event_address" class="text-xs font-black uppercase tracking-widest form-label">Adresse</label>
|
||||
<input type="text" id="event_address" name="address" required class="form-input focus:border-indigo-600" value="{{ event.address }}">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="flex-1 min-w-[120px] max-w-[200px]">
|
||||
<label for="event_zipcode" class="text-xs font-black uppercase tracking-widest form-label">Code postal</label>
|
||||
<input type="text" id="event_zipcode" name="zipcode" required maxlength="10" class="form-input focus:border-indigo-600" value="{{ event.zipcode }}">
|
||||
</div>
|
||||
<div class="flex-[2] min-w-[200px]">
|
||||
<label for="event_city" class="text-xs font-black uppercase tracking-widest form-label">Ville</label>
|
||||
<input type="text" id="event_city" name="city" required class="form-input focus:border-indigo-600" value="{{ event.city }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="event_main_picture" class="text-xs font-black uppercase tracking-widest form-label">Image principale</label>
|
||||
{% if event.eventMainPictureName %}
|
||||
<p class="text-xs font-bold text-gray-400 mb-2">Image actuelle : {{ event.eventMainPictureName }}</p>
|
||||
<div class="flex items-center gap-2 ml-auto">
|
||||
{% if event.online %}
|
||||
<span class="badge-green text-xs font-black uppercase">En ligne</span>
|
||||
{% else %}
|
||||
<span class="badge-red text-xs font-black uppercase">Hors ligne</span>
|
||||
{% endif %}
|
||||
<input type="file" id="event_main_picture" name="event_main_picture" accept="image/*" class="form-file">
|
||||
{% if event.secret %}
|
||||
<span class="badge-yellow text-xs font-black uppercase">Secret</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col lg:flex-row gap-8">
|
||||
<div class="flex-1 min-w-0">
|
||||
<form method="post" action="{{ path('app_account_edit_event', {id: event.id}) }}" enctype="multipart/form-data" class="form-col">
|
||||
<div>
|
||||
<label for="event_title" class="text-xs font-black uppercase tracking-widest form-label">Titre de l'evenement</label>
|
||||
<input type="text" id="event_title" name="title" required class="form-input focus:border-indigo-600" value="{{ event.title }}">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="event_description" class="text-xs font-black uppercase tracking-widest form-label">Description</label>
|
||||
<e-ticket-editor>
|
||||
<textarea id="event_description" name="description" rows="5" placeholder="Decrivez votre evenement...">{{ event.description }}</textarea>
|
||||
</e-ticket-editor>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="event_start_at" class="text-xs font-black uppercase tracking-widest form-label">Date et heure de debut</label>
|
||||
<input type="datetime-local" id="event_start_at" name="start_at" required class="form-input focus:border-indigo-600" value="{{ event.startAt|date('Y-m-d\\TH:i') }}">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="event_end_at" class="text-xs font-black uppercase tracking-widest form-label">Date et heure de fin</label>
|
||||
<input type="datetime-local" id="event_end_at" name="end_at" required class="form-input focus:border-indigo-600" value="{{ event.endAt|date('Y-m-d\\TH:i') }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="event_address" class="text-xs font-black uppercase tracking-widest form-label">Adresse</label>
|
||||
<input type="text" id="event_address" name="address" required class="form-input focus:border-indigo-600" value="{{ event.address }}">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="flex-1 min-w-[120px] max-w-[200px]">
|
||||
<label for="event_zipcode" class="text-xs font-black uppercase tracking-widest form-label">Code postal</label>
|
||||
<input type="text" id="event_zipcode" name="zipcode" required maxlength="10" class="form-input focus:border-indigo-600" value="{{ event.zipcode }}">
|
||||
</div>
|
||||
<div class="flex-[2] min-w-[200px]">
|
||||
<label for="event_city" class="text-xs font-black uppercase tracking-widest form-label">Ville</label>
|
||||
<input type="text" id="event_city" name="city" required class="form-input focus:border-indigo-600" value="{{ event.city }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="event_main_picture" class="text-xs font-black uppercase tracking-widest form-label">Changer l'affiche</label>
|
||||
<input type="file" id="event_main_picture" name="event_main_picture" accept="image/*" class="form-file">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn-brutal font-black uppercase text-sm tracking-widest hover:bg-indigo-600 hover:text-white transition-all">
|
||||
Enregistrer les modifications
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-3">
|
||||
<input type="checkbox" id="event_is_online" name="is_online" value="1" class="w-5 h-5 border-2 border-gray-900 cursor-pointer" {{ event.online ? 'checked' : '' }}>
|
||||
<label for="event_is_online" class="text-sm font-black uppercase tracking-widest cursor-pointer">Mettre en ligne</label>
|
||||
<div class="lg:w-[350px] flex-shrink-0">
|
||||
<div class="card-brutal overflow-hidden sticky top-24">
|
||||
<div class="section-header">
|
||||
<h2 class="text-[10px] font-black uppercase tracking-widest text-white">Affiche</h2>
|
||||
</div>
|
||||
{% if event.eventMainPictureName %}
|
||||
<img src="{{ ('/uploads/events/' ~ event.eventMainPictureName) | imagine_filter('medium') }}" alt="{{ event.title }}" class="w-full h-auto">
|
||||
{% else %}
|
||||
<div class="p-12 text-center bg-gray-50">
|
||||
<div class="text-4xl mb-4 opacity-30">📷</div>
|
||||
<p class="text-gray-400 font-bold text-sm">Aucune affiche</p>
|
||||
<p class="text-gray-300 text-xs font-bold mt-1">Ajoutez une image via le formulaire</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button type="submit" class="btn-brutal font-black uppercase text-sm tracking-widest hover:bg-indigo-600 hover:text-white transition-all">
|
||||
Enregistrer les modifications
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user