import { useState, useMemo } from "react"; import { ArrowUpRight } from "lucide-react"; import type { NewsResponse, NewsArticle } from "../api"; interface NewsGridProps { data: NewsResponse; } const CATEGORIES = [ { key: "all", label: "Alle" }, { key: "tech", label: "Tech" }, { key: "wirtschaft", label: "Wirtschaft" }, { key: "politik", label: "Politik" }, { key: "allgemein", label: "Allgemein" }, ] as const; const SOURCE_COLORS: Record = { heise: "border-gold/40 text-gold bg-gold/5", golem: "border-azure/40 text-azure bg-azure/5", spiegel: "border-cherry/40 text-cherry bg-cherry/5", tagesschau: "border-azure/40 text-azure bg-azure/5", zeit: "border-base-400 text-base-700 bg-base-200", faz: "border-mint/40 text-mint bg-mint/5", welt: "border-iris/40 text-iris bg-iris/5", t3n: "border-iris/40 text-iris bg-iris/5", default: "border-gold/30 text-gold-muted bg-gold/5", }; function sourceColor(source: string): string { const key = source.toLowerCase(); for (const [prefix, cls] of Object.entries(SOURCE_COLORS)) { if (key.includes(prefix)) return cls; } return SOURCE_COLORS.default; } function relativeTime(isoDate: string): string { try { const date = new Date(isoDate); if (isNaN(date.getTime())) return ""; const diff = Date.now() - date.getTime(); const seconds = Math.floor(diff / 1_000); const minutes = Math.floor(seconds / 60); const hours = Math.floor(minutes / 60); const days = Math.floor(hours / 24); if (seconds < 60) return "gerade eben"; if (minutes < 60) return `vor ${minutes} Min.`; if (hours < 24) return hours === 1 ? "vor 1 Stunde" : `vor ${hours} Stunden`; if (days === 1) return "gestern"; if (days < 7) return `vor ${days} Tagen`; return date.toLocaleDateString("de-DE", { day: "2-digit", month: "short" }); } catch { return ""; } } export default function NewsGrid({ data }: NewsGridProps) { const [activeCategory, setActiveCategory] = useState("all"); const filteredArticles = useMemo(() => { if (!data?.articles) return []; if (activeCategory === "all") return data.articles; return data.articles.filter( (a) => a.category?.toLowerCase() === activeCategory ); }, [data, activeCategory]); if (!data?.articles) return null; return (
{/* Section header */}
04

Nachrichten

{filteredArticles.length}
{/* Category tabs */}
{CATEGORIES.map((cat) => ( ))}
{/* Articles grid */} {filteredArticles.length === 0 ? (
Keine Artikel in dieser Kategorie.
) : (
{filteredArticles.map((article) => ( ))}
)}
); } function ArticleCard({ article }: { article: NewsArticle }) { return (
{article.source}

{article.title}

{article.category && ( {article.category} )} {relativeTime(article.published_at)}
); }