// actionPlanManager.js // Gerenciador de Planos de Ação (function(window) { 'use strict'; // Elementos específicos para planos de ação let newActionPlanBtn; let cancelActionPlanBtn; let startActionPlanBtn; let actionPlanForm; let actionPlanTitleInput; let availableTranscriptions; let availableAnalyses; let selectedDocumentsList; let actionPlansList; let actionPlanTitleDisplay; let actionPlanDate; let actionPlanDocumentsCount; let actionPlanText; let exportActionPlanPdfBtn; let copyActionPlanBtn; let backToClientFromPlanBtn; // Referências a elementos e funções externas let currentClientId; let loadingContainer; let loadingStatus; let progressFill; let progressText; let progressSteps; let clientDetailsPanel; let safeFetch; let showOnlySection; let scrollToElement; let updateProgress; let showError; let resetProgress; let activeProcessesManager; // Estado dos documentos selecionados let selectedDocuments = []; let currentActionPlanData = null; // Inicializar elementos DOM e referências function initElements() { // Elementos específicos para planos de ação newActionPlanBtn = document.getElementById('new-action-plan-btn'); cancelActionPlanBtn = document.getElementById('cancel-action-plan-btn'); startActionPlanBtn = document.getElementById('start-action-plan-btn'); actionPlanForm = document.getElementById('action-plan-form'); actionPlanTitleInput = document.getElementById('action-plan-title'); availableTranscriptions = document.getElementById('available-transcriptions'); availableAnalyses = document.getElementById('available-analyses'); selectedDocumentsList = document.getElementById('selected-documents-list'); actionPlansList = document.getElementById('action-plans-list'); actionPlanTitleDisplay = document.getElementById('action-plan-title-display'); actionPlanDate = document.getElementById('action-plan-date'); actionPlanDocumentsCount = document.getElementById('action-plan-documents-count'); actionPlanText = document.getElementById('action-plan-text'); exportActionPlanPdfBtn = document.getElementById('export-action-plan-pdf'); copyActionPlanBtn = document.getElementById('copy-action-plan'); backToClientFromPlanBtn = document.getElementById('back-to-client-from-plan'); // Elementos compartilhados loadingContainer = document.getElementById('loading-container'); loadingStatus = document.getElementById('loading-status'); progressFill = document.getElementById('progress-fill'); progressText = document.getElementById('progress-text'); progressSteps = { step1: document.getElementById('step-1'), step2: document.getElementById('step-2'), step3: document.getElementById('step-3'), step4: document.getElementById('step-4') }; clientDetailsPanel = document.getElementById('client-details-panel'); } // Função auxiliar para formatar duração function formatDuration(seconds) { if (!seconds) return '0:00'; const minutes = Math.floor(seconds / 60); const remainingSeconds = Math.floor(seconds % 60); if (minutes < 60) { return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`; } else { const hours = Math.floor(minutes / 60); const remainingMinutes = minutes % 60; return `${hours}:${remainingMinutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; } } // Mostrar formulário de novo plano de ação function showActionPlanForm() { // Limpar formulário actionPlanForm.reset(); selectedDocuments = []; updateSelectedDocumentsList(); // Carregar documentos disponíveis loadAvailableDocuments(); // Mostrar apenas o formulário de plano de ação (estado exclusivo) showOnlySection('action-plan-container'); // Scroll automático para o formulário scrollToElement('action-plan-container'); } // Carregar documentos disponíveis (transcrições e análises) async function loadAvailableDocuments() { if (!currentClientId) return; try { // Carregar transcrições usando safeFetch const transcriptions = await safeFetch(`/api/transcricoes/cliente/${currentClientId}`); if (transcriptions !== null) { // Extrair dados do wrapper da API se presente const transcriptionsArray = Array.isArray(transcriptions) ? transcriptions : (transcriptions?.data || []); renderAvailableTranscriptions(transcriptionsArray); } // Carregar análises usando safeFetch const analyses = await safeFetch(`/api/analises/cliente/${currentClientId}`); if (analyses !== null) { // Extrair dados do wrapper da API se presente const analysesArray = Array.isArray(analyses) ? analyses : (analyses?.data || []); renderAvailableAnalyses(analysesArray); } } catch (error) { console.error('Erro ao carregar documentos:', error); } } // Renderizar transcrições disponíveis function renderAvailableTranscriptions(transcriptions) { if (!transcriptions.length) { availableTranscriptions.innerHTML = `

Nenhuma transcrição disponível

`; return; } // Filtrar apenas transcrições concluídas const completedTranscriptions = transcriptions.filter(t => !t.emProgresso && !t.erro); if (!completedTranscriptions.length) { availableTranscriptions.innerHTML = `

Nenhuma transcrição concluída disponível

`; return; } availableTranscriptions.innerHTML = completedTranscriptions.map(transcription => `
${transcription.titulo}
${new Date(transcription.dataCriacao).toLocaleDateString('pt-BR')} ${formatDuration(transcription.duracao)}
`).join(''); // Adicionar eventos de clique availableTranscriptions.querySelectorAll('.document-item').forEach(item => { item.addEventListener('click', () => toggleDocumentSelection(item)); }); } // Renderizar análises disponíveis function renderAvailableAnalyses(analyses) { if (!analyses.length) { availableAnalyses.innerHTML = `

Nenhuma análise disponível

`; return; } // Filtrar apenas análises concluídas (mesmo tratamento que as transcrições) const completedAnalyses = analyses.filter(a => !a.emProgresso && !a.erro); if (!completedAnalyses.length) { availableAnalyses.innerHTML = `

Nenhuma análise concluída disponível

`; return; } availableAnalyses.innerHTML = completedAnalyses.map(analysis => `
Análise de Mercado e Estratégia
${new Date(analysis.dataCriacao).toLocaleDateString('pt-BR')}
`).join(''); // Adicionar eventos de clique availableAnalyses.querySelectorAll('.document-item').forEach(item => { item.addEventListener('click', () => toggleDocumentSelection(item)); }); } // 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 existingIndex = selectedDocuments.findIndex(doc => doc.id === id); if (existingIndex >= 0) { // Remover da seleção selectedDocuments.splice(existingIndex, 1); item.classList.remove('selected'); } else { // Adicionar à seleção selectedDocuments.push({ id, type, title }); item.classList.add('selected'); } // Atualizar lista de documentos selecionados updateSelectedDocumentsList(); // Atualizar estado do botão de envio updateSubmitButtonState(); } // Atualizar lista de documentos selecionados function updateSelectedDocumentsList() { if (!selectedDocuments.length) { selectedDocumentsList.innerHTML = `

Selecione pelo menos um documento acima

`; return; } selectedDocumentsList.innerHTML = selectedDocuments.map(doc => `
${doc.title}
${doc.type === 'transcription' ? 'Transcrição' : 'Análise'}
`).join(''); // Adicionar eventos para remover documentos selectedDocumentsList.querySelectorAll('.remove-selected-btn').forEach(btn => { btn.addEventListener('click', () => { const id = btn.dataset.id; removeDocumentFromSelection(id); }); }); } // 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(); updateSubmitButtonState(); } // Atualizar estado do botão de envio function updateSubmitButtonState() { const hasTitle = actionPlanTitleInput.value.trim().length > 0; const hasDocuments = selectedDocuments.length > 0; startActionPlanBtn.disabled = !(hasTitle && hasDocuments); } // Carregar planos de ação do cliente async function loadClientActionPlans(clientId) { try { const actionPlans = await safeFetch(`/api/planos-acao/${clientId}`); // Se safeFetch retornou null (redirecionamento), não continuar if (actionPlans === null) return; if (!actionPlans.length) { actionPlansList.innerHTML = `

Nenhum plano de ação criado

`; return; } // Ordenar por data (mais recente primeiro) actionPlans.sort((a, b) => new Date(b.dataCriacao) - new Date(a.dataCriacao)); // Renderizar lista actionPlansList.innerHTML = actionPlans.map(plan => { let statusClass = 'completed'; let statusText = 'Concluído'; if (plan.emProgresso) { statusClass = 'in-progress'; statusText = 'Em progresso'; } else if (plan.erro) { statusClass = 'error'; statusText = 'Erro'; } // Calcular total de documentos de forma segura const documentosBase = plan.documentosBase || { transcricoes: [], analises: [] }; const totalDocumentos = (documentosBase.transcricoes?.length || 0) + (documentosBase.analises?.length || 0); return `
${new Date(plan.dataCriacao).toLocaleDateString('pt-BR')}
${plan.titulo}
${totalDocumentos} documento(s) ${statusText}
`; }).join(''); // Adicionar eventos de clique actionPlansList.querySelectorAll('.action-plan-item').forEach(item => { const content = item.querySelector('.action-plan-item-content'); content.addEventListener('click', () => { const planId = item.dataset.id; viewActionPlan(planId); }); }); // Adicionar eventos para botões de delete actionPlansList.querySelectorAll('.delete-action-plan-btn').forEach(btn => { btn.addEventListener('click', (e) => { e.stopPropagation(); const planId = btn.dataset.id; deleteActionPlan(planId); }); }); } catch (error) { console.error('Erro ao carregar planos de ação:', error); actionPlansList.innerHTML = `

Erro ao carregar planos de ação. Tente novamente.

`; } } // Visualizar plano de ação async function viewActionPlan(planId) { try { const response = await fetch(`/api/planos-acao/plano/${planId}`); if (!response.ok) { throw new Error('Erro ao carregar plano de ação'); } const plan = await response.json(); currentActionPlanData = plan; // Preencher dados do plano actionPlanTitleDisplay.textContent = plan.titulo; actionPlanDate.textContent = new Date(plan.dataCriacao).toLocaleString('pt-BR'); // Calcular total de documentos de forma segura const documentosBase = plan.documentosBase || { transcricoes: [], analises: [] }; const totalDocumentos = (documentosBase.transcricoes?.length || 0) + (documentosBase.analises?.length || 0); actionPlanDocumentsCount.textContent = `${totalDocumentos} documento(s)`; // Exibir conteúdo do plano actionPlanText.innerHTML = `
${formatMarkdownForActionPlan(plan.conteudo)}
`; // Configurar botões baseado na disponibilidade do PDF if (plan.pdfUrl) { exportActionPlanPdfBtn.disabled = false; exportActionPlanPdfBtn.innerHTML = ' Abrir Relatório PDF'; // Criar preview do PDF similar às análises const pdfPreview = document.createElement('div'); pdfPreview.className = 'pdf-preview-section'; pdfPreview.innerHTML = `

Relatório PDF Pronto

Seu plano de ação estratégico foi gerado com sucesso e está pronto para visualização.

O PDF será aberto em uma nova aba do navegador
`; // Inserir preview após o conteúdo do plano actionPlanText.parentNode.insertBefore(pdfPreview, actionPlanText.nextSibling); } else { exportActionPlanPdfBtn.disabled = true; exportActionPlanPdfBtn.innerHTML = ' PDF Indisponível'; // Remover preview anterior se existir const existingPreview = document.querySelector('.pdf-preview-section'); if (existingPreview) { existingPreview.remove(); } } // Mostrar apenas a seção de resultado do plano de ação showOnlySection('action-plan-result-container'); // Scroll automático scrollToElement('action-plan-result-container'); } catch (error) { console.error('Erro ao visualizar plano de ação:', error); alert('Não foi possível carregar o plano de ação. Tente novamente.'); } } // Formatar markdown específico para planos de ação function formatMarkdownForActionPlan(text) { if (!text) return ''; let formatted = text; // Converter títulos formatted = formatted.replace(/^# (.+)$/gm, '

$1

'); formatted = formatted.replace(/^## (.+)$/gm, '

$1

'); formatted = formatted.replace(/^### (.+)$/gm, '

$1

'); formatted = formatted.replace(/^#### (.+)$/gm, '

$1

'); // Converter negrito e itálico formatted = formatted.replace(/\*\*([^*]+)\*\*/g, '$1'); formatted = formatted.replace(/\*([^*]+)\*/g, '$1'); // Converter listas formatted = formatted.replace(/^- (.+)$/gm, '
  • $1
  • '); formatted = formatted.replace(/^(\d+)\. (.+)$/gm, '
  • $2
  • '); // Agrupar listas formatted = formatted.replace(/((
  • .*<\/li>\s*)+)/g, ''); // Converter tabelas simples const tableRegex = /\|(.+)\|\n\|[-\s|]+\|\n((\|.+\|\n?)+)/g; formatted = formatted.replace(tableRegex, (match, header, separator, rows) => { const headerCells = header.split('|').map(cell => cell.trim()).filter(cell => cell); const rowsArray = rows.trim().split('\n').map(row => row.split('|').map(cell => cell.trim()).filter(cell => cell) ); let table = ''; headerCells.forEach(cell => { table += ``; }); table += ''; rowsArray.forEach(row => { table += ''; row.forEach(cell => { table += ``; }); table += ''; }); table += '
    ${cell}
    ${cell}
    '; return table; }); // Converter parágrafos formatted = formatted.replace(/\n\n/g, '

    '); formatted = `

    ${formatted}

    `; // Limpar tags vazias formatted = formatted.replace(/

    <\/p>/g, ''); formatted = formatted.replace(/

    ()/g, '$1'); formatted = formatted.replace(/(<\/h[1-6]>)<\/p>/g, '$1'); formatted = formatted.replace(/

    (