async function apiFetch(url, options = {}) { const token = localStorage.getItem('fa_token'); const headers = { 'Content-Type': 'application/json', ...(options.headers || {}) }; if (token) headers['Authorization'] = 'Bearer ' + token; const res = await fetch(url, { ...options, headers }); if (res.status === 401) { localStorage.clear(); window.location.href = '/login.html?sessao=expirada'; return; } const data = await res.json(); if (!res.ok) throw new Error(data.message || 'Erro desconhecido'); return data; } function showToast(mensagem, tipo = 'info') { const existing = document.querySelector('.fa-toast'); if (existing) existing.remove(); const styleId = 'fa-toast-style'; if (!document.getElementById(styleId)) { const style = document.createElement('style'); style.id = styleId; style.textContent = ` .fa-toast { position: fixed; bottom: 24px; right: 24px; z-index: 99999; padding: 12px 18px; border-radius: 8px; font-size: 14px; font-family: 'Poppins', sans-serif; max-width: 340px; animation: faSlideIn 0.3s ease forwards; box-shadow: 0 4px 12px rgba(0,0,0,0.15); } .fa-toast.fa-toast-sai { animation: faSlideOut 0.3s ease forwards; } .fa-toast-sucesso { background: #114455; color: #fff; } .fa-toast-erro { background: #c0392b; color: #fff; } .fa-toast-info { background: #f5f5f5; color: #1f2937; border: 1px solid #c0392b; } @keyframes faSlideIn { from { transform: translateY(30px); opacity: 0; } to { transform: translateY(0); opacity: 1; } } @keyframes faSlideOut { from { transform: translateY(0); opacity: 1; } to { transform: translateY(30px); opacity: 0; } } `; document.head.appendChild(style); } const toast = document.createElement('div'); toast.className = 'fa-toast fa-toast-' + tipo; toast.textContent = mensagem; document.body.appendChild(toast); setTimeout(() => { toast.classList.add('fa-toast-sai'); toast.addEventListener('animationend', () => toast.remove()); }, 3000); } function setButtonLoading(btn, loading, textoOriginal) { if (loading) { btn.disabled = true; btn.dataset.textoOriginal = textoOriginal || btn.textContent; btn.textContent = 'Salvando...'; } else { btn.disabled = false; if (btn.dataset.textoOriginal) { btn.textContent = btn.dataset.textoOriginal; } } } (function() { window.addEventListener('offline', () => { let banner = document.getElementById('fa-offline-banner'); if (!banner) { banner = document.createElement('div'); banner.id = 'fa-offline-banner'; banner.textContent = 'Sem conexao — algumas funcoes podem nao funcionar'; banner.style.cssText = 'position:fixed;top:0;left:0;width:100%;background:#c0392b;color:#fff;text-align:center;padding:10px;font-family:Poppins,sans-serif;font-size:14px;z-index:9999;'; document.body.prepend(banner); } }); window.addEventListener('online', () => { document.getElementById('fa-offline-banner')?.remove(); }); })();