diff --git a/.vscode/settings.json b/.vscode/settings.json index 155422b..a0de46f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "liveServer.settings.port": 5503 + "liveServer.settings.port": 5504 } \ No newline at end of file diff --git a/firebase.js b/firebase.js index 5211140..ea2dee2 100644 --- a/firebase.js +++ b/firebase.js @@ -1,16 +1,18 @@ import { initializeApp } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-app.js"; -import { getFirestore } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-firestore.js"; +import { getDatabase } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-database.js"; const firebaseConfig = { - apiKey: "SUA_API_KEY", - authDomain: "SEU_PROJETO.firebaseapp.com", - projectId: "SEU_PROJECT_ID", - storageBucket: "SEU_PROJETO.appspot.com", - messagingSenderId: "SEU_ID", - appId: "SEU_APP_ID" + apiKey: "AQUI_TUA_API_KEY", + authDomain: "AQUI.firebaseapp.com", + databaseURL: "https://condomaster-pro-ed9af-default-rtdb.europe-west1.firebasedatabase.app", + projectId: "condomaster-pro-ed9af", + storageBucket: "condomaster-pro-ed9af.appspot.com", + messagingSenderId: "AQUI", + appId: "AQUI" }; const app = initializeApp(firebaseConfig); -const db = getFirestore(app); +const db = getDatabase(app); + +export { app, db }; -export { db }; \ No newline at end of file diff --git a/index.html b/index.html index 8cb6ffc..d0ca0c1 100644 --- a/index.html +++ b/index.html @@ -98,6 +98,10 @@ Dumbbell, PartyPopper, Trophy, Map, Calendar, MapPin, Info, MessageCircle, Paperclip, Send } from 'lucide-react'; + import { app } from './firebase.js'; + import { getAuth, signInWithEmailAndPassword } from 'https://www.gstatic.com/firebasejs/12.1.0/firebase-auth.js'; + + const auth = getAuth(app); const INITIAL_RESIDENTS = [ { id: 1, unit: '1º Esq', name: 'Ana Silva', contact: '912 345 678', email: 'ana.silva@email.com', status: 'Pago', pending: 0, role: 'morador' }, @@ -1655,6 +1659,8 @@ root.render(); - + + + \ No newline at end of file diff --git a/script.js b/script.js index 998d174..3bcafc0 100644 --- a/script.js +++ b/script.js @@ -1,19 +1,9 @@ -const SUPABASE_URL = 'YOUR_SUPABASE_URL'; -const SUPABASE_KEY = 'YOUR_SUPABASE_KEY'; +import { db } from "./firebase.js"; +import { ref, get, set, remove, push, onValue } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-database.js"; - -const IS_MOCK = SUPABASE_URL.includes('YOUR_SUPABASE'); - -let supabase; - -if (!IS_MOCK) { - supabase = supabase.createClient(SUPABASE_URL, SUPABASE_KEY); -} else { - console.warn("⚠️ MOCK MODE ATIVADO: Usando LocalStorage. Configure o Supabase para persistência real."); - showToast("Modo Demo Ativado (LocalStorage)", "warning"); -} +console.log("Integração com Firebase Database Iniciada"); document.addEventListener('DOMContentLoaded', () => { checkLogin(); @@ -22,14 +12,22 @@ document.addEventListener('DOMContentLoaded', () => { function setupEventListeners() { - document.getElementById('login-form').addEventListener('submit', handleLogin); + const loginForm = document.getElementById('login-form'); + if (loginForm) loginForm.addEventListener('submit', handleLogin); + const formMorador = document.getElementById('form-morador'); + if (formMorador) formMorador.addEventListener('submit', saveMorador); + + const formTransacao = document.getElementById('form-transacao'); + if (formTransacao) formTransacao.addEventListener('submit', saveTransacao); + + const formOcorrencia = document.getElementById('form-ocorrencia'); + if (formOcorrencia) formOcorrencia.addEventListener('submit', saveOcorrencia); + + const formAviso = document.getElementById('form-aviso'); + if (formAviso) formAviso.addEventListener('submit', saveAviso); - document.getElementById('form-morador').addEventListener('submit', saveMorador); - document.getElementById('form-transacao').addEventListener('submit', saveTransacao); - document.getElementById('form-ocorrencia').addEventListener('submit', saveOcorrencia); - document.getElementById('form-aviso').addEventListener('submit', saveAviso); - + listenCondominos(); // Inicia o listener realtime para os condóminos if (sessionStorage.getItem('condoProUser')) { renderDashboard(); @@ -39,14 +37,21 @@ function setupEventListeners() { function checkLogin() { const user = sessionStorage.getItem('condoProUser'); + const loginSection = document.getElementById('login-section'); + const appLayout = document.getElementById('app-layout'); + if (user) { - document.getElementById('login-section').classList.add('d-none'); - document.getElementById('app-layout').classList.remove('d-none'); - document.getElementById('app-layout').classList.add('d-flex'); + if (loginSection) loginSection.classList.add('d-none'); + if (appLayout) { + appLayout.classList.remove('d-none'); + appLayout.classList.add('d-flex'); + } } else { - document.getElementById('login-section').classList.remove('d-none'); - document.getElementById('app-layout').classList.add('d-none'); - document.getElementById('app-layout').classList.remove('d-flex'); + if (loginSection) loginSection.classList.remove('d-none'); + if (appLayout) { + appLayout.classList.add('d-none'); + appLayout.classList.remove('d-flex'); + } } } @@ -99,39 +104,51 @@ function showToast(message, type = 'primary') { async function dbSelect(table, orderBy = null) { - if (IS_MOCK) { - const data = JSON.parse(localStorage.getItem(`condopro_${table}`)) || []; + try { + const snapshot = await get(ref(db, table)); + const data = []; + if (snapshot.exists()) { + snapshot.forEach((childSnapshot) => { + const item = childSnapshot.val(); + item.id = childSnapshot.key; + data.push(item); + }); + } if (orderBy) { - data.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); + data.sort((a, b) => { + let valA = a[orderBy.col]; + let valB = b[orderBy.col]; + if (valA < valB) return orderBy.asc ? -1 : 1; + if (valA > valB) return orderBy.asc ? 1 : -1; + return 0; + }); } return { data, error: null }; + } catch (error) { + return { data: null, error }; } - let query = supabase.from(table).select('*'); - if (orderBy) query = query.order(orderBy.col, { ascending: orderBy.asc }); - return await query; } async function dbInsert(table, row) { - row.created_at = new Date().toISOString(); - if (!row.id) row.id = Date.now(); + try { + row.created_at = new Date().toISOString(); + if (!row.id) row.id = Date.now().toString(); - if (IS_MOCK) { - const data = JSON.parse(localStorage.getItem(`condopro_${table}`)) || []; - data.push(row); - localStorage.setItem(`condopro_${table}`, JSON.stringify(data)); + await set(ref(db, `${table}/${row.id}`), row); return { data: [row], error: null }; + } catch (error) { + console.error("Erro no dbInsert:", error); + return { data: null, error }; } - return await supabase.from(table).insert([row]); } async function dbDelete(table, id) { - if (IS_MOCK) { - let data = JSON.parse(localStorage.getItem(`condopro_${table}`)) || []; - data = data.filter(item => item.id != id); // Loose comparison for ID - localStorage.setItem(`condopro_${table}`, JSON.stringify(data)); + try { + await remove(ref(db, `${table}/${id}`)); return { error: null }; + } catch (error) { + return { error }; } - return await supabase.from(table).delete().eq('id', id); } function navigateTo(viewId) { @@ -267,20 +284,90 @@ function prepareCreateMorador() { async function saveMorador(e) { e.preventDefault(); - const nome = document.getElementById('morador-nome').value; - const bloco = document.getElementById('morador-bloco').value; - const apartamento = document.getElementById('morador-apto').value; - const telefone = document.getElementById('morador-telefone').value; - const email = document.getElementById('morador-email').value; - const { error } = await dbInsert('moradores', { nome, bloco, apartamento, telefone, email }); + const fracaoInput = document.getElementById("fracao"); + const proprietarioInput = document.getElementById("proprietario"); + const contactoInput = document.getElementById("contacto"); + + // Fallback para formulário legado caso os IDs sejam diferentes + const fracao = fracaoInput ? fracaoInput.value.trim() : document.getElementById("morador-fracao")?.value.trim(); + const proprietario = proprietarioInput ? proprietarioInput.value.trim() : document.getElementById("morador-nome")?.value.trim(); + const contacto = contactoInput ? contactoInput.value.trim() : document.getElementById("morador-contacto")?.value.trim(); + + // Obter estado, assumindo um seletor ou predefinição + const estadoInput = document.getElementById("estado"); + const estado = estadoInput ? estadoInput.value : "Pago"; - if (error) showToast("Erro ao salvar: " + error.message, "danger"); - else { - bootstrap.Modal.getInstance(document.getElementById('modalMorador')).hide(); - renderMoradores(); - showToast("Morador salvo com sucesso!", "success"); + // Validação Básica + if (!fracao || !proprietario || !contacto) { + alert("Por favor, preenche todos os campos obrigatórios (fração, proprietário e contacto)."); + return; } + + try { + // Gerar um novo ID automaticamente usando push() + const condominiosRef = ref(db, "condominos"); + await push(condominiosRef, { + fracao, + proprietario, + contacto, + estado: estado, + divida: estado === "Pago" ? 0 : 50 // Lógica de exemplo + }); + + // Limpar o formulário + const form = document.getElementById('form-morador') || document.getElementById('formCondominio'); + if (form) form.reset(); + else { + if(fracaoInput) fracaoInput.value = ''; + if(proprietarioInput) proprietarioInput.value = ''; + if(contactoInput) contactoInput.value = ''; + } + + if (typeof showToast === "function") { + showToast("Condómino adicionado com sucesso!", "success"); + } else { + alert("Condómino guardado com sucesso!"); + } + + } catch (erro) { + console.error("Erro ao guardar no Firebase: ", erro); + alert("Ocorreu um erro ao guardar o condómino."); + } +} + +// Função para atualizar automaticamente a lista +function listenCondominos() { + const condominiosRef = ref(db, "condominos"); + + // onValue reage sempre que há mudanças na base de dados (adicionar, editar, remover) + onValue(condominiosRef, (snapshot) => { + const data = snapshot.val(); + // Se houver uma função render reactiva no Vanilla, chamamo-la aqui. + // Exemplo: renderCondominosLista(data); + console.log("Dados atualizados em tempo real:", data); + + // Exemplo básico de atualização de DOM se tivermos uma tabela + const tbody = document.getElementById('moradores-list'); + if (tbody && data) { + tbody.innerHTML = ''; + Object.entries(data).forEach(([id, m]) => { + const tr = document.createElement('tr'); + tr.innerHTML = ` +
${m.proprietario || 'Sem Nome'}
+ ${m.fracao || '-'} + ${m.contacto || '-'} + ${m.estado || 'Pago'} + + + + `; + tbody.appendChild(tr); + }); + } + }); } async function renderFinanceiro() { @@ -388,20 +475,9 @@ async function saveOcorrencia(e) { const fileInput = document.getElementById('ocorrencia-file'); let imagem_url = null; - if (IS_MOCK && fileInput.files.length > 0) { - showToast("Upload simulado (Mock Mode)", "info"); + if (fileInput.files.length > 0) { + showToast("Upload simulado (Firebase Storage não configurado)", "info"); imagem_url = "https://placehold.co/600x400?text=Imagem+Ocorrencia"; - } else if (fileInput.files.length > 0) { - const file = fileInput.files[0]; - const fileName = `${Date.now()}_${file.name}`; - const { data, error } = await supabase.storage.from('condopro-bucket').upload(fileName, file); - - if (error) { - showToast('Erro upload imagem: ' + error.message, "danger"); - return; - } - const { data: publicData } = supabase.storage.from('condopro-bucket').getPublicUrl(fileName); - imagem_url = publicData.publicUrl; } const { error } = await dbInsert('ocorrencias', { titulo, descricao, imagem_url, status: 'pendente' }); @@ -490,32 +566,24 @@ function exportPDF(tableId, filename) { doc.save(filename + '.pdf'); showToast("PDF gerado com sucesso!", "success"); } -import { db } from "./firebase.js"; -import { collection, addDoc } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-firestore.js"; +const guardarBtn = document.getElementById("guardar"); +if (guardarBtn) { + guardarBtn.onclick = async () => { + const fracao = document.getElementById("fracao")?.value; + const proprietario = document.getElementById("proprietario")?.value; + const contacto = document.getElementById("contacto")?.value; + console.log("A tentar guardar no Firebase..."); -import { db } from "./firebase.js"; -import { collection, addDoc } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-firestore.js"; + try { + await push(ref(db, "condominios"), { + fracao, + proprietario, + contacto + }); -document.getElementById("btnAdicionar").onclick = () => { - document.getElementById("formCondominio").style.display = "block"; -}; - -document.getElementById("guardar").onclick = async () => { - const fracao = document.getElementById("fracao").value; - const proprietario = document.getElementById("proprietario").value; - const contacto = document.getElementById("contacto").value; - - try { - await addDoc(collection(db, "condominios"), { - fracao, - proprietario, - contacto, - estado: "Pago", - divida: 0 - }); - - alert("Guardado com sucesso!"); - } catch (e) { - alert("Erro: " + e.message); - } -}; + alert("Guardado com sucesso!"); + } catch (e) { + alert("Erro: " + e.message); + } + }; +}