// Global state
let currentPage = 'dashboard';
let cloneHistory = [];
let settings = {
outputDir: 'M:\\CLONEWEB\\cloned-sites',
timeout: 30,
retries: 3,
excludedDomains: 'facebook.com\ntwitter.com\ninstagram.com\ngoogle-analytics.com\ngoogletagmanager.com'
};
// Initialize app
document.addEventListener('DOMContentLoaded', function () {
initializeApp();
});
function initializeApp() {
setupNavigation();
setupThemeToggle();
setupForms();
checkServiceStatus();
loadDashboard();
loadHistory();
loadSettings();
// Auto-refresh status every 30 seconds
setInterval(checkServiceStatus, 30000);
}
// Navigation
function setupNavigation() {
const navItems = document.querySelectorAll('.nav-item');
navItems.forEach(item => {
item.addEventListener('click', (e) => {
e.preventDefault();
const page = item.getAttribute('data-page');
navigateToPage(page);
});
});
}
function navigateToPage(page) {
// Update nav items
document.querySelectorAll('.nav-item').forEach(item => {
item.classList.remove('active');
if (item.getAttribute('data-page') === page) {
item.classList.add('active');
}
});
// Update pages
document.querySelectorAll('.page').forEach(p => {
p.classList.remove('active');
});
document.getElementById(page).classList.add('active');
// Update page title
const titles = {
'dashboard': 'Dashboard',
'new-clone': 'Nova Clonagem',
'history': 'Histórico',
'settings': 'Configurações'
};
document.getElementById('pageTitle').textContent = titles[page] || page;
currentPage = page;
// Refresh data when navigating
if (page === 'dashboard') {
loadDashboard();
} else if (page === 'history') {
loadHistory();
}
}
// Theme Toggle
function setupThemeToggle() {
const themeToggle = document.getElementById('themeToggle');
// Load saved theme
const savedTheme = localStorage.getItem('theme') || 'light';
if (savedTheme === 'dark') {
document.body.classList.add('dark-theme');
themeToggle.checked = true;
}
themeToggle.addEventListener('change', () => {
if (themeToggle.checked) {
document.body.classList.add('dark-theme');
localStorage.setItem('theme', 'dark');
} else {
document.body.classList.remove('dark-theme');
localStorage.setItem('theme', 'light');
}
});
}
// Service Status - verifica o serviço WGET na porta 3002
async function checkServiceStatus() {
const statusIndicator = document.getElementById('serviceStatus');
try {
// Verificar o serviço WGET via proxy do servidor (mesma origem)
const response = await fetch('/api/health', {
method: 'GET'
});
if (response.ok) {
statusIndicator.className = 'status-indicator online';
statusIndicator.querySelector('.status-text').textContent = 'Serviço Online';
} else {
statusIndicator.className = 'status-indicator offline';
statusIndicator.querySelector('.status-text').textContent = 'Serviço Offline';
}
} catch (error) {
statusIndicator.className = 'status-indicator offline';
statusIndicator.querySelector('.status-text').textContent = 'Serviço Offline';
}
}
// Dashboard
function loadDashboard() {
// Load from localStorage
const history = JSON.parse(localStorage.getItem('cloneHistory') || '[]');
cloneHistory = history;
// Calculate stats
const totalSites = history.length;
const totalSize = history.reduce((sum, item) => sum + (item.size || 0), 0);
const lastClone = history.length > 0 ? history[0].timestamp : null;
const successCount = history.filter(item => item.success).length;
const successRate = totalSites > 0 ? Math.round((successCount / totalSites) * 100) : 100;
// Update stats
document.getElementById('totalSites').textContent = totalSites;
document.getElementById('totalSize').textContent = formatBytes(totalSize);
document.getElementById('lastClone').textContent = lastClone ? formatRelativeTime(lastClone) : 'Nunca';
document.getElementById('successRate').textContent = successRate + '%';
// Update recent clones list
const recentClonesList = document.getElementById('recentClonesList');
if (history.length === 0) {
recentClonesList.innerHTML = `
Site Clonado com Sucesso!
${cloneRecord.url}
${cloneRecord.files} arquivos
${formatBytes(cloneRecord.size)}
`;
document.body.appendChild(dialog);
// Add styles
const style = document.createElement('style');
style.textContent = `
.success-dialog {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 10000;
animation: fadeIn 0.3s;
}
.success-dialog-content {
background: white;
border-radius: 16px;
padding: 2rem;
max-width: 500px;
text-align: center;
animation: slideUp 0.3s;
}
.success-icon {
font-size: 4rem;
color: var(--success-color);
margin-bottom: 1rem;
}
.success-dialog-content h3 {
font-size: 1.5rem;
margin-bottom: 0.5rem;
}
.success-dialog-content p {
color: var(--text-secondary);
margin-bottom: 1.5rem;
}
.success-stats {
display: flex;
justify-content: center;
gap: 2rem;
margin-bottom: 2rem;
padding: 1rem;
background: var(--bg-primary);
border-radius: 8px;
}
.success-stats span {
display: flex;
align-items: center;
gap: 0.5rem;
}
.success-actions {
display: flex;
gap: 0.5rem;
justify-content: center;
flex-wrap: wrap;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
`;
document.head.appendChild(style);
}
function closeSuccessDialog() {
const dialog = document.querySelector('.success-dialog');
if (dialog) {
dialog.remove();
}
}
// History
function loadHistory() {
const history = JSON.parse(localStorage.getItem('cloneHistory') || '[]');
cloneHistory = history;
const historyList = document.getElementById('historyList');
if (history.length === 0) {
historyList.innerHTML = `
${item.url}
${formatDate(item.timestamp)}
${item.success ? 'Sucesso' : 'Falhou'}
${item.files ? ` ${item.files} arquivos` : ''}
${item.size ? ` ${formatBytes(item.size)}` : ''}
${item.success ? `
` : ''}
`).join('');
}
function refreshHistory() {
loadHistory();
showToast('Histórico atualizado!', 'success');
}
function clearHistory() {
if (confirm('Tem certeza que deseja limpar todo o histórico? Esta ação não pode ser desfeita.')) {
localStorage.removeItem('cloneHistory');
cloneHistory = [];
loadHistory();
loadDashboard();
showToast('Histórico limpo com sucesso!', 'success');
}
}
function deleteHistoryItem(index) {
if (confirm('Remover este item do histórico?')) {
cloneHistory.splice(index, 1);
localStorage.setItem('cloneHistory', JSON.stringify(cloneHistory));
loadHistory();
loadDashboard();
showToast('Item removido!', 'success');
}
}
function recloneSite(url) {
document.getElementById('cloneUrl').value = url;
navigateToPage('new-clone');
showToast('URL carregada! Configure as opções e clique em "Iniciar Clonagem"', 'info');
}
function saveToHistory(record) {
cloneHistory.unshift(record);
// Keep only last 100 records
if (cloneHistory.length > 100) {
cloneHistory = cloneHistory.slice(0, 100);
}
localStorage.setItem('cloneHistory', JSON.stringify(cloneHistory));
}
// Settings
function loadSettings() {
const savedSettings = localStorage.getItem('cloneSettings');
if (savedSettings) {
settings = JSON.parse(savedSettings);
}
// Populate settings form (if needed)
const outDirInput = document.getElementById('settingsOutputDir');
if (outDirInput) outDirInput.value = settings.outputDir || '/root/Desktop/Clonados';
}
function saveSettings() {
const outDirInput = document.getElementById('settingsOutputDir');
if (outDirInput) settings.outputDir = outDirInput.value;
localStorage.setItem('cloneSettings', JSON.stringify(settings));
showToast('Configurações salvas!', 'success');
}
// Utility Functions
function openClonedSite(directory) {
const siteName = directory.replace(/\\/g, '/').split('/').pop();
window.open(`/api/preview/${siteName}`, '_blank');
}
function openCloneFolder(directory) {
showToast('Abrindo gerenciador de arquivos web...', 'info');
fetch('/api/open-folder', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ path: directory })
}).then(res => res.json())
.then(data => {
if (!data.success) {
showToast('Erro ao abrir pasta: ' + (data.error || ''), 'error');
} else if (data.url) {
window.open(data.url, '_blank');
}
})
.catch(err => console.error('Erro ao chamar open-folder:', err));
}
function showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
toast.innerHTML = `