/** * Script para funcionalidade de chat * Implementa a conexão entre o botão de chat e os modais de opções e seleção de documentos */ // Função para inicializar a funcionalidade de chat function initChatFunctionality() { console.log('🗨️ Inicializando funcionalidade de chat...'); // Elementos do chat const chatClientBtn = document.getElementById('chat-client-btn'); const chatOptionsModal = document.getElementById('chat-options-modal'); const chatDocumentsModal = document.getElementById('chat-documents-modal'); // Elementos de opções de chat const chatStrategyOption = document.getElementById('chat-strategy-option'); const chatClientOption = document.getElementById('chat-client-option'); // Elementos de seleção de documentos const chatAvailableAnalyses = document.getElementById('chat-available-analyses'); const chatAvailablePlans = document.getElementById('chat-available-plans'); const chatPreviousChats = document.getElementById('chat-previous-chats'); const chatSelectedDocumentsList = document.getElementById('chat-selected-documents-list'); const startChatBtn = document.getElementById('start-chat-btn'); const cancelChatDocumentsBtn = document.getElementById('cancel-chat-documents-btn'); // Botões de fechar modais const closeModalButtons = document.querySelectorAll('.close-modal'); // Estado do chat let selectedChatType = null; let selectedDocuments = []; let selectedExistingChat = null; // Verificar se os elementos existem if (!chatClientBtn) { console.error('❌ Botão de chat não encontrado'); return; } // Adicionar evento de clique ao botão de chat chatClientBtn.addEventListener('click', () => { console.log('🗨️ Botão de chat clicado'); // Verificar se há cliente selecionado if (!window.currentClientId) { console.error('❌ Nenhum cliente selecionado'); return; } // Redirecionar diretamente para a página de chat console.log('🗨️ Redirecionando diretamente para chat.html'); window.location.href = `/chat.html?cliente=${window.currentClientId}`; }); // Adicionar eventos às opções de chat if (chatStrategyOption) { chatStrategyOption.addEventListener('click', () => { console.log('🗨️ Opção de estratégia selecionada'); selectedChatType = 'strategy'; // Atualizar UI chatStrategyOption.classList.add('selected'); if (chatClientOption) chatClientOption.classList.remove('selected'); // Fechar modal de opções if (chatOptionsModal) chatOptionsModal.classList.remove('show'); // Carregar documentos disponíveis e chats existentes loadAvailableDocuments(); loadPreviousChats(); // Mostrar modal de seleção de documentos if (chatDocumentsModal) chatDocumentsModal.classList.add('show'); }); } if (chatClientOption) { chatClientOption.addEventListener('click', () => { console.log('🗨️ Opção de cliente ideal selecionada'); selectedChatType = 'client'; // Atualizar UI chatClientOption.classList.add('selected'); if (chatStrategyOption) chatStrategyOption.classList.remove('selected'); // Fechar modal de opções if (chatOptionsModal) chatOptionsModal.classList.remove('show'); // Carregar documentos disponíveis e chats existentes loadAvailableDocuments(); loadPreviousChats(); // Mostrar modal de seleção de documentos if (chatDocumentsModal) chatDocumentsModal.classList.add('show'); }); } // Adicionar evento ao botão de cancelar seleção de documentos if (cancelChatDocumentsBtn) { cancelChatDocumentsBtn.addEventListener('click', () => { console.log('🗨️ Seleção de documentos cancelada'); // Fechar modal de documentos if (chatDocumentsModal) chatDocumentsModal.classList.remove('show'); // Resetar seleções selectedChatType = null; selectedDocuments = []; selectedExistingChat = null; }); } // Adicionar evento ao botão de iniciar chat if (startChatBtn) { startChatBtn.addEventListener('click', () => { console.log('🗨️ Iniciando chat...'); // Verificar se há tipo de chat e documentos selecionados ou um chat existente selecionado if (!selectedChatType) { console.error('❌ Tipo de chat não selecionado'); return; } if (selectedExistingChat) { // Redirecionar para o chat existente redirectToExistingChat(); } else if (selectedDocuments.length === 0) { console.error('❌ Nenhum documento selecionado'); return; } else { // Iniciar novo chat startChat(); } }); } // Adicionar eventos aos botões de fechar modais closeModalButtons.forEach(button => { button.addEventListener('click', () => { const modal = button.closest('.modal'); if (modal) modal.classList.remove('show'); }); }); // Fechar modais ao clicar fora window.addEventListener('click', (e) => { if (e.target === chatOptionsModal) { chatOptionsModal.classList.remove('show'); } if (e.target === chatDocumentsModal) { chatDocumentsModal.classList.remove('show'); } }); // Função para carregar chats anteriores async function loadPreviousChats() { console.log('🗨️ Carregando chats anteriores...'); // Verificar se há cliente selecionado if (!window.currentClientId) { console.error('❌ Nenhum cliente selecionado'); return; } if (!chatPreviousChats) { console.error('❌ Elemento de chats anteriores não encontrado'); return; } try { // Mostrar indicador de carregamento chatPreviousChats.innerHTML = `

Carregando chats anteriores...

`; // Carregar chats do cliente const response = await safeFetch(`/api/chat/cliente/${window.currentClientId}`); // Verificar se a resposta é válida if (!response || !response.data || !Array.isArray(response.data)) { throw new Error('Resposta inválida ao carregar chats'); } const chats = response.data; // Filtrar chats ativos const activeChats = chats.filter(chat => chat.ativo !== false); console.log(`🗨️ Chats carregados: ${activeChats.length} de ${chats.length}`); // Renderizar chats renderPreviousChats(activeChats); } catch (error) { console.error('❌ Erro ao carregar chats anteriores:', error); // Mostrar mensagem de erro chatPreviousChats.innerHTML = `

Erro ao carregar chats anteriores

`; } } // Função para renderizar chats anteriores function renderPreviousChats(chats) { if (!chatPreviousChats) return; if (!chats || chats.length === 0) { chatPreviousChats.innerHTML = `

Nenhum chat anterior disponível

`; return; } // Ordenar chats por data (mais recente primeiro) chats.sort((a, b) => new Date(b.dataCriacao) - new Date(a.dataCriacao)); // Renderizar lista chatPreviousChats.innerHTML = chats.map(chat => { // Determinar o título e ícone com base no tipo const title = chat.tipo === 'strategy' ? 'Chat de Estratégia' : 'Chat com Cliente Ideal'; const icon = chat.tipo === 'strategy' ? 'fa-lightbulb' : 'fa-user-tie'; // Formatar data const date = new Date(chat.dataCriacao).toLocaleDateString('pt-BR'); // Contar mensagens (excluindo mensagens do sistema) const messageCount = chat.mensagens ? chat.mensagens.filter(msg => msg.role !== 'system').length : 0; return `
${title}
${date}${messageCount} mensagens
`; }).join(''); // Adicionar eventos de clique chatPreviousChats.querySelectorAll('.chat-item').forEach(item => { item.addEventListener('click', () => selectExistingChat(item)); }); } // Função para selecionar um chat existente function selectExistingChat(item) { const id = item.dataset.id; const type = item.dataset.type; // Remover seleção de todos os chats chatPreviousChats.querySelectorAll('.chat-item').forEach(chat => { chat.classList.remove('selected'); }); // Remover seleção de todos os documentos if (chatAvailableAnalyses) { chatAvailableAnalyses.querySelectorAll('.document-item').forEach(doc => { doc.classList.remove('selected'); }); } if (chatAvailablePlans) { chatAvailablePlans.querySelectorAll('.document-item').forEach(doc => { doc.classList.remove('selected'); }); } // Limpar documentos selecionados selectedDocuments = []; updateSelectedDocumentsList(); // Selecionar o chat item.classList.add('selected'); selectedExistingChat = id; selectedChatType = type; // Atualizar estado do botão if (startChatBtn) { startChatBtn.disabled = false; startChatBtn.innerHTML = ' Continuar Chat'; } } // Função para redirecionar para um chat existente function redirectToExistingChat() { if (!selectedExistingChat) return; console.log('🗨️ Redirecionando para chat existente:', selectedExistingChat); // Fechar modal if (chatDocumentsModal) chatDocumentsModal.classList.remove('show'); // Redirecionar para a página de chat com o ID do chat window.location.href = `/chat.html?cliente=${window.currentClientId}&chat=${selectedExistingChat}`; } // Função para carregar documentos disponíveis async function loadAvailableDocuments() { console.log('🗨️ Carregando documentos disponíveis...'); // Verificar se há cliente selecionado if (!window.currentClientId) { console.error('❌ Nenhum cliente selecionado'); return; } try { // Mostrar indicador de carregamento if (chatAvailableAnalyses) { chatAvailableAnalyses.innerHTML = `

Carregando análises...

`; } if (chatAvailablePlans) { chatAvailablePlans.innerHTML = `

Carregando planos de ação...

`; } // Carregar análises const analyses = await safeFetch(`/api/analises/cliente/${window.currentClientId}`); // Carregar planos de ação const plans = await safeFetch(`/api/planos-acao/${window.currentClientId}`); // Filtrar documentos com erro ou em progresso // Garantir que estamos trabalhando com arrays e filtrar documentos inválidos // Extrair dados do wrapper da API se presente const analysesArray = Array.isArray(analyses) ? analyses : (analyses?.data || []); const plansArray = Array.isArray(plans) ? plans : (plans?.data || []); // Filtrar documentos inválidos const validAnalyses = analysesArray.filter(analysis => !analysis.erro && !analysis.emProgresso); const validPlans = plansArray.filter(plan => !plan.erro && !plan.emProgresso); console.log(`🗨️ Análises após extração e filtragem: ${validAnalyses.length} de ${analysesArray.length}`); console.log(`🗨️ Planos após extração e filtragem: ${validPlans.length} de ${plansArray.length}`); // Verificar se há documentos válidos if (validAnalyses.length === 0 && validPlans.length === 0) { console.log('🗨️ Nenhum documento válido encontrado'); } console.log(`🗨️ Análises válidas: ${validAnalyses.length} de ${analyses ? analyses.length : 0}`); console.log(`🗨️ Planos válidos: ${validPlans.length} de ${plans ? plans.length : 0}`); // Renderizar análises renderAvailableAnalyses(validAnalyses); // Renderizar planos de ação renderAvailablePlans(validPlans); // Atualizar lista de documentos selecionados updateSelectedDocumentsList(); // Atualizar estado do botão de iniciar chat updateStartChatButtonState(); } catch (error) { console.error('❌ Erro ao carregar documentos:', error); // Mostrar mensagem de erro if (chatAvailableAnalyses) { chatAvailableAnalyses.innerHTML = `

Erro ao carregar análises

`; } if (chatAvailablePlans) { chatAvailablePlans.innerHTML = `

Erro ao carregar planos de ação

`; } } } // Função para renderizar análises disponíveis function renderAvailableAnalyses(analyses) { if (!chatAvailableAnalyses) return; if (!analyses || analyses.length === 0) { chatAvailableAnalyses.innerHTML = `

Nenhuma análise disponível

`; return; } // Ordenar análises por data (mais recente primeiro) analyses.sort((a, b) => new Date(b.dataCriacao) - new Date(a.dataCriacao)); // Renderizar lista chatAvailableAnalyses.innerHTML = analyses.map(analysis => `
Análise de Mercado
${new Date(analysis.dataCriacao).toLocaleDateString('pt-BR')}
`).join(''); // Adicionar eventos de clique chatAvailableAnalyses.querySelectorAll('.document-item').forEach(item => { item.addEventListener('click', () => toggleDocumentSelection(item)); }); } // Função para renderizar planos de ação disponíveis function renderAvailablePlans(plans) { if (!chatAvailablePlans) return; if (!plans || plans.length === 0) { chatAvailablePlans.innerHTML = `

Nenhum plano de ação disponível

`; return; } // Ordenar planos por data (mais recente primeiro) plans.sort((a, b) => new Date(b.dataCriacao) - new Date(a.dataCriacao)); // Renderizar lista chatAvailablePlans.innerHTML = plans.map(plan => `
${plan.titulo}
${new Date(plan.dataCriacao).toLocaleDateString('pt-BR')}
`).join(''); // Adicionar eventos de clique chatAvailablePlans.querySelectorAll('.document-item').forEach(item => { item.addEventListener('click', () => toggleDocumentSelection(item)); }); } // Função para alternar seleção de documento function toggleDocumentSelection(item) { const id = item.dataset.id; const type = item.dataset.type; const title = item.querySelector('.document-item-title').textContent; // Verificar se já está selecionado const isSelected = item.classList.contains('selected'); // Se houver um chat existente selecionado, desmarcar if (selectedExistingChat) { selectedExistingChat = null; // Remover seleção de todos os chats if (chatPreviousChats) { chatPreviousChats.querySelectorAll('.chat-item').forEach(chat => { chat.classList.remove('selected'); }); } // Atualizar texto do botão if (startChatBtn) { startChatBtn.innerHTML = ' Iniciar Chat'; } } if (isSelected) { // Remover da seleção item.classList.remove('selected'); selectedDocuments = selectedDocuments.filter(doc => doc.id !== id); } else { // Adicionar à seleção item.classList.add('selected'); selectedDocuments.push({ id, type, title }); } // Atualizar lista de documentos selecionados updateSelectedDocumentsList(); // Atualizar estado do botão de iniciar chat updateStartChatButtonState(); } // Função para atualizar lista de documentos selecionados function updateSelectedDocumentsList() { if (!chatSelectedDocumentsList) return; if (selectedDocuments.length === 0) { chatSelectedDocumentsList.innerHTML = `

Selecione pelo menos um documento acima

`; return; } chatSelectedDocumentsList.innerHTML = selectedDocuments.map(doc => `
${doc.title}
${doc.type === 'analysis' ? 'Análise' : 'Plano de Ação'}
`).join(''); // Adicionar eventos para remover documentos chatSelectedDocumentsList.querySelectorAll('.remove-selected-btn').forEach(btn => { btn.addEventListener('click', () => { const id = btn.dataset.id; removeDocumentFromSelection(id); }); }); } // Função para remover documento da seleção function removeDocumentFromSelection(id) { // Remover da lista de selecionados selectedDocuments = selectedDocuments.filter(doc => doc.id !== id); // Remover classe selected do item na lista de disponíveis const item = document.querySelector(`[data-id="${id}"]`); if (item) { item.classList.remove('selected'); } // Atualizar listas updateSelectedDocumentsList(); updateStartChatButtonState(); } // Função para atualizar estado do botão de iniciar chat function updateStartChatButtonState() { if (!startChatBtn) return; // Habilitar se houver documentos selecionados ou um chat existente selecionado startChatBtn.disabled = selectedDocuments.length === 0 && !selectedExistingChat; // Atualizar texto do botão if (selectedExistingChat) { startChatBtn.innerHTML = ' Continuar Chat'; } else { startChatBtn.innerHTML = ' Iniciar Chat'; } } // Função para iniciar chat async function startChat() { console.log('🗨️ Iniciando chat...'); console.log('🗨️ Tipo:', selectedChatType); console.log('🗨️ Documentos:', selectedDocuments); console.log('🔍 [DEBUG-STARTCHAT] Iniciando processo de criação de chat'); // Verificar se há cliente selecionado if (!window.currentClientId) { console.error('❌ Nenhum cliente selecionado'); return; } try { // Mostrar indicador de carregamento if (startChatBtn) { const originalText = startChatBtn.innerHTML; startChatBtn.innerHTML = ' Iniciando...'; startChatBtn.disabled = true; } // Preparar dados para a API const analiseIds = selectedDocuments .filter(doc => doc.type === 'analysis') .map(doc => doc.id); const planoAcaoIds = selectedDocuments .filter(doc => doc.type === 'plan') .map(doc => doc.id); const requestData = { clienteId: window.currentClientId, tipo: selectedChatType, analiseIds, planoAcaoIds }; console.log('🗨️ Iniciando chat...', requestData); console.log('🗨️ Tipo:', selectedChatType); console.log('🗨️ Documentos:', selectedDocuments); console.log('🔍 [DEBUG-STARTCHAT] Dados da requisição:', JSON.stringify(requestData)); // Criar novo chat console.log('🔍 [DEBUG-STARTCHAT] Enviando requisição POST para /api/chat'); const response = await safeFetch('/api/chat', { method: 'POST', body: JSON.stringify(requestData) }); // Logs detalhados da resposta console.log('🗨️ Resposta completa:', response); console.log('🔍 [DEBUG-STARTCHAT] Tipo da resposta:', typeof response); console.log('🔍 [DEBUG-STARTCHAT] É array?', Array.isArray(response)); console.log('🔍 [DEBUG-STARTCHAT] Propriedades:', Object.keys(response)); if (response && response.success === true) { console.log('🔍 [DEBUG-STARTCHAT] Resposta com success: true detectada'); console.log('🔍 [DEBUG-STARTCHAT] Dados:', response.data); } // Verificar se a resposta é válida - verificar especificamente success: true if (response && (response.success === true || (response.data && response._id))) { console.log('🔍 [DEBUG-STARTCHAT] Resposta válida com success: true ou contendo dados, redirecionando'); // Fechar modal if (chatDocumentsModal) chatDocumentsModal.classList.remove('show'); // Redirecionar para a página de chat console.log('🗨️ Redirecionando para chat.html'); window.location.href = `/chat.html?cliente=${window.currentClientId}`; return; } else { console.log('🔍 [DEBUG-STARTCHAT] Resposta recebida mas não atende aos critérios de validação:', response); } // Se chegou aqui, a resposta não foi bem-sucedida console.error('🔍 [DEBUG-STARTCHAT] Resposta considerada inválida ou não atende aos critérios esperados'); console.error('🔍 [DEBUG-STARTCHAT] Detalhes da resposta:', JSON.stringify(response)); throw new Error('Resposta inválida do servidor ou formato inesperado'); } catch (error) { console.error('❌ Erro ao iniciar chat:', error); console.error('🔍 [DEBUG-STARTCHAT] Detalhes do erro:', { message: error.message, stack: error.stack, name: error.name }); // Restaurar botão if (startChatBtn) { startChatBtn.innerHTML = ' Iniciar Chat'; startChatBtn.disabled = false; } // Mostrar mensagem de erro alert('Não foi possível iniciar o chat. Tente novamente.'); } } } // Inicializar quando o DOM estiver pronto document.addEventListener('DOMContentLoaded', () => { // Verificar se a funcionalidade já foi inicializada if (window.chatFunctionalityInitialized) return; // Definir codificação UTF-8 para garantir caracteres especiais document.characterSet = "UTF-8"; // Inicializar funcionalidade de chat initChatFunctionality(); // Marcar como inicializado window.chatFunctionalityInitialized = true; });