yggdrasil/src/pages/post_detail.rs

102 lines
5.0 KiB
Rust

use dioxus::prelude::*;
use crate::api::posts::{get_post_by_slug, SinglePostResponse};
use crate::components::nav::use_nav_items;
use crate::components::page_layout::PageLayout;
use crate::router::Route;
#[component]
pub fn PostDetail(slug: String) -> Element {
let route = use_route::<Route>();
let slug_clone = slug.clone();
let post_res = use_resource(move || get_post_by_slug(slug_clone.clone()));
let nav_items = use_nav_items(route);
rsx! {
PageLayout { nav_items,
match &*post_res.read() {
Some(Ok(SinglePostResponse { post: Some(post) })) => {
let date_str = post.formatted_date();
rsx! {
article { class: "py-6",
header { class: "mb-8",
h1 { class: "text-3xl md:text-4xl font-bold text-gray-900 dark:text-[#dadadb] leading-tight",
"{post.title}"
}
div { class: "mt-4 flex items-center gap-3 text-sm text-gray-500 dark:text-[#9b9c9d]",
span { "{date_str}" }
if !post.tags.is_empty() {
span { "·" }
for tag in post.tags.clone().into_iter() {
a {
class: "hover:text-gray-700 dark:hover:text-[#dadadb] transition-colors",
href: "/tags/{tag}",
onclick: move |evt| {
evt.prevent_default();
dioxus::router::navigator().push(format!("/tags/{}", tag).as_str());
},
"{tag}"
}
}
}
}
}
div {
class: "prose dark:prose-invert max-w-none text-gray-800 dark:text-[#c9cacc] leading-relaxed",
dangerous_inner_html: "{post.content_html.as_deref().unwrap_or(\"\")}"
}
div { class: "mt-12 pt-6 border-t border-gray-200 dark:border-[#333]",
button {
class: "text-sm text-gray-500 dark:text-[#9b9c9d] hover:text-gray-700 dark:hover:text-[#dadadb] transition-colors",
onclick: move |_| {
let _ = dioxus::router::navigator().push("/");
},
"← 返回首页"
}
}
}
}
}
Some(Ok(SinglePostResponse { post: None })) => {
rsx! {
div { class: "text-center py-20",
h2 { class: "text-2xl font-bold text-gray-900 dark:text-[#dadadb] mb-4",
"文章不存在"
}
p { class: "text-gray-500 dark:text-[#9b9c9d] mb-6",
"这篇文章可能已被删除或移动。"
}
button {
class: "px-6 py-2 bg-gray-900 dark:bg-[#dadadb] text-white dark:text-gray-900 rounded-full font-medium hover:opacity-80 transition-opacity",
onclick: move |_| {
let _ = dioxus::router::navigator().push("/");
},
"返回首页"
}
}
}
}
Some(Err(e)) => {
rsx! {
div { class: "text-center text-red-500 dark:text-red-400 py-20",
"加载失败: {e}"
}
}
}
None => {
rsx! {
div { class: "animate-pulse py-6 space-y-4",
div { class: "h-10 w-3/4 bg-gray-200 dark:bg-[#2a2a2a] rounded" }
div { class: "h-4 w-32 bg-gray-200 dark:bg-[#2a2a2a] rounded" }
div { class: "h-4 w-full bg-gray-200 dark:bg-[#2a2a2a] rounded mt-8" }
div { class: "h-4 w-full bg-gray-200 dark:bg-[#2a2a2a] rounded" }
div { class: "h-4 w-2/3 bg-gray-200 dark:bg-[#2a2a2a] rounded" }
}
}
}
}
}
}
}