Compare commits
10 Commits
839120f2f4
...
e1edc1afcd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1edc1afcd | ||
|
|
bd6c0d5ed8 | ||
|
|
5fc790cd42 | ||
|
|
ec5095d372 | ||
|
|
31f5d2188d | ||
|
|
e866e259bb | ||
|
|
54e99c2f7e | ||
|
|
3ba5710d8f | ||
|
|
0f6d75b1e8 | ||
|
|
ee4399aa46 |
@@ -9,44 +9,7 @@
|
||||
/* Import components */
|
||||
@import "components/hero";
|
||||
@import "components/flash";
|
||||
@import "components/footer";
|
||||
@import "components/event-finder";
|
||||
|
||||
/* Import pages */
|
||||
@import "pages/home";
|
||||
|
||||
/* Base styles */
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
line-height: 1.6;
|
||||
color: var(--color-neutral-900);
|
||||
background: var(--color-neutral-50);
|
||||
}
|
||||
|
||||
/* App wrapper */
|
||||
.app-wrapper {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Main content */
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
background: var(--color-neutral-800);
|
||||
color: var(--color-neutral-300);
|
||||
}
|
||||
|
||||
/* Flash messages */
|
||||
.flash {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Yield content */
|
||||
.yield {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,9 @@
|
||||
# This controller manages all events. It load events for homepage
|
||||
# and display for pagination.
|
||||
class EventsController < ApplicationController
|
||||
include StripeConcern
|
||||
|
||||
before_action :authenticate_user!, only: [ :checkout, :process_names, :download_ticket ]
|
||||
before_action :set_event, only: [ :show, :checkout, :process_names ]
|
||||
before_action :authenticate_user!, only: [ ]
|
||||
before_action :set_event, only: [ :show ]
|
||||
|
||||
# Display all events
|
||||
def index
|
||||
@@ -20,199 +19,13 @@ class EventsController < ApplicationController
|
||||
# Event is set by set_event callback
|
||||
end
|
||||
|
||||
# Handle checkout process - Collect names if needed or create Stripe session
|
||||
def checkout
|
||||
# Convert cart parameter to proper hash
|
||||
cart_param = params[:cart]
|
||||
cart_data = if cart_param.is_a?(String)
|
||||
JSON.parse(cart_param)
|
||||
elsif cart_param.is_a?(ActionController::Parameters)
|
||||
cart_param.to_unsafe_h
|
||||
else
|
||||
{}
|
||||
end
|
||||
|
||||
if cart_data.empty?
|
||||
redirect_to event_path(@event.slug, @event), alert: "Veuillez sélectionner au moins un billet"
|
||||
return
|
||||
end
|
||||
|
||||
# Check if any ticket types require names
|
||||
requires_names = false
|
||||
cart_data.each do |ticket_type_id, item|
|
||||
ticket_type = @event.ticket_types.find_by(id: ticket_type_id)
|
||||
next unless ticket_type
|
||||
|
||||
quantity = item["quantity"].to_i
|
||||
next if quantity <= 0
|
||||
|
||||
if ticket_type.requires_id
|
||||
requires_names = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# If names are required, redirect to name collection
|
||||
if requires_names
|
||||
session[:pending_cart] = cart_data
|
||||
redirect_to event_collect_names_path(@event.slug, @event)
|
||||
return
|
||||
end
|
||||
|
||||
# Otherwise proceed directly to payment
|
||||
process_payment(cart_data)
|
||||
end
|
||||
|
||||
|
||||
# Process submitted names and create Stripe session
|
||||
def process_names
|
||||
Rails.logger.debug "Processing names for event: #{@event.id}"
|
||||
|
||||
cart_data = session[:pending_cart] || {}
|
||||
|
||||
if cart_data.empty?
|
||||
Rails.logger.debug "Cart data is empty"
|
||||
redirect_to event_path(@event.slug, @event), alert: "Veuillez sélectionner au moins un billet"
|
||||
return
|
||||
end
|
||||
|
||||
# Store names in session for later use
|
||||
if params[:ticket_names].present?
|
||||
# Convert ActionController::Parameters to hash
|
||||
if params[:ticket_names].is_a?(ActionController::Parameters)
|
||||
session[:ticket_names] = params[:ticket_names].to_unsafe_h
|
||||
else
|
||||
session[:ticket_names] = params[:ticket_names]
|
||||
end
|
||||
end
|
||||
|
||||
Rails.logger.debug "Proceeding to payment with cart data: #{cart_data}"
|
||||
# Proceed to payment
|
||||
process_payment(cart_data)
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Download ticket PDF
|
||||
def download_ticket
|
||||
@ticket = current_user.tickets.find(params[:ticket_id])
|
||||
|
||||
respond_to do |format|
|
||||
format.pdf do
|
||||
pdf = @ticket.to_pdf
|
||||
send_data pdf,
|
||||
filename: "ticket-#{@ticket.event.name.parameterize}-#{@ticket.qr_code[0..7]}.pdf",
|
||||
type: "application/pdf",
|
||||
disposition: "attachment"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Set the current event in the controller
|
||||
#
|
||||
# Expose the current @event property to method
|
||||
def set_event
|
||||
@event = Event.includes(:ticket_types).find(params[:id])
|
||||
end
|
||||
|
||||
# Process payment and create Stripe session
|
||||
def process_payment(cart_data)
|
||||
Rails.logger.debug "Starting process_payment method"
|
||||
Rails.logger.debug "Cart data: #{cart_data}"
|
||||
|
||||
# Create order items from cart
|
||||
line_items = []
|
||||
order_items = []
|
||||
total_amount = 0
|
||||
|
||||
cart_data.each do |ticket_type_id, item|
|
||||
ticket_type = @event.ticket_types.find_by(id: ticket_type_id)
|
||||
next unless ticket_type
|
||||
|
||||
quantity = item["quantity"].to_i
|
||||
next if quantity <= 0
|
||||
|
||||
# Check availability
|
||||
available = ticket_type.quantity - ticket_type.tickets.count
|
||||
if quantity > available
|
||||
redirect_to event_path(@event.slug, @event), alert: "Pas assez de billets disponibles pour #{ticket_type.name}"
|
||||
return
|
||||
end
|
||||
|
||||
# Create Stripe line item
|
||||
line_items << {
|
||||
price_data: {
|
||||
currency: "eur",
|
||||
product_data: {
|
||||
name: "#{@event.name} - #{ticket_type.name}",
|
||||
description: ticket_type.description
|
||||
},
|
||||
unit_amount: ticket_type.price_cents
|
||||
},
|
||||
quantity: quantity
|
||||
}
|
||||
|
||||
# Store for ticket creation
|
||||
order_items << {
|
||||
ticket_type_id: ticket_type.id,
|
||||
ticket_type_name: ticket_type.name,
|
||||
quantity: quantity,
|
||||
price_cents: ticket_type.price_cents
|
||||
}
|
||||
|
||||
total_amount += ticket_type.price_cents * quantity
|
||||
end
|
||||
|
||||
if order_items.empty?
|
||||
redirect_to event_path(@event.slug, @event), alert: "Commande invalide"
|
||||
return
|
||||
end
|
||||
|
||||
# Get ticket names from session if they exist
|
||||
ticket_names = session[:ticket_names] || {}
|
||||
|
||||
# Debug: Log Stripe configuration status
|
||||
Rails.logger.debug "Stripe configuration check:"
|
||||
Rails.logger.debug " Config: #{Rails.application.config.stripe}"
|
||||
Rails.logger.debug " Secret key present: #{Rails.application.config.stripe[:secret_key].present?}"
|
||||
Rails.logger.debug " stripe_configured? method exists: #{respond_to?(:stripe_configured?)}"
|
||||
|
||||
# Check if Stripe is properly configured
|
||||
stripe_configured = Rails.application.config.stripe[:secret_key].present?
|
||||
Rails.logger.debug " Direct stripe_configured check: #{stripe_configured}"
|
||||
|
||||
unless stripe_configured
|
||||
Rails.logger.error "Stripe not configured properly - redirecting to event page"
|
||||
redirect_to event_path(@event.slug, @event), alert: "Le système de paiement n'est pas correctement configuré. Veuillez contacter l'administrateur."
|
||||
return
|
||||
end
|
||||
|
||||
# Stripe is now initialized at application startup, no need to initialize here
|
||||
Rails.logger.debug " Using globally initialized Stripe"
|
||||
|
||||
begin
|
||||
Rails.logger.debug "Creating Stripe Checkout Session"
|
||||
# Create Stripe Checkout Session
|
||||
session = Stripe::Checkout::Session.create({
|
||||
payment_method_types: [ "card" ],
|
||||
line_items: line_items,
|
||||
mode: "payment",
|
||||
success_url: payment_success_url(session_id: "{CHECKOUT_SESSION_ID}"),
|
||||
cancel_url: event_url(@event.slug, @event),
|
||||
customer_email: current_user.email,
|
||||
metadata: {
|
||||
event_id: @event.id,
|
||||
user_id: current_user.id,
|
||||
order_items: order_items.to_json,
|
||||
ticket_names: ticket_names.to_json
|
||||
}
|
||||
})
|
||||
|
||||
Rails.logger.debug "Redirecting to Stripe session URL: #{session.url}"
|
||||
redirect_to session.url, allow_other_host: true
|
||||
rescue Stripe::StripeError => e
|
||||
error_message = e.message.present? ? e.message : "Erreur Stripe inconnue"
|
||||
Rails.logger.error "Stripe error: #{error_message}"
|
||||
redirect_to event_path(@event.slug, @event), alert: "Erreur de traitement du paiement : #{error_message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,29 +5,98 @@
|
||||
class OrdersController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
before_action :set_order, only: [:show, :checkout, :retry_payment, :increment_payment_attempt]
|
||||
before_action :set_event, only: [:new, :create]
|
||||
|
||||
# Display new order form
|
||||
# Display new order form with name collection
|
||||
#
|
||||
# On this page user can complete the tickets details (first name and last name),
|
||||
# add a comment on the order.
|
||||
# On this page user can see order summary and complete the tickets details
|
||||
# (first name and last name) for each ticket ordered
|
||||
def new
|
||||
@cart_data = session[:pending_cart] || {}
|
||||
|
||||
if @cart_data.empty?
|
||||
redirect_to root_path, alert: "Veuillez d'abord sélectionner vos billets"
|
||||
redirect_to event_path(@event.slug, @event), alert: "Veuillez d'abord sélectionner vos billets sur la page de l'événement"
|
||||
return
|
||||
end
|
||||
|
||||
# Build order preview from cart data
|
||||
@event_id = session[:event_id]
|
||||
if @event_id.present?
|
||||
@event = Event.includes(:ticket_types).find_by(id: @event_id)
|
||||
redirect_to root_path, alert: "Événement non trouvé" unless @event
|
||||
else
|
||||
redirect_to root_path, alert: "Informations manquantes"
|
||||
# Build list of tickets requiring names
|
||||
@tickets_needing_names = []
|
||||
@cart_data.each do |ticket_type_id, item|
|
||||
ticket_type = @event.ticket_types.find_by(id: ticket_type_id)
|
||||
next unless ticket_type
|
||||
|
||||
quantity = item["quantity"].to_i
|
||||
next if quantity <= 0
|
||||
|
||||
quantity.times do |i|
|
||||
@tickets_needing_names << {
|
||||
ticket_type_id: ticket_type.id,
|
||||
ticket_type_name: ticket_type.name,
|
||||
ticket_type_price: ticket_type.price_cents,
|
||||
index: i
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new order with tickets
|
||||
#
|
||||
# Here a new order is created with associated tickets in draft state.
|
||||
# When user is ready they can proceed to payment via the order checkout
|
||||
def create
|
||||
@cart_data = session[:pending_cart] || {}
|
||||
|
||||
if @cart_data.empty?
|
||||
redirect_to event_path(@event.slug, @event), alert: "Aucun billet sélectionné"
|
||||
return
|
||||
end
|
||||
|
||||
success = false
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@order = current_user.orders.create!(event: @event, status: "draft")
|
||||
|
||||
order_params[:tickets_attributes]&.each do |index, ticket_attrs|
|
||||
next if ticket_attrs[:first_name].blank? || ticket_attrs[:last_name].blank?
|
||||
|
||||
ticket_type = @event.ticket_types.find(ticket_attrs[:ticket_type_id])
|
||||
|
||||
ticket = @order.tickets.build(
|
||||
ticket_type: ticket_type,
|
||||
first_name: ticket_attrs[:first_name],
|
||||
last_name: ticket_attrs[:last_name],
|
||||
status: "draft"
|
||||
)
|
||||
|
||||
unless ticket.save
|
||||
flash[:alert] = "Erreur lors de la création des billets: #{ticket.errors.full_messages.join(', ')}"
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
if @order.tickets.present?
|
||||
@order.calculate_total!
|
||||
success = true
|
||||
else
|
||||
flash[:alert] = "Aucun billet valide créé"
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
# Handle redirects outside transaction
|
||||
if success
|
||||
session[:draft_order_id] = @order.id
|
||||
session.delete(:pending_cart)
|
||||
redirect_to checkout_order_path(@order)
|
||||
else
|
||||
redirect_to event_order_new_path(@event.slug, @event.id)
|
||||
end
|
||||
rescue => e
|
||||
error_message = e.message.present? ? e.message : "Erreur inconnue"
|
||||
flash[:alert] = "Une erreur est survenue: #{error_message}"
|
||||
redirect_to event_order_new_path(@event.slug, @event.id)
|
||||
end
|
||||
|
||||
# Display order summary
|
||||
#
|
||||
#
|
||||
@@ -44,7 +113,7 @@ class OrdersController < ApplicationController
|
||||
if @order.expired?
|
||||
@order.expire_if_overdue!
|
||||
return redirect_to event_path(@order.event.slug, @order.event),
|
||||
alert: "Votre commande a expiré. Veuillez recommencer."
|
||||
alert: "Votre commande a expiré. Veuillez recommencer."
|
||||
end
|
||||
|
||||
@tickets = @order.tickets.includes(:ticket_type)
|
||||
@@ -111,7 +180,12 @@ class OrdersController < ApplicationController
|
||||
|
||||
# Send confirmation emails
|
||||
@order.tickets.each do |ticket|
|
||||
TicketMailer.purchase_confirmation(ticket).deliver_now
|
||||
begin
|
||||
TicketMailer.purchase_confirmation(ticket).deliver_now
|
||||
rescue => e
|
||||
Rails.logger.error "Failed to send confirmation email for ticket #{ticket.id}: #{e.message}"
|
||||
# Don't fail the entire payment process due to email/PDF generation issues
|
||||
end
|
||||
end
|
||||
|
||||
# Clear session data
|
||||
@@ -160,6 +234,16 @@ class OrdersController < ApplicationController
|
||||
redirect_to dashboard_path, alert: "Commande non trouvée"
|
||||
end
|
||||
|
||||
def set_event
|
||||
@event = Event.includes(:ticket_types).find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
redirect_to events_path, alert: "Événement non trouvé"
|
||||
end
|
||||
|
||||
def order_params
|
||||
params.permit(tickets_attributes: [ :ticket_type_id, :first_name, :last_name ])
|
||||
end
|
||||
|
||||
def create_stripe_session
|
||||
line_items = @order.tickets.map do |ticket|
|
||||
{
|
||||
|
||||
@@ -1,101 +1,11 @@
|
||||
# Manage tickets creation
|
||||
# Legacy tickets controller - redirects to new order system
|
||||
#
|
||||
# This controller permit users to create a new ticket for an event,
|
||||
# complete their details and proceed to payment
|
||||
# This controller now primarily handles legacy redirects and backward compatibility
|
||||
# Most ticket creation functionality has been moved to OrdersController
|
||||
class TicketsController < ApplicationController
|
||||
before_action :authenticate_user!, only: [ :new, :payment_success, :payment_cancel ]
|
||||
before_action :set_event, only: [ :new, :create ]
|
||||
before_action :authenticate_user!, only: [ :payment_success, :payment_cancel ]
|
||||
before_action :set_event, only: [ :checkout, :retry_payment ]
|
||||
|
||||
# Handle new ticket creation
|
||||
#
|
||||
# Once user selected ticket types he wans for an event
|
||||
# he cames here where he can complete his details (first_name, last_name)
|
||||
# for each ticket ordered
|
||||
def new
|
||||
@cart_data = session[:pending_cart] || {}
|
||||
|
||||
if @cart_data.empty?
|
||||
redirect_to event_path(@event.slug, @event), alert: "Veuillez d'abord sélectionner vos billets sur la page de l'événement"
|
||||
return
|
||||
end
|
||||
|
||||
# Build list of tickets requiring names
|
||||
@tickets_needing_names = []
|
||||
@cart_data.each do |ticket_type_id, item|
|
||||
ticket_type = @event.ticket_types.find_by(id: ticket_type_id)
|
||||
next unless ticket_type
|
||||
|
||||
quantity = item["quantity"].to_i
|
||||
next if quantity <= 0
|
||||
|
||||
quantity.times do |i|
|
||||
@tickets_needing_names << {
|
||||
ticket_type_id: ticket_type.id,
|
||||
ticket_type_name: ticket_type.name,
|
||||
index: i
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Create a new order with tickets
|
||||
#
|
||||
# Here a new order is created with associated tickets in draft state.
|
||||
# When user is ready they can proceed to payment via the order checkout
|
||||
def create
|
||||
@cart_data = session[:pending_cart] || {}
|
||||
|
||||
if @cart_data.empty?
|
||||
redirect_to event_path(params[:slug], params[:id]), alert: "Aucun billet sélectionné"
|
||||
return
|
||||
end
|
||||
|
||||
@event = Event.includes(:ticket_types).find(params[:id])
|
||||
success = false
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@order = current_user.orders.create!(event: @event, status: "draft")
|
||||
|
||||
ticket_params[:tickets_attributes]&.each do |index, ticket_attrs|
|
||||
next if ticket_attrs[:first_name].blank? || ticket_attrs[:last_name].blank?
|
||||
|
||||
ticket_type = @event.ticket_types.find(ticket_attrs[:ticket_type_id])
|
||||
|
||||
ticket = @order.tickets.build(
|
||||
ticket_type: ticket_type,
|
||||
first_name: ticket_attrs[:first_name],
|
||||
last_name: ticket_attrs[:last_name],
|
||||
status: "draft"
|
||||
)
|
||||
|
||||
unless ticket.save
|
||||
flash[:alert] = "Erreur lors de la création des billets: #{ticket.errors.full_messages.join(', ')}"
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
if @order.tickets.present?
|
||||
@order.calculate_total!
|
||||
success = true
|
||||
else
|
||||
flash[:alert] = "Aucun billet valide créé"
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
|
||||
# Handle redirects outside transaction
|
||||
if success
|
||||
session[:draft_order_id] = @order.id
|
||||
session.delete(:pending_cart)
|
||||
redirect_to checkout_order_path(@order)
|
||||
else
|
||||
redirect_to ticket_new_path(@event.slug, @event.id)
|
||||
end
|
||||
rescue => e
|
||||
error_message = e.message.present? ? e.message : "Erreur inconnue"
|
||||
flash[:alert] = "Une erreur est survenue: #{error_message}"
|
||||
redirect_to ticket_new_path(params[:slug], params[:id])
|
||||
end
|
||||
|
||||
# Redirect to order-based checkout
|
||||
def checkout
|
||||
@@ -147,12 +57,23 @@ class TicketsController < ApplicationController
|
||||
private
|
||||
|
||||
def set_event
|
||||
@event = Event.includes(:ticket_types).find(params[:id])
|
||||
event_id = params[:id] || session[:event_id]
|
||||
|
||||
Rails.logger.debug "TicketsController#set_event - params[:id]: #{params[:id].inspect}, session[:event_id]: #{session[:event_id].inspect}"
|
||||
|
||||
unless event_id
|
||||
Rails.logger.error "TicketsController#set_event - No event ID found"
|
||||
redirect_to events_path, alert: "Aucun événement spécifié"
|
||||
return
|
||||
end
|
||||
|
||||
@event = Event.includes(:ticket_types).find(event_id)
|
||||
Rails.logger.debug "TicketsController#set_event - Found event: #{@event.id} - #{@event.name}"
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
Rails.logger.error "TicketsController#set_event - Event not found with ID: #{event_id}"
|
||||
redirect_to events_path, alert: "Événement non trouvé"
|
||||
end
|
||||
|
||||
def ticket_params
|
||||
params.permit(tickets_attributes: [ :ticket_type_id, :first_name, :last_name ])
|
||||
end
|
||||
|
||||
def create_stripe_session
|
||||
line_items = @tickets.map do |ticket|
|
||||
|
||||
@@ -14,7 +14,7 @@ import FlashMessageController from "./flash_message_controller";
|
||||
application.register("flash-message", FlashMessageController);
|
||||
|
||||
import TicketSelectionController from "./ticket_selection_controller";
|
||||
// application.register("ticket-selection", TicketSelectionController);
|
||||
application.register("ticket-selection", TicketSelectionController);
|
||||
|
||||
import HeaderController from "./header_controller";
|
||||
application.register("header", HeaderController);
|
||||
|
||||
@@ -117,8 +117,8 @@ export default class extends Controller {
|
||||
// Store cart data in session
|
||||
await this.storeCartInSession(cartData);
|
||||
|
||||
// Redirect to orders/new page
|
||||
const OrderNewUrl = `/orders/new`;
|
||||
// Redirect to event-scoped orders/new page
|
||||
const OrderNewUrl = `/events/${this.eventSlugValue}.${this.eventIdValue}/orders/new`;
|
||||
window.location.href = OrderNewUrl;
|
||||
} catch (error) {
|
||||
console.error("Error storing cart:", error);
|
||||
|
||||
@@ -63,6 +63,10 @@ class Ticket < ApplicationRecord
|
||||
self.qr_code = SecureRandom.uuid
|
||||
break unless Ticket.exists?(qr_code: qr_code)
|
||||
end
|
||||
rescue => e
|
||||
Rails.logger.error "Failed to generate QR code for ticket: #{e.message}"
|
||||
# Generate a simple fallback QR code
|
||||
self.qr_code = "#{id || 'temp'}-#{Time.current.to_i}-#{SecureRandom.hex(4)}"
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -63,12 +63,22 @@ class TicketPdfGenerator
|
||||
pdf.text "Ticket QR Code", align: :center
|
||||
pdf.move_down 10
|
||||
|
||||
# Ensure all required data is present before generating QR code
|
||||
if ticket.qr_code.blank?
|
||||
raise "Ticket QR code is missing"
|
||||
end
|
||||
|
||||
qr_code_data = {
|
||||
ticket_id: ticket.id,
|
||||
qr_code: ticket.qr_code,
|
||||
event_id: ticket.event.id,
|
||||
user_id: ticket.user.id
|
||||
}.to_json
|
||||
event_id: ticket.event&.id,
|
||||
user_id: ticket.user&.id
|
||||
}.compact.to_json
|
||||
|
||||
# Validate QR code data before creating QR code
|
||||
if qr_code_data.blank? || qr_code_data == "{}"
|
||||
raise "QR code data is empty or invalid"
|
||||
end
|
||||
|
||||
qrcode = RQRCode::QRCode.new(qr_code_data)
|
||||
pdf.print_qr_code(qrcode, extent: 120, align: :center)
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
<div class="footer-content">
|
||||
<div class="footer-section">
|
||||
<h3>Events</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">Find Events</a></li>
|
||||
<li><a href="#">Host an Event</a></li>
|
||||
<li><a href="#">Event Categories</a></li>
|
||||
<li><a href="#">Premium Events</a></li>
|
||||
<div class="grid gap-6 mb-6 md:grid-cols-2 lg:grid-cols-4">
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">Events</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Find Events</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Host an Event</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Event Categories</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Premium Events</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h3>Community</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">Join Us</a></li>
|
||||
<li><a href="#">Member Benefits</a></li>
|
||||
<li><a href="#">Success Stories</a></li>
|
||||
<li><a href="#">Ambassador Program</a></li>
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">Community</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Join Us</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Member Benefits</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Success Stories</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Ambassador Program</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h3>Support</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">Help Center</a></li>
|
||||
<li><a href="#">Contact Us</a></li>
|
||||
<li><a href="#">Safety Guidelines</a></li>
|
||||
<li><a href="#">Cancellation Policy</a></li>
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">Support</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Help Center</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Contact Us</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Safety Guidelines</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Cancellation Policy</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-section">
|
||||
<h3>Company</h3>
|
||||
<ul class="footer-links">
|
||||
<li><a href="#">About Aperonight</a></li>
|
||||
<li><a href="#">Careers</a></li>
|
||||
<li><a href="#">Press & Media</a></li>
|
||||
<li><a href="#">Partner With Us</a></li>
|
||||
<div>
|
||||
<h3 class="font-bold text-lg text-white mb-3">Company</h3>
|
||||
<ul class="space-y-2">
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">About Aperonight</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Careers</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Press & Media</a></li>
|
||||
<li><a href="#" class="text-neutral-400 text-sm hover:text-accent-400 transition-colors duration-300">Partner With Us</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer-bottom">
|
||||
<p>© 2024 Aperonight. All rights reserved. • <a href="#" style="color: var(--color-accent-400);">Privacy Policy</a> • <a href="#" style="color: var(--color-accent-400);">Terms of Service</a></p>
|
||||
<div class="border-t border-neutral-700 pt-4 text-center text-neutral-400 text-sm">
|
||||
<p>© 2024 Aperonight. All rights reserved. • <a href="#" class="text-accent-400 hover:text-accent-300 transition-colors">Privacy Policy</a> • <a href="#" class="text-accent-400 hover:text-accent-300 transition-colors">Terms of Service</a></p>
|
||||
</div>
|
||||
@@ -1,23 +1,11 @@
|
||||
<div
|
||||
class="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100"
|
||||
>
|
||||
<div class="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100">
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<!-- Breadcrumb -->
|
||||
<nav class="mb-6" aria-label="Breadcrumb">
|
||||
<ol class="flex items-center space-x-2 text-sm">
|
||||
<%= link_to root_path, class: "text-gray-500 hover:text-purple-600 transition-colors" do %>
|
||||
<svg
|
||||
class="w-4 h-4 inline-block mr-1"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"
|
||||
/>
|
||||
<svg class="w-4 h-4 inline-block mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
|
||||
</svg>
|
||||
Accueil
|
||||
<% end %>
|
||||
@@ -56,7 +44,8 @@
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div class="bg-white rounded-2xl shadow-xl overflow-hidden">
|
||||
<!-- Event main wrapper -->
|
||||
<div class="bg-white rounded-xl shadow-xl overflow-hidden">
|
||||
<!-- Event Header with Image -->
|
||||
<% if @event.image.present? %>
|
||||
<div class="relative h-96">
|
||||
@@ -68,7 +57,7 @@
|
||||
></div>
|
||||
<div class="absolute bottom-0 left-0 right-0 p-6 md:p-8">
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-white mb-2"><%= @event.name %></h1>
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-white mb-2 text-center md:text-left"><%= @event.name %></h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -208,8 +197,8 @@
|
||||
|
||||
<!-- Right Column: Ticket Selection -->
|
||||
<div class="lg:col-span-1">
|
||||
<%= form_with url: order_new_path, method: :get, id: "checkout_form", local: true, data: {
|
||||
controller: "ticket-selection",
|
||||
<%= 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
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<link rel="apple-touch-icon" href="/icon.png">
|
||||
|
||||
<%# Includes all stylesheet files in app/assets/stylesheets %>
|
||||
<%# stylesheet_link_tag :app, "data-turbo-track": "reload" %>
|
||||
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
|
||||
<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
|
||||
|
||||
@@ -41,20 +42,11 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="footer">
|
||||
<footer class="bg-neutral-800 text-neutral-300 py-8 pb-4">
|
||||
<div class="container">
|
||||
<%= render "components/footer" %>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Initialize Lucide icons
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
if (typeof lucide !== 'undefined') {
|
||||
lucide.createIcons();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -178,9 +178,25 @@
|
||||
|
||||
<script src="https://js.stripe.com/v3/"></script>
|
||||
<script>
|
||||
const stripe = Stripe('<%= Rails.application.config.stripe[:publishable_key] %>');
|
||||
|
||||
document.getElementById('checkout-button').addEventListener('click', async function() {
|
||||
// Wait for Stripe library to load and DOM to be ready
|
||||
function initializeStripeCheckout() {
|
||||
if (typeof Stripe === 'undefined') {
|
||||
console.log('Waiting for Stripe library to load...');
|
||||
setTimeout(initializeStripeCheckout, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Initializing Stripe with publishable key:', '<%= Rails.application.config.stripe[:publishable_key] %>');
|
||||
const stripe = Stripe('<%= Rails.application.config.stripe[:publishable_key] %>');
|
||||
|
||||
const checkoutButton = document.getElementById('checkout-button');
|
||||
if (!checkoutButton) {
|
||||
console.error('Checkout button not found');
|
||||
return;
|
||||
}
|
||||
|
||||
checkoutButton.addEventListener('click', async function() {
|
||||
console.log('Checkout button clicked');
|
||||
const button = this;
|
||||
button.disabled = true;
|
||||
button.innerHTML = `
|
||||
@@ -195,6 +211,7 @@
|
||||
|
||||
try {
|
||||
// Increment payment attempt counter
|
||||
console.log('Incrementing payment attempt for order:', '<%= @order.id %>');
|
||||
const response = await fetch('<%= increment_payment_attempt_order_path(@order) %>', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -204,9 +221,12 @@
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.error('Payment attempt increment failed:', response.status, response.statusText);
|
||||
throw new Error('Failed to increment payment attempt');
|
||||
}
|
||||
|
||||
console.log('Payment attempt incremented successfully');
|
||||
|
||||
// Update button text for redirect
|
||||
button.innerHTML = `
|
||||
<div class="flex items-center justify-center">
|
||||
@@ -219,6 +239,7 @@
|
||||
`;
|
||||
|
||||
// Redirect to Stripe
|
||||
console.log('Redirecting to Stripe with session ID:', '<%= @checkout_session&.id %>');
|
||||
const stripeResult = await stripe.redirectToCheckout({
|
||||
sessionId: '<%= @checkout_session.id %>'
|
||||
});
|
||||
@@ -228,6 +249,7 @@
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Checkout error:', error);
|
||||
// Reset button on error
|
||||
button.disabled = false;
|
||||
button.innerHTML = `
|
||||
@@ -240,7 +262,15 @@
|
||||
`;
|
||||
alert('Erreur: ' + error.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initializeStripeCheckout);
|
||||
} else {
|
||||
initializeStripeCheckout();
|
||||
}
|
||||
</script>
|
||||
</div>
|
||||
<% else %>
|
||||
|
||||
@@ -1,9 +1,39 @@
|
||||
<div class="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100">
|
||||
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||
<!-- Breadcrumb -->
|
||||
<nav class="mb-8" aria-label="Breadcrumb">
|
||||
<ol class="flex items-center space-x-2 text-sm">
|
||||
<%= link_to root_path, class: "text-gray-500 hover:text-purple-600 transition-colors" do %>
|
||||
<svg class="w-4 h-4 inline-block mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"/>
|
||||
</svg>
|
||||
Accueil
|
||||
<% end %>
|
||||
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||
</svg>
|
||||
<%= link_to events_path, class: "text-gray-500 hover:text-purple-600 transition-colors" do %>
|
||||
Événements
|
||||
<% end %>
|
||||
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||
</svg>
|
||||
<%= link_to event_path(@event.slug, @event), class: "text-gray-500 hover:text-purple-600 transition-colors" do %>
|
||||
<%= @event.name %>
|
||||
<% end %>
|
||||
<svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||
</svg>
|
||||
<li class="font-medium text-gray-900" aria-current="page">
|
||||
Nouvelle commande
|
||||
</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<!-- Page Header -->
|
||||
<div class="mb-8">
|
||||
<h1 class="text-3xl font-bold text-gray-900 mb-2">Nouvelle Commande</h1>
|
||||
<p class="text-gray-600">Vérifiez vos billets avant de continuer vers le paiement</p>
|
||||
<p class="text-gray-600">Vérifiez vos billets et indiquez les noms des participants</p>
|
||||
</div>
|
||||
|
||||
<!-- Order Summary -->
|
||||
@@ -14,9 +44,9 @@
|
||||
<div class="mb-6">
|
||||
<h3 class="text-lg font-medium text-gray-800"><%= @event.name %></h3>
|
||||
<p class="text-gray-600"><%= @event.venue_name %></p>
|
||||
<% if @event.starts_at %>
|
||||
<% if @event.start_time %>
|
||||
<p class="text-sm text-gray-500">
|
||||
<%= @event.starts_at.strftime("%d/%m/%Y à %H:%M") %>
|
||||
<%= @event.start_time.strftime("%d/%m/%Y à %H:%M") %>
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -42,30 +72,69 @@
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Continue to Tickets -->
|
||||
<div class="flex justify-end">
|
||||
<%= link_to ticket_new_path,
|
||||
class: "inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-xl text-white bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500 transition-all duration-200" do %>
|
||||
<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="M13 7l5 5m0 0l-5 5m5-5H6"></path>
|
||||
</svg>
|
||||
Continuer vers les détails
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Back to Event -->
|
||||
<div class="mt-6">
|
||||
<% if @event %>
|
||||
<%= link_to event_path(@event.slug, @event),
|
||||
class: "inline-flex items-center text-purple-600 hover:text-purple-700 font-medium transition-colors" do %>
|
||||
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
|
||||
</svg>
|
||||
Retour à l'événement
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<!-- Name Collection Form -->
|
||||
<% if @tickets_needing_names.any? %>
|
||||
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 mt-6">
|
||||
<div class="p-6 md:p-8">
|
||||
<div class="text-center mb-8">
|
||||
<div class="mx-auto bg-purple-100 rounded-full p-3 w-16 h-16 flex items-center justify-center mb-4">
|
||||
<svg class="w-8 h-8 text-purple-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 class="text-2xl font-bold text-gray-900 mb-2">Informations des participants</h2>
|
||||
<p class="text-gray-600 max-w-md mx-auto">Veuillez fournir les prénoms et noms des personnes qui utiliseront les billets.</p>
|
||||
</div>
|
||||
|
||||
<%= form_with url: event_order_create_path(@event.slug, @event.id), method: :post, local: true, class: "space-y-8" do |form| %>
|
||||
<div class="space-y-6">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
<div class="bg-purple-600 rounded-full p-2 mr-3">
|
||||
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h3 class="text-xl font-semibold text-gray-900">Billets nécessitant une identification</h3>
|
||||
</div>
|
||||
<p class="text-gray-600 mb-6 text-center">Les billets suivants nécessitent que vous indiquiez le prénom et le nom de chaque participant.</p>
|
||||
|
||||
<% @tickets_needing_names.each_with_index do |ticket, index| %>
|
||||
<div class="bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl p-6 border border-purple-100">
|
||||
<div class="flex items-center mb-4">
|
||||
<div class="bg-purple-500 rounded-lg p-2 mr-3">
|
||||
<svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<h4 class="text-lg font-semibold text-gray-900"><%= ticket[:ticket_type_name] %> #<%= index + 1 %></h4>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
|
||||
<div>
|
||||
<%= form.label "tickets_attributes[#{index}][first_name]", "Prénom", class: "block text-sm font-medium text-gray-700 mb-1" %>
|
||||
<%= form.text_field "tickets_attributes[#{index}][first_name]", required: true, class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-all duration-200 shadow-sm", placeholder: "Entrez le prénom" %>
|
||||
<%= form.hidden_field "tickets_attributes[#{index}][ticket_type_id]", value: ticket[:ticket_type_id] %>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<%= form.label "tickets_attributes[#{index}][last_name]", "Nom", class: "block text-sm font-medium text-gray-700 mb-1" %>
|
||||
<%= form.text_field "tickets_attributes[#{index}][last_name]", required: true, class: "w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-purple-500 transition-all duration-200 shadow-sm", placeholder: "Entrez le nom" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row gap-4 pt-6">
|
||||
<%= link_to "Retour", event_path(@event.slug, @event), class: "px-6 py-3 border border-gray-300 text-gray-700 rounded-xl hover:bg-gray-50 text-center font-medium transition-colors duration-200" %>
|
||||
<%= form.submit "Procéder au paiement", class: "flex-1 bg-gradient-to-r from-purple-600 to-indigo-600 hover:from-purple-700 hover:to-indigo-700 text-white font-medium py-3 px-6 rounded-xl shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2 transform hover:-translate-y-0.5" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,7 +98,7 @@
|
||||
les billets.</p>
|
||||
</div>
|
||||
|
||||
<%= form_with url: ticket_create_path(@event.slug, @event), method: :post, local: true, class: "space-y-8" do |form| %>
|
||||
<%= form_with url: ticket_create_path, method: :post, local: true, class: "space-y-8" do |form| %>
|
||||
<% if @tickets_needing_names.any? %>
|
||||
<div class="space-y-6">
|
||||
<div class="flex items-center justify-center mb-2">
|
||||
|
||||
@@ -38,9 +38,9 @@ Rails.application.routes.draw do
|
||||
get "events", to: "events#index", as: "events"
|
||||
get "events/:slug.:id", to: "events#show", as: "event"
|
||||
|
||||
# === Orders ===
|
||||
|
||||
get "orders/new", to: "orders#new", as: "order_new"
|
||||
# === Orders (scoped to events) ===
|
||||
get "events/:slug.:id/orders/new", to: "orders#new", as: "event_order_new"
|
||||
post "events/:slug.:id/orders", to: "orders#create", as: "event_order_create"
|
||||
|
||||
resources :orders, only: [:show] do
|
||||
member do
|
||||
@@ -53,11 +53,7 @@ Rails.application.routes.draw do
|
||||
get "orders/payments/success", to: "orders#payment_success", as: "order_payment_success"
|
||||
get "orders/payments/cancel", to: "orders#payment_cancel", as: "order_payment_cancel"
|
||||
|
||||
# === Tickets ===
|
||||
get "tickets/new", to: "tickets#new", as: "ticket_new"
|
||||
post "tickets/create", to: "tickets#create", as: "ticket_create"
|
||||
|
||||
# Keep these for now but they redirect to order system
|
||||
# Legacy ticket routes - redirect to order system
|
||||
get "events/:slug.:id/tickets/checkout", to: "tickets#checkout", as: "ticket_checkout"
|
||||
post "events/:slug.:id/tickets/retry", to: "tickets#retry_payment", as: "ticket_retry_payment"
|
||||
get "payments/success", to: "tickets#payment_success", as: "payment_success"
|
||||
|
||||
Reference in New Issue
Block a user