fix: Update views and controllers for event image display

Update all event-related view templates and controllers to properly handle and display event images throughout the application.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
kbe
2025-10-01 08:12:47 +02:00
parent 6be8b95ed3
commit 20dcee0a5b
10 changed files with 66 additions and 26 deletions

View File

@@ -88,6 +88,7 @@ module Api
latitude: event.latitude, latitude: event.latitude,
longitude: event.longitude, longitude: event.longitude,
featured: event.featured, featured: event.featured,
image_url: event.display_image_url,
created_at: event.created_at, created_at: event.created_at,
updated_at: event.updated_at, updated_at: event.updated_at,
user: { user: {

View File

@@ -45,6 +45,8 @@ class Promoter::EventsController < ApplicationController
if @event.update(event_params) if @event.update(event_params)
redirect_to promoter_event_path(@event), notice: "Event mis à jour avec succès!" redirect_to promoter_event_path(@event), notice: "Event mis à jour avec succès!"
else else
# If validation fails and a new image was attached, purge it
@event.image.purge if @event.image.attached? && @event.changed.include?('image')
render :edit, status: :unprocessable_entity render :edit, status: :unprocessable_entity
end end
end end

View File

@@ -27,6 +27,7 @@ class Event < ApplicationRecord
# === Callbacks === # === Callbacks ===
before_validation :geocode_address, if: :should_geocode_address? before_validation :geocode_address, if: :should_geocode_address?
before_update :handle_image_replacement, if: :image_attached?
# Validations for Event attributes # Validations for Event attributes
# Basic information # Basic information
@@ -61,8 +62,26 @@ class Event < ApplicationRecord
# === Instance Methods === # === Instance Methods ===
# Get image URL prioritizing old image field if it exists
def display_image_url
# First check if old image field exists and has a value
return self[:image] if self[:image].present?
# Fall back to attached image
return nil unless image.attached?
# Return the URL for the attached image
Rails.application.routes.url_helpers.rails_blob_url(image, only_path: true)
end
# Get image variants for different display sizes # Get image variants for different display sizes
def event_image_variant(size = :medium) def event_image_variant(size = :medium)
# For old image field, return the URL directly
return self[:image] if self[:image].present?
# For attached images, process variants
return nil unless image.attached?
case size case size
when :large when :large
image.variant(resize_to_limit: [1200, 630]) image.variant(resize_to_limit: [1200, 630])
@@ -75,6 +94,11 @@ class Event < ApplicationRecord
end end
end end
# Check if event has any image (old field or attached)
def has_image?
self[:image].present? || image.attached?
end
# Check if coordinates were successfully geocoded or are fallback coordinates # Check if coordinates were successfully geocoded or are fallback coordinates
def geocoding_successful? def geocoding_successful?
coordinates_look_valid? coordinates_look_valid?
@@ -169,6 +193,19 @@ class Event < ApplicationRecord
private private
# Check if image is attached for the callback
def image_attached?
image.attached?
end
# Handle image replacement when a new image is uploaded
def handle_image_replacement
# Clear the old image field if a new image is being attached
if image.attached?
self[:image] = nil
end
end
# Determine if we should perform server-side geocoding # Determine if we should perform server-side geocoding
def should_geocode_address? def should_geocode_address?
# Don't geocode if address is blank # Don't geocode if address is blank

View File

@@ -1,7 +1,7 @@
<%= link_to event_path(event.slug, event), class: "group block p-4 rounded-lg border border-slate-200 dark:border-slate-700 hover:border-purple-300 dark:hover:border-purple-600 hover:shadow-md transition-all duration-200" do %> <%= link_to event_path(event.slug, event), class: "group block p-4 rounded-lg border border-slate-200 dark:border-slate-700 hover:border-purple-300 dark:hover:border-purple-600 hover:shadow-md transition-all duration-200" do %>
<div class="flex items-center space-x-4"> <div class="flex items-center space-x-4">
<div class="w-16 h-16 bg-slate-200 dark:bg-slate-700 rounded-lg overflow-hidden flex-shrink-0"> <div class="w-16 h-16 bg-slate-200 dark:bg-slate-700 rounded-lg overflow-hidden flex-shrink-0">
<%= image_tag event.event_image_variant(:small), alt: event.name, class: "w-full h-full object-cover" if event.image.attached? %> <%= image_tag event.event_image_variant(:small), alt: event.name, class: "w-full h-full object-cover" if event.has_image? %>
</div> </div>
<div class="flex-1 min-w-0"> <div class="flex-1 min-w-0">
<h3 class="text-lg font-semibold text-slate-900 dark:text-slate-100 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors duration-200"> <h3 class="text-lg font-semibold text-slate-900 dark:text-slate-100 group-hover:text-purple-600 dark:group-hover:text-purple-400 transition-colors duration-200">

View File

@@ -22,7 +22,7 @@
<% @events.each do |event| %> <% @events.each do |event| %>
<article class="group bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 overflow-hidden transform hover:-translate-y-1"> <article class="group bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 overflow-hidden transform hover:-translate-y-1">
<%= link_to event_path(event.slug, event), class: "block" do %> <%= link_to event_path(event.slug, event), class: "block" do %>
<% if event.image.attached? %> <% if event.has_image? %>
<div class="relative overflow-hidden aspect-[4/3]"> <div class="relative overflow-hidden aspect-[4/3]">
<%= image_tag event.event_image_variant(:medium), alt: event.name, class: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" %> <%= image_tag event.event_image_variant(:medium), alt: event.name, class: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" %>
<!-- Event featured badge --> <!-- Event featured badge -->

View File

@@ -10,7 +10,7 @@
<!-- Event main wrapper --> <!-- Event main wrapper -->
<div class="bg-white rounded-2xl shadow-xl overflow-hidden"> <div class="bg-white rounded-2xl shadow-xl overflow-hidden">
<!-- Event Header with Image --> <!-- Event Header with Image -->
<% if @event.image.attached? %> <% if @event.has_image? %>
<div class="relative h-96"> <div class="relative h-96">
<%= image_tag @event.event_image_variant(:large), class: "w-full h-full object-cover" %> <%= image_tag @event.event_image_variant(:large), class: "w-full h-full object-cover" %>
<div class="absolute inset-0 bg-gradient-to-t from-black via-black/70 to-transparent"></div> <div class="absolute inset-0 bg-gradient-to-t from-black via-black/70 to-transparent"></div>
@@ -88,11 +88,7 @@
%> %>
<% map_providers.each do |name, url| %> <% map_providers.each do |name, url| %>
<%= link_to url, target: "_blank", rel: "noopener", <%= link_to "#{icons[name]} #{name}".html_safe, url, target: "_blank", rel: "noopener", class: "inline-flex items-center px-3 py-2 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors" %>
class: "inline-flex items-center px-3 py-2 text-xs font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors" do %>
<span class="mr-1"><%= icons[name] %></span>
<%= name %>
<% end %>
<% end %> <% end %>
</div> </div>
</div> </div>
@@ -131,14 +127,7 @@
<!-- Right Column: Ticket Selection --> <!-- Right Column: Ticket Selection -->
<div class="lg:col-span-1"> <div class="lg:col-span-1">
<%= form_with url: event_order_new_path(@event.slug, @event.id), method: :get, id: "checkout_form", local: true, data: { <%= form_with url: event_order_new_path(@event.slug, @event.id), method: :get, id: "checkout_form", local: true, data: { controller: "ticket-selection", ticket_selection_target: "form", ticket_selection_event_slug_value: @event.slug, ticket_selection_event_id_value: @event.id, ticket_selection_order_new_url_value: event_order_new_path(@event.slug, @event.id), ticket_selection_store_cart_url_value: api_v1_store_cart_path } do |form| %>
controller: "ticket-selection",
ticket_selection_target: "form",
ticket_selection_event_slug_value: @event.slug,
ticket_selection_event_id_value: @event.id,
ticket_selection_order_new_url_value: event_order_new_path(@event.slug, @event.id),
ticket_selection_store_cart_url_value: api_v1_store_cart_path
} do |form| %>
<div class="bg-gradient-to-br from-purple-50 to-indigo-50 rounded-2xl border border-purple-100 p-6 shadow-sm"> <div class="bg-gradient-to-br from-purple-50 to-indigo-50 rounded-2xl border border-purple-100 p-6 shadow-sm">
<div class="flex justify-center sm:justify-start mb-6"> <div class="flex justify-center sm:justify-start mb-6">

View File

@@ -89,7 +89,7 @@
<div class="bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 overflow-hidden"> <div class="bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 overflow-hidden">
<!-- Event Image --> <!-- Event Image -->
<div class="relative overflow-hidden aspect-[4/3]"> <div class="relative overflow-hidden aspect-[4/3]">
<% if event.image.attached? %> <% if event.has_image? %>
<%= image_tag event.event_image_variant(:medium), alt: event.name, class: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" %> <%= image_tag event.event_image_variant(:medium), alt: event.name, class: "w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" %>
<% else %> <% else %>
<div class="w-full h-full bg-gradient-to-br from-purple-600 to-blue-600 flex items-center justify-center"> <div class="w-full h-full bg-gradient-to-br from-purple-600 to-blue-600 flex items-center justify-center">

View File

@@ -70,12 +70,23 @@
<%= form.label :image, "Image de couverture", class: "block text-sm font-medium text-gray-700 mb-2" %> <%= form.label :image, "Image de couverture", class: "block text-sm font-medium text-gray-700 mb-2" %>
<div class="space-y-4"> <div class="space-y-4">
<!-- Current image preview --> <!-- Current image preview -->
<% if @event.image.attached? %> <% if @event.has_image? %>
<div class="relative"> <div class="flex items-start space-x-4">
<%= image_tag @event.image.variant(resize_to_limit: [400, 225]), class: "w-full h-48 object-cover rounded-lg border border-gray-200" %> <div class="flex-shrink-0">
<div class="absolute top-2 right-2"> <% if @event.event_image_variant(:small).is_a?(String) %>
<button type="button" onclick="this.closest('div').querySelector('input[type=file]').click()" class="bg-red-500 text-white p-2 rounded-full hover:bg-red-600 transition-colors"> <!-- Old image field -->
<i data-lucide="trash-2" class="w-4 h-4"></i> <%= image_tag @event.event_image_variant(:small), class: "w-32 h-24 object-cover rounded-lg border border-gray-200" %>
<% else %>
<!-- Attached image -->
<%= image_tag @event.event_image_variant(:small), class: "w-32 h-24 object-cover rounded-lg border border-gray-200" %>
<% end %>
</div>
<div class="flex-1 min-w-0">
<p class="text-sm font-medium text-gray-900 mb-1">Image actuelle</p>
<p class="text-sm text-gray-600 mb-2">Uploader une nouvelle image pour la remplacer.</p>
<button type="button" onclick="this.closest('div').querySelector('input[type=file]').click()" class="bg-red-500 text-white p-2 rounded-lg hover:bg-red-600 transition-colors inline-flex items-center">
<i data-lucide="trash-2" class="w-4 h-4 mr-1"></i>
<span>Remplacer l'image</span>
</button> </button>
</div> </div>
</div> </div>
@@ -86,7 +97,7 @@
<%= form.file_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 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-purple-50 file:text-purple-700 hover:file:bg-purple-100", accept: "image/png,image/jpeg,image/jpg,image/webp", data: { action: "change->event-form#previewImage" } %> <%= form.file_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 file:mr-4 file:py-2 file:px-4 file:rounded-lg file:border-0 file:text-sm file:font-semibold file:bg-purple-50 file:text-purple-700 hover:file:bg-purple-100", accept: "image/png,image/jpeg,image/jpg,image/webp", data: { action: "change->event-form#previewImage" } %>
<div class="mt-1 text-sm text-gray-500"> <div class="mt-1 text-sm text-gray-500">
Formats acceptés : PNG, JPG, JPEG, WebP (max 5MB) Formats acceptés : PNG, JPG, JPEG, WebP (max 5MB)
<% if @event.image.attached? %> <% if @event.has_image? %>
<br>Laissez vide pour conserver l'image actuelle <br>Laissez vide pour conserver l'image actuelle
<% end %> <% end %>
</div> </div>

View File

@@ -63,7 +63,7 @@
<%= form.label :image, "Image de couverture", class: "block text-sm font-medium text-gray-700 mb-2" %> <%= form.label :image, "Image de couverture", class: "block text-sm font-medium text-gray-700 mb-2" %>
<div class="space-y-4"> <div class="space-y-4">
<!-- Current image preview (for edit mode) --> <!-- Current image preview (for edit mode) -->
<% if @event.image.attached? %> <% if @event.has_image? %>
<div class="relative"> <div class="relative">
<%= image_tag @event.image.variant(resize_to_limit: [400, 225]), class: "w-full h-48 object-cover rounded-lg border border-gray-200" %> <%= image_tag @event.image.variant(resize_to_limit: [400, 225]), class: "w-full h-48 object-cover rounded-lg border border-gray-200" %>
<div class="absolute top-2 right-2"> <div class="absolute top-2 right-2">

View File

@@ -174,7 +174,7 @@
<!-- Main content --> <!-- Main content -->
<div class="lg:col-span-2 space-y-6 lg:space-y-8"> <div class="lg:col-span-2 space-y-6 lg:space-y-8">
<!-- Event image --> <!-- Event image -->
<% if @event.image.attached? %> <% if @event.has_image? %>
<div class="aspect-video bg-gray-100 rounded-2xl overflow-hidden"> <div class="aspect-video bg-gray-100 rounded-2xl overflow-hidden">
<%= image_tag @event.event_image_variant(:large), alt: @event.name, class: "w-full h-full object-cover" %> <%= image_tag @event.event_image_variant(:large), alt: @event.name, class: "w-full h-full object-cover" %>
</div> </div>