import { useState, useMemo } from "react"; import { ExternalLink } 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; /** Map source names to badge colours. */ const SOURCE_COLORS: Record = { "heise": "bg-orange-500/20 text-orange-300", "golem": "bg-blue-500/20 text-blue-300", "spiegel": "bg-red-500/20 text-red-300", "tagesschau": "bg-sky-500/20 text-sky-300", "zeit": "bg-slate-500/20 text-slate-300", "faz": "bg-emerald-500/20 text-emerald-300", "welt": "bg-indigo-500/20 text-indigo-300", "t3n": "bg-purple-500/20 text-purple-300", "default": "bg-amber-500/15 text-amber-300", }; 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; } /** Return a German relative time string like "vor 2 Stunden". */ 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 (
{/* Header + category tabs */}

Nachrichten {filteredArticles.length}

{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)}
); }