feat: implement filtering and pagination for weather arts
- Add region selection for filtering weather arts by region - Implement sorting options for newest and oldest entries - Update pagination to show links for each page when applicable - Adjust the number of items displayed per page to 10 This commit enhances the user experience by allowing users to filter and sort weather arts based on their preferences. It also improves the pagination logic to provide more manageable navigation through large datasets, making it easier for users to find the artworks they are interested in.
This commit is contained in:
parent
3a6d247451
commit
a4de04874d
@ -1,8 +1,21 @@
|
||||
class ArtsController < ApplicationController
|
||||
def index
|
||||
@weather_arts = WeatherArt.includes(:city, city: [ :country, { country: :region } ])
|
||||
.order(created_at: :desc)
|
||||
.page(params[:page])
|
||||
.per(2)
|
||||
@regions = Region.all
|
||||
@current_region = Region.find(params[:region]) if params[:region].present?
|
||||
|
||||
@weather_arts = WeatherArt.includes(city: [:country, { country: :region }])
|
||||
|
||||
if @current_region
|
||||
@weather_arts = @weather_arts.joins(city: :country)
|
||||
.where(countries: { region_id: @current_region.id })
|
||||
end
|
||||
|
||||
@weather_arts = if params[:sort] == 'oldest'
|
||||
@weather_arts.order(created_at: :asc)
|
||||
else
|
||||
@weather_arts.order(created_at: :desc)
|
||||
end
|
||||
|
||||
@weather_arts = @weather_arts.page(params[:page]).per(10)
|
||||
end
|
||||
end
|
||||
|
@ -1,66 +1,167 @@
|
||||
<!-- app/views/arts/index.html.erb -->
|
||||
<div class="min-h-screen">
|
||||
<!-- 页面标题 -->
|
||||
<div class="bg-gradient-to-r from-primary/10 to-secondary/10 py-16">
|
||||
<!-- 页面标题和背景 -->
|
||||
<% featured_art = @weather_arts.first %>
|
||||
<div class="relative">
|
||||
<!-- 背景图像 -->
|
||||
<% if featured_art&.image&.attached? %>
|
||||
<div class="absolute inset-0 h-[40vh] overflow-hidden">
|
||||
<%= image_tag featured_art.image,
|
||||
class: "w-full h-full object-cover" %>
|
||||
<div class="absolute inset-0 bg-gradient-to-b from-base-100/30 via-base-100/60 to-base-100"></div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- 标题内容 -->
|
||||
<div class="relative pt-20 pb-32">
|
||||
<div class="container mx-auto px-4">
|
||||
<h1 class="text-4xl md:text-5xl font-display font-bold text-center mb-4">
|
||||
<div class="max-w-3xl mx-auto text-center space-y-6">
|
||||
<h1 class="text-4xl md:text-5xl font-display font-bold">
|
||||
Weather Arts Gallery
|
||||
</h1>
|
||||
<p class="text-xl text-center text-base-content/70 max-w-2xl mx-auto">
|
||||
Explore our collection of AI-generated weather art from cities around the world
|
||||
<p class="text-xl text-base-content/70">
|
||||
Discover AI-generated weather art from cities around the world
|
||||
</p>
|
||||
|
||||
<!-- 如果有特色图片,显示其信息 -->
|
||||
<% if featured_art %>
|
||||
<div class="text-sm text-base-content/60 pt-4">
|
||||
Latest from <%= featured_art.city.name %>, <%= featured_art.city.country.name %>
|
||||
<span class="mx-2">•</span>
|
||||
<%= featured_art.weather_date.strftime("%B %d, %Y") %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container mx-auto px-4 py-12">
|
||||
<!-- 筛选导航 -->
|
||||
<div class="container mx-auto px-4 -mt-8">
|
||||
<div class="bg-base-100 shadow-xl rounded-box p-6 mb-12">
|
||||
<!-- 筛选选项 -->
|
||||
<div class="flex flex-wrap gap-4 justify-center items-center">
|
||||
<!-- 时间排序 -->
|
||||
<div class="dropdown">
|
||||
<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="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<%= params[:sort] == 'oldest' ? 'Oldest First' : 'Newest First' %>
|
||||
<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">
|
||||
<li>
|
||||
<%= link_to "Newest First", arts_path(sort: 'newest', region: params[:region]),
|
||||
class: "#{'active' if params[:sort] != 'oldest'}" %>
|
||||
</li>
|
||||
<li>
|
||||
<%= link_to "Oldest First", arts_path(sort: 'oldest', region: params[:region]),
|
||||
class: "#{'active' if params[:sort] == 'oldest'}" %>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 区域筛选 -->
|
||||
<div class="dropdown">
|
||||
<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="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&.name || 'All Regions' %>
|
||||
<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">
|
||||
<li>
|
||||
<%= link_to "All Regions", arts_path(sort: params[:sort]),
|
||||
class: "#{'active' unless @current_region}" %>
|
||||
</li>
|
||||
<div class="divider my-1"></div>
|
||||
<% @regions.each do |region| %>
|
||||
<li>
|
||||
<%= link_to region.name, arts_path(region: region.id, sort: params[:sort]),
|
||||
class: "#{'active' if @current_region == region}" %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 结果统计 -->
|
||||
<div class="text-center text-sm text-base-content/70 mt-4">
|
||||
Showing <%= @weather_arts.total_count %> weather arts
|
||||
<% if @current_region %>
|
||||
from <%= @current_region.name %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 图片网格 -->
|
||||
<div class="container mx-auto px-4 pb-16">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
|
||||
<% @weather_arts.each do |art| %>
|
||||
<div class="card bg-base-100 shadow-xl hover:shadow-2xl transition-all duration-300 group">
|
||||
<!-- 图片 -->
|
||||
<div class="card bg-base-100 shadow-xl hover:shadow-2xl transition-all duration-300 group overflow-hidden">
|
||||
<!-- 图片部分 -->
|
||||
<figure class="relative aspect-square overflow-hidden">
|
||||
<% if art.image.attached? %>
|
||||
<%= image_tag art.image,
|
||||
class: "w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-500" %>
|
||||
<!-- 渐变遮罩 -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
|
||||
<!-- 悬停时显示的信息 -->
|
||||
<div class="absolute inset-0 p-6 flex flex-col justify-end opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<h3 class="text-white font-display text-xl mb-2">
|
||||
<!-- 渐变遮罩 -->
|
||||
<div class="absolute inset-0 bg-gradient-to-t from-black via-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
|
||||
<!-- 悬停信息 -->
|
||||
<div class="absolute inset-0 p-6 flex flex-col justify-end translate-y-4 opacity-0 group-hover:translate-y-0 group-hover:opacity-100 transition-all duration-300">
|
||||
<div class="text-white space-y-2">
|
||||
<h3 class="text-xl font-display font-bold">
|
||||
<%= art.city.name %>
|
||||
</h3>
|
||||
<p class="text-white/80 text-sm">
|
||||
<%= art.weather_date.strftime("%B %d, %Y") %>
|
||||
</p>
|
||||
<p class="text-white/90 mt-2">
|
||||
<%= art.temperature %>°C, <%= art.description %>
|
||||
<p class="text-sm text-white/80">
|
||||
<%= art.city.country.name %>
|
||||
</p>
|
||||
<div class="flex items-center gap-2 text-white/90">
|
||||
<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 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z" />
|
||||
</svg>
|
||||
<%= art.description %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</figure>
|
||||
|
||||
<!-- 快速信息 -->
|
||||
<!-- 信息部分 -->
|
||||
<div class="card-body p-4">
|
||||
<div class="flex justify-between items-start">
|
||||
<div class="flex justify-between items-start mb-3">
|
||||
<div>
|
||||
<h3 class="font-display font-bold">
|
||||
<h3 class="font-display font-bold leading-tight">
|
||||
<%= art.city.name %>
|
||||
</h3>
|
||||
<p class="text-sm text-base-content/70">
|
||||
<%= art.city.country.name %>
|
||||
<%= art.weather_date.strftime("%B %d, %Y") %>
|
||||
</p>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-lg font-bold"><%= art.temperature %>°C</div>
|
||||
<div class="text-2xl font-bold text-primary">
|
||||
<%= art.temperature %>°C
|
||||
</div>
|
||||
<div class="text-sm text-base-content/70">
|
||||
<%= art.weather_date.strftime("%b %d") %>
|
||||
<%= art.humidity %>% humidity
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= link_to city_weather_art_path(art.city, art),
|
||||
class: "btn btn-ghost btn-sm w-full mt-3" do %>
|
||||
class: "btn btn-primary btn-sm w-full" do %>
|
||||
View Details
|
||||
<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="M14 5l7 7m0 0l-7 7m7-7H3" />
|
||||
</svg>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@ -68,13 +169,19 @@
|
||||
</div>
|
||||
|
||||
<!-- 分页 -->
|
||||
<% if @weather_arts.total_pages > 1 %>
|
||||
<div class="flex justify-center mt-12">
|
||||
<div class="btn-group">
|
||||
<%= link_to_prev_page @weather_arts, 'Previous',
|
||||
<%= link_to_prev_page @weather_arts, "Previous",
|
||||
class: "btn btn-outline #{'btn-disabled' unless @weather_arts.prev_page}" %>
|
||||
<%= link_to_next_page @weather_arts, 'Next',
|
||||
<% @weather_arts.total_pages.times do |i| %>
|
||||
<%= link_to i + 1, arts_path(page: i + 1, region: params[:region], sort: params[:sort]),
|
||||
class: "btn btn-outline #{'btn-active' if @weather_arts.current_page == i + 1}" %>
|
||||
<% end %>
|
||||
<%= link_to_next_page @weather_arts, "Next",
|
||||
class: "btn btn-outline #{'btn-disabled' unless @weather_arts.next_page}" %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user