import React, { useEffect, useState } from 'react'; import { CondoService } from '../services/mockDb'; import { AppSettings, Family, User, AlertDefinition, Condo, Notice, NoticeIconType, NoticeRead } from '../types'; import { Save, Building, Coins, Plus, Pencil, Trash2, X, CalendarCheck, AlertTriangle, User as UserIcon, Server, Bell, Clock, FileText, Lock, Megaphone, CheckCircle2, Info, Hammer, Link as LinkIcon, Eye, Calendar, List, UserCog, Mail, Power } from 'lucide-react'; export const SettingsPage: React.FC = () => { const currentUser = CondoService.getCurrentUser(); const isAdmin = currentUser?.role === 'admin'; // Tab configuration type TabType = 'profile' | 'general' | 'condos' | 'families' | 'users' | 'notices' | 'alerts' | 'smtp'; const [activeTab, setActiveTab] = useState(isAdmin ? 'general' : 'profile'); const [loading, setLoading] = useState(true); // Profile State const [profileForm, setProfileForm] = useState({ name: currentUser?.name || '', phone: currentUser?.phone || '', password: '', receiveAlerts: currentUser?.receiveAlerts ?? true }); const [profileSaving, setProfileSaving] = useState(false); const [profileMsg, setProfileMsg] = useState(''); // General Settings State const [activeCondo, setActiveCondo] = useState(undefined); const [globalSettings, setGlobalSettings] = useState(null); // Condos Management State const [condos, setCondos] = useState([]); const [showCondoModal, setShowCondoModal] = useState(false); const [editingCondo, setEditingCondo] = useState(null); const [condoForm, setCondoForm] = useState({ name: '', address: '', defaultMonthlyQuota: 100 }); const [saving, setSaving] = useState(false); const [successMsg, setSuccessMsg] = useState(''); // Families State const [families, setFamilies] = useState([]); const [showFamilyModal, setShowFamilyModal] = useState(false); const [editingFamily, setEditingFamily] = useState(null); const [familyForm, setFamilyForm] = useState<{ name: string; unitNumber: string; contactEmail: string; customMonthlyQuota: string; // Use string for input handling, parse to number on save }>({ name: '', unitNumber: '', contactEmail: '', customMonthlyQuota: '' }); // Users State const [users, setUsers] = useState([]); const [showUserModal, setShowUserModal] = useState(false); const [editingUser, setEditingUser] = useState(null); const [userForm, setUserForm] = useState({ name: '', email: '', password: '', phone: '', role: 'user', familyId: '', receiveAlerts: true }); // Alerts State const [alerts, setAlerts] = useState([]); const [showAlertModal, setShowAlertModal] = useState(false); const [editingAlert, setEditingAlert] = useState(null); const [alertForm, setAlertForm] = useState>({ subject: '', body: '', daysOffset: 1, offsetType: 'before_next_month', sendHour: 9, active: true }); // Notices (Bacheca) State const [notices, setNotices] = useState([]); const [showNoticeModal, setShowNoticeModal] = useState(false); const [editingNotice, setEditingNotice] = useState(null); const [noticeForm, setNoticeForm] = useState<{ title: string; content: string; type: NoticeIconType; link: string; condoId: string; active: boolean; }>({ title: '', content: '', type: 'info', link: '', condoId: '', active: true }); const [noticeReadStats, setNoticeReadStats] = useState>({}); // Notice Details Modal const [showReadDetailsModal, setShowReadDetailsModal] = useState(false); const [selectedNoticeId, setSelectedNoticeId] = useState(null); useEffect(() => { const fetchData = async () => { try { if (isAdmin) { const [condoList, activeC, gSettings, fams, usrs, alrts, allNotices] = await Promise.all([ CondoService.getCondos(), CondoService.getActiveCondo(), CondoService.getSettings(), CondoService.getFamilies(), CondoService.getUsers(), CondoService.getAlerts(), CondoService.getNotices() ]); setCondos(condoList); setActiveCondo(activeC); setGlobalSettings(gSettings); setFamilies(fams); setUsers(usrs); setAlerts(alrts); setNotices(allNotices); // Fetch read stats for notices const stats: Record = {}; for (const n of allNotices) { const reads = await CondoService.getNoticeReadStatus(n.id); stats[n.id] = reads; } setNoticeReadStats(stats); } else { const activeC = await CondoService.getActiveCondo(); setActiveCondo(activeC); } } catch(e) { console.error(e); } finally { setLoading(false); } }; fetchData(); }, [isAdmin]); // --- Profile Handlers --- const handleProfileSubmit = async (e: React.FormEvent) => { e.preventDefault(); setProfileSaving(true); setProfileMsg(''); try { await CondoService.updateProfile(profileForm); setProfileMsg('Profilo aggiornato con successo!'); setTimeout(() => setProfileMsg(''), 3000); setProfileForm(prev => ({ ...prev, password: '' })); } catch (e) { setProfileMsg('Errore aggiornamento profilo'); } finally { setProfileSaving(false); } }; // --- General Handlers --- const handleGeneralSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!activeCondo) return; setSaving(true); setSuccessMsg(''); try { await CondoService.saveCondo(activeCondo); setSuccessMsg('Dati condominio aggiornati!'); setTimeout(() => setSuccessMsg(''), 3000); const list = await CondoService.getCondos(); setCondos(list); } catch (e) { console.error(e); } finally { setSaving(false); } }; const handleSmtpSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!globalSettings) return; setSaving(true); try { await CondoService.updateSettings(globalSettings); setSuccessMsg('Configurazione SMTP salvata!'); setTimeout(() => setSuccessMsg(''), 3000); } catch (e) { console.error(e); } finally { setSaving(false); } }; const handleNewYear = async () => { if (!globalSettings) return; const nextYear = globalSettings.currentYear + 1; if (window.confirm(`Sei sicuro di voler chiudere l'anno ${globalSettings.currentYear} e aprire il ${nextYear}?`)) { setSaving(true); try { const newSettings = { ...globalSettings, currentYear: nextYear }; await CondoService.updateSettings(newSettings); setGlobalSettings(newSettings); setSuccessMsg(`Anno ${nextYear} aperto!`); } catch(e) { console.error(e); } finally { setSaving(false); } } }; // --- Condo Management Handlers --- const openAddCondoModal = () => { setEditingCondo(null); setCondoForm({ name: '', address: '', defaultMonthlyQuota: 100 }); setShowCondoModal(true); }; const openEditCondoModal = (c: Condo) => { setEditingCondo(c); setCondoForm({ name: c.name, address: c.address || '', defaultMonthlyQuota: c.defaultMonthlyQuota }); setShowCondoModal(true); }; const handleCondoSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { // FIX: Do not generate ID for new condo, let backend/service handle it (POST vs PUT check) const payload: Condo = { id: editingCondo ? editingCondo.id : '', name: condoForm.name, address: condoForm.address, defaultMonthlyQuota: condoForm.defaultMonthlyQuota }; const savedCondo = await CondoService.saveCondo(payload); const list = await CondoService.getCondos(); setCondos(list); if (activeCondo?.id === savedCondo.id) { setActiveCondo(savedCondo); } // Auto-select if it's the first one or none selected if (!activeCondo && list.length === 1) { CondoService.setActiveCondo(savedCondo.id); } setShowCondoModal(false); window.dispatchEvent(new Event('condo-updated')); } catch (e) { console.error(e); alert("Errore nel salvataggio del condominio"); } }; const handleDeleteCondo = async (id: string) => { if(!window.confirm("Eliminare questo condominio? Attenzione: operazione irreversibile.")) return; try { await CondoService.deleteCondo(id); setCondos(await CondoService.getCondos()); window.dispatchEvent(new Event('condo-updated')); } catch (e) { console.error(e); } }; // --- Family Handlers --- const openAddFamilyModal = () => { setEditingFamily(null); setFamilyForm({ name: '', unitNumber: '', contactEmail: '', customMonthlyQuota: '' }); setShowFamilyModal(true); }; const openEditFamilyModal = (family: Family) => { setEditingFamily(family); setFamilyForm({ name: family.name, unitNumber: family.unitNumber, contactEmail: family.contactEmail || '', customMonthlyQuota: family.customMonthlyQuota ? family.customMonthlyQuota.toString() : '' }); setShowFamilyModal(true); }; const handleDeleteFamily = async (id: string) => { if (!window.confirm('Eliminare questa famiglia?')) return; try { await CondoService.deleteFamily(id); setFamilies(families.filter(f => f.id !== id)); } catch (e) { console.error(e); } }; const handleFamilySubmit = async (e: React.FormEvent) => { e.preventDefault(); try { const quota = familyForm.customMonthlyQuota ? parseFloat(familyForm.customMonthlyQuota) : undefined; if (editingFamily) { const updatedFamily = { ...editingFamily, name: familyForm.name, unitNumber: familyForm.unitNumber, contactEmail: familyForm.contactEmail, customMonthlyQuota: quota }; await CondoService.updateFamily(updatedFamily); setFamilies(families.map(f => f.id === updatedFamily.id ? updatedFamily : f)); } else { const newFamily = await CondoService.addFamily({ name: familyForm.name, unitNumber: familyForm.unitNumber, contactEmail: familyForm.contactEmail, customMonthlyQuota: quota }); setFamilies([...families, newFamily]); } setShowFamilyModal(false); } catch (e: any) { console.error(e); alert(`Errore: ${e.message || "Impossibile salvare la famiglia"}`); } }; // --- User Handlers --- const openAddUserModal = () => { setEditingUser(null); setUserForm({ name: '', email: '', password: '', phone: '', role: 'user', familyId: '', receiveAlerts: true }); setShowUserModal(true); }; const openEditUserModal = (user: User) => { setEditingUser(user); setUserForm({ name: user.name || '', email: user.email, password: '', phone: user.phone || '', role: user.role || 'user', familyId: user.familyId || '', receiveAlerts: user.receiveAlerts ?? true }); setShowUserModal(true); }; const handleUserSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { if (editingUser) { await CondoService.updateUser(editingUser.id, userForm); } else { await CondoService.createUser(userForm); } setUsers(await CondoService.getUsers()); setShowUserModal(false); } catch (e) { alert("Errore"); } }; const handleDeleteUser = async (id: string) => { if(!window.confirm("Eliminare utente?")) return; await CondoService.deleteUser(id); setUsers(users.filter(u => u.id !== id)); }; // --- Notice Handlers --- const openAddNoticeModal = () => { setEditingNotice(null); setNoticeForm({ title: '', content: '', type: 'info', link: '', condoId: activeCondo?.id || '', active: true }); setShowNoticeModal(true); }; const openEditNoticeModal = (n: Notice) => { setEditingNotice(n); setNoticeForm({ title: n.title, content: n.content, type: n.type, link: n.link || '', condoId: n.condoId, active: n.active }); setShowNoticeModal(true); }; const handleNoticeSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { const payload: Notice = { id: editingNotice ? editingNotice.id : '', ...noticeForm, date: editingNotice ? editingNotice.date : new Date().toISOString() }; await CondoService.saveNotice(payload); setNotices(await CondoService.getNotices()); setShowNoticeModal(false); } catch (e) { console.error(e); } }; const handleDeleteNotice = async (id: string) => { if(!window.confirm("Eliminare annuncio?")) return; await CondoService.deleteNotice(id); setNotices(notices.filter(n => n.id !== id)); }; const toggleNoticeActive = async (notice: Notice) => { try { const updated = { ...notice, active: !notice.active }; await CondoService.saveNotice(updated); setNotices(notices.map(n => n.id === notice.id ? updated : n)); } catch(e) { console.error(e); } }; const openReadDetails = (noticeId: string) => { setSelectedNoticeId(noticeId); setShowReadDetailsModal(true); }; // --- Alert Handlers --- const openAddAlertModal = () => { setEditingAlert(null); setAlertForm({ subject: '', body: '', daysOffset: 1, offsetType: 'before_next_month', sendHour: 9, active: true }); setShowAlertModal(true); }; const openEditAlertModal = (alert: AlertDefinition) => { setEditingAlert(alert); setAlertForm(alert); setShowAlertModal(true); }; const handleAlertSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { const payload: AlertDefinition = { id: editingAlert ? editingAlert.id : '', subject: alertForm.subject!, body: alertForm.body!, daysOffset: Number(alertForm.daysOffset), offsetType: alertForm.offsetType as any, sendHour: Number(alertForm.sendHour), active: alertForm.active! }; const saved = await CondoService.saveAlert(payload); setAlerts(editingAlert ? alerts.map(a => a.id === saved.id ? saved : a) : [...alerts, saved]); setShowAlertModal(false); } catch (e) { console.error(e); } }; const handleDeleteAlert = async (id: string) => { if(!window.confirm("Eliminare avviso?")) return; await CondoService.deleteAlert(id); setAlerts(alerts.filter(a => a.id !== id)); }; const getCondoName = (id: string) => condos.find(c => c.id === id)?.name || 'Sconosciuto'; // --- TABS CONFIG --- const tabs: {id: TabType, label: string, icon: React.ReactNode}[] = [ { id: 'profile', label: 'Profilo', icon: }, ]; if (isAdmin) { tabs.push( { id: 'general', label: 'Condominio', icon: }, { id: 'condos', label: 'Lista Condomini', icon: }, { id: 'families', label: 'Famiglie', icon: }, { id: 'users', label: 'Utenti', icon: }, { id: 'notices', label: 'Bacheca', icon: }, { id: 'alerts', label: 'Avvisi Email', icon: }, { id: 'smtp', label: 'Impostazioni Posta', icon: } ); } if (loading) return
Caricamento...
; return (

Impostazioni

{activeCondo ? `Gestione: ${activeCondo.name}` : 'Pannello di Controllo'}

{/* Tabs */}
{tabs.map(tab => ( ))}
{/* Profile Tab */} {activeTab === 'profile' && (

Il Tuo Profilo

setProfileForm({...profileForm, name: e.target.value})} className="w-full border p-2.5 rounded-lg text-slate-700"/>
setProfileForm({...profileForm, phone: e.target.value})} className="w-full border p-2.5 rounded-lg text-slate-700"/>
setProfileForm({...profileForm, password: e.target.value})} className="w-full border p-2.5 rounded-lg text-slate-700"/>
)} {/* General Tab */} {isAdmin && activeTab === 'general' && (
{!activeCondo ? (
Nessun condominio selezionato. Crea un condominio nella sezione "Lista Condomini".
) : (

Dati Condominio Corrente

setActiveCondo({ ...activeCondo, name: e.target.value })} className="w-full border p-2.5 rounded-lg text-slate-700" placeholder="Nome" required /> setActiveCondo({ ...activeCondo, address: e.target.value })} className="w-full border p-2.5 rounded-lg text-slate-700" placeholder="Indirizzo" />
setActiveCondo({ ...activeCondo, defaultMonthlyQuota: parseFloat(e.target.value) })} className="w-full border p-2.5 rounded-lg text-slate-700" placeholder="Quota Default" required />
{successMsg}
)} {globalSettings && (

Anno Fiscale

Corrente: {globalSettings.currentYear}

)}
)} {/* Condos List Tab */} {isAdmin && activeTab === 'condos' && (

I Tuoi Condomini

{condos.map(condo => (
{activeCondo?.id === condo.id &&
Attivo
}

{condo.name}

{condo.address || 'Nessun indirizzo'}

))}
)} {/* Families Tab */} {isAdmin && activeTab === 'families' && (
{!activeCondo ? (

Seleziona o crea un condominio per gestire le famiglie.

) : ( <>
Famiglie in: {activeCondo.name}
{families.map(family => ( ))}
NomeInternoEmailQuotaAzioni
{family.name} {family.unitNumber} {family.contactEmail} {family.customMonthlyQuota ? ( € {family.customMonthlyQuota} ) : ( Default (€ {activeCondo.defaultMonthlyQuota}) )}
)}
)} {/* Users Tab */} {isAdmin && activeTab === 'users' && (
{users.map(u => ( ))}
UtenteRuoloAzioni
{u.name}
{u.email}
{u.role}
)} {/* NOTICES (BACHECA) TAB */} {isAdmin && activeTab === 'notices' && (

Bacheca Condominiale

Pubblica avvisi visibili a tutti i condomini.

{notices.map(notice => (
{notice.type === 'warning' ? : notice.type === 'maintenance' ? : notice.type === 'event' ? : }

{notice.title}

{getCondoName(notice.condoId)} • {new Date(notice.date).toLocaleDateString()}

{notice.content}

{notice.link && Allegato}
{/* Toggle Active */} {/* Reads Counter */}
))} {notices.length === 0 &&
Nessun avviso pubblicato.
}
)} {/* Alerts Tab */} {isAdmin && activeTab === 'alerts' && (

Avvisi Automatici Email

{alerts.map(a => (

{a.subject}

{a.body}

))}
)} {isAdmin && activeTab === 'smtp' && (

Server SMTP Globale

{globalSettings && (
setGlobalSettings({...globalSettings, smtpConfig: {...globalSettings.smtpConfig!, host: e.target.value}})} className="border p-2 rounded text-slate-700"/> setGlobalSettings({...globalSettings, smtpConfig: {...globalSettings.smtpConfig!, port: parseInt(e.target.value)}})} className="border p-2 rounded text-slate-700"/>
setGlobalSettings({...globalSettings, smtpConfig: {...globalSettings.smtpConfig!, user: e.target.value}})} className="border p-2 rounded text-slate-700"/> setGlobalSettings({...globalSettings, smtpConfig: {...globalSettings.smtpConfig!, pass: e.target.value}})} className="border p-2 rounded text-slate-700"/>
)}
)} {/* MODALS */} {/* CONDO MODAL */} {showCondoModal && (

{editingCondo ? 'Modifica Condominio' : 'Nuovo Condominio'}

setCondoForm({...condoForm, name: e.target.value})} required /> setCondoForm({...condoForm, address: e.target.value})} />
Quota Default € setCondoForm({...condoForm, defaultMonthlyQuota: parseFloat(e.target.value)})} />
)} {/* NOTICE MODAL */} {showNoticeModal && (

{editingNotice ? 'Modifica Avviso' : 'Nuovo Avviso'}

setNoticeForm({...noticeForm, title: e.target.value})} required />