This commit is contained in:
2026-05-07 09:25:19 +01:00
parent f6b7a98471
commit a7f8e39aae
2 changed files with 128 additions and 24 deletions

View File

@@ -341,12 +341,23 @@
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [error, setError] = useState('');
const [isLoading, setIsLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
if (isLoading) return;
setError('');
setIsLoading(true);
const success = await onLogin(email, password);
setIsLoading(false);
if (!success) {
setError('Email ou Palavra-passe incorreta');
setTimeout(() => {
setError('');
}, 5000);
}
};
@@ -392,8 +403,15 @@
</div>
)}
<div className="space-y-4">
<button type="submit" className="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 rounded-lg transition-colors shadow-lg shadow-blue-500/30">
Entrar
<button type="submit" disabled={isLoading} className={`w-full ${isLoading ? 'bg-blue-400 dark:bg-blue-600/50 cursor-not-allowed' : 'bg-blue-600 hover:bg-blue-700 shadow-lg shadow-blue-500/30'} text-white font-bold py-3 rounded-lg transition-colors flex justify-center items-center gap-2`}>
{isLoading ? (
<>
<div className="w-5 h-5 border-2 border-white/30 border-t-white rounded-full animate-spin"></div>
A entrar...
</>
) : (
'Entrar'
)}
</button>
</div>
</form>
@@ -472,7 +490,7 @@
userId = 'admin_001';
} else {
const residentUser = residents.find(r => r.email && r.email.toLowerCase() === email.toLowerCase());
if (residentUser && (password === residentUser.contact || password === '1234')) {
if (residentUser && (password === residentUser.password || password === '1234')) {
role = residentUser.role || 'morador';
userName = residentUser.name + (residentUser.unit && residentUser.unit !== 'Pendente' ? ` (${residentUser.unit})` : '');
userId = residentUser.id || userId;
@@ -763,7 +781,8 @@
try {
if (editingItem) {
const residentRef = ref(db, `condominos/${editingItem.id}`);
await set(residentRef, {
const updatedData = {
...editingItem,
unit: formData.unit || '',
name: formData.name || '',
contact: formData.contact || '',
@@ -771,7 +790,11 @@
status: formData.status || 'Pago',
pending: Number(formData.pending) || 0,
role: formData.role || 'morador'
});
};
if (formData.password) {
updatedData.password = formData.password;
}
await set(residentRef, updatedData);
showNotification(`Condómino ${formData.name} atualizado`);
} else {
const residentsListRef = ref(db, 'condominos');
@@ -781,6 +804,7 @@
name: formData.name || '',
contact: formData.contact || '',
email: formData.email || '',
password: formData.password || '1234',
status: formData.status || 'Pago',
pending: Number(formData.pending) || 0,
role: formData.role || 'morador'
@@ -1265,6 +1289,73 @@
const ProfileView = ({ theme, setTheme }) => {
const [activeSection, setActiveSection] = useState('personal');
const isMorador = userRole !== 'admin';
const [formData, setFormData] = useState({
name: 'A carregar...',
role: '...',
email: '',
contact: '',
address: ''
});
useEffect(() => {
if (isMorador) {
const currentUserData = residents.find(r => r.id === currentUserId) || {};
setFormData({
name: currentUserData.name || currentUserName || '',
role: `Fração ${currentUserData.unit || 'N/A'}`,
email: currentUserData.email || '',
contact: currentUserData.contact || '',
address: 'Morada do Condomínio'
});
} else {
const adminRef = ref(db, 'configuracoes/admin_profile');
const unsub = onValue(adminRef, (snapshot) => {
if (snapshot.exists()) {
setFormData(snapshot.val());
} else {
setFormData({
name: 'Administrador do Condomínio',
role: 'Síndico / Gestor',
email: 'admin@mycondominium.pt',
contact: '+351 912 345 678',
address: 'Rua das Flores, nº 123, Escritório 2B'
});
}
});
return () => unsub();
}
}, [residents, currentUserId, userRole, currentUserName, isMorador]);
const handleChange = (field, value) => {
setFormData(prev => ({ ...prev, [field]: value }));
};
const handleSave = async () => {
if (isMorador) {
const currentUserData = residents.find(r => r.id === currentUserId);
if (currentUserData && currentUserData.id) {
try {
await set(ref(db, `condominos/${currentUserData.id}/email`), formData.email);
await set(ref(db, `condominos/${currentUserData.id}/contact`), formData.contact);
showNotification('Dados atualizados com sucesso!', 'success');
sendSystemNotification('Um utilizador atualizou os seus dados pessoais.', 'info', 'admin');
} catch (error) {
console.error("Erro ao guardar os dados:", error);
showNotification('Erro ao guardar os dados.', 'error');
}
}
} else {
try {
await set(ref(db, 'configuracoes/admin_profile'), formData);
showNotification('Alterações guardadas com sucesso!', 'success');
} catch (error) {
console.error("Erro ao guardar perfil admin:", error);
showNotification('Erro ao guardar as alterações.', 'error');
}
}
};
return (
<div className="bg-white dark:bg-dark-surface rounded-xl shadow-sm border border-slate-100 dark:border-dark-border overflow-hidden animate-fade-in flex flex-col h-full transition-colors">
@@ -1314,19 +1405,16 @@
<h3 className="text-lg font-bold text-slate-800 dark:text-white mb-6 pb-2 border-b border-slate-100 dark:border-dark-border">Dados Pessoais</h3>
<div className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<InputGroup label="Nome Completo" value="Administrador do Condomínio" disabled />
<InputGroup label="Cargo" value="Síndico / Gestor" disabled />
<InputGroup label="Nome Completo" value={formData.name} onChange={(e) => handleChange('name', e.target.value)} disabled={isMorador} />
<InputGroup label={isMorador ? "Fração" : "Cargo"} value={formData.role} onChange={(e) => handleChange('role', e.target.value)} disabled={isMorador} />
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<InputGroup label="Email" value="admin@mycondominium.pt" type="email" />
<InputGroup label="Telefone" value="+351 912 345 678" />
<InputGroup label="Email" value={formData.email} onChange={(e) => handleChange('email', e.target.value)} type="email" />
<InputGroup label="Telefone" value={formData.contact} onChange={(e) => handleChange('contact', e.target.value)} />
</div>
<InputGroup label="Morada (Sede)" value="Rua das Flores, nº 123, Escritório 2B" />
<InputGroup label={isMorador ? "Morada" : "Morada (Sede)"} value={formData.address} onChange={(e) => handleChange('address', e.target.value)} disabled={isMorador} />
<div className="flex justify-end mt-6">
<button onClick={() => {
showNotification('Alterações guardadas com sucesso!', 'success');
sendSystemNotification('Um utilizador atualizou os seus dados pessoais.', 'info', 'admin');
}} className="bg-blue-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-blue-700 shadow-sm transition-colors">
<button onClick={handleSave} className="bg-blue-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-blue-700 shadow-sm transition-colors">
Guardar Alterações
</button>
</div>
@@ -2256,7 +2344,10 @@
<InputGroup label="Fração" name="unit" value={formData.unit || ''} onChange={handleInputChange} placeholder="Ex: 1º Esq" required />
<InputGroup label="Nome Completo" name="name" value={formData.name || ''} onChange={handleInputChange} placeholder="Nome do proprietário" required />
<InputGroup label="Email" type="email" name="email" value={formData.email || ''} onChange={handleInputChange} placeholder="email@exemplo.com" />
<InputGroup label="Contacto" name="contact" value={formData.contact || ''} onChange={handleInputChange} placeholder="912 345 678" />
<div className="grid grid-cols-2 gap-4">
<InputGroup label="Telemóvel" name="contact" value={formData.contact || ''} onChange={handleInputChange} placeholder="912 345 678" required />
<InputGroup label="Palavra-passe" type="text" name="password" value={formData.password || ''} onChange={handleInputChange} placeholder={editingItem ? "Deixar em branco para manter" : "1234"} required={!editingItem} />
</div>
<div className="grid grid-cols-2 gap-4">
<InputGroup label="Estado" name="status" value={formData.status || 'Pago'} onChange={handleInputChange} options={[{ value: 'Pago', label: 'Pago' }, { value: 'Pendente', label: 'Pendente' }, { value: 'Atrasado', label: 'Atrasado' }]} />
<InputGroup label="Valor Pendente (€)" type="number" name="pending" value={formData.pending || 0} onChange={handleInputChange} />