"use client";
import { useState, useRef, useEffect, FC } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import clsx from 'clsx';
// --- TYPE DEFINITIONS ---
interface Message {
role: 'user' | 'assistant';
content: string;
}
// --- SVG ICONS ---
const VedaMDLogo: FC = () => (
);
const SettingsIcon: FC = () => (
);
const ArrowRightIcon: FC = () => (
);
// --- UI COMPONENTS ---
const Header: FC = () => (
);
const WelcomeScreen: FC<{ onTemplateClick: (query: string) => void }> = ({ onTemplateClick }) => {
const templates = [
"What is the recommended antibiotic regimen for puerperal sepsis according to national guidelines?",
"What are the steps for active management of the third stage of labor (AMTSL)",
];
return (
Welcome to VedaMD
Get trusted clinical answers based on Sri Lankan health guidelines
{templates.map((query) => (
onTemplateClick(query)}
className="button-secondary text-left"
>
{query}
))}
);
};
const ChatMessage: FC<{ message: Message }> = ({ message }) => {
const isUser = message.role === 'user';
return (
);
};
const ChatForm: FC<{
input: string;
setInput: (value: string) => void;
handleSubmit: (e: React.SyntheticEvent | string) => void;
isLoading: boolean;
}> = ({ input, setInput, handleSubmit, isLoading }) => (
);
const Footer: FC = () => (
© 2024 VedaMD. All rights reserved.
);
// --- MAIN PAGE COMPONENT ---
export default function Home() {
const [conversation, setConversation] = useState([]);
const [input, setInput] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
const timeoutId = setTimeout(scrollToBottom, 100);
return () => clearTimeout(timeoutId);
}, [conversation]);
const handleSubmit = async (e: React.SyntheticEvent | string) => {
const query = (typeof e === 'string' ? e : input).trim();
if (typeof e !== 'string') e.preventDefault();
if (!query || isLoading) return;
setIsLoading(true);
setError(null);
if (typeof e !== 'string') setInput('');
const userMessage: Message = { role: 'user', content: query };
const currentConversation = [...conversation, userMessage];
setConversation(currentConversation);
try {
// Convert conversation history to Gradio ChatInterface format
const gradioHistory = currentConversation.slice(0, -1).map(msg => [
msg.role === 'user' ? msg.content : '',
msg.role === 'assistant' ? msg.content : ''
]).filter(pair => pair[0] || pair[1]);
// Call Gradio ChatInterface API
const response = await fetch(`${process.env.NEXT_PUBLIC_HF_API_URL}/call/predict`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
data: [query, gradioHistory]
}),
});
if (!response.ok) {
const errorText = await response.text().catch(() => 'Network error occurred');
throw new Error(`API Error: ${response.status} - ${errorText}`);
}
const data = await response.json();
const botMessage: Message = {
role: 'assistant',
content: data.data[0] || 'No response received from the medical assistant.'
};
setConversation([...currentConversation, botMessage]);
} catch (err: any) {
const errorMessageText = err.message || "An unexpected error occurred.";
setError(errorMessageText);
const errorMessage: Message = { role: 'assistant', content: errorMessageText };
setConversation([...currentConversation, errorMessage]);
} finally {
setIsLoading(false);
}
};
return (
{conversation.length === 0 ? (
) : (
{conversation.map((message, index) => (
))}
)}
);
}