// API base URL const API_BASE = '/api'; // Initialize document.addEventListener('DOMContentLoaded', () => { loadBooks(); loadSchedules(); // Event listeners document.getElementById('send-btn').addEventListener('click', sendChatMessage); document.getElementById('chat-input').addEventListener('keypress', (e) => { if (e.key === 'Enter') sendChatMessage(); }); document.getElementById('upload-btn').addEventListener('click', uploadPDF); document.getElementById('add-schedule-btn').addEventListener('click', addSchedule); }); async function sendChatMessage() { const input = document.getElementById('chat-input'); const button = document.getElementById('send-btn'); const message = input.value.trim(); if (!message || button.disabled) return; button.disabled = true; // Add user message to chat addMessage(message, 'user'); input.value = ''; // Show loading showLoading(); try { const response = await fetch(`${API_BASE}/chat`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message, top_k: 3 }), }); const data = await response.json().catch(() => ({})); if (!response.ok) { const detail = typeof data.detail === 'string' ? data.detail : 'Erro ao enviar mensagem'; throw new Error(detail); } hideLoading(); addMessage(data.response, 'bot'); if (data.sources && data.sources.length > 0) { const sourceText = data.sources.map((source) => { const meta = source.metadata || source; return `📖 ${meta.title || 'Desconhecido'} (trecho ${meta.chunk_id ?? '?'})`; }).join('\n'); addMessage(`Fontes:\n${sourceText}`, 'bot'); } } catch (error) { hideLoading(); addMessage(`Erro: ${error.message}`, 'bot'); } finally { button.disabled = false; input.focus(); } } function addMessage(content, type) { const container = document.getElementById('chat-messages'); const messageDiv = document.createElement('div'); messageDiv.className = `message ${type}`; const body = document.createElement('div'); body.className = 'message-content'; body.textContent = content; messageDiv.appendChild(body); container.appendChild(messageDiv); container.scrollTop = container.scrollHeight; } function showLoading() { const container = document.getElementById('chat-messages'); const loadingDiv = document.createElement('div'); loadingDiv.id = 'chat-loading'; loadingDiv.className = 'message bot'; loadingDiv.innerHTML = '
'; container.appendChild(loadingDiv); container.scrollTop = container.scrollHeight; } function hideLoading() { const loading = document.getElementById('chat-loading'); if (loading) loading.remove(); } async function loadBooks() { try { const response = await fetch(`${API_BASE}/books`); const books = await response.json(); const booksList = document.getElementById('books-list'); booksList.innerHTML = ''; if (books.length === 0) { booksList.innerHTML = 'Nenhum livro encontrado.
'; return; } books.forEach(book => { const bookDiv = document.createElement('div'); bookDiv.className = 'book-item'; const icon = document.createElement('div'); icon.className = 'book-icon'; icon.textContent = '📖'; const name = document.createElement('div'); name.className = 'book-name'; name.textContent = book.title; bookDiv.append(icon, name); booksList.appendChild(bookDiv); }); // Update book dropdown const select = document.getElementById('schedule-book'); select.innerHTML = ''; books.forEach(book => { const option = document.createElement('option'); option.value = book.title; option.textContent = book.title; select.appendChild(option); }); } catch (error) { console.error('Erro ao carregar livros:', error); } } async function uploadPDF() { const fileInput = document.getElementById('file-input'); const file = fileInput.files[0]; if (!file) { alert('Selecione um arquivo PDF primeiro'); return; } const statusDiv = document.getElementById('upload-status'); statusDiv.textContent = 'Enviando...'; try { const formData = new FormData(); formData.append('file', file); const response = await fetch(`${API_BASE}/upload`, { method: 'POST', body: formData, }); if (!response.ok) { throw new Error('Erro ao fazer upload'); } const data = await response.json(); statusDiv.textContent = `✅ ${data.filename} enviado com sucesso!`; statusDiv.style.color = '#4caf50'; setTimeout(() => { statusDiv.textContent = ''; fileInput.value = ''; }, 3000); // Reload books loadBooks(); } catch (error) { statusDiv.textContent = `❌ Erro: ${error.message}`; statusDiv.style.color = '#f44336'; } } async function loadSchedules() { try { const response = await fetch(`${API_BASE}/schedules`); const schedules = await response.json(); renderSchedules(schedules); } catch (error) { console.error('Erro ao carregar agendamentos:', error); } } function renderSchedules(schedules) { const container = document.getElementById('schedules-list'); container.innerHTML = ''; if (schedules.length === 0) { container.innerHTML = 'Nenhum agendamento.
'; return; } schedules.forEach(schedule => { const div = document.createElement('div'); div.className = 'schedule-item'; const info = document.createElement('div'); info.className = 'schedule-info'; const time = document.createElement('span'); time.className = 'schedule-time'; time.textContent = formatDateTime(schedule.time); const book = document.createElement('span'); book.className = 'schedule-book'; book.textContent = schedule.book || 'Todos os livros'; info.append(time, book); const remove = document.createElement('button'); remove.className = 'schedule-delete'; remove.type = 'button'; remove.textContent = 'Excluir'; remove.addEventListener('click', () => deleteSchedule(schedule.id)); div.append(info, remove); container.appendChild(div); }); } async function addSchedule() { const timeInput = document.getElementById('schedule-time'); const bookSelect = document.getElementById('schedule-book'); if (!timeInput.value) { alert('Selecione uma data e hora'); return; } try { const response = await fetch(`${API_BASE}/schedules`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ time: timeInput.value, book: bookSelect.value || null, enabled: true, }), }); if (!response.ok) { throw new Error('Erro ao criar agendamento'); } const schedule = await response.json(); loadSchedules(); timeInput.value = ''; bookSelect.value = ''; } catch (error) { alert(`Erro: ${error.message}`); } } async function deleteSchedule(scheduleId) { if (!confirm('Tem certeza que deseja excluir este agendamento?')) { return; } try { const response = await fetch(`${API_BASE}/schedules/${scheduleId}`, { method: 'DELETE', }); if (!response.ok) { throw new Error('Erro ao excluir agendamento'); } loadSchedules(); } catch (error) { alert(`Erro: ${error.message}`); } } function formatDateTime(dateString) { const date = new Date(dateString); return date.toLocaleString('pt-BR'); }