import React, { useState, useEffect, useMemo } from 'react';
import {
Scale, Users, Search, FileText, ChevronRight,
ArrowRight, AlertTriangle, CheckCircle2, BarChart3, Activity, Leaf,
DollarSign, Edit, Loader2, Phone, Database, CloudLightning, Info,
Mail, Handshake, Heart
} from 'lucide-react';
// --- API Configurations ---
const apiKey = ""; // Gemini API Key injected by environment
const CONGRESS_API_KEY = "YOUR_API_KEY_HERE";
// --- Utilities ---
const fetchWithTimeout = async (resource, options = {}, timeout = 10000) => {
const controller = new AbortController();
const id = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(resource, { ...options, signal: controller.signal });
clearTimeout(id);
return response;
} catch (error) {
clearTimeout(id);
throw error;
}
};
const extractJson = (text) => {
if (!text) return null;
try {
const match = text.match(/\{[\s\S]*\}/);
return match ? JSON.parse(match[0]) : JSON.parse(text);
} catch (e) { return null; }
};
const truncateText = (text, limit = 120) => {
if (!text) return "";
return text.length > limit ? text.substring(0, limit).trim() + "..." : text;
};
// Stubbed Gemini call — replace with real API call
const callGemini = async (prompt, wantJson = false) => {
console.warn('callGemini stub invoked', { prompt, wantJson });
return null;
};
// --- Fallback Data ---
const REAL_BILLS_SNAPSHOT = [
{
id: "H.R. 7521", level: "Federal", jurisdiction: "US Congress",
shortTitle: "TikTok Divestiture Bill",
fullTitle: "H.R. 7521: Protecting Americans from Foreign Adversary Controlled Applications Act",
status: "Passed House", progress: 50, sponsor: "Rep. Mike Gallagher",
summary: "Prohibits app stores from distributing applications controlled by foreign adversaries unless they divest ownership.",
healthScore: 65, riskLevel: "Moderate",
ratings: { constitutionality: 70, bipartisanship: 85, publicOpinion: 60 },
sectors: {
environment: { score: 50, pros: [], cons: [] },
economy: { score: 60, pros: ["Domestic Tech Growth"], cons: ["Creator Economy Impact"] },
social: { score: 55, pros: ["National Security"], cons: ["Free Speech Concerns"] }
},
isAnalyzed: true
},
{
id: "S. 1409", level: "Federal", jurisdiction: "US Congress",
shortTitle: "Kids Online Safety Act",
fullTitle: "S. 1409: Kids Online Safety Act",
status: "Senate Floor", progress: 60, sponsor: "Sen. Richard Blumenthal",
summary: "Imposes a duty of care on online platforms to prevent minors from accessing harmful content, requiring age verification.",
healthScore: 58, riskLevel: "High",
ratings: { constitutionality: 55, bipartisanship: 75, publicOpinion: 80 },
sectors: {
environment: { score: 50, pros: [], cons: [] },
economy: { score: 45, pros: ["Compliance Tech"], cons: ["Platform Liability"] },
social: { score: 60, pros: ["Child Safety"], cons: ["Censorship Risk"] }
},
isAnalyzed: true
}
];
// --- Components ---
const AITooltip = ({ content }) => (
{content || "AI-generated estimate based on reading the actual bill text. Not an official rating."}
);
const AuxRating = ({ icon: Icon, label, value }) => (
);
const HealthGauge = ({ score }) => {
const radius = 38;
const circumference = 2 * Math.PI * radius;
const strokeDashoffset = circumference - ((score || 0) / 100) * circumference;
const color = score >= 75 ? "text-emerald-500" : score >= 50 ? "text-amber-500" : "text-rose-500";
return (
);
};
const SectorCard = ({ icon: Icon, title, data }) => {
const safeData = data || { score: 0, pros: [], cons: [] };
const isPositive = safeData.score >= 50;
return (
Pros
{safeData.pros?.length ? safeData.pros.slice(0,2).map((p, i) => (- • {p}
)) : - None
}
Risks
{safeData.cons?.length ? safeData.cons.slice(0,2).map((c, i) => (- • {c}
)) : - None
}
);
};
const FilterButton = ({ active, onClick, icon: Icon, count, label, colorClass }) => (
);
const BillCard = ({ bill, onClick }) => {
if (bill.isAnalyzing) {
return (
);
}
return (
onClick(bill)} className="bg-white p-5 rounded-2xl border border-slate-200 shadow-sm hover:shadow-md hover:border-indigo-400 transition-all cursor-pointer group flex flex-col h-full relative">
{bill.id}
{bill.healthScore > 0 &&
}
{bill.shortTitle}
{truncateText(bill.summary, 120)}
{bill.status}
);
};
const App = () => {
const [bills, setBills] = useState(() => {
const saved = typeof localStorage !== 'undefined' ? localStorage.getItem('cp_bills_cache') : null;
return saved ? JSON.parse(saved) : REAL_BILLS_SNAPSHOT;
});
const [selectedBill, setSelectedBill] = useState(null);
const [currentView, setCurrentView] = useState('dashboard');
const [isFetching, setIsFetching] = useState(false);
const [lastRefreshed, setLastRefreshed] = useState(() => (typeof localStorage !== 'undefined' && localStorage.getItem('cp_last_sync')) || new Date().toISOString());
const [filter, setFilter] = useState('all');
const [searchTerm, setSearchTerm] = useState("");
const [notifications, setNotifications] = useState([]);
const [userDistrict] = useState({ city: "Washington", state: "DC", stateName: "District of Columbia", fedRep: "Del. Eleanor Norton", stateRep: "Councilmember", district: "DC-AL" });
const minutesAgo = Math.floor((new Date().getTime() - new Date(lastRefreshed).getTime()) / 60000);
useEffect(() => { localStorage.setItem('cp_bills_cache', JSON.stringify(bills)); }, [bills]);
useEffect(() => { localStorage.setItem('cp_last_sync', lastRefreshed); }, [lastRefreshed]);
const callGeminiSafe = async (prompt) => {
const res = await callGemini(prompt, true);
return extractJson(res);
};
const syncLatest = async () => {
setIsFetching(true);
try {
if (!CONGRESS_API_KEY || CONGRESS_API_KEY.includes("YOUR")) throw new Error("Key missing");
const res = await fetchWithTimeout(`https://api.congress.gov/v3/bill?congress=119&limit=6&sort=updateDate+desc&api_key=${CONGRESS_API_KEY}`);
const data = await res.json();
const rawBills = data.bills.map(b => ({
id: `${b.type.toUpperCase()} ${b.number}`,
type: b.type, number: b.number, level: "Federal", jurisdiction: "US Congress",
shortTitle: b.title, fullTitle: b.title, status: "Active", progress: 15,
isAnalyzing: true, isAnalyzed: false
}));
setBills(prev => {
const ids = new Set(prev.map(p => p.id));
return [...rawBills.filter(r => !ids.has(r.id)), ...prev];
});
setLastRefreshed(new Date().toISOString());
} catch (e) {
alert("Congress.gov API unavailable. Using fallback data.");
setBills(REAL_BILLS_SNAPSHOT);
} finally { setIsFetching(false); }
};
useEffect(() => {
const pending = bills.filter(b => b.isAnalyzing);
if (pending.length > 0) {
pending.forEach(async (bill) => {
try {
const prompt = `Analyze this bill text: "${bill.fullTitle}". Return JSON: { summary, healthScore, riskLevel, ratings, sectors, projections }`;
const analysis = await callGeminiSafe(prompt);
setBills(prev => prev.map(p => p.id === bill.id ? { ...p, ...(analysis || {}), isAnalyzing: false, isAnalyzed: true } : p));
} catch (e) {
setBills(prev => prev.map(p => p.id === bill.id ? { ...p, isAnalyzing: false, analysisFailed: true, summary: "Analysis failed. Read raw text in details." } : p));
}
});
}
}, [bills]);
const stats = useMemo(() => ({
active: bills.length,
critical: bills.filter(b => b.riskLevel === 'High').length,
voting: bills.filter(b => b.progress > 50).length
}), [bills]);
const filteredBills = useMemo(() => {
let list = searchTerm ? bills : bills.filter(b => b.level === 'Federal' || b.jurisdiction === userDistrict.stateName);
if (filter === 'high_risk') list = list.filter(b => b.riskLevel === 'High');
if (filter === 'voting') list = list.filter(b => b.progress > 50);
if (searchTerm) list = list.filter(b => (b.fullTitle + b.id).toLowerCase().includes(searchTerm.toLowerCase()));
return list;
}, [bills, filter, searchTerm, userDistrict]);
const addNotification = (msg) => setNotifications(n => [...n, { id: Date.now(), msg }]);
return (
{selectedBill ? (
setSelectedBill(null)} userDistrict={userDistrict} addNotification={addNotification} />
) : currentView === 'legislation' ? (
) : (
Active Docket
Live data analyzed for {userDistrict.stateName}
setFilter('all')} icon={FileText} count={stats.active} label="All Bills" colorClass={{ bg: 'bg-indigo-50', text: 'text-indigo-600' }} />
setFilter('high_risk')} icon={AlertTriangle} count={stats.critical} label="High Risk" colorClass={{ bg: 'bg-rose-50', text: 'text-rose-600' }} />
setFilter('voting')} icon={CheckCircle2} count={stats.voting} label="Advanced" colorClass={{ bg: 'bg-emerald-50', text: 'text-emerald-600' }} />
{filteredBills.map(bill => ())}
)}
{notifications.slice(-3).map(n => (
{n.msg}
))}
);
};
const BillDetail = ({ bill, onBack, userDistrict, addNotification }) => {
const [persona, setPersona] = useState("");
const [personalImpact, setPersonalImpact] = useState(null);
const [loading, setLoading] = useState(false);
const checkImpact = async () => {
setLoading(true);
const prompt = `How does bill ${bill.id} impact a ${persona} in ${userDistrict.stateName}? 2-3 sentences. No JSON.`;
const res = await callGemini(prompt, false);
setPersonalImpact((res && res.text) || res || "Analysis unavailable.");
setLoading(false);
};
return (
{bill.level}
{bill.fullTitle}
{bill.sponsor} • {bill.status}
AI Analysis
{bill.summary}
Personal Impact
{!personalImpact ? (
setPersona(e.target.value)} />
) : (
"{personalImpact}"
)}
);
};
const LegislationView = ({ bills, onSelect }) => (