HEAD

ENERGIA

const API_URL = 'api.php'; let currentUser = null; let proposals = []; const stages = ['Novo lead', 'Visita técnica', 'Proposta enviada', 'Negociação', 'Fechado', 'Instalado', 'Perdido']; document.getElementById('login-form').addEventListener('submit', async (e) => { e.preventDefault(); try { const res = await fetch(`${API_URL}?action=login`, { method: 'POST', body: JSON.stringify({ email: document.getElementById('email').value, password: document.getElementById('password').value }) }); const text = await res.text(); // Lê como texto primeiro para evitar erro de JSON const data = JSON.parse(text); if(data.success) { currentUser = data.user; document.getElementById('login-screen').classList.add('hidden'); document.getElementById('user-greeting').innerText = `Olá, ${currentUser.name}`; if(currentUser.role === 'admin') { document.getElementById('dashboard-area').classList.remove('hidden'); carregarDashboard(); } else { document.getElementById('area-custos').style.display = 'none'; } carregarPropostas(); } else { alert(data.error || 'Credenciais inválidas.'); } } catch (error) { console.error(error); alert('Erro ao conectar com o servidor. Verifique o api.php.'); } }); async function logout() { await fetch(`${API_URL}?action=logout`); location.reload(); } async function carregarPropostas() { const res = await fetch(`${API_URL}?action=get_proposals`); proposals = await res.json(); renderKanban(); } async function carregarDashboard() { const res = await fetch(`${API_URL}?action=dashboard_stats`); const stats = await res.json(); document.getElementById('dash-total').innerText = stats.total; document.getElementById('dash-fechados').innerText = stats.fechados; document.getElementById('dash-conversao').innerText = stats.conversao + '%'; } function renderKanban() { const board = document.getElementById('kanban-board'); board.innerHTML = ''; stages.forEach(stage => { const col = document.createElement('div'); col.className = 'kanban-col bg-gray-200 rounded-lg p-4 flex flex-col shadow-sm border border-gray-300 h-full overflow-y-auto'; col.innerHTML = `

${stage} ${proposals.filter(p=>p.stage===stage).length}

`; proposals.filter(p => p.stage === stage).forEach(p => { const card = document.createElement('div'); card.className = 'bg-white p-4 rounded-lg shadow-sm mb-3 cursor-pointer hover:shadow-md border-l-4 border-headGreen transition'; card.innerHTML = `
${p.client_name}
${p.city} | ${p.consumption} kWh
R$ ${parseFloat(p.final_price).toLocaleString('pt-BR', {minimumFractionDigits:2})}
`; card.onclick = () => abrirProposta(p); col.appendChild(card); }); board.appendChild(col); }); } function calcularCustosBase() { const qty = parseFloat(document.getElementById('prop-qty').value) || 0; const power = parseFloat(document.getElementById('prop-power').value) || 0; const kwp = (qty * power) / 1000; document.getElementById('display-kwp').innerText = kwp.toFixed(2); if (qty > 0) document.getElementById('prop-instalacao').value = (qty * 120).toFixed(2); if (kwp > 0) document.getElementById('prop-infra').value = (kwp * 200).toFixed(2); calcFinal(); } function calcFinal() { const kit = parseFloat(document.getElementById('prop-kit').value) || 0; const proj = parseFloat(document.getElementById('prop-projeto').value) || 0; const inst = parseFloat(document.getElementById('prop-instalacao').value) || 0; const infra = parseFloat(document.getElementById('prop-infra').value) || 0; const margem = parseFloat(document.getElementById('prop-margem').value) || 25; const custos = kit + proj + inst + infra; const fator = (100 - margem) / 100; const final = fator > 0 ? custos / fator : 0; document.getElementById('display-final').innerText = final.toLocaleString('pt-BR', {minimumFractionDigits:2, maximumFractionDigits:2}); return final; } function novaProposta() { document.getElementById('form-proposta').reset(); document.getElementById('prop-id').value = ''; document.getElementById('display-final').innerText = '0,00'; document.getElementById('display-kwp').innerText = '0.00'; document.getElementById('modal-proposta').classList.remove('hidden'); } function fecharModal() { document.getElementById('modal-proposta').classList.add('hidden'); } function abrirProposta(p) { document.getElementById('prop-id').value = p.id; document.getElementById('prop-cliente').value = p.client_name; document.getElementById('prop-doc').value = p.client_doc || ''; document.getElementById('prop-cidade').value = p.city; document.getElementById('prop-consumo').value = p.consumption; document.getElementById('prop-inversor').value = p.inverter_brand; document.getElementById('prop-painel').value = p.panel_brand; document.getElementById('prop-qty').value = p.panel_qty; document.getElementById('prop-power').value = p.panel_power; if(currentUser.role === 'admin') { document.getElementById('prop-kit').value = p.kit_price; document.getElementById('prop-projeto').value = p.project_price; document.getElementById('prop-instalacao').value = p.install_price; document.getElementById('prop-infra').value = p.infra_price; document.getElementById('prop-margem').value = p.margin; } calcularCustosBase(); document.getElementById('display-final').innerText = parseFloat(p.final_price).toLocaleString('pt-BR', {minimumFractionDigits:2}); document.getElementById('modal-proposta').classList.remove('hidden'); } async function salvarProposta() { const finalP = calcFinal(); const data = { id: document.getElementById('prop-id').value, client_name: document.getElementById('prop-cliente').value, client_doc: document.getElementById('prop-doc').value, client_phone: '', city: document.getElementById('prop-cidade').value, consumption: document.getElementById('prop-consumo').value, inverter_brand: document.getElementById('prop-inversor').value, panel_brand: document.getElementById('prop-painel').value, panel_qty: document.getElementById('prop-qty').value, panel_power: document.getElementById('prop-power').value, kit_price: document.getElementById('prop-kit').value || 0, project_price: document.getElementById('prop-projeto').value || 0, install_price: document.getElementById('prop-instalacao').value || 0, infra_price: document.getElementById('prop-infra').value || 0, margin: document.getElementById('prop-margem').value || 25 }; const res = await fetch(`${API_URL}?action=save_proposal`, { method: 'POST', body: JSON.stringify(data) }); if((await res.json()).success) { fecharModal(); carregarPropostas(); } } function formatMoney(value) { return parseFloat(value).toLocaleString('pt-BR', {minimumFractionDigits: 2, maximumFractionDigits: 2}); } // O restante da função gerarPDFReal() mantém-se exatamente igual a partir daqui... ``` *(Certifique-se apenas de não apagar a sua função `gerarPDFReal()` que vinha logo a seguir no código anterior).* ### 2. Verifique o Ficheiro `api.php` Se a correção acima lançar o alerta *"Erro ao conectar com o servidor"*, significa que a Hostinger bloqueou a sessão. Certifique-se de que a primeira linha do seu ficheiro `api.php` (antes de qualquer espaço em branco) é estritamente: ```php