From e86b84ba61cb3d37d20919471a7c0e82d973e46a Mon Sep 17 00:00:00 2001 From: kbe Date: Sat, 6 Sep 2025 22:55:27 +0200 Subject: [PATCH] feat: Enhance user dashboard and order management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add orders index action to OrdersController with pagination support - Simplify dashboard to focus on user orders and actions - Redesign order show page with improved layout and ticket access - Remove complex event metrics in favor of streamlined order management - Add direct links to ticket downloads and better order navigation - Improve responsive design and user experience across order views 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- app/controllers/orders_controller.rb | 8 + app/controllers/pages_controller.rb | 34 ++-- app/views/orders/index.html.erb | 106 ++++++++++ app/views/orders/show.html.erb | 290 +++++++++++++++++++-------- app/views/pages/dashboard.html.erb | 249 ++++++++++++++--------- config/routes.rb | 2 +- 6 files changed, 481 insertions(+), 208 deletions(-) create mode 100644 app/views/orders/index.html.erb diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 14c4af4..bffa5e4 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -97,6 +97,14 @@ class OrdersController < ApplicationController redirect_to event_order_new_path(@event.slug, @event.id) end + # Display all user orders + def index + @orders = current_user.orders.includes(:event, tickets: :ticket_type) + .where(status: [ "paid", "completed" ]) + .order(created_at: :desc) + .page(params[:page]) + end + # Display order summary # # diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 56c346c..ad6b423 100755 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -17,30 +17,28 @@ class PagesController < ApplicationController # User dashboard showing personalized content # Accessible only to authenticated users def dashboard - # Metrics for dashboard cards - @booked_events = current_user.orders.joins(tickets: { ticket_type: :event }) - .where(events: { state: :published }) - .where(orders: { status: [ "paid", "completed" ] }) - .sum("1") - @events_today = Event.published.where("DATE(start_time) = ?", Date.current).count - @events_tomorrow = Event.published.where("DATE(start_time) = ?", Date.current + 1).count - @upcoming_events = Event.published.upcoming.count - - # User's booked events - @user_booked_events = Event.joins(ticket_types: { tickets: :order }) - .where(orders: { user: current_user }, tickets: { status: "active" }) - .distinct - .limit(5) + # User's orders with associated data + @user_orders = current_user.orders.includes(:event, tickets: :ticket_type) + .where(status: [ "paid", "completed" ]) + .order(created_at: :desc) + .limit(10) # Draft orders that can be retried @draft_orders = current_user.orders.includes(tickets: [ :ticket_type, :event ]) .can_retry_payment .order(:expires_at) - # Events sections - @today_events = Event.published.where("DATE(start_time) = ?", Date.current).order(start_time: :asc) - @tomorrow_events = Event.published.where("DATE(start_time) = ?", Date.current + 1).order(start_time: :asc) - @other_events = Event.published.upcoming.where.not("DATE(start_time) IN (?)", [ Date.current, Date.current + 1 ]).order(start_time: :asc).page(params[:page]) + # Simplified upcoming events preview - only show if user has orders + if @user_orders.any? + ordered_event_ids = @user_orders.map(&:event).map(&:id) + @upcoming_preview_events = Event.published + .upcoming + .where.not(id: ordered_event_ids) + .order(start_time: :asc) + .limit(6) + else + @upcoming_preview_events = [] + end end # Events page showing all published events with pagination diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb new file mode 100644 index 0000000..e51f4f2 --- /dev/null +++ b/app/views/orders/index.html.erb @@ -0,0 +1,106 @@ +
+ +
+
+

Toutes mes commandes

+

Consultez l'historique de toutes vos commandes

+
+ + <%= link_to dashboard_path, class: "inline-flex items-center px-4 py-2 bg-purple-100 hover:bg-purple-200 text-purple-700 font-medium rounded-lg transition-colors duration-200" do %> + + Retour au tableau de bord + <% end %> +
+ + + <% if @orders.any? %> +
+ <% @orders.each do |order| %> +
+
+
+
+
+

<%= order.event.name %>

+ + <%= order.status.humanize %> + +
+ +
+
+ + <%= order.event.start_time.strftime("%d %B %Y Ă  %H:%M") %> +
+
+ + <%= order.event.venue_name %> +
+
+ + <%= pluralize(order.tickets.count, 'billet') %> +
+
+ +
+ Commande #<%= order.id %> • <%= order.created_at.strftime("%d/%m/%Y") %> • <%= order.total_amount_euros %>€ +
+
+ +
+ <%= link_to order_path(order), + class: "inline-flex items-center px-3 py-2 bg-purple-600 hover:bg-purple-700 text-white text-sm font-medium rounded-lg transition-colors duration-200" do %> + + Voir détails + <% end %> +
+
+ + +
+
+ <% order.tickets.limit(3).each do |ticket| %> +
+
+ + <%= ticket.ticket_type.name %> + - <%= ticket.first_name %> <%= ticket.last_name %> +
+
+ <%= link_to ticket_download_path(ticket.qr_code), + class: "text-purple-600 hover:text-purple-800 dark:text-purple-400 dark:hover:text-purple-200" do %> + + <% end %> +
+
+ <% end %> + <% if order.tickets.count > 3 %> +
+ et <%= order.tickets.count - 3 %> autre<%= order.tickets.count - 3 > 1 ? 's' : '' %> billet<%= order.tickets.count - 3 > 1 ? 's' : '' %> +
+ <% end %> +
+
+
+
+ <% end %> +
+ + +
+ <%= paginate @orders %> +
+ <% else %> +
+
+ +
+

Aucune commande

+

Vous n'avez encore passé aucune commande.

+ <%= link_to events_path, class: "inline-flex items-center px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors duration-200" do %> + + Découvrir les événements + <% end %> +
+ <% end %> +
\ No newline at end of file diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb index 26450f8..1036117 100644 --- a/app/views/orders/show.html.erb +++ b/app/views/orders/show.html.erb @@ -1,102 +1,214 @@ -
+
- - -
-
-

Détails de la commande

-
-
- - - - Commande #<%= @order.id %> -
-
- - - - <%= @order.status.titleize %> -
-
- -
-

Billets commandés

- <% @tickets.each do |ticket| %> -
-
-

<%= ticket.ticket_type.name %>

-
- - - - <%= ticket.first_name %> <%= ticket.last_name %> -
-
- Statut: <%= ticket.status.titleize %> -
-
-
-
<%= ticket.price_euros %>€
-
-
- <% end %> -
- -
-
- Total - <%= @order.total_amount_euros %>€ -
-

TVA incluse

-
- -
-
- <%= link_to event_path(@order.event.slug, @order.event), class: "bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium py-2 px-4 rounded-lg transition-colors" do %> +

Détails de la Commande

+
+
+ +
+
+

Détails de Votre Commande

+
- - + + - Retour à l'événement +
+ Commande n°<%= @order.id %> + <%= @order.created_at.strftime("%d %B %Y") %> +
+
+
+ + <% if @order.status == 'paid' || @order.status == 'completed' %> + + <% else %> + + <% end %> + + + <%= @order.status.humanize %> + +
+
+
+ + +
+

Événement

+
+

<%= @order.event.name %>

+
+ <% if @order.event.start_time %> +
+ + + + <%= @order.event.start_time.strftime("%d %B %Y Ă  %H:%M") %> +
+ <% end %> + <% if @order.event.venue_name.present? %> +
+ + + + + <%= @order.event.venue_name %> +
+ <% end %> + <% if @order.event.venue_address.present? %> +
+ + + + <%= @order.event.venue_address %> +
+ <% end %> +
+
+
+ + +
+

Récapitulatif

+ + <% @tickets.each do |ticket| %> +
+
+

<%= ticket.ticket_type.name %>

+
+ + + + <%= ticket.first_name %> <%= ticket.last_name %> +
+ <% if @order.status == 'paid' || @order.status == 'completed' %> +
+ + + + Actif +
+ <% end %> +
+
+
<%= ticket.price_euros %>€
+
<% end %> - <% if @order.can_retry_payment? %> - <%= link_to checkout_order_path(@order), class: "bg-purple-600 hover:bg-purple-700 text-white font-medium py-2 px-4 rounded-lg transition-colors" do %> -
- - +
+ + +
+
+ Total <%= @order.status == 'paid' || @order.status == 'completed' ? 'payé' : 'à payer' %> + + <%= @order.total_amount_euros %>€ + +
+
+
+ + +
+ <% if @order.status == 'paid' || @order.status == 'completed' %> + +
+

Accédez à Vos Billets

+

Téléchargez ou consultez vos billets

+
+ +
+ +
+
+ + - Procéder au paiement +
+
+

Télécharger Vos Billets

+

Gardez vos billets sur votre téléphone ou imprimez-les.

+
+ <% @tickets.each_with_index do |ticket, index| %> +
+ <%= link_to ticket_path(ticket.qr_code), class: "flex-1 flex items-center text-purple-700 hover:text-purple-800 font-medium" do %> +
+ <%= index + 1 %> +
+ <%= ticket.first_name %> <%= ticket.last_name %> + <% end %> + <%= link_to ticket_download_path(ticket.qr_code), class: "ml-3 p-2 text-purple-600 hover:text-purple-800 hover:bg-purple-200 rounded-lg transition-colors", title: "Télécharger le billet PDF" do %> + + + + <% end %> +
+ <% end %> +
+
+
+ + +
+
+ + + +
+
+

Le Jour de l'Événement

+

Présentez votre billet (QR code) à l'entrée. Arrivez un peu en avance !

+
+
+
+ <% else %> + +
+

Paiement Requis

+

Votre commande nécessite un paiement

+
+ + <% if @order.can_retry_payment? %> +
+ <%= link_to checkout_order_path(@order), class: "block w-full text-center py-3 px-4 bg-orange-600 hover:bg-orange-700 text-white font-medium rounded-lg transition-colors" do %> +
+ + + + Procéder au Paiement +
+ <% end %> +
+ <% end %> + <% end %> + + +
+
+ <%= link_to dashboard_path, class: "block w-full text-center py-3 px-4 bg-purple-600 hover:bg-purple-700 text-white font-medium rounded-lg transition-colors" do %> +
+ + + + Retour au Tableau de Bord
<% end %> - <% end %> + <%= link_to event_path(@order.event.slug, @order.event), class: "block w-full text-center py-3 px-4 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 transition-colors" do %> +
+ + + + Voir l'Événement Complet +
+ <% end %> +
diff --git a/app/views/pages/dashboard.html.erb b/app/views/pages/dashboard.html.erb index 376f154..b694cb9 100755 --- a/app/views/pages/dashboard.html.erb +++ b/app/views/pages/dashboard.html.erb @@ -1,39 +1,36 @@
- -
-
-

Tableau de bord

+ +
+
+
+

Mon tableau de bord

+

Gérez vos commandes et accédez à vos billets

+
<% if current_user.promoter? %> -
- <%= link_to promoter_events_path, class: "inline-flex items-center px-4 py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200" do %> +
+ <%= link_to promoter_events_path, class: "inline-flex items-center justify-center px-4 py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200 text-sm sm:text-base" do %> - Mes événements + 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 %> + <%= link_to new_promoter_event_path, class: "inline-flex items-center justify-center px-4 py-2 bg-black text-white font-medium rounded-lg hover:bg-gray-800 transition-colors duration-200 text-sm sm:text-base" do %> - Créer un événement + Créer un Événement <% end %>
+ <% else %> + <%= link_to events_path, class: "inline-flex items-center justify-center px-4 py-2 bg-purple-600 text-white font-medium rounded-lg hover:bg-purple-700 transition-colors duration-200 text-sm sm:text-base" do %> + + Découvrir des Événements + <% end %> <% end %>
-
- - <%= render partial: 'components/metric_card', locals: { title: "Mes réservations", value: @booked_events, classes: "from-green-100 to-emerald-100" } %> - - <%= render partial: 'components/metric_card', locals: { title: "Événements aujourd'hui", value: @events_today, classes: "from-blue-100 to-sky-100" } %> - - <%= render partial: 'components/metric_card', locals: { title: "Événements demain", value: @events_tomorrow, classes: "from-purple-100 to-indigo-100" } %> - - <%= render partial: 'components/metric_card', locals: { title: "À venir", value: @upcoming_events, classes: "from-orange-100 to-amber-100" } %> - -
<% if @draft_orders.any? %> -
+
@@ -41,7 +38,7 @@ - Commandes en attente de paiement + Commandes en Attente de Paiement

Vous avez des commandes qui nécessitent un paiement

@@ -62,7 +59,7 @@

- Commande #<%= order.id %> + Order #<%= order.id %>
@@ -92,7 +89,7 @@ <%= link_to retry_payment_order_path(order), method: :post, class: "inline-flex items-center px-4 py-2 bg-orange-600 text-white text-sm font-medium rounded-lg hover:bg-orange-700 transition-colors duration-200" do %> - Reprendre le paiement (<%= order.total_amount_euros %>€) + Reprendre le Paiement (€<%= order.total_amount_euros %>) <% end %>
@@ -102,96 +99,148 @@
<% end %> - -
+ +
-

Mes événements réservés

+
+

Mes Commandes

+ + <%= pluralize(@user_orders.count, 'commande') %> + +
- <% if @user_booked_events.any? %> -
    - <% @user_booked_events.each do |event| %> -
  • - <%= render partial: 'components/event_item', locals: { event: event } %> -
  • + <% if @user_orders.any? %> +
    + <% @user_orders.each do |order| %> +
    +
    +
    +
    +

    <%= order.event.name %>

    + + <%= order.status.humanize %> + +
    + +
    +
    + + <%= order.event.start_time.strftime("%d %B %Y Ă  %H:%M") %> +
    +
    + + <%= order.event.venue_name %> +
    +
    + + <%= pluralize(order.tickets.count, 'billet') %> +
    +
    + +
    + Order #<%= order.id %> • <%= order.created_at.strftime("%m/%d/%Y") %> • €<%= order.total_amount_euros %> +
    +
    + +
    + <%= link_to order_path(order), + class: "inline-flex items-center px-3 py-2 bg-purple-600 hover:bg-purple-700 text-white text-sm font-medium rounded-lg transition-colors duration-200" do %> + + Voir les Détails + <% end %> +
    +
    + + +
    +
    + <% order.tickets.limit(3).each do |ticket| %> +
    +
    + + <%= ticket.ticket_type.name %> + - <%= ticket.first_name %> <%= ticket.last_name %> +
    +
    + <%= link_to ticket_download_path(ticket.qr_code), + class: "text-purple-600 hover:text-purple-800 dark:text-purple-400 dark:hover:text-purple-200" do %> + + <% end %> +
    +
    + <% end %> + <% if order.tickets.count > 3 %> +
    + et <%= pluralize(order.tickets.count - 3, 'autre billet') %> +
    + <% end %> +
    +
    +
    <% end %> -
- <% if @booked_events > 5 %> +
+ + <% if @user_orders.count >= 10 %>
- <%= link_to "Voir toutes mes réservations", "#", class: "text-purple-600 dark:text-purple-400 hover:text-purple-800 dark:hover:text-purple-200 font-medium transition-colors duration-200" %> + <%= link_to "Voir Toutes Mes Commandes", orders_path, class: "text-purple-600 dark:text-purple-400 hover:text-purple-800 dark:hover:text-purple-200 font-medium transition-colors duration-200" %>
<% end %> <% else %> -
-

Vous n'avez encore réservé aucun événement.

- <%= link_to "Découvrir les événements", events_path, class: "inline-flex items-center px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors duration-200" %> +
+
+ +
+

Aucune Commande

+

Vous n'avez pas encore passé de commandes.

+ <%= link_to events_path, class: "inline-flex items-center px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors duration-200" do %> + + Découvrir des Événements + <% end %>
<% end %>
- -
-
-

Évenements du jour

-
-
- <% if @today_events.any? %> -
    - <% @today_events.each do |event| %> -
  • - <%= render partial: 'components/event_item', locals: { event: event } %> -
  • + + <% if @user_orders.any? %> +
    +
    +
    +

    Découvrir d'autres événements

    + <%= link_to events_path, class: "text-purple-600 dark:text-purple-400 hover:text-purple-800 dark:hover:text-purple-200 font-medium text-sm transition-colors duration-200" do %> + Voir tout → <% end %> -
- <% else %> -

Aucun évenement aujourd'hui.

- <% end %> -
-
- - -
-
-

Évenements de demain

-
-
- <% if @tomorrow_events.any? %> -
    - <% @tomorrow_events.each do |event| %> -
  • - <%= render partial: 'components/event_item', locals: { event: event } %> -
  • - <% end %> -
- <% else %> -

Aucune partie demain.

- <% end %> -
-
- - -
-
-

Autres évenements à venir

-
-
- <% if @other_events.any? %> -
    - <% @other_events.each do |event| %> -
  • - <%= render partial: 'components/event_item', locals: { event: event } %> -
  • - <% end %> -
- - -
- <%= paginate @other_events %>
- <% else %> -

Aucune autre partie Ă  venir.

- <% end %> +
+
+ <% if @upcoming_preview_events.any? %> +
+ <% @upcoming_preview_events.each do |event| %> +
+

<%= event.name %>

+
+
+ + <%= event.start_time.strftime("%d %B") %> +
+
+ + <%= event.venue_name %> +
+
+
+ <%= link_to event_path(event.slug, event), class: "text-purple-600 dark:text-purple-400 hover:text-purple-800 dark:hover:text-purple-200 text-sm font-medium" do %> + Voir l'Événement → + <% end %> +
+
+ <% end %> +
+ <% else %> +

Aucun événement à venir pour le moment.

+ <% end %> +
-
+ <% end %>
diff --git a/config/routes.rb b/config/routes.rb index 5ad6caf..1a45a52 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -42,7 +42,7 @@ Rails.application.routes.draw do get "orders/new/events/:slug.:id", to: "orders#new", as: "event_order_new" post "orders/create/events/:slug.:id", to: "orders#create", as: "event_order_create" - resources :orders, only: [ :show ] do + resources :orders, only: [ :index, :show ] do member do get :checkout post :retry_payment