Compare commits
4 Commits
0a3a913f66
...
2aae7fe8ea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2aae7fe8ea | ||
|
|
b8efa1e26d | ||
|
|
9e6c48dc5c | ||
|
|
6e3413a128 |
@@ -4,8 +4,8 @@ require "rqrcode"
|
|||||||
|
|
||||||
# PDF ticket generator service using Prawn
|
# PDF ticket generator service using Prawn
|
||||||
#
|
#
|
||||||
# Generates PDF tickets with QR codes for event entry validation
|
# Generates simple, compact PDF tickets with QR codes for event entry validation
|
||||||
# Includes event details, venue information, and unique QR code for each ticket
|
# Clean, minimalist design that fits on a single page
|
||||||
class TicketPdfGenerator
|
class TicketPdfGenerator
|
||||||
# Suppress Prawn's internationalization warning for built-in fonts
|
# Suppress Prawn's internationalization warning for built-in fonts
|
||||||
Prawn::Fonts::AFM.hide_m17n_warning = true
|
Prawn::Fonts::AFM.hide_m17n_warning = true
|
||||||
@@ -20,14 +20,14 @@ class TicketPdfGenerator
|
|||||||
# Header
|
# Header
|
||||||
pdf.fill_color "2D1B69"
|
pdf.fill_color "2D1B69"
|
||||||
pdf.font "Helvetica", style: :bold, size: 24
|
pdf.font "Helvetica", style: :bold, size: 24
|
||||||
pdf.text "ApéroNight", align: :center
|
pdf.text ENV.fetch("APP_NAME", "Aperonight"), align: :center
|
||||||
pdf.move_down 10
|
pdf.move_down 10
|
||||||
|
|
||||||
# Event name
|
# Event name
|
||||||
pdf.fill_color "000000"
|
pdf.fill_color "000000"
|
||||||
pdf.font "Helvetica", style: :bold, size: 18
|
pdf.font "Helvetica", style: :bold, size: 18
|
||||||
pdf.text ticket.event.name, align: :center
|
pdf.text ticket.event.name, align: :center
|
||||||
pdf.move_down 20
|
pdf.move_down 10
|
||||||
|
|
||||||
# Ticket info box
|
# Ticket info box
|
||||||
pdf.stroke_color "E5E7EB"
|
pdf.stroke_color "E5E7EB"
|
||||||
@@ -40,21 +40,29 @@ class TicketPdfGenerator
|
|||||||
pdf.font "Helvetica", size: 12
|
pdf.font "Helvetica", size: 12
|
||||||
|
|
||||||
# Customer name
|
# Customer name
|
||||||
pdf.text "Ticket Holder:", style: :bold
|
pdf.indent 10 do
|
||||||
pdf.text "#{ticket.first_name} #{ticket.last_name}"
|
pdf.text "Ticket Holder:", style: :bold
|
||||||
|
pdf.text "#{ticket.first_name} #{ticket.last_name}"
|
||||||
|
end
|
||||||
pdf.move_down 8
|
pdf.move_down 8
|
||||||
|
|
||||||
# Ticket details
|
# Ticket details
|
||||||
pdf.text "Ticket Type:", style: :bold
|
pdf.indent 10 do
|
||||||
pdf.text ticket.ticket_type.name
|
pdf.text "Ticket Type:", style: :bold
|
||||||
|
pdf.text ticket.ticket_type.name
|
||||||
|
end
|
||||||
pdf.move_down 8
|
pdf.move_down 8
|
||||||
|
|
||||||
pdf.text "Price:", style: :bold
|
pdf.indent 10 do
|
||||||
pdf.text "€#{ticket.price_euros}"
|
pdf.text "Price:", style: :bold
|
||||||
|
pdf.text "€#{ticket.price_euros}"
|
||||||
|
end
|
||||||
pdf.move_down 8
|
pdf.move_down 8
|
||||||
|
|
||||||
pdf.text "Date & Time:", style: :bold
|
pdf.indent 10 do
|
||||||
pdf.text ticket.event.start_time.strftime("%B %d, %Y at %I:%M %p")
|
pdf.text "Date & Time:", style: :bold
|
||||||
|
pdf.text ticket.event.start_time.strftime("%B %d, %Y at %I:%M %p")
|
||||||
|
end
|
||||||
pdf.move_down 20
|
pdf.move_down 20
|
||||||
|
|
||||||
# Venue information
|
# Venue information
|
||||||
@@ -71,7 +79,7 @@ class TicketPdfGenerator
|
|||||||
# QR Code
|
# QR Code
|
||||||
pdf.fill_color "000000"
|
pdf.fill_color "000000"
|
||||||
pdf.font "Helvetica", style: :bold, size: 14
|
pdf.font "Helvetica", style: :bold, size: 14
|
||||||
pdf.text "Ticket QR Code", align: :center
|
pdf.text "QR Code", align: :center
|
||||||
pdf.move_down 10
|
pdf.move_down 10
|
||||||
|
|
||||||
# Ensure all required data is present before generating QR code
|
# Ensure all required data is present before generating QR code
|
||||||
@@ -102,13 +110,19 @@ class TicketPdfGenerator
|
|||||||
# QR code text
|
# QR code text
|
||||||
pdf.font "Helvetica", size: 8
|
pdf.font "Helvetica", size: 8
|
||||||
pdf.fill_color "6B7280"
|
pdf.fill_color "6B7280"
|
||||||
pdf.text "QR Code: #{ticket.qr_code[0..7]}...", align: :center
|
pdf.text "#{ticket.qr_code}", align: :center
|
||||||
|
|
||||||
|
|
||||||
|
# Ticket ID
|
||||||
|
pdf.font "Helvetica", size: 8
|
||||||
|
pdf.fill_color "6B7280"
|
||||||
|
pdf.text "Ticket ID: #{ticket.id}", align: :center
|
||||||
|
|
||||||
# Footer
|
# Footer
|
||||||
pdf.move_down 30
|
pdf.move_down 30
|
||||||
pdf.stroke_color "E5E7EB"
|
pdf.stroke_color "E5E7EB"
|
||||||
pdf.horizontal_line 0, 310
|
pdf.horizontal_line 0, 310
|
||||||
pdf.move_down 10
|
pdf.move_down 6
|
||||||
|
|
||||||
pdf.font "Helvetica", size: 8
|
pdf.font "Helvetica", size: 8
|
||||||
pdf.fill_color "6B7280"
|
pdf.fill_color "6B7280"
|
||||||
@@ -121,6 +135,136 @@ class TicketPdfGenerator
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def create_simple_header(pdf)
|
||||||
|
# Brand name
|
||||||
|
pdf.fill_color "6366F1"
|
||||||
|
pdf.font "Helvetica", style: :bold, size: 24
|
||||||
|
pdf.text "AperoNight", align: :center
|
||||||
|
|
||||||
|
pdf.move_down 5
|
||||||
|
pdf.font "Helvetica", size: 10
|
||||||
|
pdf.fill_color "64748B"
|
||||||
|
pdf.text "Billet d'entree", align: :center
|
||||||
|
|
||||||
|
pdf.move_down 20
|
||||||
|
|
||||||
|
# Simple divider line
|
||||||
|
pdf.stroke_color "E5E7EB"
|
||||||
|
pdf.horizontal_line 0, pdf.bounds.width
|
||||||
|
pdf.move_down 20
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_ticket_info(pdf)
|
||||||
|
# Event name - prominent
|
||||||
|
pdf.fill_color "1F2937"
|
||||||
|
pdf.font "Helvetica", style: :bold, size: 18
|
||||||
|
pdf.text ticket.event.name, align: :center
|
||||||
|
pdf.move_down 15
|
||||||
|
|
||||||
|
# Two-column layout for ticket details
|
||||||
|
pdf.bounding_box([0, pdf.cursor], width: pdf.bounds.width, height: 120) do
|
||||||
|
# Left column
|
||||||
|
pdf.bounding_box([0, pdf.cursor], width: pdf.bounds.width / 2 - 20, height: 120) do
|
||||||
|
create_info_item(pdf, "Date", ticket.event.start_time.strftime("%d %B %Y"))
|
||||||
|
create_info_item(pdf, "Heure", ticket.event.start_time.strftime("%H:%M"))
|
||||||
|
create_info_item(pdf, "Lieu", ticket.event.venue_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Right column
|
||||||
|
pdf.bounding_box([pdf.bounds.width / 2 + 20, pdf.cursor], width: pdf.bounds.width / 2 - 20, height: 120) do
|
||||||
|
create_info_item(pdf, "Type", ticket.ticket_type.name)
|
||||||
|
create_info_item(pdf, "Prix", "#{sprintf('%.2f', ticket.price_euros)} EUR")
|
||||||
|
create_info_item(pdf, "Titulaire", "#{ticket.first_name} #{ticket.last_name}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pdf.move_down 30
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_info_item(pdf, label, value)
|
||||||
|
pdf.font "Helvetica", style: :bold, size: 9
|
||||||
|
pdf.fill_color "64748B"
|
||||||
|
pdf.text label.upcase
|
||||||
|
|
||||||
|
pdf.move_down 2
|
||||||
|
pdf.font "Helvetica", size: 11
|
||||||
|
pdf.fill_color "1F2937"
|
||||||
|
pdf.text value
|
||||||
|
pdf.move_down 12
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_qr_section(pdf)
|
||||||
|
# Center the QR code horizontally
|
||||||
|
qr_size = 120
|
||||||
|
x_position = (pdf.bounds.width - qr_size) / 2
|
||||||
|
|
||||||
|
pdf.bounding_box([x_position, pdf.cursor], width: qr_size, height: qr_size + 40) do
|
||||||
|
# QR Code title
|
||||||
|
pdf.font "Helvetica", style: :bold, size: 12
|
||||||
|
pdf.fill_color "1F2937"
|
||||||
|
pdf.text "Code d'entree", align: :center
|
||||||
|
pdf.move_down 10
|
||||||
|
|
||||||
|
# Generate QR code
|
||||||
|
generate_simple_qr_code(pdf, qr_size)
|
||||||
|
|
||||||
|
pdf.move_down 10
|
||||||
|
|
||||||
|
# QR code ID
|
||||||
|
pdf.font "Helvetica", size: 8
|
||||||
|
pdf.fill_color "64748B"
|
||||||
|
pdf.text "ID: #{ticket.qr_code[0..15]}...", align: :center
|
||||||
|
end
|
||||||
|
|
||||||
|
pdf.move_down 40
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_simple_qr_code(pdf, size)
|
||||||
|
# Ensure all required data is present before generating QR code
|
||||||
|
if ticket.qr_code.blank?
|
||||||
|
raise "Ticket QR code is missing"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Build QR code data with safe association loading
|
||||||
|
qr_code_data = build_qr_code_data(ticket)
|
||||||
|
|
||||||
|
# Validate QR code data before creating QR code
|
||||||
|
if qr_code_data.blank? || qr_code_data == "{}"
|
||||||
|
Rails.logger.error "QR code data is empty: ticket_id=#{ticket.id}, qr_code=#{ticket.qr_code}, event_id=#{ticket.ticket_type&.event_id}, user_id=#{ticket.order&.user_id}"
|
||||||
|
raise "QR code data is empty or invalid"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Ensure qr_code_data is a proper string for QR code generation
|
||||||
|
unless qr_code_data.is_a?(String) && qr_code_data.length > 2
|
||||||
|
Rails.logger.error "QR code data is not a valid string: #{qr_code_data.inspect} (class: #{qr_code_data.class})"
|
||||||
|
raise "QR code data must be a valid string"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate QR code
|
||||||
|
pdf.print_qr_code(qr_code_data, extent: size, align: :center)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_simple_footer(pdf)
|
||||||
|
# Security notice
|
||||||
|
pdf.font "Helvetica", size: 8
|
||||||
|
pdf.fill_color "64748B"
|
||||||
|
pdf.text "Ce billet est valable pour une seule entree.", align: :center
|
||||||
|
pdf.text "Presentez ce code QR a l'entree de l'evenement.", align: :center
|
||||||
|
|
||||||
|
pdf.move_down 10
|
||||||
|
|
||||||
|
# Divider line
|
||||||
|
pdf.stroke_color "E5E7EB"
|
||||||
|
pdf.horizontal_line 0, pdf.bounds.width
|
||||||
|
pdf.move_down 5
|
||||||
|
|
||||||
|
# Generation timestamp
|
||||||
|
pdf.font "Helvetica", size: 7
|
||||||
|
pdf.fill_color "9CA3AF"
|
||||||
|
timestamp = "Genere le #{Time.current.strftime('%d/%m/%Y a %H:%M')}"
|
||||||
|
pdf.text timestamp, align: :center
|
||||||
|
end
|
||||||
|
|
||||||
def build_qr_code_data(ticket)
|
def build_qr_code_data(ticket)
|
||||||
# Try multiple approaches to get valid QR code data
|
# Try multiple approaches to get valid QR code data
|
||||||
begin
|
begin
|
||||||
@@ -150,4 +294,4 @@ class TicketPdfGenerator
|
|||||||
# Final fallback: simple ticket identifier
|
# Final fallback: simple ticket identifier
|
||||||
"TICKET-#{ticket.id}"
|
"TICKET-#{ticket.id}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Vos billets
|
Vos billets
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<% @tickets.each do |ticket| %>
|
<% @tickets.each do |ticket| %>
|
||||||
<div class="bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl border border-purple-100 p-5">
|
<div class="bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl border border-purple-100 p-5">
|
||||||
@@ -82,9 +82,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<%= link_to download_ticket_path(ticket, format: :pdf),
|
<%= link_to ticket_download_path(ticket.qr_code, format: :pdf),
|
||||||
class: "inline-flex items-center px-4 py-2 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-lg hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
class: "inline-flex items-center px-4 py-2 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-lg hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
||||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 pt-4 border-t border-purple-100 flex items-center justify-between">
|
<div class="mt-4 pt-4 border-t border-purple-100 flex items-center justify-between">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<svg class="w-4 h-4 text-gray-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 text-gray-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<h3 class="font-bold text-blue-800 mb-1">Important</h3>
|
<h3 class="font-bold text-blue-800 mb-1">Important</h3>
|
||||||
<p class="text-sm text-blue-700">
|
<p class="text-sm text-blue-700">
|
||||||
Veuillez télécharger et sauvegarder vos billets. Présentez-les à l'entrée du lieu pour accéder à l'événement.
|
Veuillez télécharger et sauvegarder vos billets. Présentez-les à l'entrée du lieu pour accéder à l'événement.
|
||||||
Un email de confirmation avec vos billets a été envoyé à votre adresse email.
|
Un email de confirmation avec vos billets a été envoyé à votre adresse email.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -128,15 +128,15 @@
|
|||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
<%= link_to dashboard_path,
|
<%= link_to dashboard_path,
|
||||||
class: "inline-flex items-center justify-center px-6 py-3 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-xl hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 font-medium shadow-sm" do %>
|
class: "inline-flex items-center justify-center px-6 py-3 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-xl hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 font-medium shadow-sm" do %>
|
||||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Tableau de bord
|
Tableau de bord
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= link_to events_path,
|
<%= link_to events_path,
|
||||||
class: "inline-flex items-center justify-center px-6 py-3 bg-white text-gray-700 rounded-xl border border-gray-300 hover:bg-gray-50 transition-all duration-200 font-medium shadow-sm" do %>
|
class: "inline-flex items-center justify-center px-6 py-3 bg-white text-gray-700 rounded-xl border border-gray-300 hover:bg-gray-50 transition-all duration-200 font-medium shadow-sm" do %>
|
||||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||||
@@ -147,4 +147,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<!-- Tickets List -->
|
<!-- Tickets List -->
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<h3 class="text-lg font-semibold text-gray-900 mb-4">Vos billets</h3>
|
<h3 class="text-lg font-semibold text-gray-900 mb-4">Vos billets</h3>
|
||||||
|
|
||||||
<% @order.tickets.each do |ticket| %>
|
<% @order.tickets.each do |ticket| %>
|
||||||
<div class="flex items-center justify-between py-3 border-b border-gray-100 last:border-b-0">
|
<div class="flex items-center justify-between py-3 border-b border-gray-100 last:border-b-0">
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
<p class="text-gray-600 text-sm mb-3">Gardez vos billets sur votre téléphone ou imprimez-les.</p>
|
<p class="text-gray-600 text-sm mb-3">Gardez vos billets sur votre téléphone ou imprimez-les.</p>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<% @order.tickets.each do |ticket| %>
|
<% @order.tickets.each do |ticket| %>
|
||||||
<%= link_to download_ticket_path(ticket), class: "inline-flex items-center px-3 py-2 border border-purple-300 rounded-md text-sm font-medium text-purple-700 bg-purple-50 hover:bg-purple-100 transition-colors mr-2 mb-2" do %>
|
<%= link_to ticket_download_path(ticket.qr_code), class: "inline-flex items-center px-3 py-2 border border-purple-300 rounded-md text-sm font-medium text-purple-700 bg-purple-50 hover:bg-purple-100 transition-colors mr-2 mb-2" do %>
|
||||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/>
|
||||||
</svg>
|
</svg>
|
||||||
@@ -188,4 +188,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Vos billets
|
Vos billets
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<% @tickets.each do |ticket| %>
|
<% @tickets.each do |ticket| %>
|
||||||
<div class="bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl border border-purple-100 p-5">
|
<div class="bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl border border-purple-100 p-5">
|
||||||
@@ -82,9 +82,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center space-x-2">
|
<div class="flex items-center space-x-2">
|
||||||
<%= link_to download_ticket_path(ticket, format: :pdf),
|
<%= link_to ticket_download_path(ticket.qr_code, format: :pdf),
|
||||||
class: "inline-flex items-center px-4 py-2 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-lg hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
class: "inline-flex items-center px-4 py-2 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-lg hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 text-sm font-medium shadow-sm" do %>
|
||||||
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 pt-4 border-t border-purple-100 flex items-center justify-between">
|
<div class="mt-4 pt-4 border-t border-purple-100 flex items-center justify-between">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<svg class="w-4 h-4 text-gray-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-4 h-4 text-gray-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<h3 class="font-bold text-blue-800 mb-1">Important</h3>
|
<h3 class="font-bold text-blue-800 mb-1">Important</h3>
|
||||||
<p class="text-sm text-blue-700">
|
<p class="text-sm text-blue-700">
|
||||||
Veuillez télécharger et sauvegarder vos billets. Présentez-les à l'entrée du lieu pour accéder à l'événement.
|
Veuillez télécharger et sauvegarder vos billets. Présentez-les à l'entrée du lieu pour accéder à l'événement.
|
||||||
Un email de confirmation avec vos billets a été envoyé à votre adresse email.
|
Un email de confirmation avec vos billets a été envoyé à votre adresse email.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -128,15 +128,15 @@
|
|||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
<div class="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
<%= link_to dashboard_path,
|
<%= link_to dashboard_path,
|
||||||
class: "inline-flex items-center justify-center px-6 py-3 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-xl hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 font-medium shadow-sm" do %>
|
class: "inline-flex items-center justify-center px-6 py-3 bg-gradient-to-r from-purple-600 to-indigo-600 text-white rounded-xl hover:from-purple-700 hover:to-indigo-700 transition-all duration-200 font-medium shadow-sm" do %>
|
||||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"></path>
|
||||||
</svg>
|
</svg>
|
||||||
Tableau de bord
|
Tableau de bord
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= link_to events_path,
|
<%= link_to events_path,
|
||||||
class: "inline-flex items-center justify-center px-6 py-3 bg-white text-gray-700 rounded-xl border border-gray-300 hover:bg-gray-50 transition-all duration-200 font-medium shadow-sm" do %>
|
class: "inline-flex items-center justify-center px-6 py-3 bg-white text-gray-700 rounded-xl border border-gray-300 hover:bg-gray-50 transition-all duration-200 font-medium shadow-sm" do %>
|
||||||
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||||
@@ -147,4 +147,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user