From d91a56f8b223121a37e5198271eb4a3ce0d5a5d5 Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 29 Jun 2026 13:15:50 +0800 Subject: [PATCH] refactor(admin): extract comments filter tabs into FilterTabs component --- src/components/ui.rs | 35 +++++++++++++++++++++++++++++++++++ src/pages/admin/comments.rs | 17 ++++++----------- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/components/ui.rs b/src/components/ui.rs index 674cb05..27355c7 100644 --- a/src/components/ui.rs +++ b/src/components/ui.rs @@ -185,3 +185,38 @@ pub fn EmptyState(message: &'static str, variant: &'static str) -> Element { div { class: "{class}", "{message}" } } } + +/// 筛选选项卡组件。 +/// +/// 用于切换不同的视图或筛选条件(例如:全部、待审核、已通过等)。 +/// +/// Props: +/// - `items`:选项卡列表,每一项为 `(value, label)` +/// - `active_value`:当前选中的值 +/// - `on_change`:选项卡切换时的回调 +#[component] +pub fn FilterTabs( + items: Vec<(&'static str, &'static str)>, + active_value: String, + on_change: EventHandler, +) -> Element { + rsx! { + div { class: "flex gap-1 border-b border-paper-border", + for (value, label) in items { + button { + key: "{value}", + class: if active_value == *value { + "cursor-pointer px-4 py-2 text-sm font-medium border-b-2 border-paper-accent text-paper-primary" + } else { + "cursor-pointer px-4 py-2 text-sm font-medium text-paper-secondary hover:text-paper-primary transition-colors" + }, + onclick: { + let v = value.to_string(); + move |_| on_change.call(v.clone()) + }, + "{label}" + } + } + } + } +} diff --git a/src/pages/admin/comments.rs b/src/pages/admin/comments.rs index 6468bd2..97d6b9a 100644 --- a/src/pages/admin/comments.rs +++ b/src/pages/admin/comments.rs @@ -18,7 +18,7 @@ use crate::components::skeletons::atoms::SkeletonBox; use crate::components::skeletons::delayed_skeleton::DelayedSkeleton; use crate::components::empty_state::EmptyState; use crate::components::ui::{ - Pagination, StatusBadge, ADMIN_CARD_CLASS, ADMIN_ROW_HOVER, ADMIN_TABLE_CLASS, + FilterTabs, Pagination, StatusBadge, ADMIN_CARD_CLASS, ADMIN_ROW_HOVER, ADMIN_TABLE_CLASS, BTN_TEXT_AMBER, BTN_TEXT_GREEN, BTN_TEXT_RED, BTN_SOLID_AMBER, BTN_SOLID_GREEN, BTN_SOLID_RED, CHECKBOX_CLASS, }; @@ -129,20 +129,15 @@ pub fn AdminCommentsPage(page: i32) -> Element { div { class: "space-y-6", h1 { class: "text-2xl font-bold text-paper-primary", "评论管理" } - div { class: "flex gap-1 border-b border-paper-border", - for (status, label) in [ + FilterTabs { + items: vec![ ("", "全部"), ("pending", "待审核"), ("approved", "已通过"), ("spam", "垃圾箱"), - ] - { - button { - class: if active_filter() == status { "cursor-pointer px-4 py-2 text-sm font-medium border-b-2 border-paper-accent text-paper-primary" } else { "cursor-pointer px-4 py-2 text-sm font-medium text-paper-secondary hover:text-paper-primary transition-colors" }, - onclick: move |_| active_filter.set(status.to_string()), - "{label}" - } - } + ], + active_value: active_filter(), + on_change: move |v| active_filter.set(v), } if !selected_ids().is_empty() {