feat(interest): add public interest tracking for members of Congress
Adds Google Trends, NewsAPI, and Google News RSS scoring for members,
mirroring the existing bill interest pipeline. Member profiles now show
a Public Interest chart (with signal breakdown) and a Related News panel.
Key changes:
- New member_trend_scores + member_news_articles tables (migration 0008)
- fetch_gnews_articles() added to news_service for unlimited RSS article storage
- Bill news fetcher now combines NewsAPI + Google News RSS (more coverage)
- New member_interest Celery worker with scheduled news + trend tasks
- GET /members/{id}/trend and /news API endpoints
- TrendChart redesigned with signal breakdown badges and bar+line combo chart
- NewsPanel accepts generic article shape (bills and members)
Co-Authored-By: Jack Levy
This commit is contained in:
@@ -13,7 +13,9 @@ import {
|
||||
FileText,
|
||||
Users,
|
||||
} from "lucide-react";
|
||||
import { useMember, useMemberBills } from "@/lib/hooks/useMembers";
|
||||
import { useMember, useMemberBills, useMemberTrend, useMemberNews } from "@/lib/hooks/useMembers";
|
||||
import { TrendChart } from "@/components/bills/TrendChart";
|
||||
import { NewsPanel } from "@/components/bills/NewsPanel";
|
||||
import { FollowButton } from "@/components/shared/FollowButton";
|
||||
import { BillCard } from "@/components/shared/BillCard";
|
||||
import { cn, partyBadgeColor } from "@/lib/utils";
|
||||
@@ -28,6 +30,8 @@ export default function MemberDetailPage({ params }: { params: Promise<{ id: str
|
||||
const { id } = use(params);
|
||||
const { data: member, isLoading } = useMember(id);
|
||||
const { data: billsData } = useMemberBills(id);
|
||||
const { data: trendData } = useMemberTrend(id, 30);
|
||||
const { data: newsData } = useMemberNews(id);
|
||||
|
||||
if (isLoading) return <div className="text-center py-20 text-muted-foreground">Loading...</div>;
|
||||
if (!member) return <div className="text-center py-20 text-muted-foreground">Member not found.</div>;
|
||||
@@ -156,6 +160,12 @@ export default function MemberDetailPage({ params }: { params: Promise<{ id: str
|
||||
|
||||
{/* Right column */}
|
||||
<div className="space-y-4">
|
||||
{/* Public Interest */}
|
||||
<TrendChart data={trendData ?? []} title="Public Interest" />
|
||||
|
||||
{/* News */}
|
||||
<NewsPanel articles={newsData} />
|
||||
|
||||
{/* Legislation stats */}
|
||||
{(member.sponsored_count != null || member.cosponsored_count != null) && (
|
||||
<div className="bg-card border border-border rounded-lg p-4 space-y-3">
|
||||
|
||||
Reference in New Issue
Block a user