use dioxus::prelude::*; use tavern::{Adventurer, Legend, Lore, Tale}; use crate::server::*; const AUTHOR_CSS: Asset = asset!("/assets/css/blog_author.css"); const LIST_CSS: Asset = asset!("/assets/css/blog_list.css"); const NAV_CSS: Asset = asset!("/assets/css/blog_nav.css"); const POST_CSS: Asset = asset!("/assets/css/blog_post.css"); const TAG_CSS: Asset = asset!("/assets/css/blog_tag.css"); #[derive(Clone, Copy, PartialEq)] pub enum TagStyle { Regular, Easy, Medium, Hard } #[derive(Clone, Copy, PartialEq)] pub enum Tag { LeetCode, Embedded, Simulation, Web } #[component] pub fn TagItem(tag: Tag, style: TagStyle) -> Element { let text = match tag { Tag::LeetCode => { "LeetCode" } Tag::Embedded => { "Embedded" } Tag::Simulation => { "Simulation" } Tag::Web => { "Web" } }; let tag_style = match style { TagStyle::Regular => { "none" } TagStyle::Easy => { "easy" } TagStyle::Medium => { "medium" } TagStyle::Hard => { "hard" } }; rsx! { li { class: "tag_item", a { class: "{tag_style}", "{text}" } } } } #[component] pub fn TagList(children: Element) -> Element { rsx! { document::Link { rel: "stylesheet", href: TAG_CSS } h5 { class: "blog_tag_style", ul { class: "tag_list", {children} } } } } /* #[component] pub fn BlogAuthor() -> Element { rsx! { document::Link { rel: "stylesheet", href: AUTHOR_CSS } section { class: "blog_author_style", } } } #[component] pub fn BlogItem(title: String, slug: String, author: String, summary: String, tags: Vec<(Tag, TagStyle)>) -> Element { rsx! { li { class: "blog_item", Link { to: Page::Post { slug: slug }, h1 { "{title}" } } TagList { for (tag, style) in tags { TagItem { tag: tag, style: style } } } h4 { "Author: {author}" } p { "{summary}" } } } } #[component] pub fn BlogList(children: Element) -> Element { rsx! { document::Link { rel: "stylesheet", href: LIST_CSS } section { class: "blog_list_style", ul { class: "blog_list", {children} } } } } #[component] pub fn BlogNav() -> Element { rsx! { document::Link { rel: "stylesheet", href: NAV_CSS } section { class: "blog_nav_style", div { class: "tag_style", h3 { "Categories" } ul { class: "tag_list", li { class: "tag_item", a { href: "/blog.html", "LeetCode" } } li { class: "tag_item", a { href: "/blog.html", "Embedded" } } li { class: "tag_item", a { href: "/blog.html", "Simulation" } } li { class: "tag_item", a { href: "/blog.html", "Web" } } } } SocialButtonList { SocialButton { link: String::from("https://www.linkedin.com/company/cybermages-llc"), company: Company::LinkedIn, size: Size::Small } SocialButton { link: String::from("https://bsky.app/profile/cybermages.tech"), company: Company::Bluesky, size: Size::Small } } } } } */ #[component] pub fn PostHeaderAuthor(name: String, handle: String, profile_link: String) -> Element { rsx! { h4 { "Author: ", a { href: "{profile_link}", "{name} @{handle}" } } } } #[component] pub fn PostHeader(title: String, author: String, tags: Vec) -> Element { let Ok(author) = use_server_future(move || get_author(author.clone())) else { return rsx! { p { "Failed to load author." } } }; rsx! { h1 { "{title}" } TagList { for category in tags { TagItem { tag: Tag::LeetCode, style: TagStyle::Regular } } } match &*author.read() { Some(Ok(author)) => { rsx! { PostHeaderAuthor { name: author.name.clone(), handle: author.handle.clone(), profile_link: author.legend.profile.clone() } } } Some(Err(e)) => { rsx! { p { "Unable to show post header." } p { "{e}" } } } None => { rsx! { p { "Loading..." } } } } } } #[component] pub fn BlogPost(slug: String, children: Element) -> Element { let test_slug = slug.clone(); // 1. Fetch the blog post using the slug. let post = use_server_future(move || { let url_slug = slug.clone(); async move { get_blog_post(url_slug).await } })?; // Then build the component. rsx! { document::Link { rel: "stylesheet", href: POST_CSS } article { class: "blog_post_style", match &*post.read() { Some(Ok(post)) => { rsx! { PostHeader { title: post.lore.title.clone(), author: post.lore.author.clone(), tags: post.lore.tags.clone() } div { dangerous_inner_html: "{post.story}" } } } Some(Err(e)) => { rsx! { p { "Unable to show desired post." } p { "Trying to get: {test_slug}" } p { "{e}" } } } None => { rsx! { p { "Loading..." } } } } {children} } } }