Separates controllers (api/, the #[server] endpoints) from business services (server/services/), background scheduling (server/jobs/, renamed from pipeline.rs), infra bootstrap/config (server/mod.rs, server/config.rs), and view components (app/), each one file per responsibility instead of the previous server.rs/app.rs/pipeline.rs grab-bags. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoXS1ERDGC1P189RqmUxAF
31 lines
994 B
Rust
31 lines
994 B
Rust
use crate::api;
|
|
use crate::api::ArticleView;
|
|
use dioxus::prelude::*;
|
|
|
|
#[component]
|
|
pub fn ArticleRow(article: ArticleView) -> Element {
|
|
let score_pct = article.final_score.map(|s| (s * 100.0).round() as i32);
|
|
rsx! {
|
|
li { class: "article-row",
|
|
a { href: "{article.url}", target: "_blank", "{article.title}" }
|
|
if let Some(pct) = score_pct {
|
|
span { class: "score", "{pct}%" }
|
|
}
|
|
p { class: "summary", "{article.summary}" }
|
|
div { class: "topics",
|
|
for topic in article.topics.iter() {
|
|
span { class: "topic-tag", "{topic}" }
|
|
}
|
|
}
|
|
button {
|
|
onclick: move |_| {
|
|
let id = article.id.clone();
|
|
async move {
|
|
let _ = api::articles::mark_dismissed(id).await;
|
|
}
|
|
},
|
|
"Not relevant"
|
|
}
|
|
}
|
|
}
|
|
}
|