feat: add state filtering to cities index
- Implement state filtering in the CitiesController - Add new scope `by_state` in the City model - Update cities index view to include state dropdown - Add slug column to states for friendly URLs - Update English locale to include 'All States' This commit enhances the cities index page by allowing users to filter cities based on the selected state. It introduces a new scope in the City model for state filtering and updates the view to present a dropdown for state selection. Additionally, it adds a slug column to the states table to support friendly URLs, improving the overall user experience.
This commit is contained in:
parent
fe5c0d5113
commit
f51dc8370b
@ -21,6 +21,11 @@ class CitiesController < ApplicationController
|
||||
@cities = @cities.by_country(@current_country.id) if @current_country
|
||||
end
|
||||
|
||||
if params[:state]
|
||||
@current_state = State.friendly.find(params[:state])
|
||||
@cities = @cities.by_state(@current_state.id) if @current_state
|
||||
end
|
||||
|
||||
@cities = @cities.page(params[:page]).per(12)
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -19,6 +19,7 @@ class City < ApplicationRecord
|
||||
|
||||
scope :by_region, ->(region_id) { joins(:country).where(countries: { region_id: region_id }) }
|
||||
scope :by_country, ->(country_id) { where(country_id: country_id) }
|
||||
scope :by_state, ->(state_id) { where(state_id: state_id) }
|
||||
scope :active, -> { where(active: true) }
|
||||
scope :inactive, -> { where(active: false) }
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
class State < ApplicationRecord
|
||||
extend FriendlyId
|
||||
friendly_id :name, use: :slugged
|
||||
|
||||
belongs_to :country
|
||||
has_many :cities
|
||||
|
||||
|
@ -47,8 +47,10 @@
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-ghost gap-2">
|
||||
<!-- 大洲/地区 (Region) SVG - 使用地球仪图标 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/>
|
||||
</svg>
|
||||
<%= @current_region&.localized_name || t("text.all_regions") %>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
@ -76,8 +78,10 @@
|
||||
<% if @current_region %>
|
||||
<div class="dropdown dropdown-bottom">
|
||||
<button class="btn btn-ghost gap-2">
|
||||
<!-- 国家 (Country) SVG - 现代旗帜图标 -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 21v-4m0 0V5a2 2 0 012-2h6.5l1 1H21l-3 6 3 6h-8.5l-1-1H5a2 2 0 00-2 2zm9-13.5V9" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M4 5a1 1 0 011-1h14a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h14a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6z"/>
|
||||
</svg>
|
||||
<%= @current_country&.localized_name || t("text.all_countries") %>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
@ -101,6 +105,39 @@
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if @current_country %>
|
||||
<div class="dropdown dropdown-bottom">
|
||||
<button class="btn btn-ghost gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
|
||||
</svg>
|
||||
<%= @current_state&.name || t("text.all_states") %>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</button>
|
||||
<ul class="dropdown-content z-[1] menu p-2 shadow-lg bg-base-100 rounded-box w-52 max-h-80 overflow-y-auto flex-nowrap">
|
||||
<li>
|
||||
<%= link_to "#{t("text.all_in")} #{@current_country.localized_name}",
|
||||
cities_path(region: @current_region.slug),
|
||||
class: "#{@current_country ? '' : 'active'}" %>
|
||||
</li>
|
||||
<div class="divider my-1"></div>
|
||||
<% @current_country.states.order(:name).each do |state| %>
|
||||
<li>
|
||||
<%= link_to "#{state.name}",
|
||||
cities_path(region: @current_region.slug, country: @current_country.slug, state: state.slug),
|
||||
class: "#{@current_state == state ? 'active' : ''}" %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-sm text-base-content/70 hidden">
|
||||
|
@ -67,6 +67,7 @@ en:
|
||||
search_cities: "Search cities..."
|
||||
all_regions: "All Regions"
|
||||
all_countries: "All Countries"
|
||||
all_states: "All States"
|
||||
all_in: "All in"
|
||||
showing: "Showing"
|
||||
weather_arts: "Weather Arts"
|
||||
|
6
db/migrate/20250226011649_add_slug_to_states.rb
Normal file
6
db/migrate/20250226011649_add_slug_to_states.rb
Normal file
@ -0,0 +1,6 @@
|
||||
class AddSlugToStates < ActiveRecord::Migration[8.0]
|
||||
def change
|
||||
add_column :states, :slug, :string
|
||||
add_index :states, :slug, unique: true
|
||||
end
|
||||
end
|
4
db/schema.rb
generated
4
db/schema.rb
generated
@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_02_11_035423) do
|
||||
ActiveRecord::Schema[8.0].define(version: 2025_02_26_011649) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_catalog.plpgsql"
|
||||
|
||||
@ -205,7 +205,9 @@ ActiveRecord::Schema[8.0].define(version: 2025_02_11_035423) do
|
||||
t.string "wiki_data_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "slug"
|
||||
t.index ["country_id"], name: "index_states_on_country_id"
|
||||
t.index ["slug"], name: "index_states_on_slug", unique: true
|
||||
end
|
||||
|
||||
create_table "subregions", force: :cascade do |t|
|
||||
|
Loading…
Reference in New Issue
Block a user