adicionar condóminos
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"liveServer.settings.port": 5503
|
"liveServer.settings.port": 5504
|
||||||
}
|
}
|
||||||
20
firebase.js
20
firebase.js
@@ -1,16 +1,18 @@
|
|||||||
import { initializeApp } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-app.js";
|
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 = {
|
const firebaseConfig = {
|
||||||
apiKey: "SUA_API_KEY",
|
apiKey: "AQUI_TUA_API_KEY",
|
||||||
authDomain: "SEU_PROJETO.firebaseapp.com",
|
authDomain: "AQUI.firebaseapp.com",
|
||||||
projectId: "SEU_PROJECT_ID",
|
databaseURL: "https://condomaster-pro-ed9af-default-rtdb.europe-west1.firebasedatabase.app",
|
||||||
storageBucket: "SEU_PROJETO.appspot.com",
|
projectId: "condomaster-pro-ed9af",
|
||||||
messagingSenderId: "SEU_ID",
|
storageBucket: "condomaster-pro-ed9af.appspot.com",
|
||||||
appId: "SEU_APP_ID"
|
messagingSenderId: "AQUI",
|
||||||
|
appId: "AQUI"
|
||||||
};
|
};
|
||||||
|
|
||||||
const app = initializeApp(firebaseConfig);
|
const app = initializeApp(firebaseConfig);
|
||||||
const db = getFirestore(app);
|
const db = getDatabase(app);
|
||||||
|
|
||||||
|
export { app, db };
|
||||||
|
|
||||||
export { db };
|
|
||||||
@@ -98,6 +98,10 @@
|
|||||||
Dumbbell, PartyPopper, Trophy, Map, Calendar, MapPin, Info,
|
Dumbbell, PartyPopper, Trophy, Map, Calendar, MapPin, Info,
|
||||||
MessageCircle, Paperclip, Send
|
MessageCircle, Paperclip, Send
|
||||||
} from 'lucide-react';
|
} 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 = [
|
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' },
|
{ 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(<App />);
|
root.render(<App />);
|
||||||
</script>
|
</script>
|
||||||
<!-- Firebase configs moved to top in React Module -->
|
<!-- Firebase configs moved to top in React Module -->
|
||||||
|
<script type="module" src="script.js"></script>
|
||||||
|
<script type="module" src="firebase.js"></script>
|
||||||
|
<script type="module" src="script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
236
script.js
236
script.js
@@ -1,19 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
const SUPABASE_URL = 'YOUR_SUPABASE_URL';
|
import { db } from "./firebase.js";
|
||||||
const SUPABASE_KEY = 'YOUR_SUPABASE_KEY';
|
import { ref, get, set, remove, push, onValue } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-database.js";
|
||||||
|
|
||||||
|
console.log("Integração com Firebase Database Iniciada");
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
checkLogin();
|
checkLogin();
|
||||||
@@ -22,14 +12,22 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
function setupEventListeners() {
|
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);
|
||||||
|
|
||||||
document.getElementById('form-morador').addEventListener('submit', saveMorador);
|
const formTransacao = document.getElementById('form-transacao');
|
||||||
document.getElementById('form-transacao').addEventListener('submit', saveTransacao);
|
if (formTransacao) formTransacao.addEventListener('submit', saveTransacao);
|
||||||
document.getElementById('form-ocorrencia').addEventListener('submit', saveOcorrencia);
|
|
||||||
document.getElementById('form-aviso').addEventListener('submit', saveAviso);
|
|
||||||
|
|
||||||
|
const formOcorrencia = document.getElementById('form-ocorrencia');
|
||||||
|
if (formOcorrencia) formOcorrencia.addEventListener('submit', saveOcorrencia);
|
||||||
|
|
||||||
|
const formAviso = document.getElementById('form-aviso');
|
||||||
|
if (formAviso) formAviso.addEventListener('submit', saveAviso);
|
||||||
|
|
||||||
|
listenCondominos(); // Inicia o listener realtime para os condóminos
|
||||||
|
|
||||||
if (sessionStorage.getItem('condoProUser')) {
|
if (sessionStorage.getItem('condoProUser')) {
|
||||||
renderDashboard();
|
renderDashboard();
|
||||||
@@ -39,14 +37,21 @@ function setupEventListeners() {
|
|||||||
|
|
||||||
function checkLogin() {
|
function checkLogin() {
|
||||||
const user = sessionStorage.getItem('condoProUser');
|
const user = sessionStorage.getItem('condoProUser');
|
||||||
|
const loginSection = document.getElementById('login-section');
|
||||||
|
const appLayout = document.getElementById('app-layout');
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
document.getElementById('login-section').classList.add('d-none');
|
if (loginSection) loginSection.classList.add('d-none');
|
||||||
document.getElementById('app-layout').classList.remove('d-none');
|
if (appLayout) {
|
||||||
document.getElementById('app-layout').classList.add('d-flex');
|
appLayout.classList.remove('d-none');
|
||||||
|
appLayout.classList.add('d-flex');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
document.getElementById('login-section').classList.remove('d-none');
|
if (loginSection) loginSection.classList.remove('d-none');
|
||||||
document.getElementById('app-layout').classList.add('d-none');
|
if (appLayout) {
|
||||||
document.getElementById('app-layout').classList.remove('d-flex');
|
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) {
|
async function dbSelect(table, orderBy = null) {
|
||||||
if (IS_MOCK) {
|
try {
|
||||||
const data = JSON.parse(localStorage.getItem(`condopro_${table}`)) || [];
|
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) {
|
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 };
|
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) {
|
async function dbInsert(table, row) {
|
||||||
|
try {
|
||||||
row.created_at = new Date().toISOString();
|
row.created_at = new Date().toISOString();
|
||||||
if (!row.id) row.id = Date.now();
|
if (!row.id) row.id = Date.now().toString();
|
||||||
|
|
||||||
if (IS_MOCK) {
|
await set(ref(db, `${table}/${row.id}`), row);
|
||||||
const data = JSON.parse(localStorage.getItem(`condopro_${table}`)) || [];
|
|
||||||
data.push(row);
|
|
||||||
localStorage.setItem(`condopro_${table}`, JSON.stringify(data));
|
|
||||||
return { data: [row], error: null };
|
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) {
|
async function dbDelete(table, id) {
|
||||||
if (IS_MOCK) {
|
try {
|
||||||
let data = JSON.parse(localStorage.getItem(`condopro_${table}`)) || [];
|
await remove(ref(db, `${table}/${id}`));
|
||||||
data = data.filter(item => item.id != id); // Loose comparison for ID
|
|
||||||
localStorage.setItem(`condopro_${table}`, JSON.stringify(data));
|
|
||||||
return { error: null };
|
return { error: null };
|
||||||
|
} catch (error) {
|
||||||
|
return { error };
|
||||||
}
|
}
|
||||||
return await supabase.from(table).delete().eq('id', id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function navigateTo(viewId) {
|
function navigateTo(viewId) {
|
||||||
@@ -267,20 +284,90 @@ function prepareCreateMorador() {
|
|||||||
|
|
||||||
async function saveMorador(e) {
|
async function saveMorador(e) {
|
||||||
e.preventDefault();
|
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");
|
||||||
|
|
||||||
if (error) showToast("Erro ao salvar: " + error.message, "danger");
|
// Fallback para formulário legado caso os IDs sejam diferentes
|
||||||
else {
|
const fracao = fracaoInput ? fracaoInput.value.trim() : document.getElementById("morador-fracao")?.value.trim();
|
||||||
bootstrap.Modal.getInstance(document.getElementById('modalMorador')).hide();
|
const proprietario = proprietarioInput ? proprietarioInput.value.trim() : document.getElementById("morador-nome")?.value.trim();
|
||||||
renderMoradores();
|
const contacto = contactoInput ? contactoInput.value.trim() : document.getElementById("morador-contacto")?.value.trim();
|
||||||
showToast("Morador salvo com sucesso!", "success");
|
|
||||||
|
// Obter estado, assumindo um seletor ou predefinição
|
||||||
|
const estadoInput = document.getElementById("estado");
|
||||||
|
const estado = estadoInput ? estadoInput.value : "Pago";
|
||||||
|
|
||||||
|
// 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 = `
|
||||||
|
<td><div class="fw-bold">${m.proprietario || 'Sem Nome'}</div></td>
|
||||||
|
<td>${m.fracao || '-'}</td>
|
||||||
|
<td>${m.contacto || '-'}</td>
|
||||||
|
<td>${m.estado || 'Pago'}</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-danger" onclick="deleteItem('condominos', '${id}')">
|
||||||
|
Eliminar
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
`;
|
||||||
|
tbody.appendChild(tr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderFinanceiro() {
|
async function renderFinanceiro() {
|
||||||
@@ -388,20 +475,9 @@ async function saveOcorrencia(e) {
|
|||||||
const fileInput = document.getElementById('ocorrencia-file');
|
const fileInput = document.getElementById('ocorrencia-file');
|
||||||
let imagem_url = null;
|
let imagem_url = null;
|
||||||
|
|
||||||
if (IS_MOCK && fileInput.files.length > 0) {
|
if (fileInput.files.length > 0) {
|
||||||
showToast("Upload simulado (Mock Mode)", "info");
|
showToast("Upload simulado (Firebase Storage não configurado)", "info");
|
||||||
imagem_url = "https://placehold.co/600x400?text=Imagem+Ocorrencia";
|
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' });
|
const { error } = await dbInsert('ocorrencias', { titulo, descricao, imagem_url, status: 'pendente' });
|
||||||
@@ -490,32 +566,24 @@ function exportPDF(tableId, filename) {
|
|||||||
doc.save(filename + '.pdf');
|
doc.save(filename + '.pdf');
|
||||||
showToast("PDF gerado com sucesso!", "success");
|
showToast("PDF gerado com sucesso!", "success");
|
||||||
}
|
}
|
||||||
import { db } from "./firebase.js";
|
const guardarBtn = document.getElementById("guardar");
|
||||||
import { collection, addDoc } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-firestore.js";
|
if (guardarBtn) {
|
||||||
|
guardarBtn.onclick = async () => {
|
||||||
import { db } from "./firebase.js";
|
const fracao = document.getElementById("fracao")?.value;
|
||||||
import { collection, addDoc } from "https://www.gstatic.com/firebasejs/12.1.0/firebase-firestore.js";
|
const proprietario = document.getElementById("proprietario")?.value;
|
||||||
|
const contacto = document.getElementById("contacto")?.value;
|
||||||
document.getElementById("btnAdicionar").onclick = () => {
|
console.log("A tentar guardar no Firebase...");
|
||||||
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 {
|
try {
|
||||||
await addDoc(collection(db, "condominios"), {
|
await push(ref(db, "condominios"), {
|
||||||
fracao,
|
fracao,
|
||||||
proprietario,
|
proprietario,
|
||||||
contacto,
|
contacto
|
||||||
estado: "Pago",
|
|
||||||
divida: 0
|
|
||||||
});
|
});
|
||||||
|
|
||||||
alert("Guardado com sucesso!");
|
alert("Guardado com sucesso!");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
alert("Erro: " + e.message);
|
alert("Erro: " + e.message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user