develop #3
117
app/controllers/promoter/events_controller.rb
Normal file
117
app/controllers/promoter/events_controller.rb
Normal file
@@ -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
|
||||
28
app/javascript/controllers/event_form_controller.js
Normal file
28
app/javascript/controllers/event_form_controller.js
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
<div class="container mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<!-- Hero section with metrics -->
|
||||
<div class="mb-8">
|
||||
<h1 class="text-3xl font-bold text-slate-900 dark:text-slate-100 mb-6">Tableau de bord</h1>
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h1 class="text-3xl font-bold text-slate-900 dark:text-slate-100">Tableau de bord</h1>
|
||||
|
||||
<!-- Promoter Actions -->
|
||||
<% if current_user.promoter? %>
|
||||
<div class="flex items-center space-x-3">
|
||||
<%= 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 %>
|
||||
<i data-lucide="calendar-plus" class="w-4 h-4 mr-2"></i>
|
||||
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 %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer un événement
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
|
||||
<%= render partial: 'components/metric_card', locals: { title: "Mes réservations", value: @booked_events, classes: "from-green-100 to-emerald-100" } %>
|
||||
|
||||
184
app/views/promoter/events/edit.html.erb
Normal file
184
app/views/promoter/events/edit.html.erb
Normal file
@@ -0,0 +1,184 @@
|
||||
<% content_for(:title, "Modifier #{@event.name}") %>
|
||||
|
||||
<div class="container py-8">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<div class="mb-8">
|
||||
<div class="flex items-center space-x-4">
|
||||
<%= link_to promoter_event_path(@event), class: "text-gray-400 hover:text-gray-600 transition-colors" do %>
|
||||
<i data-lucide="arrow-left" class="w-5 h-5"></i>
|
||||
<% end %>
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2">Modifier l'événement</h1>
|
||||
<p class="text-gray-600"><%= @event.name %></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= form_with model: [:promoter, @event], local: true, class: "space-y-8", data: { controller: "event-form" } do |form| %>
|
||||
<% if @event.errors.any? %>
|
||||
<div class="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<i data-lucide="alert-circle" class="w-5 h-5 text-red-400"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-red-800">
|
||||
<%= pluralize(@event.errors.count, "erreur") %> à corriger :
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-red-700">
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<% @event.errors.full_messages.each do |message| %>
|
||||
<li><%= message %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Basic Information -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Informations générales</h3>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<%= 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" } %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" } %>
|
||||
<p class="mt-1 text-sm text-gray-500">
|
||||
<% if @event.published? %>
|
||||
<i data-lucide="alert-triangle" class="w-4 h-4 inline text-yellow-500"></i>
|
||||
Attention: Modifier le slug d'un événement publié peut casser les liens existants.
|
||||
<% else %>
|
||||
Utilisé dans l'URL de l'événement
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<%= 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..." %>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<%= 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" %>
|
||||
<p class="mt-1 text-sm text-gray-500">URL de l'image de couverture de l'événement</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Date & Time -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Date et heure</h3>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if @event.published? && @event.tickets.any? %>
|
||||
<div class="mt-4 p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||||
<div class="flex">
|
||||
<i data-lucide="alert-triangle" class="w-5 h-5 text-yellow-400 mt-0.5 mr-2"></i>
|
||||
<p class="text-sm text-yellow-800">
|
||||
Des billets ont déjà été vendus pour cet événement. Modifier la date pourrait impacter les participants.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Venue Information -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Lieu de l'événement</h3>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-500">
|
||||
<i data-lucide="info" class="w-4 h-4 inline mr-1"></i>
|
||||
Utilisez un service comme <a href="https://www.latlong.net/" target="_blank" class="text-purple-600 hover:text-purple-800">latlong.net</a> pour obtenir les coordonnées GPS.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<% if @event.published? && @event.tickets.any? %>
|
||||
<div class="mt-4 p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||||
<div class="flex">
|
||||
<i data-lucide="alert-triangle" class="w-5 h-5 text-yellow-400 mt-0.5 mr-2"></i>
|
||||
<p class="text-sm text-yellow-800">
|
||||
Des billets ont déjà été vendus pour cet événement. Modifier le lieu pourrait impacter les participants.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Options -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Options</h3>
|
||||
|
||||
<div class="flex items-center">
|
||||
<%= 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" %>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">Les événements mis en avant apparaissent en premier sur la page d'accueil.</p>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-4">
|
||||
<%= 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? %>
|
||||
<p class="text-sm text-yellow-600">
|
||||
<i data-lucide="info" class="w-4 h-4 inline mr-1"></i>
|
||||
<%= @event.tickets.count %> billet(s) déjà vendu(s)
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<%= 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" %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
136
app/views/promoter/events/index.html.erb
Normal file
136
app/views/promoter/events/index.html.erb
Normal file
@@ -0,0 +1,136 @@
|
||||
<% content_for(:title, "Mes événements") %>
|
||||
|
||||
<div class="container py-8">
|
||||
<div class="mb-8 flex items-center justify-between">
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2">Mes événements</h1>
|
||||
<p class="text-gray-600">Gérez tous vos événements depuis cette interface</p>
|
||||
</div>
|
||||
<%= 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 %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer un événement
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% if @events.any? %>
|
||||
<div class="bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="w-full">
|
||||
<thead class="bg-gray-50 border-b border-gray-200">
|
||||
<tr>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Événement</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Statut</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Lieu</th>
|
||||
<th class="px-6 py-4 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
<% @events.each do |event| %>
|
||||
<tr class="hover:bg-gray-50 transition-colors duration-150">
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center">
|
||||
<div class="h-12 w-12 rounded-lg bg-gradient-to-br from-purple-500 to-pink-500 flex items-center justify-center flex-shrink-0">
|
||||
<i data-lucide="calendar" class="w-6 h-6 text-white"></i>
|
||||
</div>
|
||||
<div class="ml-4">
|
||||
<div class="text-sm font-medium text-gray-900">
|
||||
<%= link_to event.name, promoter_event_path(event), class: "hover:text-purple-600 transition-colors" %>
|
||||
</div>
|
||||
<div class="text-sm text-gray-500 truncate max-w-xs">
|
||||
<%= event.description.truncate(60) %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<% case event.state %>
|
||||
<% when "draft" %>
|
||||
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-gray-100 text-gray-800">
|
||||
<i data-lucide="edit-3" class="w-3 h-3 mr-1"></i>
|
||||
Brouillon
|
||||
</span>
|
||||
<% when "published" %>
|
||||
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800">
|
||||
<i data-lucide="eye" class="w-3 h-3 mr-1"></i>
|
||||
Publié
|
||||
</span>
|
||||
<% when "canceled" %>
|
||||
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-red-100 text-red-800">
|
||||
<i data-lucide="x-circle" class="w-3 h-3 mr-1"></i>
|
||||
Annulé
|
||||
</span>
|
||||
<% when "sold_out" %>
|
||||
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-blue-100 text-blue-800">
|
||||
<i data-lucide="users" class="w-3 h-3 mr-1"></i>
|
||||
Complet
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
<% if event.featured? %>
|
||||
<span class="inline-flex px-2 py-1 text-xs font-semibold rounded-full bg-yellow-100 text-yellow-800 ml-1">
|
||||
<i data-lucide="star" class="w-3 h-3 mr-1"></i>
|
||||
À la une
|
||||
</span>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500">
|
||||
<% if event.start_time %>
|
||||
<div><%= event.start_time.strftime("%d/%m/%Y") %></div>
|
||||
<div class="text-xs text-gray-400"><%= event.start_time.strftime("%H:%M") %></div>
|
||||
<% else %>
|
||||
<span class="text-gray-400">Date non définie</span>
|
||||
<% end %>
|
||||
</td>
|
||||
<td class="px-6 py-4 text-sm text-gray-500">
|
||||
<div><%= event.venue_name %></div>
|
||||
<div class="text-xs text-gray-400 truncate max-w-xs"><%= event.venue_address %></div>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<div class="flex items-center space-x-2">
|
||||
<%= link_to promoter_event_path(event), class: "text-gray-400 hover:text-gray-600 transition-colors", title: "Voir" do %>
|
||||
<i data-lucide="eye" class="w-4 h-4"></i>
|
||||
<% end %>
|
||||
<%= link_to edit_promoter_event_path(event), class: "text-gray-400 hover:text-blue-600 transition-colors", title: "Modifier" do %>
|
||||
<i data-lucide="edit" class="w-4 h-4"></i>
|
||||
<% 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 %>
|
||||
<i data-lucide="upload" class="w-4 h-4"></i>
|
||||
<% 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 %>
|
||||
<i data-lucide="download" class="w-4 h-4"></i>
|
||||
<% 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 %>
|
||||
<i data-lucide="trash-2" class="w-4 h-4"></i>
|
||||
<% end %>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<%= paginate @events if respond_to?(:paginate) %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="bg-white rounded-lg border-2 border-dashed border-gray-300 p-12 text-center">
|
||||
<div class="mx-auto h-24 w-24 rounded-full bg-gray-100 flex items-center justify-center mb-6">
|
||||
<i data-lucide="calendar-plus" class="w-12 h-12 text-gray-400"></i>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900 mb-2">Aucun événement</h3>
|
||||
<p class="text-gray-500 mb-6">Vous n'avez pas encore créé d'événement. Commencez dès maintenant !</p>
|
||||
<%= 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 %>
|
||||
<i data-lucide="plus" class="w-4 h-4 mr-2"></i>
|
||||
Créer mon premier événement
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
146
app/views/promoter/events/new.html.erb
Normal file
146
app/views/promoter/events/new.html.erb
Normal file
@@ -0,0 +1,146 @@
|
||||
<% content_for(:title, "Créer un événement") %>
|
||||
|
||||
<div class="container py-8">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<div class="mb-8">
|
||||
<div class="flex items-center space-x-4">
|
||||
<%= link_to promoter_events_path, class: "text-gray-400 hover:text-gray-600 transition-colors" do %>
|
||||
<i data-lucide="arrow-left" class="w-5 h-5"></i>
|
||||
<% end %>
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2">Créer un événement</h1>
|
||||
<p class="text-gray-600">Remplissez les informations de votre événement</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= form_with model: [:promoter, @event], local: true, class: "space-y-8", data: { controller: "event-form" } do |form| %>
|
||||
<% if @event.errors.any? %>
|
||||
<div class="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div class="flex">
|
||||
<div class="flex-shrink-0">
|
||||
<i data-lucide="alert-circle" class="w-5 h-5 text-red-400"></i>
|
||||
</div>
|
||||
<div class="ml-3">
|
||||
<h3 class="text-sm font-medium text-red-800">
|
||||
<%= pluralize(@event.errors.count, "erreur") %> à corriger :
|
||||
</h3>
|
||||
<div class="mt-2 text-sm text-red-700">
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
<% @event.errors.full_messages.each do |message| %>
|
||||
<li><%= message %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Basic Information -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Informations générales</h3>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<%= 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" } %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" } %>
|
||||
<p class="mt-1 text-sm text-gray-500">Utilisé dans l'URL de l'événement</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<%= 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..." %>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<%= 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" %>
|
||||
<p class="mt-1 text-sm text-gray-500">URL de l'image de couverture de l'événement</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Date & Time -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Date et heure</h3>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Venue Information -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Lieu de l'événement</h3>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= 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" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-500">
|
||||
<i data-lucide="info" class="w-4 h-4 inline mr-1"></i>
|
||||
Utilisez un service comme <a href="https://www.latlong.net/" target="_blank" class="text-purple-600 hover:text-purple-800">latlong.net</a> pour obtenir les coordonnées GPS.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Options -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-6">Options</h3>
|
||||
|
||||
<div class="flex items-center">
|
||||
<%= 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" %>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">Les événements mis en avant apparaissent en premier sur la page d'accueil.</p>
|
||||
</div>
|
||||
|
||||
<!-- Actions -->
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-4">
|
||||
<%= link_to promoter_events_path, class: "text-gray-500 hover:text-gray-700 transition-colors" do %>
|
||||
Annuler
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<%= 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" %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
231
app/views/promoter/events/show.html.erb
Normal file
231
app/views/promoter/events/show.html.erb
Normal file
@@ -0,0 +1,231 @@
|
||||
<% content_for(:title, @event.name) %>
|
||||
|
||||
<div class="container py-8">
|
||||
<!-- Header with actions -->
|
||||
<div class="mb-8">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="flex items-center space-x-4">
|
||||
<%= link_to promoter_events_path, class: "text-gray-400 hover:text-gray-600 transition-colors" do %>
|
||||
<i data-lucide="arrow-left" class="w-5 h-5"></i>
|
||||
<% end %>
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2"><%= @event.name %></h1>
|
||||
<div class="flex items-center space-x-4 text-sm text-gray-500">
|
||||
<span class="flex items-center">
|
||||
<i data-lucide="calendar" class="w-4 h-4 mr-1"></i>
|
||||
<%= @event.start_time&.strftime("%d/%m/%Y à %H:%M") || "Date non définie" %>
|
||||
</span>
|
||||
<span class="flex items-center">
|
||||
<i data-lucide="map-pin" class="w-4 h-4 mr-1"></i>
|
||||
<%= @event.venue_name %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3">
|
||||
<%= 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 %>
|
||||
<i data-lucide="edit" class="w-4 h-4 mr-2"></i>
|
||||
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 %>
|
||||
<i data-lucide="upload" class="w-4 h-4 mr-2"></i>
|
||||
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 %>
|
||||
<i data-lucide="download" class="w-4 h-4 mr-2"></i>
|
||||
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 %>
|
||||
<i data-lucide="x-circle" class="w-4 h-4 mr-2"></i>
|
||||
Annuler
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status banner -->
|
||||
<div class="mb-8">
|
||||
<% case @event.state %>
|
||||
<% when "draft" %>
|
||||
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="edit-3" class="w-5 h-5 text-gray-400 mr-3"></i>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-gray-900">Événement en brouillon</h3>
|
||||
<p class="text-sm text-gray-500">Cet événement n'est pas visible publiquement. Publiez-le pour le rendre accessible aux utilisateurs.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% when "published" %>
|
||||
<div class="bg-green-50 border border-green-200 rounded-lg p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="eye" class="w-5 h-5 text-green-400 mr-3"></i>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-green-900">Événement publié</h3>
|
||||
<p class="text-sm text-green-700">Cet événement est visible publiquement et les utilisateurs peuvent acheter des billets.</p>
|
||||
</div>
|
||||
<div class="ml-auto">
|
||||
<%= link_to event_path(@event.slug, @event), target: "_blank", class: "text-green-600 hover:text-green-800 font-medium text-sm" do %>
|
||||
Voir publiquement <i data-lucide="external-link" class="w-4 h-4 inline ml-1"></i>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% when "canceled" %>
|
||||
<div class="bg-red-50 border border-red-200 rounded-lg p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="x-circle" class="w-5 h-5 text-red-400 mr-3"></i>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-red-900">Événement annulé</h3>
|
||||
<p class="text-sm text-red-700">Cet événement a été annulé et n'est plus accessible aux utilisateurs.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% when "sold_out" %>
|
||||
<div class="bg-blue-50 border border-blue-200 rounded-lg p-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="users" class="w-5 h-5 text-blue-400 mr-3"></i>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-blue-900">Événement complet</h3>
|
||||
<p class="text-sm text-blue-700">Tous les billets pour cet événement ont été vendus.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @event.featured? %>
|
||||
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-4 mt-4">
|
||||
<div class="flex items-center">
|
||||
<i data-lucide="star" class="w-5 h-5 text-yellow-400 mr-3"></i>
|
||||
<div>
|
||||
<h3 class="text-sm font-medium text-yellow-900">Événement à la une</h3>
|
||||
<p class="text-sm text-yellow-700">Cet événement est mis en avant sur la page d'accueil.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Event details -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<!-- Main content -->
|
||||
<div class="lg:col-span-2 space-y-8">
|
||||
<!-- Event image -->
|
||||
<% if @event.image.present? %>
|
||||
<div class="aspect-video bg-gray-100 rounded-lg overflow-hidden">
|
||||
<img src="<%= @event.image %>" alt="<%= @event.name %>" class="w-full h-full object-cover">
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Description -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Description</h3>
|
||||
<div class="prose prose-gray max-w-none">
|
||||
<%= simple_format(@event.description) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Location details -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Lieu</h3>
|
||||
<div class="space-y-3">
|
||||
<div class="flex items-start space-x-3">
|
||||
<i data-lucide="building" class="w-5 h-5 text-gray-400 mt-0.5"></i>
|
||||
<div>
|
||||
<p class="font-medium text-gray-900"><%= @event.venue_name %></p>
|
||||
<p class="text-gray-500"><%= @event.venue_address %></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-3 text-sm text-gray-500">
|
||||
<i data-lucide="map-pin" class="w-4 h-4"></i>
|
||||
<span><%= @event.latitude %>, <%= @event.longitude %></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="space-y-6">
|
||||
<!-- Event stats -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Statistiques</h3>
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-gray-500">Types de billets</span>
|
||||
<span class="font-medium"><%= @event.ticket_types.count %></span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-gray-500">Billets vendus</span>
|
||||
<span class="font-medium"><%= @event.tickets.count %></span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-gray-500">Revenus</span>
|
||||
<span class="font-medium">
|
||||
<%= number_to_currency(@event.tickets.sum(:price_cents) / 100.0, unit: "€") %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Event info -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Informations</h3>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<span class="text-sm text-gray-500">Slug</span>
|
||||
<p class="font-mono text-sm"><%= @event.slug %></p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-sm text-gray-500">Créé le</span>
|
||||
<p class="text-sm"><%= @event.created_at.strftime("%d/%m/%Y à %H:%M") %></p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-sm text-gray-500">Modifié le</span>
|
||||
<p class="text-sm"><%= @event.updated_at.strftime("%d/%m/%Y à %H:%M") %></p>
|
||||
</div>
|
||||
<% if @event.start_time %>
|
||||
<div>
|
||||
<span class="text-sm text-gray-500">Début</span>
|
||||
<p class="text-sm"><%= @event.start_time.strftime("%d/%m/%Y à %H:%M") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if @event.end_time %>
|
||||
<div>
|
||||
<span class="text-sm text-gray-500">Fin</span>
|
||||
<p class="text-sm"><%= @event.end_time.strftime("%d/%m/%Y à %H:%M") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick actions -->
|
||||
<div class="bg-white rounded-lg border border-gray-200 p-6">
|
||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Actions rapides</h3>
|
||||
<div class="space-y-3">
|
||||
<%= 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 %>
|
||||
<i data-lucide="ticket" class="w-4 h-4 mr-2"></i>
|
||||
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 %>
|
||||
<i data-lucide="users" class="w-4 h-4 mr-2"></i>
|
||||
Marquer comme complet
|
||||
<% end %>
|
||||
<hr class="border-gray-200">
|
||||
<%= 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 %>
|
||||
<i data-lucide="trash-2" class="w-4 h-4 mr-2"></i>
|
||||
Supprimer l'événement
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user