import { faCheck, faCircle, faExternalLinkAlt, } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { useMutation } from "urql"; import type { GetReadArticlesQuery, GetUnreadArticlesQuery, } from "../graphql/generated/graphql"; import { MarkArticleReadDocument, MarkArticleUnreadDocument, } from "../graphql/generated/graphql"; interface Props { articles: NonNullable< | GetUnreadArticlesQuery["unreadArticles"] | GetReadArticlesQuery["readArticles"] >; showReadStatus?: boolean; } export function ArticleList({ articles, showReadStatus = true }: Props) { const [, markArticleRead] = useMutation(MarkArticleReadDocument); const [, markArticleUnread] = useMutation(MarkArticleUnreadDocument); const handleToggleRead = async ( articleId: string, isCurrentlyRead: boolean, ) => { if (isCurrentlyRead) { await markArticleUnread({ id: articleId }); } else { await markArticleRead({ id: articleId }); } }; const handleArticleClick = async (article: (typeof articles)[0]) => { // Open article in new tab and mark as read if it's unread window.open(article.url, "_blank"); if (!article.isRead) { await markArticleRead({ id: article.id }); } }; if (articles.length === 0) { return (
No articles found.
); } // Group articles by feed const articlesByFeed = articles.reduce( (acc, article) => { const feedId = article.feed.id; if (!acc[feedId]) { acc[feedId] = { feed: article.feed, articles: [], }; } acc[feedId].articles.push(article); return acc; }, {} as Record< string, { feed: { id: string; title: string }; articles: typeof articles } >, ); return (
{Object.values(articlesByFeed).map(({ feed, articles: feedArticles }) => (

{feed.title} ({feedArticles.length} article {feedArticles.length !== 1 ? "s" : ""})

{feedArticles.map((article) => (
{showReadStatus && ( )}
))}
))}
); }