jtimoteo's picture
Crie um app web em React com Firebase Authentication e Cloud Firestore.
704a5c0 verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FireMaster Control Hub</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-auth-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.6.0/firebase-firestore-compat.js"></script>
<style>
.gradient-bg {
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.transition-all {
transition: all 0.3s ease;
}
</style>
</head>
<body class="gradient-bg min-h-screen flex items-center justify-center">
<div id="app" class="w-full max-w-md mx-4">
<!-- Login Card -->
<div id="login-card" class="bg-white rounded-xl shadow-2xl overflow-hidden transition-all">
<div class="p-8">
<div class="flex justify-center mb-8">
<div class="bg-red-100 p-4 rounded-full">
<i data-feather="shield" class="text-red-500 w-10 h-10"></i>
</div>
</div>
<h2 class="text-2xl font-bold text-center text-gray-800 mb-6">Acesso Restrito</h2>
<form id="login-form" class="space-y-4">
<div>
<label class="block text-gray-700 text-sm font-medium mb-1" for="email">E-mail</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i data-feather="mail" class="text-gray-500"></i>
</div>
<input id="email" type="email" class="w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500 focus:border-transparent" placeholder="seu@email.com" required>
</div>
</div>
<div>
<label class="block text-gray-700 text-sm font-medium mb-1" for="password">Senha</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i data-feather="lock" class="text-gray-500"></i>
</div>
<input id="password" type="password" class="w-full pl-10 pr-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-red-500 focus:border-transparent" placeholder="••••••••" required>
<button type="button" id="toggle-password" class="absolute inset-y-0 right-0 pr-3 flex items-center">
<i data-feather="eye" class="text-gray-500"></i>
</button>
</div>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<input id="remember" type="checkbox" class="h-4 w-4 text-red-600 focus:ring-red-500 border-gray-300 rounded">
<label for="remember" class="ml-2 block text-sm text-gray-700">Lembrar senha</label>
</div>
</div>
<div>
<button type="submit" class="w-full bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded-lg transition duration-200 flex items-center justify-center">
<i data-feather="log-in" class="mr-2"></i> Entrar
</button>
</div>
</form>
</div>
<div class="bg-gray-50 px-8 py-4 border-t border-gray-200">
<p class="text-sm text-gray-600 text-center">Sistema de controle de acesso - FireMaster 🔥</p>
</div>
</div>
<!-- Dashboard (hidden by default) -->
<div id="dashboard" class="hidden">
<!-- Content will be loaded dynamically -->
</div>
</div>
<script>
// Firebase configuration
const firebaseConfig = {
apiKey: "AIzaSyDdP3jJq5X8X9Q5Q5Q5Q5Q5Q5Q5Q5Q5Q5Q",
authDomain: "firemaster-control-hub.firebaseapp.com",
projectId: "firemaster-control-hub",
storageBucket: "firemaster-control-hub.appspot.com",
messagingSenderId: "123456789012",
appId: "1:123456789012:web:abcd1234efgh5678ijkl90"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
const auth = firebase.auth();
const db = firebase.firestore();
// DOM elements
const loginForm = document.getElementById('login-form');
const emailInput = document.getElementById('email');
const passwordInput = document.getElementById('password');
const togglePasswordBtn = document.getElementById('toggle-password');
const rememberCheckbox = document.getElementById('remember');
const loginCard = document.getElementById('login-card');
const dashboard = document.getElementById('dashboard');
// Toggle password visibility
togglePasswordBtn.addEventListener('click', () => {
const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
passwordInput.setAttribute('type', type);
togglePasswordBtn.innerHTML = feather.icons[type === 'password' ? 'eye' : 'eye-off'].toSvg();
});
// Check saved credentials
if (localStorage.getItem('remember') === 'true') {
rememberCheckbox.checked = true;
emailInput.value = localStorage.getItem('email') || '';
passwordInput.value = localStorage.getItem('password') || '';
}
// Login form submission
loginForm.addEventListener('submit', (e) => {
e.preventDefault();
const email = emailInput.value;
const password = passwordInput.value;
if (rememberCheckbox.checked) {
localStorage.setItem('remember', 'true');
localStorage.setItem('email', email);
localStorage.setItem('password', password);
} else {
localStorage.removeItem('remember');
localStorage.removeItem('email');
localStorage.removeItem('password');
}
auth.signInWithEmailAndPassword(email, password)
.then((userCredential) => {
// Check if user is master
if (email === 'julianotimoteo@usinapitangueiras.com.br') {
loadMasterDashboard();
} else {
checkUserPermissions(userCredential.user.uid);
}
})
.catch((error) => {
alert('Erro de autenticação: ' + error.message);
});
});
function checkUserPermissions(uid) {
db.collection('users').doc(uid).get()
.then((doc) => {
if (doc.exists) {
const userData = doc.data();
// TODO: Implement permission check and load appropriate dashboard
alert('Bem-vindo, ' + userData.nome);
} else {
alert('Usuário não encontrado no sistema');
auth.signOut();
}
})
.catch((error) => {
console.error('Error checking permissions:', error);
alert('Erro ao verificar permissões');
});
}
function loadMasterDashboard() {
loginCard.classList.add('hidden');
dashboard.classList.remove('hidden');
// Load master dashboard content
dashboard.innerHTML = `
<div class="bg-white rounded-xl shadow-2xl overflow-hidden">
<div class="bg-red-600 p-4 text-white">
<div class="flex items-center justify-between">
<h1 class="text-xl font-bold">Painel Master</h1>
<button id="logout-btn" class="flex items-center space-x-1 bg-red-700 hover:bg-red-800 px-3 py-1 rounded-lg transition">
<i data-feather="log-out" class="w-4 h-4"></i>
<span>Sair</span>
</button>
</div>
<p class="text-sm opacity-90">Bem-vindo, Master</p>
</div>
<div class="p-6">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
<div class="bg-blue-50 p-4 rounded-lg border border-blue-100">
<div class="flex items-center space-x-3">
<div class="bg-blue-100 p-2 rounded-full">
<i data-feather="users" class="text-blue-600 w-5 h-5"></i>
</div>
<div>
<p class="text-sm text-gray-500">Usuários</p>
<h3 id="user-count" class="text-2xl font-bold">0</h3>
</div>
</div>
</div>
<div class="bg-green-50 p-4 rounded-lg border border-green-100">
<div class="flex items-center space-x-3">
<div class="bg-green-100 p-2 rounded-full">
<i data-feather="activity" class="text-green-600 w-5 h-5"></i>
</div>
<div>
<p class="text-sm text-gray-500">Leituras</p>
<h3 id="reading-count" class="text-2xl font-bold">0</h3>
</div>
</div>
</div>
</div>
<div class="space-y-4">
<button id="manage-users-btn" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition flex items-center justify-center space-x-2">
<i data-feather="users" class="w-4 h-4"></i>
<span>Gerenciar Usuários</span>
</button>
<button id="view-readings-btn" class="w-full bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg transition flex items-center justify-center space-x-2">
<i data-feather="activity" class="w-4 h-4"></i>
<span>Visualizar Leituras</span>
</button>
<button id="settings-btn" class="w-full bg-purple-600 hover:bg-purple-700 text-white font-medium py-2 px-4 rounded-lg transition flex items-center justify-center space-x-2">
<i data-feather="settings" class="w-4 h-4"></i>
<span>Configurações</span>
</button>
</div>
</div>
</div>
`;
// Initialize logout button
document.getElementById('logout-btn').addEventListener('click', () => {
auth.signOut().then(() => {
window.location.reload();
});
});
// Initialize other buttons
document.getElementById('manage-users-btn').addEventListener('click', () => {
loadUserManagement();
});
// Load initial counts
loadCounts();
feather.replace();
}
function loadCounts() {
// Load user count
db.collection('users').get().then((querySnapshot) => {
document.getElementById('user-count').textContent = querySnapshot.size;
});
// Load reading count
db.collection('leituras_esp32').get().then((querySnapshot) => {
document.getElementById('reading-count').textContent = querySnapshot.size;
});
}
function loadUserManagement() {
dashboard.innerHTML = `
<div class="bg-white rounded-xl shadow-2xl overflow-hidden">
<div class="bg-blue-600 p-4 text-white">
<div class="flex items-center justify-between">
<div class="flex items-center space-x-2">
<button id="back-to-dashboard" class="flex items-center">
<i data-feather="chevron-left" class="w-5 h-5"></i>
</button>
<h1 class="text-xl font-bold">Gerenciar Usuários</h1>
</div>
<button id="add-user-btn" class="flex items-center space-x-1 bg-blue-700 hover:bg-blue-800 px-3 py-1 rounded-lg transition">
<i data-feather="plus" class="w-4 h-4"></i>
<span>Adicionar</span>
</button>
</div>
</div>
<div class="p-4">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nome</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">E-mail</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Função</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Ações</th>
</tr>
</thead>
<tbody id="users-table-body" class="bg-white divide-y divide-gray-200">
<!-- Users will be loaded here -->
</tbody>
</table>
</div>
</div>
</div>
`;
// Back button
document.getElementById('back-to-dashboard').addEventListener('click', loadMasterDashboard);
// Add user button
document.getElementById('add-user-btn').addEventListener('click', showAddUserModal);
// Load users
loadUsersTable();
feather.replace();
}
function loadUsersTable() {
const usersTableBody = document.getElementById('users-table-body');
usersTableBody.innerHTML = '<tr><td colspan="4" class="px-6 py-4 text-center">Carregando...</td></tr>';
db.collection('users').get().then((querySnapshot) => {
usersTableBody.innerHTML = '';
if (querySnapshot.empty) {
usersTableBody.innerHTML = '<tr><td colspan="4" class="px-6 py-4 text-center">Nenhum usuário encontrado</td></tr>';
return;
}
querySnapshot.forEach((doc) => {
const user = doc.data();
const row = document.createElement('tr');
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap">${user.nome || 'N/A'}</td>
<td class="px-6 py-4 whitespace-nowrap">${user.email || 'N/A'}</td>
<td class="px-6 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
${user.funcao === 'Master' ? 'bg-purple-100 text-purple-800' :
user.funcao === 'Líder' ? 'bg-blue-100 text-blue-800' :
'bg-green-100 text-green-800'}">
${user.funcao || 'Operação'}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button data-id="${doc.id}" class="edit-user text-indigo-600 hover:text-indigo-900 mr-3">Editar</button>
<button data-id="${doc.id}" class="delete-user text-red-600 hover:text-red-900">Excluir</button>
</td>
`;
usersTableBody.appendChild(row);
});
// Add event listeners to edit/delete buttons
document.querySelectorAll('.edit-user').forEach(btn => {
btn.addEventListener('click', (e) => {
const userId = e.target.getAttribute('data-id');
showEditUserModal(userId);
});
});
document.querySelectorAll('.delete-user').forEach(btn => {
btn.addEventListener('click', (e) => {
const userId = e.target.getAttribute('data-id');
deleteUser(userId);
});
});
});
}
function showAddUserModal() {
// TODO: Implement add user modal
alert('Funcionalidade de adicionar usuário será implementada aqui');
}
function showEditUserModal(userId) {
// TODO: Implement edit user modal
alert('Funcionalidade de editar usuário será implementada aqui para o ID: ' + userId);
}
function deleteUser(userId) {
if (confirm('Tem certeza que deseja excluir este usuário?')) {
db.collection('users').doc(userId).delete()
.then(() => {
alert('Usuário excluído com sucesso');
loadUsersTable();
})
.catch((error) => {
alert('Erro ao excluir usuário: ' + error.message);
});
}
}
// Initialize Feather Icons
feather.replace();
</script>
</body>
</html>