diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index fdbc6e281..d460b1ac5 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -6,7 +6,35 @@ module Admin def index authorize User - @users = policy_scope(User).order(:email) + scope = policy_scope(User) + .left_joins(family: :subscription) + .includes(family: :subscription) + + scope = scope.where(role: params[:role]) if params[:role].present? + scope = apply_trial_filter(scope) if params[:trial_status].present? + + @users = scope.order( + Arel.sql( + "CASE " \ + "WHEN subscriptions.status = 'trialing' THEN 0 " \ + "WHEN subscriptions.id IS NULL THEN 1 " \ + "ELSE 2 END, " \ + "subscriptions.trial_ends_at ASC NULLS LAST, users.email ASC" + ) + ) + + family_ids = @users.map(&:family_id).uniq + @accounts_count_by_family = Account.where(family_id: family_ids).group(:family_id).count + @entries_count_by_family = Entry.joins(:account).where(accounts: { family_id: family_ids }).group("accounts.family_id").count + + user_ids = @users.map(&:id).uniq + @last_login_by_user = Session.where(user_id: user_ids).group(:user_id).maximum(:created_at) + @sessions_count_by_user = Session.where(user_id: user_ids).group(:user_id).count + + @trials_expiring_in_7_days = Subscription + .where(status: :trialing) + .where(trial_ends_at: Time.current..7.days.from_now) + .count end def update @@ -34,5 +62,17 @@ module Admin def user_params params.require(:user).permit(:role) end + + def apply_trial_filter(scope) + case params[:trial_status] + when "expiring_soon" + scope.where(subscriptions: { status: :trialing }) + .where(subscriptions: { trial_ends_at: Time.current..7.days.from_now }) + when "trialing" + scope.where(subscriptions: { status: :trialing }) + else + scope + end + end end end diff --git a/app/views/admin/users/index.html.erb b/app/views/admin/users/index.html.erb index 002e1a06c..abc09a652 100644 --- a/app/views/admin/users/index.html.erb +++ b/app/views/admin/users/index.html.erb @@ -1,53 +1,120 @@ <%= content_for :page_title, t(".title") %> -
<%= t(".description") %>
+<%= t(".description") %>
+<%= user.display_name %>
-<%= user.email %>
-<%= t(".summary.trials_expiring_7_days") %>
+<%= @trials_expiring_in_7_days %>
+| <%= t(".table.user") %> | +<%= t(".table.trial_ends_at") %> | +<%= t(".table.family_accounts") %> | +<%= t(".table.family_transactions") %> | +<%= t(".table.role") %> | +
|---|---|---|---|---|
|
+
+
+
+ <%= user.initials %>
+
+
+
+ <%= user.display_name %> +<%= user.email %> ++ <%= t(".table.last_login") %>: <%= @last_login_by_user[user.id]&.to_fs(:long) || t(".table.never") %> + <%= t(".table.session_count") %>: <%= number_with_delimiter(@sessions_count_by_user[user.id] || 0) %> + + |
+ + <%= user.family.subscription&.trial_ends_at&.to_fs(:long) || t(".not_available") %> + | ++ <%= number_with_delimiter(@accounts_count_by_family[user.family_id] || 0) %> + | ++ <%= number_with_delimiter(@entries_count_by_family[user.family_id] || 0) %> + | ++ <% if user.id == Current.user.id %> + <%= t(".you") %> + <% else %> + <%= form_with model: [:admin, user], method: :patch, class: "flex items-center justify-end gap-2" do |form| %> + <%= form.select :role, + options_for_select([ + [t(".roles.guest"), "guest"], + [t(".roles.member", default: "Member"), "member"], + [t(".roles.admin"), "admin"], + [t(".roles.super_admin"), "super_admin"] + ], user.role), + {}, + class: "text-sm rounded-lg border border-primary bg-container text-primary px-2 py-1", + onchange: "this.form.requestSubmit()" %> + <% end %> + <% end %> + | +
<%= t(".no_users") %>
<%= t(".no_users") %>
-