Default view stays the all-feeds joined article list, now with a sidebar listing every subscribed feed so a reader can pin down to one feed's articles. Filtering happens server-side (list_ranked_articles now takes an optional feed_id). Pulled in the sidebar/badge/scroll_area (plus their sheet/skeleton/ tooltip/separator dependencies) components via `dx components add` instead of hand-rolling nav/tag/scroll markup, matching this project's existing pattern of using the Dioxus component library over raw elements (see button/input). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PqTJmazHBQK878vjQ4JnnF
32 lines
1.1 KiB
Rust
32 lines
1.1 KiB
Rust
use crate::api;
|
|
use crate::api::ArticleView;
|
|
use crate::components::badge::{Badge, BadgeVariant};
|
|
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 {
|
|
Badge { variant: BadgeVariant::Secondary, "{pct}%" }
|
|
}
|
|
p { class: "summary", "{article.summary}" }
|
|
div { class: "topics",
|
|
for topic in article.topics.iter() {
|
|
Badge { variant: BadgeVariant::Outline, "{topic}" }
|
|
}
|
|
}
|
|
button {
|
|
onclick: move |_| {
|
|
let id = article.id.clone();
|
|
async move {
|
|
let _ = api::articles::mark_dismissed(id).await;
|
|
}
|
|
},
|
|
"Not relevant"
|
|
}
|
|
}
|
|
}
|
|
}
|