import { useState, useRef, useEffect } from "react"; const API_URL = import.meta.env.VITE_API_URL || "https://nedaktovops-eurlex-chat-api.hf.space"; const CONFIDENCE_COLORS = { high: { bg: "bg-green-100", text: "text-green-800", label: "High confidence" }, medium: { bg: "bg-yellow-100", text: "text-yellow-800", label: "Medium confidence" }, low: { bg: "bg-red-100", text: "text-red-800", label: "Low confidence" }, }; function ConfidenceBadge({ level }) { const color = CONFIDENCE_COLORS[level] || CONFIDENCE_COLORS.low; if (!level) return null; return ( {color.label} ); } function CitationLink({ celex }) { const url = `https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:${celex}`; return ( {celex} ); } function SourceList({ sources }) { if (!sources || sources.length === 0) return null; // Deduplicate by CELEX const seen = new Set(); const unique = sources.filter(s => { if (seen.has(s.celex)) return false; seen.add(s.celex); return true; }); return (

Sources:

{unique.slice(0, 6).map((s) => ( {s.article && ({s.article})} ))} {unique.length > 6 && ( +{unique.length - 6} more )}
); } function FeedbackButtons({ messageId, onFeedback }) { const [feedback, setFeedback] = useState(null); if (feedback) return null; // Already voted return (
); } export default function ChatWidget() { const [messages, setMessages] = useState([ { role: "assistant", content: "Hi! I'm an AI assistant specialized in EU law. Ask me anything about EU regulations, directives, or legislation.", }, ]); const [input, setInput] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const messagesEndRef = useRef(null); useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }, [messages]); const sendMessage = async () => { const query = input.trim(); if (!query || loading) return; setInput(""); setError(null); setMessages((prev) => [...prev, { role: "user", content: query }]); setLoading(true); try { const res = await fetch(`${API_URL}/chat`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query }), }); if (!res.ok) { const data = await res.json(); throw new Error(data.detail || `Error ${res.status}`); } const data = await res.json(); setMessages((prev) => [ ...prev, { role: "assistant", content: data.answer, confidence: data._confidence, citations: data.citations || [], sources: data.sources || [], }, ]); } catch (err) { setError(err.message); setMessages((prev) => [ ...prev, { role: "assistant", content: `Sorry, I encountered an error: ${err.message}. Please try again.`, }, ]); } finally { setLoading(false); } }; const handleKeyDown = (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); sendMessage(); } }; return (
Ask about EU Law Powered by Groq Llama 3.3
{messages.map((msg, i) => (
{msg.confidence && (
)}
{msg.content}
{msg.sources && msg.sources.length > 0 && ( )} {msg.role === "assistant" && i > 0 && ( console.log("Feedback:", id, dir)} /> )}
))} {loading && (
Thinking...
)}