Skip to content

Commit 9d1c813

Browse files
authored
Feature/sort users (#70)
* Add users sorting * Fixing dropdown
1 parent 2811ca5 commit 9d1c813

4 files changed

Lines changed: 120 additions & 13 deletions

File tree

app/controllers/users_controller.rb

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,43 @@ def index
1313
@filter_company = params[:company]
1414
end
1515

16-
@users = @users.order(github_stars_sum: :desc, published_posts_count: :desc, github_repos_count: :desc)
17-
.page(params[:page])
18-
.per(20)
16+
# Sorting
17+
@sort = params[:sort].presence || "top"
18+
@dir = params[:dir] == "asc" ? "asc" : "desc"
19+
20+
# Normalize legacy/alternate sort params to our toggle model
21+
case @sort
22+
when "old"
23+
@sort = "new"
24+
@dir = "asc"
25+
when "za", "z-a"
26+
@sort = "az"
27+
@dir = "desc"
28+
end
29+
30+
direction = @dir.to_sym
31+
32+
@users = case @sort
33+
when "new"
34+
@users.order(created_at: direction)
35+
when "old"
36+
@users.order(created_at: direction)
37+
when "projects"
38+
@users.order(github_repos_count: direction)
39+
when "posts"
40+
@users.order(published_posts_count: direction)
41+
when "comments"
42+
@users.order(published_comments_count: direction)
43+
when "stars"
44+
@users.order(github_stars_sum: direction)
45+
when "az"
46+
# Toggle A–Z vs Z–A using direction
47+
@users.order(Arel.sql("COALESCE(name, username) #{direction == :asc ? 'ASC' : 'DESC'}"))
48+
else
49+
@users.order(github_stars_sum: direction, published_posts_count: direction, github_repos_count: direction)
50+
end
51+
52+
@users = @users.page(params[:page]).per(20)
1953
end
2054

2155
def show

app/views/users/_repository_tile.html.erb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,9 @@
2121

2222
<!-- Repository Description -->
2323
<% if repository[:description].present? %>
24-
<p class="text-gray-600 mb-4 line-clamp-2">
24+
<p class="text-gray-600 mb-4">
2525
<%= repository[:description] %>
2626
</p>
27-
<% else %>
28-
<p class="text-gray-400 italic mb-4">
29-
<%= t('users.repository_tile.no_description') %>
30-
</p>
3127
<% end %>
3228

3329
<!-- Repository Metrics -->

app/views/users/index.html.erb

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,67 @@
3030
<div class="space-y-8">
3131
<!-- Header -->
3232
<h1 class="text-4xl font-black text-gray-900 mb-4"><%= t('users.index.title') %></h1>
33-
<p class="text-lg text-gray-600">
34-
<%= t('users.index.description') %>
35-
</p>
33+
<div class="md:flex md:items-center md:justify-between w-full">
34+
<p class="text-left text-lg text-gray-600 md:flex-1 min-w-0">
35+
<% if user_signed_in? %>
36+
<%= t('users.index.description', count: (@users.respond_to?(:total_count) ? @users.total_count : @users.count)) %>
37+
<% else %>
38+
<%= link_to t('users.index.join'), github_auth_with_return_path, class: "underline hover:text-red-600 transition-colors" %>
39+
<%= t('users.index.join_suffix', count: (@users.respond_to?(:total_count) ? @users.total_count : @users.count)) %>
40+
<% end %>
41+
</p>
42+
43+
<div class="relative md:ml-auto mt-2 md:mt-0 flex-shrink-0" data-controller="dropdown">
44+
<button type="button" class="flex items-center gap-x-1 text-sm rounded-full cursor-pointer bg-gray-100 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 px-3 py-2" data-action="click->dropdown#toggle click@window->dropdown#hide">
45+
<span class="text-gray-400"><%= t('users.index.sort_label') %>:</span>
46+
<span class="text-gray-700 font-medium">
47+
<% effective_sort = (@sort == 'old' ? 'new' : @sort) %>
48+
<% effective_dir = (@sort == 'old' ? 'asc' : @dir) %>
49+
<% closed_label = case effective_sort
50+
when 'new' then (effective_dir == 'asc' ? t('users.index.sort.new_reverse') : t('users.index.sort.new'))
51+
when 'projects' then (effective_dir == 'asc' ? t('users.index.sort.projects_reverse') : t('users.index.sort.projects'))
52+
when 'posts' then (effective_dir == 'asc' ? t('users.index.sort.posts_reverse') : t('users.index.sort.posts'))
53+
when 'comments' then (effective_dir == 'asc' ? t('users.index.sort.comments_reverse') : t('users.index.sort.comments'))
54+
when 'stars' then (effective_dir == 'asc' ? t('users.index.sort.stars_reverse') : t('users.index.sort.stars'))
55+
when 'az' then (effective_dir == 'asc' ? t('users.index.sort.az') : t('users.index.sort.az_reverse'))
56+
else (effective_dir == 'asc' ? t('users.index.sort.top_reverse') : t('users.index.sort.top'))
57+
end %>
58+
<%= closed_label %>
59+
</span>
60+
<%= inline_svg_tag "chevron-down.svg", class: "ml-1 h-5 w-5 text-gray-400" %>
61+
</button>
62+
63+
<div class="hidden absolute mt-2 w-64 divide-y divide-gray-100 rounded-md bg-white shadow-lg ring-1 ring-black/5 focus:outline-none left-0 md:left-auto md:right-0 origin-top-left md:origin-top-right" data-dropdown-target="menu">
64+
<div class="py-1">
65+
<% # Helper to compute label and dir per option, showing the opposite for current based on direction %>
66+
<% def sort_link(label_key, reverse_label_key, key, current_sort, current_dir, filters)
67+
is_current = (current_sort == key)
68+
label = if is_current
69+
# If currently ascending, opposite is descending -> use main label; if descending, opposite is ascending -> use reverse label
70+
current_dir == 'asc' ? t(label_key) : t(reverse_label_key)
71+
else
72+
t(label_key)
73+
end
74+
dir = if is_current
75+
current_dir == 'asc' ? 'desc' : 'asc'
76+
else
77+
# Defaults: az -> asc, others -> desc
78+
key == 'az' ? 'asc' : 'desc'
79+
end
80+
link_to label, users_path(sort: key, dir: dir, location: filters[:location], company: filters[:company]), class: "block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:bg-gray-100 focus:text-gray-900 focus:outline-none cursor-pointer"
81+
end %>
82+
83+
<%= sort_link('users.index.sort.top', 'users.index.sort.top_reverse', 'top', @sort, @dir, { location: @filter_location, company: @filter_company }) %>
84+
<%= sort_link('users.index.sort.new', 'users.index.sort.new_reverse', 'new', @sort, @dir, { location: @filter_location, company: @filter_company }) %>
85+
<%= sort_link('users.index.sort.projects', 'users.index.sort.projects_reverse', 'projects', @sort, @dir, { location: @filter_location, company: @filter_company }) %>
86+
<%= sort_link('users.index.sort.posts', 'users.index.sort.posts_reverse', 'posts', @sort, @dir, { location: @filter_location, company: @filter_company }) %>
87+
<%= sort_link('users.index.sort.comments', 'users.index.sort.comments_reverse', 'comments', @sort, @dir, { location: @filter_location, company: @filter_company }) %>
88+
<%= sort_link('users.index.sort.stars', 'users.index.sort.stars_reverse', 'stars', @sort, @dir, { location: @filter_location, company: @filter_company }) %>
89+
<%= sort_link('users.index.sort.az', 'users.index.sort.az_reverse', 'az', @sort, @dir, { location: @filter_location, company: @filter_company }) %>
90+
</div>
91+
</div>
92+
</div>
93+
</div>
3694

3795
<!-- Active Filters -->
3896
<% if @filter_location.present? || @filter_company.present? %>

config/locales/en.yml

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ en:
3838
apple_app_title: &apple_app_title "WhyRuby"
3939
community:
4040
title: &community_title "Community"
41-
description: &community_description "Connect with passionate Ruby developers from around the world and explore their projects, posts, and stories"
41+
description: &community_description "Connect with %{count} passionate Ruby developers from around the world and explore their projects, posts, and stories"
42+
description_static: &community_description_static "Connect with passionate Ruby developers from around the world and explore their projects, posts, and stories"
4243
keywords: &community_keywords "ruby developers, ruby community, ruby programmers, rails developers"
4344
keywords:
4445
base: &keywords_base "Ruby, Ruby on Rails"
@@ -90,7 +91,7 @@ en:
9091
users:
9192
index:
9293
title: *community_title
93-
summary: *community_description
94+
summary: *community_description_static
9495
keywords: *community_keywords
9596
show:
9697
title: "%{display_name} (@%{username})"
@@ -102,9 +103,27 @@ en:
102103
index:
103104
title: *community_title
104105
description: *community_description
106+
join: "Join"
107+
join_suffix: "%{count} passionate Ruby developers from around the world and explore their projects, posts, and stories"
105108
keywords: *community_keywords
106109
invite_friends: "Invite your Ruby friends to join →"
107110
join_community: "Sign in with GitHub to appear on this page →"
111+
sort_label: "Sort"
112+
sort:
113+
top: "Top contributors"
114+
top_reverse: "Least contributors"
115+
new: "Newcomers"
116+
new_reverse: "Old members"
117+
projects: "Top projects"
118+
projects_reverse: "Fewest projects"
119+
posts: "Top posts"
120+
posts_reverse: "Fewest posts"
121+
comments: "Top comments"
122+
comments_reverse: "Fewest comments"
123+
stars: "Top stars"
124+
stars_reverse: "Fewest stars"
125+
az: "A–Z by name"
126+
az_reverse: "Z–A by name"
108127
show:
109128
view_all_repositories: "View all Ruby repositories on GitHub →"
110129
no_ruby_projects: "No Ruby projects found on GitHub."

0 commit comments

Comments
 (0)