SokratesAI / frontend /src /components /DocumentProcessor.jsx
Alleinzellgaenger's picture
Implement chunk loading tips, and autoscrolling to conversation regarding a specific chunk
f444dc0
raw
history blame
7.05 kB
import 'katex/dist/katex.min.css';
import { useState, useEffect } from 'react';
// Import custom hooks
import { useDocumentProcessor } from '../hooks/useDocumentProcessor';
import { useChunkNavigation } from '../hooks/useChunkNavigation';
import { usePanelResize } from '../hooks/usePanelResize';
// Import components
import LoadingAnimation from './LoadingAnimation';
import DocumentViewer from './DocumentViewer';
import ChunkPanel from './ChunkPanel';
import ProgressBar from './ProgressBar';
function DocumentProcessor() {
// State for PDF navigation
const [pdfNavigation, setPdfNavigation] = useState(null);
// State for first LLM response loading
const [waitingForFirstResponse, setWaitingForFirstResponse] = useState(false);
// Custom hooks
const {
fileInputRef,
selectedFile,
processing,
uploadProgress,
documentData,
handleFileChange,
processDocument,
setSelectedFile
} = useDocumentProcessor();
const {
chunkStates,
currentChunkIndex,
chunkExpanded,
showChat,
isTransitioning,
goToNextChunk,
goToPrevChunk,
skipChunk,
markChunkUnderstood,
startInteractiveLesson,
setChunkExpanded,
setShowChat,
setChunkAsInteractive,
updateGlobalChatHistory,
getGlobalChatHistory,
addMessageToChunk,
getCurrentChunkMessages,
hasChunkMessages,
isChunkCompleted,
canEditChunk
} = useChunkNavigation(documentData, null);
const {
leftPanelWidth,
isDragging,
containerRef,
handleMouseDown
} = usePanelResize(50);
// Sync PDF page navigation with chunk switching
useEffect(() => {
if (pdfNavigation && documentData && documentData.chunks[currentChunkIndex]) {
const currentChunk = documentData.chunks[currentChunkIndex];
if (currentChunk.page && pdfNavigation.goToPage) {
pdfNavigation.goToPage(currentChunk.page);
}
}
}, [currentChunkIndex, pdfNavigation, documentData]);
// Simplified startInteractiveLesson
const handleStartInteractiveLesson = () => {
startInteractiveLesson();
};
// Early returns for different states
if (!selectedFile) {
return (
<div className="h-screen bg-gray-50 flex items-center justify-center">
<input
ref={fileInputRef}
type="file"
accept=".pdf"
className="hidden"
onChange={handleFileChange}
/>
<button
onClick={() => fileInputRef.current.click()}
className="px-6 py-3 bg-white shadow-md hover:shadow-lg text-gray-700 font-medium rounded-lg transition-all"
>
Select PDF
</button>
</div>
);
}
if (!documentData) {
return (
<div className="h-screen bg-gray-50 flex items-center justify-center">
<div className="flex gap-4">
<button
onClick={processDocument}
className="px-6 py-3 bg-white shadow-md hover:shadow-lg text-gray-700 font-medium rounded-lg transition-all"
>
Process
</button>
<button
onClick={() => setSelectedFile(null)}
className="px-6 py-3 bg-white shadow-md hover:shadow-lg text-gray-700 font-medium rounded-lg transition-all"
>
← Back
</button>
</div>
</div>
);
}
// Main render
return (
<div
ref={containerRef}
className="h-screen bg-gray-100 flex gap-2 p-6 overflow-hidden"
style={{ cursor: isDragging ? 'col-resize' : 'default' }}
>
{/* Left Panel - Document */}
<div style={{ width: `${leftPanelWidth}%`, height: '100%' }} className="flex flex-col">
{/* Document Viewer */}
<div className="flex-1 min-h-0">
<DocumentViewer
selectedFile={selectedFile}
documentData={documentData}
onPageChange={setPdfNavigation}
/>
</div>
</div>
{/* Resizable Divider */}
<div
className="flex items-center justify-center cursor-col-resize group transition-all duration-200"
style={{ width: '8px' }}
onMouseDown={handleMouseDown}
>
<div
className="w-px h-full rounded-full transition-all duration-200 group-hover:shadow-lg"
style={{
backgroundColor: isDragging ? 'rgba(59, 130, 246, 0.8)' : 'transparent',
boxShadow: isDragging ? '0 0 8px rgba(59, 130, 246, 0.8)' : 'none'
}}
></div>
</div>
{/* Right Panel Container */}
<div
className="flex flex-col"
style={{ width: `${100 - leftPanelWidth}%` }}
> {/* Progress Bar */}
<div className="mb-4 flex-shrink-0">
<ProgressBar
currentChunkIndex={currentChunkIndex}
totalChunks={documentData?.chunks?.length || 0}
onChunkClick={null} // Start with linear progression only
/>
</div>
{/* Chunk Panel */}
<div className="flex-1 flex flex-col min-h-0 bg-white rounded-lg shadow-sm">
<ChunkPanel
documentData={documentData}
currentChunkIndex={currentChunkIndex}
showChat={showChat}
isTransitioning={isTransitioning}
updateGlobalChatHistory={updateGlobalChatHistory}
getGlobalChatHistory={getGlobalChatHistory}
addMessageToChunk={addMessageToChunk}
getCurrentChunkMessages={getCurrentChunkMessages}
hasChunkMessages={hasChunkMessages}
isChunkCompleted={isChunkCompleted}
canEditChunk={canEditChunk}
setWaitingForFirstResponse={setWaitingForFirstResponse}
markChunkUnderstood={markChunkUnderstood}
skipChunk={skipChunk}
goToPrevChunk={goToPrevChunk}
/>
</div>
</div>
</div>
);
}
export default DocumentProcessor;