import { useState } from 'react'; export const useChunkNavigation = (documentData, clearTypingAnimation) => { const [chunkStates, setChunkStates] = useState({}); const [currentChunkIndex, setCurrentChunkIndex] = useState(0); const [chunkExpanded, setChunkExpanded] = useState(true); const [globalChatHistory, setGlobalChatHistory] = useState([]); const [showChat, setShowChat] = useState(true); const [isTransitioning, setIsTransitioning] = useState(false); const [completedChunks, setCompletedChunks] = useState(new Set()); const goToNextChunk = () => { if (documentData && currentChunkIndex < documentData.chunks.length - 1) { if (clearTypingAnimation) { clearTypingAnimation(); } setCurrentChunkIndex(currentChunkIndex + 1); setChunkExpanded(true); } }; const goToPrevChunk = () => { if (currentChunkIndex > 0) { if (clearTypingAnimation) { clearTypingAnimation(); } setCurrentChunkIndex(currentChunkIndex - 1); setChunkExpanded(true); } }; const sendAutomatedMessage = async (action) => { if (!documentData || currentChunkIndex >= documentData.chunks.length - 1) return; setIsTransitioning(true); const nextChunkIndex = currentChunkIndex + 1; const nextChunk = documentData.chunks[nextChunkIndex]; // Mark current chunk as completed setCompletedChunks(prev => new Set(prev).add(currentChunkIndex)); // Update chunk index immediately for UI feedback setCurrentChunkIndex(nextChunkIndex); setChunkExpanded(true); // Check if we already have messages for this chunk if (hasChunkMessages(nextChunkIndex)) { // Don't generate new response, just navigate setIsTransitioning(false); return; } try { const response = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ messages: globalChatHistory, currentChunk: documentData.chunks[currentChunkIndex]?.text || '', nextChunk: nextChunk.text, action: action, document: documentData ? JSON.stringify(documentData) : '' }) }); const data = await response.json(); addMessageToChunk( { role: 'assistant', content: data.content || 'Let\'s continue to the next section.' }, nextChunkIndex ); // Clear any animations after successful response if (clearTypingAnimation) { clearTypingAnimation(); } } catch (error) { console.error('Error in automated transition:', error); // Clear animations on error too if (clearTypingAnimation) { clearTypingAnimation(); } } finally { setIsTransitioning(false); } }; const skipChunk = () => { return sendAutomatedMessage('skip'); }; const markChunkUnderstood = () => { return sendAutomatedMessage('understood'); }; const startInteractiveLesson = (startChunkLessonFn) => { setChunkStates(prev => ({ ...prev, [currentChunkIndex]: 'interactive' })); startChunkLessonFn(currentChunkIndex); }; const setChunkAsInteractive = () => { // No longer tracking status - this is just for compatibility }; const updateGlobalChatHistory = (messages) => { setGlobalChatHistory(messages); }; const getGlobalChatHistory = () => { return globalChatHistory; }; const addMessageToChunk = (message, chunkIndex) => { const messageWithChunk = { ...message, chunkIndex }; setGlobalChatHistory(prev => [...prev, messageWithChunk]); }; const getCurrentChunkMessages = () => { return globalChatHistory.filter(msg => msg.chunkIndex === currentChunkIndex); }; const hasChunkMessages = (chunkIndex) => { return globalChatHistory.some(msg => msg.chunkIndex === chunkIndex); }; const isChunkCompleted = (chunkIndex) => { return completedChunks.has(chunkIndex); }; const canEditChunk = (chunkIndex) => { return chunkIndex === currentChunkIndex && !isChunkCompleted(chunkIndex); }; return { chunkStates, currentChunkIndex, chunkExpanded, showChat, isTransitioning, goToNextChunk, goToPrevChunk, skipChunk, markChunkUnderstood, startInteractiveLesson, setChunkExpanded, setShowChat, setChunkAsInteractive, updateGlobalChatHistory, getGlobalChatHistory, addMessageToChunk, getCurrentChunkMessages, hasChunkMessages, isChunkCompleted, canEditChunk }; };