Spaces:
Sleeping
Sleeping
File size: 7,050 Bytes
c075953 4a6c290 c075953 a706099 02158b8 a706099 f444dc0 e79fdda a706099 4a6c290 8066d07 4a6c290 a706099 8d0b379 f444dc0 a706099 8d0b379 f444dc0 98d2bd7 a706099 9ded9e1 a706099 4a6c290 98d2bd7 a706099 9ded9e1 c075953 a706099 c075953 e79fdda c075953 e79fdda c075953 e79fdda c075953 e79fdda c075953 e79fdda c075953 e79fdda c075953 a706099 c075953 e79fdda f444dc0 c075953 b1e57e4 e79fdda a706099 e79fdda f444dc0 e79fdda a706099 8d0b379 f444dc0 8066d07 f444dc0 a706099 e79fdda b1e57e4 a706099 c075953 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
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; |