!DOCTYPE html
html lang=pt-PT class=transition-colors duration-300
head
meta charset=UTF-8
meta name=viewport content=width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no
titleAgroxys - Portal de Vendas Premiumtitle
script src=httpscdn.tailwindcss.comscript
script src=httpscdn.jsdelivr.netnpmchart.jsscript
script
tailwind.config = {
darkMode 'class',
theme {
extend {
colors {
agroxys { darkest '#05140a', dark '#0f4c23', main '#1a7a3a', gold '#d4af37', light '#f4f7f5' }
}
}
}
}
script
style
.hide { display none !important; }
.fade-in { animation fadeIn 0.3s ease-in-out; }
@keyframes fadeIn { from { opacity 0; transform translateY(10px); } to { opacity 1; transform translateY(0); } }
.spinner { border 2px solid rgba(212, 175, 55, 0.3); border-radius 50%; border-top 2px solid #d4af37; width 16px; height 16px; animation spin 1s linear infinite; }
@keyframes spin { 0% { transform rotate(0deg); } 100% { transform rotate(360deg); } }
.scrollbar-hide-webkit-scrollbar { display none; }
.scrollbar-hide { -ms-overflow-style none; scrollbar-width none; }
@media print {
body not(#printArea) { display none !important; }
#printArea { display block !important; position absolute; left 0; top 0; width 100%; padding 30px; background white; color black; z-index 9999; }
}
style
head
body class=text-gray-800 darktext-gray-200 bg-[#f4f7f5] darkbg-agroxys-darkest h-screen flex flex-col overflow-hidden transition-colors duration-300
div id=cloudSync class=absolute top-0 left-12 -translate-x-12 bg-agroxys-gold text-agroxys-darkest text-[10px] font-black px-6 py-1.5 rounded-b-xl shadow-md z-[60] flex items-center space-x-2 hide
div class=spinner border-agroxys-darkestdiv
span id=syncTextSINCRONIZANDO...span
div
!-- Ecrã de Login --
div id=loginScreen class=absolute inset-0 bg-agroxys-dark flex items-center justify-center z-50 p-4
div class=bg-white darkbg-[#0a2010] rounded-[2rem] shadow-2xl w-full max-w-md overflow-hidden border border-agroxys-gold30 fade-in
div class=p-8 flex flex-col items-center bg-agroxys-darkest border-b-4 border-agroxys-gold text-center
h2 class=text-3xl font-black text-white tracking-widest uppercaseAgroxysh2
p class=text-agroxys-gold text-[10px] font-black tracking-widest mt-1SISTEMA COMERCIAL PREMIUMp
div
div class=p-8 space-y-4
input type=email id=authEmail placeholder=E-mail class=w-full border-2 border-gray-100 darkborder-gray-800 bg-gray-50 darkbg-[#07160b] darktext-white rounded-xl p-3 outline-none focusborder-agroxys-gold font-bold
input type=password id=authPassword placeholder=Palavra-passe class=w-full border-2 border-gray-100 darkborder-gray-800 bg-gray-50 darkbg-[#07160b] darktext-white rounded-xl p-3 outline-none focusborder-agroxys-gold transition-all onkeypress=if(event.key === 'Enter') handleAuth()
button type=button onclick=handleAuth() id=btnLogin class=w-full bg-agroxys-dark text-agroxys-gold font-black py-4 rounded-xl shadow-lg uppercase tracking-widest text-sm border border-agroxys-gold50 activescale-95 transition-all flex justify-center items-center h-[56px]Entrarbutton
div
div
div
!-- Aplicação Principal --
div id=appScreen class=hide flex-col h-full w-full
header class=bg-agroxys-darkest text-white p-3 smpx-6 shadow-md flex justify-between items-center border-b-2 border-agroxys-gold shrink-0
div class=flex items-center space-x-3
div class=w-8 h-8 bg-agroxys-gold rounded flex items-center justify-center font-black text-agroxys-darkestAdiv
div
h1 class=text-sm font-black uppercase leading-noneAgroxysh1
p id=headerInfo class=text-[8px] text-agroxys-gold font-bold uppercasep
div
div
div class=flex items-center space-x-2
button type=button onclick=toggleDarkMode() class=p-2 bg-white5 rounded-lg text-agroxys-goldsvg class=w-4 h-4 fill=none stroke=currentColor viewBox=0 0 24 24path stroke-linecap=round stroke-linejoin=round stroke-width=2 d=M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646zpathsvgbutton
button type=button onclick=logout() class=text-[9px] bg-red-900 text-white font-black px-4 py-2 rounded-lg border border-red-700 transition uppercase tracking-widest activescale-90Sairbutton
div
header
nav class=flex bg-white darkbg-[#07160b] shadow-sm shrink-0 border-b darkborder-gray-800
button type=button id=tab-pedido class=flex-1 py-4 text-center font-black border-b-[3px] border-agroxys-gold text-agroxys-dark darktext-agroxys-gold uppercase text-[10px] onclick=switchTab('pedido')IA Assistentebutton
button type=button id=tab-vendas class=flex-1 py-4 text-center font-bold border-b-[3px] border-transparent text-gray-400 uppercase text-[10px] onclick=switchTab('vendas')Painel Gerencialbutton
nav
main id=view-pedido class=flex-1 overflow-hidden flex flex-col relative bg-[#f4f7f5] darkbg-agroxys-darkest
div id=chatBox class=flex-1 overflow-y-auto p-4 space-y-4 pb-4div
footer class=bg-white darkbg-[#0a2010] p-3 shadow-[0_-10px_40px_rgba(0,0,0,0.1)] border-t darkborder-gray-800 shrink-0 z-10 flex flex-col space-y-2
!-- Balões Originais --
div class=flex space-x-2 overflow-x-auto scrollbar-hide pb-1
button type=button onclick=setChatText('Quero lançar uma Nova Venda. O que precisa') class=shrink-0 bg-gray-50 darkbg-black30 border border-gray-200 darkborder-gray-800 text-[10px] font-bold px-4 py-2 rounded-full text-agroxys-dark darktext-agroxys-gold transition-all activescale-95 hoverborder-agroxys-gold🛒 Nova Vendabutton
button type=button onclick=setChatText('Quero fazer uma Nova Reserva de produtos.') class=shrink-0 bg-gray-50 darkbg-black30 border border-gray-200 darkborder-gray-800 text-[10px] font-bold px-4 py-2 rounded-full text-agroxys-dark darktext-agroxys-gold transition-all activescale-95 hoverborder-agroxys-gold📅 Nova Reservabutton
button type=button onclick=setChatText('Tenho Dúvidas I.A., pode me ajudar com informações de produtos') class=shrink-0 bg-gray-50 darkbg-black30 border border-gray-200 darkborder-gray-800 text-[10px] font-bold px-4 py-2 rounded-full text-agroxys-dark darktext-agroxys-gold transition-all activescale-95 hoverborder-agroxys-gold🤖 Dúvidas I.A.button
button type=button onclick=setChatText('Como está o Clima Hoje na minha região') class=shrink-0 bg-gray-50 darkbg-black30 border border-gray-200 darkborder-gray-800 text-[10px] font-bold px-4 py-2 rounded-full text-agroxys-dark darktext-agroxys-gold transition-all activescale-95 hoverborder-agroxys-gold🌤️ Clima Hojebutton
button type=button onclick=setChatText('Mostre um Resumo Home das minhas vendas.') class=shrink-0 bg-gray-50 darkbg-black30 border border-gray-200 darkborder-gray-800 text-[10px] font-bold px-4 py-2 rounded-full text-agroxys-dark darktext-agroxys-gold transition-all activescale-95 hoverborder-agroxys-gold🏠 Homebutton
div
div class=flex space-x-2 items-end
textarea id=chatInput rows=1 placeholder=Ex Nova venda de 50 litros de Soja a 45 cada... class=flex-1 border-2 border-gray-100 darkborder-gray-800 darkbg-black20 darktext-white rounded-xl p-3 text-sm focusborder-agroxys-gold outline-none resize-none scrollbar-hide onkeypress=if(event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); sendMessage(); }textarea
button type=button id=btnSend onclick=sendMessage() class=bg-agroxys-dark text-agroxys-gold rounded-xl p-3 h-[48px] w-[48px] shadow-lg flex items-center justify-center font-black activescale-90 transition-all border border-agroxys-gold40 shrink-0🚀button
div
footer
main
main id=view-vendas class=flex-1 overflow-y-auto p-4 hide fade-in
section id=adminUsersSection class=hide mb-8 p-4 bg-white darkbg-[#0a2010] rounded-2xl border darkborder-gray-800 shadow-sm
h3 class=text-xs font-black uppercase text-agroxys-gold mb-4 flex items-center gap-2
svg class=w-4 h-4 fill=none stroke=currentColor viewBox=0 0 24 24path stroke-linecap=round stroke-linejoin=round stroke-width=2 d=M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1zpathsvg
Cadastrar Novo Vendedor
h3
div class=grid grid-cols-1 smgrid-cols-4 gap-2
input type=text id=newUserName placeholder=Nome Completo class=border darkborder-gray-800 darkbg-black20 p-2 rounded-lg text-xs outline-none focusborder-agroxys-gold
input type=email id=newUserEmail placeholder=E-mail (Login) class=border darkborder-gray-800 darkbg-black20 p-2 rounded-lg text-xs outline-none focusborder-agroxys-gold
input type=password id=newUserPass placeholder=Palavra-passe class=border darkborder-gray-800 darkbg-black20 p-2 rounded-lg text-xs outline-none focusborder-agroxys-gold
button type=button onclick=registrarVendedor() class=bg-agroxys-gold text-agroxys-darkest font-black p-2 rounded-lg text-[10px] uppercase shadow-md activescale-95 transition-allSalvarbutton
div
section
div id=kpiContainer class=grid grid-cols-2 smgrid-cols-4 gap-3 mb-6div
div class=bg-white darkbg-[#0a2010] rounded-2xl shadow-md border darkborder-gray-800 overflow-hidden
table class=w-full text-left text-[10px] smtext-xs
thead class=bg-gray-50 darkbg-black30 text-gray-400 uppercase font-black tracking-widest
trth class=p-3Datathth class=p-3Cidadethth class=p-3Clientethth class=p-3 text-rightValorthth class=p-3 text-centerAçõesthtr
thead
tbody id=tablePedidos class=divide-y divide-gray-50 darkdivide-gray-80050tbody
table
div
main
div
div id=toast class=fixed bottom-24 left-12 -translate-x-12 bg-agroxys-darkest text-agroxys-gold px-6 py-3 rounded-full text-[9px] font-black uppercase tracking-widest shadow-2xl border border-agroxys-gold40 opacity-0 transition-opacity pointer-events-none z-[100]div
div id=printArea class=hidediv
script type=module
import { initializeApp } from httpswww.gstatic.comfirebasejs11.6.1firebase-app.js;
import { getAuth, signInWithEmailAndPassword, createUserWithEmailAndPassword, signOut } from httpswww.gstatic.comfirebasejs11.6.1firebase-auth.js;
import { getFirestore, collection, onSnapshot, doc, setDoc, getDoc } from httpswww.gstatic.comfirebasejs11.6.1firebase-firestore.js;
const CONFIG_FIREBASE = {
apiKey AIzaSyChhUaSc58li0ft4WQ4ClKrsW9htawaxQs,
authDomain agroxys-5edd6.firebaseapp.com,
projectId agroxys-5edd6,
storageBucket agroxys-5edd6.firebasestorage.app,
messagingSenderId 837054803057,
appId 1837054803057webbc636c568652008f4d3fd0
};
const GEMINI_API_KEY = AIzaSyAVvcx-_jdMxMNoyB67enqyuCE5ViaMIxg;
const PROJ_ID = 'agroxys-5edd6';
let db, auth, currentUser, ordersDB = [], convHistory = [], isSaving = false;
const app = initializeApp(CONFIG_FIREBASE);
db = getFirestore(app);
auth = getAuth(app);
const authSecondary = getAuth(initializeApp(CONFIG_FIREBASE, secondary));
==========================================
LOGIN & SESSÃO
==========================================
window.handleAuth = async () = {
const em = document.getElementById('authEmail').value.trim().toLowerCase();
const pw = document.getElementById('authPassword').value;
const btn = document.getElementById('btnLogin');
if(!em !pw) return showToast(Preencha todos os campos.);
btn.disabled = true;
btn.innerHTML = 'div class=spinner border-white m-autodiv';
try {
const userCredential = await signInWithEmailAndPassword(auth, em, pw);
const user = userCredential.user;
const docRef = doc(db, 'artifacts', PROJ_ID, 'public', 'data', 'vendedores', user.uid);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
currentUser = { id user.uid, ...docSnap.data() };
} else {
currentUser = { id user.uid, name Admin Agroxys, role em === matheusnespolo@hotmail.com ADMIN VENDEDOR, email em };
}
localStorage.setItem('agroxys_sess', JSON.stringify(currentUser));
initApp();
} catch(e) {
showToast(Login incorreto ou conta inexistente.);
btn.disabled = false;
btn.innerHTML = 'Entrar';
}
};
window.logout = async () = {
await signOut(auth);
localStorage.removeItem('agroxys_sess');
window.location.reload();
};
const initApp = () = {
document.getElementById('loginScreen').classList.add('hide');
document.getElementById('appScreen').classList.remove('hide');
document.getElementById('appScreen').classList.add('flex');
document.getElementById('headerInfo').textContent = `${currentUser.name.split(' ')[0]} ${currentUser.role}`;
if(currentUser.role === 'ADMIN') document.getElementById('adminUsersSection').classList.remove('hide');
listenDB();
document.getElementById('chatBox').innerHTML = '';
convHistory = [];
addMsg(`Assistente Agroxys ativo. Olá ${currentUser.name.split(' ')[0]}, o que vamos fazer hoje`, 'ai');
};
==========================================
INTERFACE & CHAT
==========================================
window.switchTab = (t) = {
document.getElementById('view-pedido').classList.toggle('hide', t !== 'pedido');
document.getElementById('view-vendas').classList.toggle('hide', t !== 'vendas');
const active = flex-1 py-4 text-center font-black border-b-[3px] border-agroxys-gold text-agroxys-dark darktext-agroxys-gold uppercase text-[10px];
const inactive = flex-1 py-4 text-center font-bold border-b-[3px] border-transparent text-gray-400 uppercase text-[10px];
document.getElementById('tab-pedido').className = t === 'pedido' active inactive;
document.getElementById('tab-vendas').className = t === 'vendas' active inactive;
};
window.setChatText = (txt) = {
const input = document.getElementById('chatInput');
input.value = txt;
input.focus();
};
const addMsg = (text, sender) = {
const d = document.createElement('div');
const formattedText = sender === 'ai' text.replace((.)g, 'b$1b') text;
d.className = `p-3 rounded-2xl max-w-[85%] text-xs fade-in leading-relaxed ${sender === 'user' 'bg-agroxys-darkest text-agroxys-gold self-end rounded-tr-none' 'bg-white darkbg-[#07160b] text-gray-700 darktext-gray-300 self-start rounded-tl-none border darkborder-gray-800 shadow-sm'}`;
d.innerHTML = formattedText;
document.getElementById('chatBox').appendChild(d);
document.getElementById('chatBox').scrollTop = document.getElementById('chatBox').scrollHeight;
convHistory.push({role sender === 'user' 'user' 'model', parts [{text text}]});
};
const showToast = (m) = {
const t = document.getElementById('toast');
t.textContent = m; t.style.opacity = '1';
setTimeout(() = t.style.opacity = '0', 3000);
};
window.toggleDarkMode = () = document.documentElement.classList.toggle('dark');
==========================================
I.A. GEMINI
==========================================
window.sendMessage = async () = {
const inp = document.getElementById('chatInput');
const msg = inp.value.trim();
if(!msg) return;
inp.value = '';
addMsg(msg, 'user');
const btn = document.getElementById('btnSend');
btn.disabled = true;
btn.innerHTML = 'div class=spinner border-agroxys-golddiv';
try {
const res = await fetch(`httpsgenerativelanguage.googleapis.comv1betamodelsgemini-2.5-flash-preview-09-2025generateContentkey=${GEMINI_API_KEY}`, {
method 'POST', headers {'Content-Type' 'applicationjson'},
body JSON.stringify({
contents convHistory,
systemInstruction { parts [{ text `Você é o assistente comercial da Agroxys. Seja profissional e ágil. Se o pedido for Nova Venda ou Nova Reserva, colete Cliente, Cidade, Itens (Quantidade e Valor Unitário). Calcule TOTAL = QTD UNITÁRIO. Se for Dúvidas IA, Clima ou Home, responda apropriadamente. QUANDO tiver os dados de uma venda completos, retorne sua resposta e NO FINAL insira OBRIGATORIAMENTE APENAS ESTE BLOCO JSON {clienteNome,cidadeCidade,total100,itens[{nomeProd,qtd1,unit100,sub100}]}` }] }
})
});
if (!res.ok) throw new Error(Erro na API.);
const data = await res.json();
const txt = data.candidates.[0].content.parts.[0].text Erro de processamento.;
const match = txt.match(({.})s);
if(match) {
try {
const order = JSON.parse(match[1]);
addMsg(txt.replace(.s, '').trim(), 'ai');
renderOrderCard(order);
} catch (err) {
addMsg(Erro ao estruturar o pedido. Por favor, confirme os valores., 'ai');
}
} else {
addMsg(txt, 'ai');
}
} catch(e) {
addMsg(Erro de conexão com a I.A. Tente novamente., 'ai');
} finally {
btn.disabled = false; btn.innerHTML = '🚀'; inp.focus();
}
};
const renderOrderCard = (o) = {
const tempId = Date.now().toString();
window[`tempOrder_${tempId}`] = o;
const div = document.createElement('div');
div.id = `card_${tempId}`;
div.className = bg-white darkbg-[#07160b] p-4 rounded-2xl border-2 border-agroxys-gold shadow-xl space-y-3 fade-in max-w-[85%] self-start mt-2;
div.innerHTML = `
h4 class=font-black text-[10px] uppercase text-agroxys-gold border-b darkborder-gray-800 pb-1 flex justify-between
spanValidar Lançamentospanspan class=bg-agroxys-gold20 text-agroxys-gold px-2 py-0.5 rounded text-[8px]Pendentespan
h4
div class=text-xs space-y-1 text-gray-700 darktext-gray-300
pb class=text-gray-900 darktext-whiteCidadeb ${o.cidade '-'}p
pb class=text-gray-900 darktext-whiteClienteb ${o.cliente '-'}p
pb class=text-gray-900 darktext-whiteTotalb R$ ${Number(o.total 0).toLocaleString('pt-BR', {minimumFractionDigits 2})}p
div
button type=button id=btn_${tempId} onclick=saveVenda('${tempId}') class=w-full bg-agroxys-dark text-agroxys-gold py-3 rounded-xl font-black text-[10px] uppercase activescale-95 transition-all border border-agroxys-gold40Confirmar e Lançarbutton`;
document.getElementById('chatBox').appendChild(div);
document.getElementById('chatBox').scrollTop = document.getElementById('chatBox').scrollHeight;
};
==========================================
FIRESTORE E DADOS
==========================================
window.saveVenda = async (tempId) = {
if(isSaving) return;
const o = window[`tempOrder_${tempId}`];
if(!o) return;
isSaving = true;
const btn = document.getElementById(`btn_${tempId}`);
if(btn) { btn.disabled = true; btn.innerHTML = 'Processando...'; }
document.getElementById('cloudSync').classList.remove('hide');
try {
if(!auth.currentUser) throw new Error(Sessão expirada.);
const id = Date.now().toString();
await setDoc(doc(db, 'artifacts', PROJ_ID, 'public', 'data', 'pedidos', id), {
...o, status 'Aprovado', data new Date().toISOString(),
vendedor currentUser.name, vendedorEmail currentUser.email
});
showToast(Venda Gravada!);
const card = document.getElementById(`card_${tempId}`);
if(card) card.innerHTML = `div class=text-center p-2 text-green-600 font-bold text-xs✅ Pedido Lançado com Sucessodiv`;
delete window[`tempOrder_${tempId}`];
} catch(e) {
showToast(Erro ao gravar pedido.);
if(btn) { btn.disabled = false; btn.innerHTML = 'Tentar Novamente'; }
} finally {
document.getElementById('cloudSync').classList.add('hide');
isSaving = false;
}
};
const listenDB = () = {
document.getElementById('cloudSync').classList.remove('hide');
onSnapshot(collection(db, 'artifacts', PROJ_ID, 'public', 'data', 'pedidos'), s = {
ordersDB = [];
s.forEach(d = {
const data = d.data();
if(currentUser.role === 'ADMIN' data.vendedorEmail === currentUser.email) ordersDB.push({id d.id, ...data});
});
ordersDB.sort((a,b) = new Date(b.data) - new Date(a.data));
renderDashboard();
document.getElementById('cloudSync').classList.add('hide');
}, (error) = {
document.getElementById('cloudSync').classList.add('hide');
});
};
const renderDashboard = () = {
const tb = document.getElementById('tablePedidos'), kpi = document.getElementById('kpiContainer');
let total = 0;
tb.innerHTML = ordersDB.map(o = {
total += Number(o.total 0);
return `tr class=border-b darkborder-gray-80050 hoverbg-gray-50 darkhoverbg-white5 transition-colors
td class=p-3 text-gray-500 font-medium whitespace-nowrap${new Date(o.data).toLocaleDateString('pt-BR')}td
td class=p-3 font-black uppercase truncate max-w-[80px]${o.cidade '-'}td
td class=p-3 font-black uppercase truncate max-w-[100px]${o.cliente}td
td class=p-3 text-right font-black text-agroxys-dark darktext-agroxys-gold whitespace-nowrapR$ ${Number(o.total).toLocaleString('pt-BR', {minimumFractionDigits2})}td
td class=p-3 text-centerbutton type=button onclick=imprimirPDF('${o.id}') class=bg-gray-100 darkbg-gray-800 p-2 rounded text-[9px] font-bold text-gray-700 darktext-gray-300PDFbuttontd
tr`;
}).join('');
if(ordersDB.length === 0) tb.innerHTML = `trtd colspan=5 class=p-6 text-center text-gray-400 font-bold text-xs uppercaseNenhum pedido.tdtr`;
kpi.innerHTML = `
div class=bg-white darkbg-[#0a2010] p-4 rounded-xl border darkborder-gray-800 shadow-sm col-span-2
p class=text-[8px] uppercase font-black text-gray-400 mb-1Faturamento Totalp
p class=text-xl smtext-2xl font-black text-agroxys-dark darktext-agroxys-goldR$ ${total.toLocaleString('pt-BR', {minimumFractionDigits 2})}p
div
div class=bg-white darkbg-[#0a2010] p-4 rounded-xl border darkborder-gray-800 shadow-sm
p class=text-[8px] uppercase font-black text-gray-400 mb-1Pedidosp
p class=text-xl smtext-2xl font-black text-gray-800 darktext-white${ordersDB.length}p
div`;
};
window.registrarVendedor = async () = {
const name = document.getElementById('newUserName').value.trim();
const email = document.getElementById('newUserEmail').value.trim().toLowerCase();
const pass = document.getElementById('newUserPass').value.trim();
if(!name !email !pass) return showToast(Preencha todos os dados.);
if(pass.length 6) return showToast(Mínimo 6 caracteres.);
document.getElementById('cloudSync').classList.remove('hide');
try {
const userCred = await createUserWithEmailAndPassword(authSecondary, email, pass);
await setDoc(doc(db, 'artifacts', PROJ_ID, 'public', 'data', 'vendedores', userCred.user.uid), {
name, email, role 'VENDEDOR', createdAt new Date().toISOString()
});
await signOut(authSecondary);
showToast(Vendedor cadastrado com sucesso!);
document.getElementById('newUserName').value = ''; document.getElementById('newUserEmail').value = ''; document.getElementById('newUserPass').value = '';
} catch(e) { showToast(Erro. E-mail já existe ou falha.); } finally { document.getElementById('cloudSync').classList.add('hide'); }
};
window.imprimirPDF = (id) = {
const o = ordersDB.find(x = x.id === id);
if(!o) return;
const pa = document.getElementById('printArea');
pa.innerHTML = `div style=padding40px; border2px solid #0f4c23; border-radius15px; backgroundwhite; colorblack; font-familysans-serif;
h1 style=color#0f4c23; text-aligncenter; font-size24px; margin-bottom 20px;AGROXYS - ROMANEIOh1
pbDatab ${new Date(o.data).toLocaleString('pt-BR')}ppbCidadeb ${o.cidade '-'}p
pbClienteb ${o.cliente.toUpperCase()}ppbVendedorb ${o.vendedor}p
hr style=margin20px 0;table style=width100%; border-collapsecollapse; margin-top20px; font-size 14px;
tr style=background#f4f7f5;th style=border1px solid #ddd; padding10px; text-alignleft;Itemthth style=border1px solid #ddd; padding10px; text-alignright;Subtotalthtr
${o.itens o.itens.map(i = `trtd style=border1px solid #ddd; padding10px;${i.qtd}x ${i.nome}tdtd style=border1px solid #ddd; padding10px; text-alignright;R$ ${Number(i.sub).toLocaleString('pt-BR', {minimumFractionDigits2})}tdtr`).join('') ''}
table
div style=margin-top40px; text-alignright; padding20px; background#0f4c23; colorwhite; border-radius10px;
p style=margin0; font-size12px;TOTALph2 style=margin0; font-size36px;R$ ${Number(o.total).toLocaleString('pt-BR', {minimumFractionDigits 2})}h2
divdiv`;
pa.classList.remove('hide'); setTimeout(() = { window.print(); pa.classList.add('hide'); }, 600);
};
window.onload = () = {
try {
const sess = localStorage.getItem('agroxys_sess');
if(sess) { currentUser = JSON.parse(sess); initApp(); }
} catch(e) { localStorage.removeItem('agroxys_sess'); }
};
script
body
html