From c5f6b2f6b314b54b422d676e4eadf59a82159d64 Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Fri, 27 Mar 2026 13:09:43 -0700 Subject: [PATCH] feat: Add admin dashboard with statistics cards --- app/actions/admin/index.rb | 73 ++++++++++++++++++++++++ app/templates/admin/index.html.erb | 91 ++++++++++++++++++++++++++++++ app/views/admin/index.rb | 14 +++++ 3 files changed, 178 insertions(+) create mode 100644 app/actions/admin/index.rb create mode 100644 app/templates/admin/index.html.erb create mode 100644 app/views/admin/index.rb diff --git a/app/actions/admin/index.rb b/app/actions/admin/index.rb new file mode 100644 index 0000000..22c6af5 --- /dev/null +++ b/app/actions/admin/index.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +module EuchreCamp + module Actions + module Admin + class Index < EuchreCamp::Action + include Deps[ + players_repo: 'repositories.players', + events_repo: 'repositories.events', + matches_repo: 'repositories.matches' + ] + + def handle(request, response) + # Check if user has permission to view admin panel + user = current_user(request) + unless user && EuchreCamp::Services::Authorization.can?(user, :view_admin_panel) + response.flash[:error] = 'Access denied' + response.redirect_to '/rankings' + return + end + + # Get dashboard statistics + total_players = players_repo.all.length + active_tournaments = events_repo.upcoming.length + completed_tournaments = events_repo.completed.length + recent_matches = get_recent_matches + + user = current_user(request) + render_with_player(request, response, + total_players: total_players, + active_tournaments: active_tournaments, + completed_tournaments: completed_tournaments, + recent_matches: recent_matches, + current_user: user + ) + end + + private + + def get_recent_matches + rom = EuchreCamp::App["persistence.rom"] + matches = rom.relations[:matches] + .order(Sequel.desc(:id)) + .limit(5) + .to_a + + # Get player names + all_players = rom.relations[:players].to_a.to_h { |p| [p[:id], p] } + + matches.map do |match| + team_1 = [ + all_players[match[:team_1_p1_id]], + all_players[match[:team_1_p2_id]] + ].compact + team_2 = [ + all_players[match[:team_2_p1_id]], + all_players[match[:team_2_p2_id]] + ].compact + + { + id: match[:id], + team_1: team_1, + team_2: team_2, + score: "#{match[:team_1_score]}-#{match[:team_2_score]}", + status: match[:status], + played_at: match[:played_at] + } + end + end + end + end + end +end diff --git a/app/templates/admin/index.html.erb b/app/templates/admin/index.html.erb new file mode 100644 index 0000000..44697bf --- /dev/null +++ b/app/templates/admin/index.html.erb @@ -0,0 +1,91 @@ +

Admin Dashboard

+ +
+
+
<%= total_players %>
+
Total Players
+ Manage Players → +
+ +
+
<%= active_tournaments %>
+
Active Tournaments
+ Manage Tournaments → +
+ +
+
<%= completed_tournaments %>
+
Completed Tournaments
+ View History → +
+ +
+
<%= recent_matches.count %>
+
Recent Matches
+ Record Match → +
+
+ +
+ +
+

Quick Actions

+
+ <% if defined?(current_user) && current_user %> + Record Match Result + <% if EuchreCamp::Services::Authorization.can?(current_user, :create_tournament) %> + Create Tournament + <% end %> + <% if EuchreCamp::Services::Authorization.can?(current_user, :edit_any_record) %> + Add Player + <% end %> + Upload CSV + <% else %> + Record Match Result + <% end %> +
+
+ +
+ +
+

Recent Matches

+ <% if recent_matches.any? %> + + + + + + + + + + + + <% recent_matches.each do |match| %> + + + + + + + + <% end %> + +
Match IDTeam 1ScoreTeam 2Date
<%= match[:id] %><%= match[:team_1].map { |p| p[:name] }.join(' + ') %><%= match[:score] %><%= match[:team_2].map { |p| p[:name] }.join(' + ') %><%= match[:played_at]&.strftime('%Y-%m-%d') || '-' %>
+ <% else %> +

No matches recorded yet.

+ <% end %> +
+ +
+ + diff --git a/app/views/admin/index.rb b/app/views/admin/index.rb new file mode 100644 index 0000000..20575a6 --- /dev/null +++ b/app/views/admin/index.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module EuchreCamp + module Views + module Admin + class Index < EuchreCamp::View + expose :total_players + expose :active_tournaments + expose :completed_tournaments + expose :recent_matches + end + end + end +end