"use client"; import { use, useEffect, useRef } from "react"; import Link from "next/link"; import { ArrowLeft, ExternalLink, FileX, User } from "lucide-react"; import { useBill, useBillNews, useBillTrend } from "@/lib/hooks/useBills"; import { BriefPanel } from "@/components/bills/BriefPanel"; import { ActionTimeline } from "@/components/bills/ActionTimeline"; import { TrendChart } from "@/components/bills/TrendChart"; import { NewsPanel } from "@/components/bills/NewsPanel"; import { FollowButton } from "@/components/shared/FollowButton"; import { billLabel, chamberBadgeColor, congressLabel, formatDate, partyBadgeColor, cn } from "@/lib/utils"; export default function BillDetailPage({ params }: { params: Promise<{ id: string }> }) { const { id } = use(params); const billId = decodeURIComponent(id); const { data: bill, isLoading } = useBill(billId); const { data: trendData } = useBillTrend(billId, 30); const { data: newsArticles, refetch: refetchNews } = useBillNews(billId); // When the bill page is opened with no stored articles, the backend queues // a Celery news-fetch task that takes a few seconds to complete. // Retry up to 3 times (every 6 s) so articles appear without a manual refresh. // newsRetryRef resets on bill navigation so each bill gets its own retry budget. const newsRetryRef = useRef(0); useEffect(() => { newsRetryRef.current = 0; }, [billId]); useEffect(() => { if (newsArticles === undefined || newsArticles.length > 0) return; if (newsRetryRef.current >= 3) return; const timer = setTimeout(() => { newsRetryRef.current += 1; refetchNews(); }, 6000); return () => clearTimeout(timer); }, [newsArticles]); // eslint-disable-line react-hooks/exhaustive-deps if (isLoading) { return
Loading bill...
; } if (!bill) { return (

Bill not found.

← Back to bills
); } const label = billLabel(bill.bill_type, bill.bill_number); return (
{/* Header */}
{label} {bill.chamber && ( {bill.chamber} )} {congressLabel(bill.congress_number)}

{bill.short_title || bill.title || "Untitled Bill"}

{bill.sponsor && (
{bill.sponsor.name} {bill.sponsor.party && ( {bill.sponsor.party} )} {bill.sponsor.state && {bill.sponsor.state}}
)}

{bill.introduced_date && ( Introduced: {formatDate(bill.introduced_date)} )} {bill.congress_url && ( congress.gov )}

{/* Content grid */}
{bill.briefs.length > 0 ? ( ) : bill.has_document ? (

Analysis pending

Bill text was retrieved but has not yet been analyzed. Check back shortly.

) : (
No bill text published

As of {new Date().toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" })},{" "} no official text has been received for{" "} {billLabel(bill.bill_type, bill.bill_number)}. Analysis will be generated automatically once text is published on Congress.gov.

{bill.congress_url && ( Check status on Congress.gov )}
)}
); }