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