const urlInput = document.getElementById('urlInput'); const startBtn = document.getElementById('startBtn'); const heroSection = document.getElementById('hero'); const loadingSection = document.getElementById('loading'); const resultSection = document.getElementById('result'); const terminalLog = document.getElementById('terminalLog'); const progressCircle = document.getElementById('progressCircle'); let clonedData = null; startBtn.addEventListener('click', startCloning); urlInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') startCloning(); }); document.getElementById('btnOpenSite').addEventListener('click', () => { if (clonedData && clonedData.data && clonedData.data.path) { // Construct local URL. Server serves //index.html // We know server serves static files from cloned-sites directly if configured? // Wait, server.js serves ../cloned-sites as static. // so path is just /FolderName/index.html const dirName = clonedData.data.path.split('\\').pop().split('/').pop(); window.open(`/${dirName}/index.html`, '_blank'); } }); document.getElementById('btnOpenFolder').addEventListener('click', () => { if (clonedData && clonedData.data && clonedData.data.path) { fetch('/api/open-folder', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path: clonedData.data.path }) }); } }); async function startCloning() { const url = urlInput.value.trim(); if (!url) { showToast('Por favor, insira uma URL válida', 'error'); return; } // Switch UI heroSection.classList.add('hidden'); loadingSection.classList.remove('hidden'); // Simulate Terminal Logs log('Iniciando puppeteer...'); let progress = 0; const progressInterval = setInterval(() => { if (progress < 90) { progress += Math.random() * 5; updateProgress(progress); } }, 1000); const logMessages = [ 'Configurando viewport 1920x1080...', 'Interceptando requisições de rede...', 'Analisando DOM e Shadow DOM...', 'Baixando assets estáticos...', 'Processando estilos computados...', 'Otimizando imagens...', 'Verificando integridade...' ]; let msgIndex = 0; const msgInterval = setInterval(() => { if (msgIndex < logMessages.length) { log(logMessages[msgIndex]); msgIndex++; } }, 2500); try { const response = await fetch('/api/smart-clone', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url }) }); const data = await response.json(); clonedData = data; clearInterval(progressInterval); clearInterval(msgInterval); updateProgress(100); if (data.success) { log('Clonagem concluída com sucesso!'); setTimeout(() => { showResult(data); }, 1000); } else { throw new Error(data.error || 'Erro desconhecido'); } } catch (error) { clearInterval(progressInterval); clearInterval(msgInterval); showToast('Erro: ' + error.message, 'error'); log('❌ Erro fatal: ' + error.message); setTimeout(() => { heroSection.classList.remove('hidden'); loadingSection.classList.add('hidden'); }, 3000); } } function updateProgress(value) { // 283 is the circumference const dashboard = 283; const offset = dashboard - (value / 100) * dashboard; progressCircle.style.strokeDashoffset = offset; } function log(msg) { const div = document.createElement('div'); div.className = 'log-line'; div.innerText = `> ${msg}`; terminalLog.appendChild(div); terminalLog.scrollTop = terminalLog.scrollHeight; } function showResult(data) { loadingSection.classList.add('hidden'); resultSection.classList.remove('hidden'); // Handle Verification Images const verifyContainer = document.getElementById('verificationContainer'); if (data.data.verification) { verifyContainer.style.display = 'block'; // Paths are relative to site dir. // We need to construct URL to fetch them. const dirName = data.data.path.split('\\').pop().split('/').pop(); document.getElementById('imgOriginal').src = `/${dirName}/${data.data.verification.original}`; document.getElementById('imgClone').src = `/${dirName}/${data.data.verification.clone}`; } else { verifyContainer.style.display = 'none'; } } function showToast(msg, type = 'info') { const toast = document.createElement('div'); toast.style.position = 'fixed'; toast.style.bottom = '20px'; toast.style.right = '20px'; toast.style.background = type === 'error' ? '#ef4444' : '#10b981'; toast.style.color = 'white'; toast.style.padding = '1rem 2rem'; toast.style.borderRadius = '8px'; toast.style.zIndex = '1000'; toast.innerText = msg; document.body.appendChild(toast); setTimeout(() => toast.remove(), 3000); }