`).join('');
// Adicionar eventos para remover documentos
this.elements.selectedDocumentsList.querySelectorAll('.remove-selected-btn').forEach(btn => {
btn.addEventListener('click', () => {
const id = btn.dataset.id;
this.removeDocumentFromSelection(id);
});
});
},
// Remover documento da seleção
removeDocumentFromSelection: function(id) {
// Remover da lista de selecionados
this.selectedDocuments = this.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
this.updateSelectedDocumentsList();
this.updateSubmitButtonState();
},
// Atualizar estado do botão de envio
updateSubmitButtonState: function() {
const hasTitle = this.elements.actionPlanTitleInput.value.trim().length > 0;
const hasDocuments = this.selectedDocuments.length > 0;
this.elements.startActionPlanBtn.disabled = !(hasTitle && hasDocuments);
},
// Submeter formulário de plano de ação
submitActionPlanForm: async function(event) {
event.preventDefault();
if (!this.elements.actionPlanTitleInput.value.trim()) {
alert('O título do plano de ação é obrigatório');
return;
}
if (!this.selectedDocuments.length) {
alert('Selecione pelo menos um documento');
return;
}
try {
// Registrar processo no painel de processos ativos
const client = JaniceApp.state.currentClients.find(c => c._id === JaniceApp.state.currentClientId);
const processId = JaniceApp.state.activeProcessesManager.registerProcess(
'plano-acao',
JaniceApp.state.currentClientId,
`Plano de Ação: ${this.elements.actionPlanTitleInput.value.trim()}`
);
// Mostrar tela de carregamento IMEDIATAMENTE
JaniceApp.utils.showOnlySection('loading-container');
// Adaptar interface para plano de ação
document.querySelector('.loading-text').textContent = 'Gerando plano de ação estratégico...';
JaniceApp.elements.loadingStatus.textContent = 'Preparando análise dos documentos selecionados...';
// Resetar e configurar progresso específico para planos de ação
this.resetProgress();
this.setupActionPlanProgressSteps();
// Iniciar simulação de progresso imediatamente
this.startActionPlanProgressSimulation();
// Preparar dados - separar por tipo conforme esperado pelo backend
const transcricaoIds = this.selectedDocuments
.filter(doc => doc.type === 'transcription')
.map(doc => doc.id);
const analiseIds = this.selectedDocuments
.filter(doc => doc.type === 'analysis')
.map(doc => doc.id);
const requestData = {
titulo: this.elements.actionPlanTitleInput.value.trim(),
transcricaoIds,
analiseIds
};
// Debug: verificar dados sendo enviados
console.log('🔄 [DEBUG-PLANO-ACAO] Dados enviados:', requestData);
// Enviar requisição
const response = await fetch(`/api/planos-acao/${JaniceApp.state.currentClientId}/gerar`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestData)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Erro ao criar plano de ação');
}
const plan = await response.json();
// Armazenar ID do plano para monitoramento
window.currentActionPlanId = plan.planoId;
// Iniciar monitoramento do progresso real
this.startActionPlanMonitoring(plan.planoId);
} catch (error) {
console.error('Erro ao criar plano de ação:', error);
this.showError(error.message || 'Ocorreu um erro ao criar o plano de ação.');
}
},
// Configurar etapas específicas para planos de ação
setupActionPlanProgressSteps: function() {
document.getElementById('step-1').querySelector('.step-text').textContent = 'Análise de Documentos';
document.getElementById('step-2').querySelector('.step-text').textContent = 'Processamento IA';
document.getElementById('step-3').querySelector('.step-text').textContent = 'Geração de Estratégias';
document.getElementById('step-4').querySelector('.step-text').textContent = 'Finalização';
},
// Iniciar simulação de progresso para planos de ação
startActionPlanProgressSimulation: function() {
// Adicionar informações específicas sobre o processo
const infoElement = document.createElement('div');
infoElement.className = 'action-plan-progress-info';
infoElement.style.cssText = `
margin: 20px 0;
padding: 15px;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-radius: 8px;
border-left: 4px solid #28a745;
font-size: 14px;
line-height: 1.5;
`;
infoElement.innerHTML = `
Processamento Inteligente em Andamento
Nossa IA está analisando os documentos selecionados para criar um plano de ação estratégico personalizado.
Este processo pode levar alguns minutos para garantir a máxima qualidade e relevância.
Tempo estimado: 2-5 minutos dependendo da quantidade de conteúdo a ser analisado.
`;
// Inserir após a barra de progresso
const progressContainer = document.querySelector('.progress-container');
if (progressContainer && !progressContainer.querySelector('.action-plan-progress-info')) {
progressContainer.appendChild(infoElement);
}
// Simular progresso inicial mais lento e realista
const progressSteps = [
{ percentage: 15, message: 'Carregando documentos selecionados...', step: 1, stepStatus: 'active', delay: 1000 },
{ percentage: 35, message: 'Analisando conteúdo com IA...', step: 2, stepStatus: 'active', delay: 2000 },
{ percentage: 60, message: 'Gerando estratégias personalizadas...', step: 3, stepStatus: 'active', delay: 3000 },
{ percentage: 85, message: 'Finalizando plano de ação...', step: 4, stepStatus: 'active', delay: 2000 }
];
let currentStep = 0;
const executeNextStep = () => {
if (currentStep < progressSteps.length) {
const step = progressSteps[currentStep];
this.updateProgress(step);
currentStep++;
setTimeout(executeNextStep, step.delay);
}
// Não completar automaticamente - aguardar resposta real do servidor
};
// Iniciar após pequeno delay para dar sensação de início
setTimeout(executeNextStep, 500);
},
// Monitorar progresso real do plano de ação
startActionPlanMonitoring: function(planId) {
// Verificar status a cada 5 segundos
const checkInterval = setInterval(async () => {
try {
const response = await fetch(`/api/planos-acao/plano/${planId}`);
if (!response.ok) {
console.error('Erro ao verificar status do plano de ação');
return;
}
const plan = await response.json();
// Se não está mais em progresso
if (!plan.emProgresso) {
clearInterval(checkInterval);
if (plan.erro) {
// Mostrar erro
this.showError(plan.mensagemErro || 'Erro ao gerar plano de ação');
} else {
// Completar progresso e mostrar resultado
this.updateProgress({
percentage: 100,
message: 'Plano de ação concluído com sucesso!',
step: 4,
stepStatus: 'completed'
});
// Aguardar 2 segundos antes de mostrar resultado
setTimeout(() => {
// Recarregar lista de planos de ação
this.loadClientActionPlans(JaniceApp.state.currentClientId);
// 🔧 CORREÇÃO: Usar showOnlySection para garantir transição correta
// Mostrar o plano criado automaticamente
this.viewActionPlan(planId);
}, 2000);
}
}
} catch (error) {
console.error('Erro ao monitorar plano de ação:', error);
}
}, 5000); // Verificar a cada 5 segundos
// Timeout de segurança (10 minutos)
setTimeout(() => {
clearInterval(checkInterval);
if (document.getElementById('loading-container').style.display !== 'none') {
this.showError('Timeout: O plano de ação está demorando mais que o esperado. Verifique a lista de planos de ação em alguns minutos.');
}
}, 600000); // 10 minutos
},
// Carregar planos de ação do cliente
loadClientActionPlans: async function(clientId) {
try {
const actionPlans = await JaniceApp.utils.safeFetch(`/api/planos-acao/${clientId}`);
// Se safeFetch retornou null (redirecionamento), não continuar
if (actionPlans === null) return;
if (!actionPlans.length) {
this.elements.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
this.elements.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 `
`;
// Configurar botões baseado na disponibilidade do PDF
if (plan.pdfUrl) {
this.elements.exportActionPlanPdfBtn.disabled = false;
this.elements.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
this.elements.actionPlanText.parentNode.insertBefore(pdfPreview, this.elements.actionPlanText.nextSibling);
} else {
this.elements.exportActionPlanPdfBtn.disabled = true;
this.elements.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
JaniceApp.utils.showOnlySection('action-plan-result-container');
// Scroll automático
JaniceApp.utils.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.');
}
},
// Deletar plano de ação
deleteActionPlan: async function(planId) {
if (!confirm('Tem certeza que deseja excluir este plano de ação? Esta ação não pode ser desfeita.')) {
return;
}
try {
const response = await fetch(`/api/planos-acao/plano/${planId}`, {
method: 'DELETE'
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || 'Erro ao excluir plano de ação');
}
// Recarregar lista de planos de ação
if (JaniceApp.state.currentClientId) {
this.loadClientActionPlans(JaniceApp.state.currentClientId);
}
console.log('✅ Plano de ação excluído com sucesso');
} catch (error) {
console.error('Erro ao excluir plano de ação:', error);
alert('Não foi possível excluir o plano de ação. Tente novamente.');
}
},
// Copiar plano de ação
copyActionPlan: function() {
if (!JaniceApp.state.currentActionPlanData) return;
const planContent = JaniceApp.state.currentActionPlanData.conteudo;
navigator.clipboard.writeText(planContent)
.then(() => {
const originalText = this.elements.copyActionPlanBtn.innerHTML;
this.elements.copyActionPlanBtn.innerHTML = ' Copiado!';
setTimeout(() => {
this.elements.copyActionPlanBtn.innerHTML = originalText;
}, 2000);
})
.catch(err => {
console.error('Erro ao copiar: ', err);
});
},
// Exportar PDF do plano de ação
exportActionPlanPdf: function() {
if (!JaniceApp.state.currentActionPlanData) return;
if (JaniceApp.state.currentActionPlanData.pdfUrl) {
window.open(`/api/planos-acao/pdf/${JaniceApp.state.currentActionPlanData._id}`, '_blank');
} else {
alert('PDF não disponível para este plano de ação.');
}
},
// Formatar markdown específico para planos de ação
formatMarkdownForActionPlan: function(text) {
if (!text) return '';
let formatted = text;
// Converter títulos
formatted = formatted.replace(/^# (.+)$/gm, '
`;
}, 1000);
},
// Mostrar modal de edição de imagem
showEditImageModal: async function(imageId) {
console.log('✏️ Editando imagem:', imageId);
try {
// Buscar dados da imagem
const imageData = await this.getImageData(imageId);
if (!imageData) {
alert('Imagem não encontrada');
return;
}
this.currentEditImageId = imageId;
// Preencher formulário
document.getElementById('edit-image-preview').src = imageData.url;
document.getElementById('edit-image-title').value = imageData.titulo;
document.getElementById('edit-image-type').value = imageData.tipo;
document.getElementById('edit-image-description').value = imageData.prompt || '';
// Mostrar modal
const modal = document.getElementById('edit-image-modal');
if (modal) {
modal.classList.add('show');
}
} catch (error) {
console.error('❌ Erro ao carregar dados da imagem:', error);
alert('Não foi possível carregar os dados da imagem.');
}
},
// Fechar modal de edição
closeEditModal: function() {
const modal = document.getElementById('edit-image-modal');
if (modal) {
modal.classList.remove('show');
this.currentEditImageId = null;
}
},
// Salvar edição da imagem
saveImageEdit: async function() {
if (!this.currentEditImageId) {
alert('Erro: ID da imagem não encontrado');
return;
}
try {
const title = document.getElementById('edit-image-title').value.trim();
const type = document.getElementById('edit-image-type').value;
const description = document.getElementById('edit-image-description').value.trim();
const newImageFile = document.getElementById('edit-image-file').files[0];
if (!title) {
alert('O título é obrigatório');
return;
}
console.log('✏️ Salvando edição da imagem:', this.currentEditImageId);
let updateData = {
titulo: title,
tipo: type,
prompt: description
};
// Se há nova imagem, fazer upload primeiro
if (newImageFile) {
console.log('📤 Fazendo upload da nova imagem...');
// Validar arquivo
if (!newImageFile.type.startsWith('image/')) {
alert('Arquivo deve ser uma imagem');
return;
}
if (newImageFile.size > 10 * 1024 * 1024) {
alert('Arquivo muito grande (máximo 10MB)');
return;
}
// Upload para Cloudinary
const uploadResponse = await fetch('/api/cloudinary/signature', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
folder: 'gallery-uploads'
})
});
if (!uploadResponse.ok) {
throw new Error('Erro ao obter assinatura do Cloudinary');
}
const { signature, timestamp, cloudName, apiKey } = await uploadResponse.json();
const cloudinaryData = new FormData();
cloudinaryData.append('file', newImageFile);
cloudinaryData.append('signature', signature);
cloudinaryData.append('timestamp', timestamp);
cloudinaryData.append('api_key', apiKey);
cloudinaryData.append('folder', 'gallery-uploads');
const cloudinaryResponse = await fetch(`https://api.cloudinary.com/v1_1/${cloudName}/image/upload`, {
method: 'POST',
body: cloudinaryData
});
if (!cloudinaryResponse.ok) {
throw new Error('Erro no upload da nova imagem');
}
const cloudinaryResult = await cloudinaryResponse.json();
updateData.novaImagemUrl = cloudinaryResult.secure_url;
updateData.novoPublicId = cloudinaryResult.public_id;
}
// Salvar alterações
const response = await fetch(`/api/mockups/galeria/imagem/${this.currentEditImageId}/editar`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(updateData)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Erro ao salvar alterações');
}
console.log('✅ Imagem editada com sucesso');
// Fechar modal e recarregar galeria
this.closeEditModal();
this.loadGallery();
} catch (error) {
console.error('❌ Erro ao editar imagem:', error);
alert('Não foi possível salvar as alterações. Tente novamente.');
}
},
// Obter dados de uma imagem específica
getImageData: async function(imageId) {
try {
// Buscar na galeria atual
const response = await JaniceApp.utils.safeFetch(`/api/mockups/galeria/${JaniceApp.state.currentClientId}`);
if (!response) return null;
let images = [];
if (Array.isArray(response)) {
images = response;
} else if (response.imagens && Array.isArray(response.imagens)) {
images = response.imagens;
} else if (response.data && Array.isArray(response.data)) {
images = response.data;
}
return images.find(img => img.id === imageId);
} catch (error) {
console.error('❌ Erro ao buscar dados da imagem:', error);
return null;
}
},
// Utilitários
formatFileSize: function(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
},
getFileExtension: function(filename) {
return filename.split('.').pop().toLowerCase();
}
};
// ===== MÓDULO DE MOCKUPS =====
JaniceApp.modules.mockups = {
// Estado do módulo
currentMockupData: null,
currentVariations: [],
selectedVariations: [],
init: function() {
console.log('🎨 Inicializando módulo de Mockups...');
// Configurar eventos
this.setupEvents();
console.log('✅ Módulo de Mockups inicializado');
},
setupEvents: function() {
// Botão de novo mockup
const newMockupBtn = document.getElementById('new-mockup-btn');
if (newMockupBtn) {
newMockupBtn.addEventListener('click', () => this.showMockupModal());
}
// Modal de mockup
const mockupModal = document.getElementById('mockup-modal');
if (mockupModal) {
// Fechar modal
const closeButtons = mockupModal.querySelectorAll('.close-modal');
closeButtons.forEach(btn => {
btn.addEventListener('click', () => this.closeMockupModal());
});
// Cancelar mockup
const cancelBtn = document.getElementById('cancel-mockup-btn');
if (cancelBtn) {
cancelBtn.addEventListener('click', () => this.closeMockupModal());
}
// Submeter formulário
const mockupForm = document.getElementById('mockup-form');
if (mockupForm) {
mockupForm.addEventListener('submit', (e) => this.submitMockupForm(e));
}
// Toggle configurações avançadas
const toggleAdvanced = document.getElementById('toggle-advanced');
if (toggleAdvanced) {
toggleAdvanced.addEventListener('click', () => this.toggleAdvancedSettings());
}
// Sliders com valores dinâmicos
this.setupSliders();
}
// Modal de variações
const variationsModal = document.getElementById('mockup-variations-modal');
if (variationsModal) {
// Fechar modal
const closeButtons = variationsModal.querySelectorAll('.close-modal');
closeButtons.forEach(btn => {
btn.addEventListener('click', () => this.closeVariationsModal());
});
// Regenerar mockup
const regenerateBtn = document.getElementById('regenerate-mockup-btn');
if (regenerateBtn) {
regenerateBtn.addEventListener('click', () => this.regenerateMockup());
}
// Salvar selecionadas
const saveSelectedBtn = document.getElementById('save-selected-btn');
if (saveSelectedBtn) {
saveSelectedBtn.addEventListener('click', () => this.saveSelectedVariations());
}
}
// Modal de galeria
const galleryModal = document.getElementById('gallery-modal');
if (galleryModal) {
// Fechar modal
const closeButtons = galleryModal.querySelectorAll('.close-modal');
closeButtons.forEach(btn => {
btn.addEventListener('click', () => this.closeGalleryModal());
});
const closeGalleryBtn = document.getElementById('close-gallery-modal');
if (closeGalleryBtn) {
closeGalleryBtn.addEventListener('click', () => this.closeGalleryModal());
}
// Download da galeria
const downloadBtn = document.getElementById('download-gallery-image');
if (downloadBtn) {
downloadBtn.addEventListener('click', () => this.downloadGalleryImage());
}
}
// Botão de atualizar galeria
const refreshGalleryBtn = document.getElementById('refresh-gallery-btn');
if (refreshGalleryBtn) {
refreshGalleryBtn.addEventListener('click', () => this.loadGallery());
}
// Filtros da galeria
const filterBtns = document.querySelectorAll('.filter-btn');
filterBtns.forEach(btn => {
btn.addEventListener('click', () => this.filterGallery(btn.dataset.filter));
});
// Botão de upload de imagens
const uploadImagesBtn = document.getElementById('upload-images-btn');
if (uploadImagesBtn) {
uploadImagesBtn.addEventListener('click', () => this.showUploadModal());
}
// Modal de upload
const uploadModal = document.getElementById('upload-images-modal');
if (uploadModal) {
// Fechar modal
const closeButtons = uploadModal.querySelectorAll('.close-modal');
closeButtons.forEach(btn => {
btn.addEventListener('click', () => this.closeUploadModal());
});
// Cancelar upload
const cancelBtn = document.getElementById('cancel-upload-btn');
if (cancelBtn) {
cancelBtn.addEventListener('click', () => this.closeUploadModal());
}
// Iniciar upload
const startUploadBtn = document.getElementById('start-upload-btn');
if (startUploadBtn) {
startUploadBtn.addEventListener('click', () => this.startUpload());
}
// Configurar drag & drop
this.setupUploadDragDrop();
}
// Modal de edição
const editModal = document.getElementById('edit-image-modal');
if (editModal) {
// Fechar modal
const closeButtons = editModal.querySelectorAll('.close-modal');
closeButtons.forEach(btn => {
btn.addEventListener('click', () => this.closeEditModal());
});
// Cancelar edição
const cancelBtn = document.getElementById('cancel-edit-btn');
if (cancelBtn) {
cancelBtn.addEventListener('click', () => this.closeEditModal());
}
// Salvar edição
const saveBtn = document.getElementById('save-edit-btn');
if (saveBtn) {
saveBtn.addEventListener('click', () => this.saveImageEdit());
}
}
},
setupSliders: function() {
// CFG Slider
const cfgSlider = document.getElementById('mockup-cfg');
const cfgValue = document.getElementById('cfg-value');
if (cfgSlider && cfgValue) {
cfgSlider.addEventListener('input', () => {
cfgValue.textContent = cfgSlider.value;
});
}
// Steps Slider
const stepsSlider = document.getElementById('mockup-steps');
const stepsValue = document.getElementById('steps-value');
if (stepsSlider && stepsValue) {
stepsSlider.addEventListener('input', () => {
stepsValue.textContent = stepsSlider.value;
});
}
// Quality Slider
const qualitySlider = document.getElementById('mockup-quality');
const qualityValue = document.getElementById('quality-value');
if (qualitySlider && qualityValue) {
qualitySlider.addEventListener('input', () => {
qualityValue.textContent = qualitySlider.value;
});
}
},
showMockupModal: function() {
console.log('🎨 Abrindo modal de mockup...');
const modal = document.getElementById('mockup-modal');
if (modal) {
// Resetar formulário
const form = document.getElementById('mockup-form');
if (form) {
form.reset();
// Restaurar valores padrão dos sliders
const cfgSlider = document.getElementById('mockup-cfg');
const stepsSlider = document.getElementById('mockup-steps');
const qualitySlider = document.getElementById('mockup-quality');
if (cfgSlider) {
cfgSlider.value = 3.5;
document.getElementById('cfg-value').textContent = '3.5';
}
if (stepsSlider) {
stepsSlider.value = 28;
document.getElementById('steps-value').textContent = '28';
}
if (qualitySlider) {
qualitySlider.value = 90;
document.getElementById('quality-value').textContent = '90';
}
}
modal.classList.add('show');
}
},
closeMockupModal: function() {
const modal = document.getElementById('mockup-modal');
if (modal) {
modal.classList.remove('show');
}
},
toggleAdvancedSettings: function() {
const content = document.getElementById('advanced-content');
const toggle = document.getElementById('toggle-advanced');
if (content && toggle) {
const isVisible = content.style.display === 'block';
content.style.display = isVisible ? 'none' : 'block';
const icon = toggle.querySelector('.fa-chevron-down');
if (icon) {
icon.style.transform = isVisible ? 'rotate(0deg)' : 'rotate(180deg)';
}
}
},
submitMockupForm: async function(event) {
event.preventDefault();
console.log('🎨 Submetendo formulário de mockup...');
// Validar campos obrigatórios
const requiredFields = ['mockup-title', 'mockup-type', 'mockup-aspect-ratio', 'mockup-style', 'mockup-prompt'];
for (const fieldId of requiredFields) {
const field = document.getElementById(fieldId);
if (!field || !field.value.trim()) {
alert(`O campo ${fieldId.replace('mockup-', '').replace('-', ' ')} é obrigatório`);
return;
}
}
try {
// Coletar dados do formulário
const formData = this.collectFormData();
console.log('🎨 Dados do formulário:', formData);
// Fechar modal de criação
this.closeMockupModal();
// Mostrar tela de carregamento
JaniceApp.utils.showOnlySection('loading-container');
// Adaptar interface para mockup
document.querySelector('.loading-text').textContent = 'Gerando mockup com IA...';
JaniceApp.elements.loadingStatus.textContent = 'Preparando geração de 4 variações...';
// Resetar e configurar progresso específico para mockups
this.resetProgress();
this.setupMockupProgressSteps();
// Iniciar simulação de progresso
this.startMockupProgressSimulation();
// Enviar requisição para gerar mockup
const response = await JaniceApp.utils.safeFetch('/api/mockups/gerar', {
method: 'POST',
body: JSON.stringify({
...formData,
clienteId: JaniceApp.state.currentClientId
})
});
if (!response) {
throw new Error('Resposta inválida do servidor');
}
// Armazenar dados do mockup atual
this.currentMockupData = formData;
// Como o mockupId não é retornado imediatamente, vamos monitorar a lista de mockups
// para detectar quando um novo mockup aparecer com status 'aguardando_selecao'
this.startMockupListMonitoring();
} catch (error) {
console.error('❌ Erro ao gerar mockup:', error);
this.showError(error.message || 'Ocorreu um erro ao gerar o mockup.');
}
},
collectFormData: function() {
return {
titulo: document.getElementById('mockup-title').value.trim(),
configuracao: {
tipoArte: document.getElementById('mockup-type').value,
aspectRatio: document.getElementById('mockup-aspect-ratio').value,
estilo: document.getElementById('mockup-style').value,
cores: document.getElementById('mockup-colors').value || '',
elementos: document.getElementById('mockup-elements').value || '',
setor: document.getElementById('mockup-sector').value || '',
publico: document.getElementById('mockup-audience').value || '',
mood: document.getElementById('mockup-mood').value || '',
renderStyle: document.getElementById('mockup-render-style').value || ''
},
prompt: document.getElementById('mockup-prompt').value.trim(),
configuracaoTecnica: {
cfg: parseFloat(document.getElementById('mockup-cfg').value),
steps: parseInt(document.getElementById('mockup-steps').value),
outputFormat: document.getElementById('mockup-format').value,
outputQuality: parseInt(document.getElementById('mockup-quality').value)
}
};
},
setupMockupProgressSteps: function() {
document.getElementById('step-1').querySelector('.step-text').textContent = 'Preparando Prompt';
document.getElementById('step-2').querySelector('.step-text').textContent = 'Gerando com IA';
document.getElementById('step-3').querySelector('.step-text').textContent = 'Processando Variações';
document.getElementById('step-4').querySelector('.step-text').textContent = 'Finalização';
},
startMockupProgressSimulation: function() {
// Adicionar informações específicas sobre o processo
const infoElement = document.createElement('div');
infoElement.className = 'mockup-progress-info';
infoElement.style.cssText = `
margin: 20px 0;
padding: 15px;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
border-radius: 8px;
border-left: 4px solid #6a5acd;
font-size: 14px;
line-height: 1.5;
`;
infoElement.innerHTML = `
Geração de Mockup em Andamento
Nossa IA está criando 4 variações únicas do seu mockup usando o modelo Flux 1.1 Pro.
Cada variação terá características visuais diferentes para você escolher a melhor.