import React, { useState, useRef, useEffect, useCallback } from 'react'; import { Upload, MessageSquare, Send, Bot, User, FileText, Loader2, RefreshCw, Sun, Moon } from 'lucide-react'; export default function App() { const [file, setFile] = useState(null); const [previewUrl, setPreviewUrl] = useState(null); const [uploading, setUploading] = useState(false); const [uploadStatus, setUploadStatus] = useState({ type: '', message: '' }); const [isIndexed, setIsIndexed] = useState(false); const [messages, setMessages] = useState([ { role: 'assistant', text: 'Hello! Upload a PDF document on the left, and I will help you analyze its text, structural layouts, and embedded images instantly.' } ]); const [input, setInput] = useState(''); const [loadingAnswer, setLoadingAnswer] = useState(false); const [darkMode, setDarkMode] = useState(true); const [sidebarWidth, setSidebarWidth] = useState(450); const [isResizing, setIsResizing] = useState(false); const chatEndRef = useRef(null); useEffect(() => { if (darkMode) { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } }, [darkMode]); useEffect(() => { return () => { if (previewUrl) URL.revokeObjectURL(previewUrl); }; }, [previewUrl]); useEffect(() => { chatEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages, loadingAnswer]); const startResizing = useCallback((e) => { e.preventDefault(); setIsResizing(true); }, []); const stopResizing = useCallback(() => { setIsResizing(false); }, []); const resize = useCallback((e) => { if (!isResizing) return; const newWidth = Math.max(320, Math.min(e.clientX, window.innerWidth - 350)); setSidebarWidth(newWidth); }, [isResizing]); useEffect(() => { if (isResizing) { window.addEventListener('mousemove', resize); window.addEventListener('mouseup', stopResizing); } else { window.removeEventListener('mousemove', resize); window.removeEventListener('mouseup', stopResizing); } return () => { window.removeEventListener('mousemove', resize); window.removeEventListener('mouseup', stopResizing); }; }, [isResizing, resize, stopResizing]); const handleFileChange = (e) => { const selectedFile = e.target.files[0]; if (selectedFile && selectedFile.type === "application/pdf") { setFile(selectedFile); setIsIndexed(false); setUploadStatus({ type: '', message: '' }); const localUrl = URL.createObjectURL(selectedFile); setPreviewUrl(localUrl); } else if (selectedFile) { setUploadStatus({ type: 'error', message: 'Invalid file type. Please select a genuine .PDF document.' }); } }; const handleUpload = async () => { if (!file) return; setUploading(true); setUploadStatus({ type: '', message: '' }); const formData = new FormData(); formData.append('file', file); try { // CHANGED: Removed http://127.0.0.1:8000 const response = await fetch('/api/upload', { method: 'POST', body: formData, }); const data = await response.json(); if (response.ok) { setUploadStatus({ type: 'success', message: data.message }); setIsIndexed(true); setMessages(prev => [...prev, { role: 'assistant', text: `📁 "${file.name}" has been processed and indexed successfully! You can now ask me anything about it.` }]); } else { setUploadStatus({ type: 'error', message: data.detail || 'Failed to parse file.' }); } } catch (err) { setUploadStatus({ type: 'error', message: 'Could not connect to FastAPI server.' }); } finally { setUploading(false); } }; const handleSendMessage = async (e) => { e.preventDefault(); if (!input.trim() || loadingAnswer) return; const userQuery = input.trim(); setMessages(prev => [...prev, { role: 'user', text: userQuery }]); setInput(''); setLoadingAnswer(true); try { // CHANGED: Removed http://127.0.0.1:8000 const response = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: userQuery }), }); const data = await response.json(); if (response.ok) { setMessages(prev => [...prev, { role: 'assistant', text: data.answer }]); } else { setMessages(prev => [...prev, { role: 'assistant', text: `⚠️ Error: ${data.detail || 'Failed to retrieve response.'}` }]); } } catch (err) { setMessages(prev => [...prev, { role: 'assistant', text: '⚠️ Connection lost.' }]); } finally { setLoadingAnswer(false); } }; return (

DocuSense AI

{isIndexed && ( )}
{!isIndexed ? (

Document Portal

{file ? file.name : "Drag & drop file or click to browse"}

Accepts document format standard .PDF

{file && ( )} {uploadStatus.message && (
{uploadStatus.message}
)}
) : (
PDF
{file?.name} Size: {(file?.size / (1024 * 1024)).toFixed(2)} MB
Live Viewer
{previewUrl ? (