diff --git a/app/controllers/promoter/events_controller.rb b/app/controllers/promoter/events_controller.rb
new file mode 100644
index 0000000..3f2deda
--- /dev/null
+++ b/app/controllers/promoter/events_controller.rb
@@ -0,0 +1,117 @@
+# Promoter Events Controller
+#
+# Handles event management for promoters (event organizers)
+# Allows promoters to create, edit, delete and manage their events
+class Promoter::EventsController < ApplicationController
+ before_action :authenticate_user!
+ before_action :ensure_can_manage_events!
+ before_action :set_event, only: [:show, :edit, :update, :destroy, :publish, :unpublish, :cancel, :mark_sold_out]
+
+ # Display all events for the current promoter
+ def index
+ @events = current_user.events.order(created_at: :desc).page(params[:page]).per(10)
+ end
+
+ # Display a specific event for the promoter
+ def show
+ # Event is set by set_event callback
+ end
+
+ # Show form to create a new event
+ def new
+ @event = current_user.events.build
+ end
+
+ # Create a new event
+ def create
+ @event = current_user.events.build(event_params)
+
+ if @event.save
+ redirect_to promoter_event_path(@event), notice: 'Event créé avec succès!'
+ else
+ render :new, status: :unprocessable_entity
+ end
+ end
+
+ # Show form to edit an existing event
+ def edit
+ # Event is set by set_event callback
+ end
+
+ # Update an existing event
+ def update
+ if @event.update(event_params)
+ redirect_to promoter_event_path(@event), notice: 'Event mis à jour avec succès!'
+ else
+ render :edit, status: :unprocessable_entity
+ end
+ end
+
+ # Delete an event
+ def destroy
+ @event.destroy
+ redirect_to promoter_events_path, notice: 'Event supprimé avec succès!'
+ end
+
+ # Publish an event (make it visible to public)
+ def publish
+ if @event.draft?
+ @event.update(state: :published)
+ redirect_to promoter_event_path(@event), notice: 'Event publié avec succès!'
+ else
+ redirect_to promoter_event_path(@event), alert: 'Cet event ne peut pas être publié.'
+ end
+ end
+
+ # Unpublish an event (make it draft)
+ def unpublish
+ if @event.published?
+ @event.update(state: :draft)
+ redirect_to promoter_event_path(@event), notice: 'Event dépublié avec succès!'
+ else
+ redirect_to promoter_event_path(@event), alert: 'Cet event ne peut pas être dépublié.'
+ end
+ end
+
+ # Cancel an event
+ def cancel
+ if @event.published?
+ @event.update(state: :canceled)
+ redirect_to promoter_event_path(@event), notice: 'Event annulé avec succès!'
+ else
+ redirect_to promoter_event_path(@event), alert: 'Cet event ne peut pas être annulé.'
+ end
+ end
+
+ # Mark event as sold out
+ def mark_sold_out
+ if @event.published?
+ @event.update(state: :sold_out)
+ redirect_to promoter_event_path(@event), notice: 'Event marqué comme complet!'
+ else
+ redirect_to promoter_event_path(@event), alert: 'Cet event ne peut pas être marqué comme complet.'
+ end
+ end
+
+ private
+
+ def ensure_can_manage_events!
+ unless current_user.can_manage_events?
+ redirect_to dashboard_path, alert: 'Vous n\'avez pas les permissions nécessaires pour gérer des événements.'
+ end
+ end
+
+ def set_event
+ @event = current_user.events.find(params[:id])
+ rescue ActiveRecord::RecordNotFound
+ redirect_to promoter_events_path, alert: 'Event non trouvé ou vous n\'avez pas accès à cet event.'
+ end
+
+ def event_params
+ params.require(:event).permit(
+ :name, :slug, :description, :image,
+ :venue_name, :venue_address, :latitude, :longitude,
+ :start_time, :end_time, :featured
+ )
+ end
+end
\ No newline at end of file
diff --git a/app/javascript/controllers/event_form_controller.js b/app/javascript/controllers/event_form_controller.js
new file mode 100644
index 0000000..cc031b1
--- /dev/null
+++ b/app/javascript/controllers/event_form_controller.js
@@ -0,0 +1,28 @@
+import { Controller } from "@hotwired/stimulus"
+
+// Event form controller for handling form interactions
+// Handles auto-slug generation from event names
+export default class extends Controller {
+ static targets = ["name", "slug"]
+
+ connect() {
+ console.log("Event form controller connected")
+ }
+
+ // Auto-generate slug from name input
+ generateSlug() {
+ // Only auto-generate if slug field is empty
+ if (this.slugTarget.value === "") {
+ const slug = this.nameTarget.value
+ .toLowerCase()
+ .normalize("NFD")
+ .replace(/[\u0300-\u036f]/g, "") // Remove accents
+ .replace(/[^a-z0-9\s-]/g, "") // Remove special chars
+ .replace(/\s+/g, "-") // Replace spaces with dashes
+ .replace(/-+/g, "-") // Remove duplicate dashes
+ .replace(/^-|-$/g, "") // Remove leading/trailing dashes
+
+ this.slugTarget.value = slug
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/javascript/controllers/index.js b/app/javascript/controllers/index.js
index 89b7279..593b714 100755
--- a/app/javascript/controllers/index.js
+++ b/app/javascript/controllers/index.js
@@ -19,6 +19,9 @@ application.register("ticket-selection", TicketSelectionController);
import HeaderController from "./header_controller"
application.register("header", HeaderController);
+import EventFormController from "./event_form_controller"
+application.register("event-form", EventFormController);
+
diff --git a/app/models/user.rb b/app/models/user.rb
index bb14b14..8076d13 100755
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -27,4 +27,16 @@ class User < ApplicationRecord
validates :last_name, length: { minimum: 3, maximum: 12, allow_blank: true }
validates :first_name, length: { minimum: 3, maximum: 12, allow_blank: true }
validates :company_name, length: { minimum: 3, maximum: 12, allow_blank: true }
+
+ # Authorization methods
+ def can_manage_events?
+ # For now, all authenticated users can manage events
+ # This can be extended later with role-based permissions
+ true
+ end
+
+ def promoter?
+ # Alias for can_manage_events? to make views more semantic
+ can_manage_events?
+ end
end
diff --git a/app/views/pages/dashboard.html.erb b/app/views/pages/dashboard.html.erb
index a611596..b476858 100755
--- a/app/views/pages/dashboard.html.erb
+++ b/app/views/pages/dashboard.html.erb
@@ -1,7 +1,23 @@
-
Tableau de bord
+
+
Tableau de bord
+
+
+ <% if current_user.promoter? %>
+
+ <%= link_to promoter_events_path, class: "inline-flex items-center px-4 py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200" do %>
+
+ Mes événements
+ <% end %>
+ <%= link_to new_promoter_event_path, class: "inline-flex items-center px-4 py-2 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
+
+ Créer un événement
+ <% end %>
+
+ <% end %>
+
<%= render partial: 'components/metric_card', locals: { title: "Mes réservations", value: @booked_events, classes: "from-green-100 to-emerald-100" } %>
diff --git a/app/views/promoter/events/edit.html.erb b/app/views/promoter/events/edit.html.erb
new file mode 100644
index 0000000..8139a5d
--- /dev/null
+++ b/app/views/promoter/events/edit.html.erb
@@ -0,0 +1,184 @@
+<% content_for(:title, "Modifier #{@event.name}") %>
+
+
+
+
+
+ <%= link_to promoter_event_path(@event), class: "text-gray-400 hover:text-gray-600 transition-colors" do %>
+
+ <% end %>
+
+
Modifier l'événement
+
<%= @event.name %>
+
+
+
+
+ <%= form_with model: [:promoter, @event], local: true, class: "space-y-8", data: { controller: "event-form" } do |form| %>
+ <% if @event.errors.any? %>
+
+
+
+
+
+
+
+ <%= pluralize(@event.errors.count, "erreur") %> à corriger :
+
+
+
+ <% @event.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+
+
+
+ <% end %>
+
+
+
+
Informations générales
+
+
+
+ <%= form.label :name, "Nom de l'événement", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :name, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Ex: Soirée d'ouverture", data: { "event-form-target": "name", action: "input->event-form#generateSlug" } %>
+
+
+
+ <%= form.label :slug, "Slug (URL)", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :slug, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "soiree-ouverture", data: { "event-form-target": "slug" } %>
+
+ <% if @event.published? %>
+
+ Attention: Modifier le slug d'un événement publié peut casser les liens existants.
+ <% else %>
+ Utilisé dans l'URL de l'événement
+ <% end %>
+
+
+
+
+
+ <%= form.label :description, "Description", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_area :description, rows: 4, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Décrivez votre événement..." %>
+
+
+
+ <%= form.label :image, "Image (URL)", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.url_field :image, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "https://example.com/image.jpg" %>
+
URL de l'image de couverture de l'événement
+
+
+
+
+
+
Date et heure
+
+
+
+ <%= form.label :start_time, "Date et heure de début", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.datetime_local_field :start_time,
+ value: @event.start_time&.strftime("%Y-%m-%dT%H:%M"),
+ class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" %>
+
+
+
+ <%= form.label :end_time, "Date et heure de fin", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.datetime_local_field :end_time,
+ value: @event.end_time&.strftime("%Y-%m-%dT%H:%M"),
+ class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" %>
+
+
+
+ <% if @event.published? && @event.tickets.any? %>
+
+
+
+
+ Des billets ont déjà été vendus pour cet événement. Modifier la date pourrait impacter les participants.
+
+
+
+ <% end %>
+
+
+
+
+
Lieu de l'événement
+
+
+
+ <%= form.label :venue_name, "Nom du lieu", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :venue_name, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Ex: Le Grand Rex" %>
+
+
+
+ <%= form.label :venue_address, "Adresse", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :venue_address, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Ex: 1 Boulevard Poissonnière, 75002 Paris" %>
+
+
+
+
+ <%= form.label :latitude, "Latitude", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.number_field :latitude, step: :any, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "48.8566" %>
+
+
+
+ <%= form.label :longitude, "Longitude", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.number_field :longitude, step: :any, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "2.3522" %>
+
+
+
+
+
+ Utilisez un service comme latlong.net pour obtenir les coordonnées GPS.
+
+
+
+ <% if @event.published? && @event.tickets.any? %>
+
+
+
+
+ Des billets ont déjà été vendus pour cet événement. Modifier le lieu pourrait impacter les participants.
+
+
+
+ <% end %>
+
+
+
+
+
Options
+
+
+ <%= form.check_box :featured, class: "h-4 w-4 text-purple-600 border-gray-300 rounded focus:ring-purple-500" %>
+ <%= form.label :featured, "Mettre en avant sur la page d'accueil", class: "ml-2 text-sm text-gray-700" %>
+
+
Les événements mis en avant apparaissent en premier sur la page d'accueil.
+
+
+
+
+
+ <%= link_to promoter_event_path(@event), class: "text-gray-500 hover:text-gray-700 transition-colors" do %>
+ Annuler
+ <% end %>
+ <% if @event.published? && @event.tickets.any? %>
+
+
+ <%= @event.tickets.count %> billet(s) déjà vendu(s)
+
+ <% end %>
+
+
+
+ <%= form.submit "Sauvegarder les modifications", class: "inline-flex items-center px-6 py-3 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200" %>
+
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/views/promoter/events/index.html.erb b/app/views/promoter/events/index.html.erb
new file mode 100644
index 0000000..adfca3c
--- /dev/null
+++ b/app/views/promoter/events/index.html.erb
@@ -0,0 +1,136 @@
+<% content_for(:title, "Mes événements") %>
+
+
+
+
+
Mes événements
+
Gérez tous vos événements depuis cette interface
+
+ <%= link_to new_promoter_event_path, class: "inline-flex items-center px-6 py-3 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
+
+ Créer un événement
+ <% end %>
+
+
+ <% if @events.any? %>
+
+
+
+
+
+ | Événement |
+ Statut |
+ Date |
+ Lieu |
+ Actions |
+
+
+
+ <% @events.each do |event| %>
+
+
+
+
+
+
+
+
+ <%= link_to event.name, promoter_event_path(event), class: "hover:text-purple-600 transition-colors" %>
+
+
+ <%= event.description.truncate(60) %>
+
+
+
+ |
+
+ <% case event.state %>
+ <% when "draft" %>
+
+
+ Brouillon
+
+ <% when "published" %>
+
+
+ Publié
+
+ <% when "canceled" %>
+
+
+ Annulé
+
+ <% when "sold_out" %>
+
+
+ Complet
+
+ <% end %>
+
+ <% if event.featured? %>
+
+
+ À la une
+
+ <% end %>
+ |
+
+ <% if event.start_time %>
+ <%= event.start_time.strftime("%d/%m/%Y") %>
+ <%= event.start_time.strftime("%H:%M") %>
+ <% else %>
+ Date non définie
+ <% end %>
+ |
+
+ <%= event.venue_name %>
+ <%= event.venue_address %>
+ |
+
+
+ <%= link_to promoter_event_path(event), class: "text-gray-400 hover:text-gray-600 transition-colors", title: "Voir" do %>
+
+ <% end %>
+ <%= link_to edit_promoter_event_path(event), class: "text-gray-400 hover:text-blue-600 transition-colors", title: "Modifier" do %>
+
+ <% end %>
+ <% if event.draft? %>
+ <%= button_to publish_promoter_event_path(event), method: :patch, class: "text-gray-400 hover:text-green-600 transition-colors", title: "Publier" do %>
+
+ <% end %>
+ <% elsif event.published? %>
+ <%= button_to unpublish_promoter_event_path(event), method: :patch, class: "text-gray-400 hover:text-yellow-600 transition-colors", title: "Dépublier" do %>
+
+ <% end %>
+ <% end %>
+ <%= button_to promoter_event_path(event), method: :delete,
+ data: { confirm: "Êtes-vous sûr de vouloir supprimer cet événement ?" },
+ class: "text-gray-400 hover:text-red-600 transition-colors", title: "Supprimer" do %>
+
+ <% end %>
+
+ |
+
+ <% end %>
+
+
+
+
+
+
+ <%= paginate @events if respond_to?(:paginate) %>
+
+ <% else %>
+
+
+
+
+
Aucun événement
+
Vous n'avez pas encore créé d'événement. Commencez dès maintenant !
+ <%= link_to new_promoter_event_path, class: "inline-flex items-center px-6 py-3 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200" do %>
+
+ Créer mon premier événement
+ <% end %>
+
+ <% end %>
+
\ No newline at end of file
diff --git a/app/views/promoter/events/new.html.erb b/app/views/promoter/events/new.html.erb
new file mode 100644
index 0000000..39b9777
--- /dev/null
+++ b/app/views/promoter/events/new.html.erb
@@ -0,0 +1,146 @@
+<% content_for(:title, "Créer un événement") %>
+
+
+
+
+
+ <%= link_to promoter_events_path, class: "text-gray-400 hover:text-gray-600 transition-colors" do %>
+
+ <% end %>
+
+
Créer un événement
+
Remplissez les informations de votre événement
+
+
+
+
+ <%= form_with model: [:promoter, @event], local: true, class: "space-y-8", data: { controller: "event-form" } do |form| %>
+ <% if @event.errors.any? %>
+
+
+
+
+
+
+
+ <%= pluralize(@event.errors.count, "erreur") %> à corriger :
+
+
+
+ <% @event.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+
+
+
+ <% end %>
+
+
+
+
Informations générales
+
+
+
+ <%= form.label :name, "Nom de l'événement", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :name, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Ex: Soirée d'ouverture", data: { "event-form-target": "name", action: "input->event-form#generateSlug" } %>
+
+
+
+ <%= form.label :slug, "Slug (URL)", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :slug, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "soiree-ouverture", data: { "event-form-target": "slug" } %>
+
Utilisé dans l'URL de l'événement
+
+
+
+
+ <%= form.label :description, "Description", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_area :description, rows: 4, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Décrivez votre événement..." %>
+
+
+
+ <%= form.label :image, "Image (URL)", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.url_field :image, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "https://example.com/image.jpg" %>
+
URL de l'image de couverture de l'événement
+
+
+
+
+
+
Date et heure
+
+
+
+ <%= form.label :start_time, "Date et heure de début", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.datetime_local_field :start_time, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" %>
+
+
+
+ <%= form.label :end_time, "Date et heure de fin", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.datetime_local_field :end_time, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" %>
+
+
+
+
+
+
+
Lieu de l'événement
+
+
+
+ <%= form.label :venue_name, "Nom du lieu", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :venue_name, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Ex: Le Grand Rex" %>
+
+
+
+ <%= form.label :venue_address, "Adresse", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.text_field :venue_address, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "Ex: 1 Boulevard Poissonnière, 75002 Paris" %>
+
+
+
+
+ <%= form.label :latitude, "Latitude", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.number_field :latitude, step: :any, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "48.8566" %>
+
+
+
+ <%= form.label :longitude, "Longitude", class: "block text-sm font-medium text-gray-700 mb-2" %>
+ <%= form.number_field :longitude, step: :any, class: "w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent", placeholder: "2.3522" %>
+
+
+
+
+
+ Utilisez un service comme latlong.net pour obtenir les coordonnées GPS.
+
+
+
+
+
+
+
Options
+
+
+ <%= form.check_box :featured, class: "h-4 w-4 text-purple-600 border-gray-300 rounded focus:ring-purple-500" %>
+ <%= form.label :featured, "Mettre en avant sur la page d'accueil", class: "ml-2 text-sm text-gray-700" %>
+
+
Les événements mis en avant apparaissent en premier sur la page d'accueil.
+
+
+
+
+
+ <%= link_to promoter_events_path, class: "text-gray-500 hover:text-gray-700 transition-colors" do %>
+ Annuler
+ <% end %>
+
+
+
+ <%= form.submit "Créer en brouillon", class: "inline-flex items-center px-6 py-3 bg-gray-600 text-white font-medium rounded-lg hover:bg-gray-700 transition-colors duration-200" %>
+
+
+ <% end %>
+
+
+
diff --git a/app/views/promoter/events/show.html.erb b/app/views/promoter/events/show.html.erb
new file mode 100644
index 0000000..f43bbf5
--- /dev/null
+++ b/app/views/promoter/events/show.html.erb
@@ -0,0 +1,231 @@
+<% content_for(:title, @event.name) %>
+
+
+
+
+
+
+ <%= link_to promoter_events_path, class: "text-gray-400 hover:text-gray-600 transition-colors" do %>
+
+ <% end %>
+
+
<%= @event.name %>
+
+
+
+ <%= @event.start_time&.strftime("%d/%m/%Y à %H:%M") || "Date non définie" %>
+
+
+
+ <%= @event.venue_name %>
+
+
+
+
+
+ <%= link_to edit_promoter_event_path(@event), class: "inline-flex items-center px-4 py-2 bg-white border border-gray-300 text-gray-700 font-medium rounded-lg hover:bg-gray-50 transition-colors duration-200" do %>
+
+ Modifier
+ <% end %>
+
+ <% if @event.draft? %>
+ <%= button_to publish_promoter_event_path(@event), method: :patch, class: "inline-flex items-center px-4 py-2 bg-green-600 text-white font-medium rounded-lg hover:bg-green-700 transition-colors duration-200" do %>
+
+ Publier
+ <% end %>
+ <% elsif @event.published? %>
+ <%= button_to unpublish_promoter_event_path(@event), method: :patch, class: "inline-flex items-center px-4 py-2 bg-yellow-600 text-white font-medium rounded-lg hover:bg-yellow-700 transition-colors duration-200" do %>
+
+ Dépublier
+ <% end %>
+ <% end %>
+
+ <% if @event.published? %>
+ <%= button_to cancel_promoter_event_path(@event), method: :patch, class: "inline-flex items-center px-4 py-2 bg-red-600 text-white font-medium rounded-lg hover:bg-red-700 transition-colors duration-200", data: { confirm: "Êtes-vous sûr de vouloir annuler cet événement ?" } do %>
+
+ Annuler
+ <% end %>
+ <% end %>
+
+
+
+
+
+
+ <% case @event.state %>
+ <% when "draft" %>
+
+
+
+
+
Événement en brouillon
+
Cet événement n'est pas visible publiquement. Publiez-le pour le rendre accessible aux utilisateurs.
+
+
+
+ <% when "published" %>
+
+
+
+
+
Événement publié
+
Cet événement est visible publiquement et les utilisateurs peuvent acheter des billets.
+
+
+ <%= link_to event_path(@event.slug, @event), target: "_blank", class: "text-green-600 hover:text-green-800 font-medium text-sm" do %>
+ Voir publiquement
+ <% end %>
+
+
+
+ <% when "canceled" %>
+
+
+
+
+
Événement annulé
+
Cet événement a été annulé et n'est plus accessible aux utilisateurs.
+
+
+
+ <% when "sold_out" %>
+
+
+
+
+
Événement complet
+
Tous les billets pour cet événement ont été vendus.
+
+
+
+ <% end %>
+
+ <% if @event.featured? %>
+
+
+
+
+
Événement à la une
+
Cet événement est mis en avant sur la page d'accueil.
+
+
+
+ <% end %>
+
+
+
+
+
+
+
+ <% if @event.image.present? %>
+
+

+
+ <% end %>
+
+
+
+
Description
+
+ <%= simple_format(@event.description) %>
+
+
+
+
+
+
Lieu
+
+
+
+
+
<%= @event.venue_name %>
+
<%= @event.venue_address %>
+
+
+
+
+ <%= @event.latitude %>, <%= @event.longitude %>
+
+
+
+
+
+
+
+
+
+
Statistiques
+
+
+ Types de billets
+ <%= @event.ticket_types.count %>
+
+
+ Billets vendus
+ <%= @event.tickets.count %>
+
+
+ Revenus
+
+ <%= number_to_currency(@event.tickets.sum(:price_cents) / 100.0, unit: "€") %>
+
+
+
+
+
+
+
+
Informations
+
+
+
Slug
+
<%= @event.slug %>
+
+
+
Créé le
+
<%= @event.created_at.strftime("%d/%m/%Y à %H:%M") %>
+
+
+
Modifié le
+
<%= @event.updated_at.strftime("%d/%m/%Y à %H:%M") %>
+
+ <% if @event.start_time %>
+
+
Début
+
<%= @event.start_time.strftime("%d/%m/%Y à %H:%M") %>
+
+ <% end %>
+ <% if @event.end_time %>
+
+
Fin
+
<%= @event.end_time.strftime("%d/%m/%Y à %H:%M") %>
+
+ <% end %>
+
+
+
+
+
+
Actions rapides
+
+ <%= link_to "#", class: "w-full inline-flex items-center px-4 py-2 bg-gray-50 text-gray-700 font-medium rounded-lg hover:bg-gray-100 transition-colors duration-200" do %>
+
+ Gérer les billets
+ <% end %>
+ <%= button_to mark_sold_out_promoter_event_path(@event), method: :patch, class: "w-full inline-flex items-center px-4 py-2 bg-gray-50 text-gray-700 font-medium rounded-lg hover:bg-gray-100 transition-colors duration-200", disabled: !@event.published? do %>
+
+ Marquer comme complet
+ <% end %>
+
+ <%= button_to promoter_event_path(@event), method: :delete,
+ data: { confirm: "Êtes-vous sûr de vouloir supprimer cet événement ? Cette action est irréversible." },
+ class: "w-full inline-flex items-center px-4 py-2 text-red-600 font-medium rounded-lg hover:bg-red-50 transition-colors duration-200" do %>
+
+ Supprimer l'événement
+ <% end %>
+
+
+
+
+
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index b73975e..fbc4b51 100755
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -34,6 +34,18 @@ Rails.application.routes.draw do
# === Pages ===
get "dashboard", to: "pages#dashboard", as: "dashboard"
+ # === Promoter Routes ===
+ namespace :promoter do
+ resources :events do
+ member do
+ patch :publish
+ patch :unpublish
+ patch :cancel
+ patch :mark_sold_out
+ end
+ end
+ end
+
# === Events ===
get "events", to: "events#index", as: "events"
get "events/:slug.:id", to: "events#show", as: "event"