Update Settings.tsx

This commit is contained in:
2025-12-12 00:08:37 +01:00
committed by GitHub
parent e050a372a5
commit 0906b0d972

View File

@@ -7,7 +7,7 @@ import {
AlertTriangle, User as UserIcon, Server, Bell, Clock, FileText,
Lock, Megaphone, CheckCircle2, Info, Hammer, Link as LinkIcon,
Eye, Calendar, List, UserCog, Mail, Power, MapPin, CreditCard,
ToggleLeft, ToggleRight, LayoutGrid, PieChart, Users, Send, Cloud, HardDrive
ToggleLeft, ToggleRight, LayoutGrid, PieChart, Users, Send, Cloud, HardDrive, ChevronRight
} from 'lucide-react';
export const SettingsPage: React.FC = () => {
@@ -203,359 +203,62 @@ export const SettingsPage: React.FC = () => {
fetchData();
}, [isPrivileged]);
// --- HANDLERS ---
// --- HANDLERS (Omitted details for brevity as they are unchanged) ---
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);
}
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); }
};
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);
}
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 handleFeaturesSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!globalSettings) return;
setSaving(true);
try {
await CondoService.updateSettings(globalSettings);
setSuccessMsg('Configurazione salvata!');
setTimeout(() => setSuccessMsg(''), 3000);
window.location.reload();
} catch(e) {
console.error(e);
} finally {
setSaving(false);
}
e.preventDefault(); if (!globalSettings) return; setSaving(true);
try { await CondoService.updateSettings(globalSettings); setSuccessMsg('Configurazione salvata!'); setTimeout(() => setSuccessMsg(''), 3000); window.location.reload(); } 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('');
setShowSmtpModal(false);
}, 2000);
} catch (e) {
console.error(e);
} finally {
setSaving(false);
}
e.preventDefault(); if (!globalSettings) return; setSaving(true);
try { await CondoService.updateSettings(globalSettings); setSuccessMsg('Configurazione SMTP salvata!'); setTimeout(() => { setSuccessMsg(''); setShowSmtpModal(false); }, 2000); } catch (e) { console.error(e); } finally { setSaving(false); }
};
const handleSmtpTest = async () => {
if (!globalSettings?.smtpConfig) return;
setTestingSmtp(true);
setTestSmtpMsg('');
try {
await CondoService.testSmtpConfig(globalSettings.smtpConfig);
setTestSmtpMsg('Successo! Email di prova inviata.');
} catch(e: any) {
setTestSmtpMsg('Errore: ' + (e.message || "Impossibile connettersi"));
} finally {
setTestingSmtp(false);
}
if (!globalSettings?.smtpConfig) return; setTestingSmtp(true); setTestSmtpMsg('');
try { await CondoService.testSmtpConfig(globalSettings.smtpConfig); setTestSmtpMsg('Successo! Email di prova inviata.'); } catch(e: any) { setTestSmtpMsg('Errore: ' + (e.message || "Impossibile connettersi")); } finally { setTestingSmtp(false); }
};
const handleStorageSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!globalSettings) return;
setSaving(true);
try {
await CondoService.updateSettings(globalSettings);
setSuccessMsg('Configurazione Storage salvata!');
setTimeout(() => setSuccessMsg(''), 3000);
} catch (e) { console.error(e); }
finally { setSaving(false); }
e.preventDefault(); if (!globalSettings) return; setSaving(true);
try { await CondoService.updateSettings(globalSettings); setSuccessMsg('Configurazione Storage 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);
}
}
};
// CRUD Handlers (omitted repeated code for brevity, logic is same as before)
const openAddCondoModal = () => {
setEditingCondo(null);
setCondoForm({ name: '', address: '', streetNumber: '', city: '', province: '', zipCode: '', notes: '', paypalClientId: '', defaultMonthlyQuota: 100, dueDay: 10 });
setShowCondoModal(true);
};
const openEditCondoModal = (c: Condo) => {
setEditingCondo(c);
setCondoForm({ name: c.name, address: c.address || '', streetNumber: c.streetNumber || '', city: c.city || '', province: c.province || '', zipCode: c.zipCode || '', notes: c.notes || '', paypalClientId: c.paypalClientId || '', defaultMonthlyQuota: c.defaultMonthlyQuota, dueDay: c.dueDay || 10 });
setShowCondoModal(true);
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); } }
};
// CRUD Handlers
const openAddCondoModal = () => { setEditingCondo(null); setCondoForm({ name: '', address: '', streetNumber: '', city: '', province: '', zipCode: '', notes: '', paypalClientId: '', defaultMonthlyQuota: 100, dueDay: 10 }); setShowCondoModal(true); };
const openEditCondoModal = (c: Condo) => { setEditingCondo(c); setCondoForm({ name: c.name, address: c.address || '', streetNumber: c.streetNumber || '', city: c.city || '', province: c.province || '', zipCode: c.zipCode || '', notes: c.notes || '', paypalClientId: c.paypalClientId || '', defaultMonthlyQuota: c.defaultMonthlyQuota, dueDay: c.dueDay || 10 }); setShowCondoModal(true); };
const handleCondoSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const payload: Condo = {
id: editingCondo ? editingCondo.id : '',
name: condoForm.name,
address: condoForm.address,
streetNumber: condoForm.streetNumber,
city: condoForm.city,
province: condoForm.province,
zipCode: condoForm.zipCode,
notes: condoForm.notes,
paypalClientId: condoForm.paypalClientId,
defaultMonthlyQuota: condoForm.defaultMonthlyQuota,
dueDay: condoForm.dueDay
e.preventDefault(); try { const payload: Condo = { id: editingCondo ? editingCondo.id : '', name: condoForm.name, address: condoForm.address, streetNumber: condoForm.streetNumber, city: condoForm.city, province: condoForm.province, zipCode: condoForm.zipCode, notes: condoForm.notes, paypalClientId: condoForm.paypalClientId, defaultMonthlyQuota: condoForm.defaultMonthlyQuota, dueDay: condoForm.dueDay }; const savedCondo = await CondoService.saveCondo(payload); const list = await CondoService.getCondos(); setCondos(list); if (activeCondo?.id === savedCondo.id) { setActiveCondo(savedCondo); } 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. Assicurati di essere amministratore."); }
};
const savedCondo = await CondoService.saveCondo(payload);
const list = await CondoService.getCondos();
setCondos(list);
if (activeCondo?.id === savedCondo.id) { setActiveCondo(savedCondo); }
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. Assicurati di essere amministratore.");
}
};
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);
}
};
const openAddFamilyModal = () => {
setEditingFamily(null);
setFamilyForm({ name: '', unitNumber: '', stair: '', floor: '', notes: '', contactEmail: '', customMonthlyQuota: '' });
setShowFamilyModal(true);
};
const openEditFamilyModal = (family: Family) => {
setEditingFamily(family);
setFamilyForm({ name: family.name, unitNumber: family.unitNumber, stair: family.stair || '', floor: family.floor || '', notes: family.notes || '', 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 && familyForm.customMonthlyQuota.trim() !== '' ? parseFloat(familyForm.customMonthlyQuota) : undefined;
const payload: any = {
name: familyForm.name,
unitNumber: familyForm.unitNumber,
stair: familyForm.stair,
floor: familyForm.floor,
notes: familyForm.notes,
contactEmail: familyForm.contactEmail,
customMonthlyQuota: quota
};
if (editingFamily) {
const updatedFamily = { ...editingFamily, ...payload };
await CondoService.updateFamily(updatedFamily);
setFamilies(families.map(f => f.id === updatedFamily.id ? updatedFamily : f));
} else {
const newFamily = await CondoService.addFamily(payload);
setFamilies([...families, newFamily]);
}
setShowFamilyModal(false);
} catch (e: any) {
console.error(e);
alert(`Errore: ${e.message || "Impossibile salvare la famiglia."}`);
}
};
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(activeCondo?.id));
setShowUserModal(false);
} catch (e) {
alert("Errore nel salvataggio utente");
}
};
const handleDeleteUser = async (id: string) => {
if(!window.confirm("Eliminare utente?")) return;
await CondoService.deleteUser(id);
setUsers(users.filter(u => u.id !== id));
};
const openAddNoticeModal = () => {
setEditingNotice(null);
setNoticeTargetMode('all');
setNoticeForm({ title: '', content: '', type: 'info', link: '', condoId: activeCondo?.id || '', active: true, targetFamilyIds: [] });
setShowNoticeModal(true);
};
const openEditNoticeModal = (n: Notice) => {
setEditingNotice(n);
const isTargeted = n.targetFamilyIds && n.targetFamilyIds.length > 0;
setNoticeTargetMode(isTargeted ? 'specific' : 'all');
setNoticeForm({ title: n.title, content: n.content, type: n.type, link: n.link || '', condoId: n.condoId, active: n.active, targetFamilyIds: n.targetFamilyIds || [] });
setShowNoticeModal(true);
};
const handleNoticeSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const payload: Notice = {
id: editingNotice ? editingNotice.id : '',
...noticeForm,
targetFamilyIds: noticeTargetMode === 'all' ? [] : noticeForm.targetFamilyIds,
date: editingNotice ? editingNotice.date : new Date().toISOString()
};
await CondoService.saveNotice(payload);
setNotices(await CondoService.getNotices(activeCondo?.id));
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 toggleNoticeFamilyTarget = (familyId: string) => {
setNoticeForm(prev => {
const current = prev.targetFamilyIds;
if (current.includes(familyId)) {
return { ...prev, targetFamilyIds: current.filter(id => id !== familyId) };
} else {
return { ...prev, targetFamilyIds: [...current, familyId] };
}
});
};
const openReadDetails = (noticeId: string) => {
setSelectedNoticeId(noticeId);
setShowReadDetailsModal(true);
};
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';
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); } };
const openAddFamilyModal = () => { setEditingFamily(null); setFamilyForm({ name: '', unitNumber: '', stair: '', floor: '', notes: '', contactEmail: '', customMonthlyQuota: '' }); setShowFamilyModal(true); };
const openEditFamilyModal = (family: Family) => { setEditingFamily(family); setFamilyForm({ name: family.name, unitNumber: family.unitNumber, stair: family.stair || '', floor: family.floor || '', notes: family.notes || '', 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 && familyForm.customMonthlyQuota.trim() !== '' ? parseFloat(familyForm.customMonthlyQuota) : undefined; const payload: any = { name: familyForm.name, unitNumber: familyForm.unitNumber, stair: familyForm.stair, floor: familyForm.floor, notes: familyForm.notes, contactEmail: familyForm.contactEmail, customMonthlyQuota: quota }; if (editingFamily) { const updatedFamily = { ...editingFamily, ...payload }; await CondoService.updateFamily(updatedFamily); setFamilies(families.map(f => f.id === updatedFamily.id ? updatedFamily : f)); } else { const newFamily = await CondoService.addFamily(payload); setFamilies([...families, newFamily]); } setShowFamilyModal(false); } catch (e: any) { console.error(e); alert(`Errore: ${e.message || "Impossibile salvare la famiglia."}`); } };
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(activeCondo?.id)); setShowUserModal(false); } catch (e) { alert("Errore nel salvataggio utente"); } };
const handleDeleteUser = async (id: string) => { if(!window.confirm("Eliminare utente?")) return; await CondoService.deleteUser(id); setUsers(users.filter(u => u.id !== id)); };
const openAddNoticeModal = () => { setEditingNotice(null); setNoticeTargetMode('all'); setNoticeForm({ title: '', content: '', type: 'info', link: '', condoId: activeCondo?.id || '', active: true, targetFamilyIds: [] }); setShowNoticeModal(true); };
const openEditNoticeModal = (n: Notice) => { setEditingNotice(n); const isTargeted = n.targetFamilyIds && n.targetFamilyIds.length > 0; setNoticeTargetMode(isTargeted ? 'specific' : 'all'); setNoticeForm({ title: n.title, content: n.content, type: n.type, link: n.link || '', condoId: n.condoId, active: n.active, targetFamilyIds: n.targetFamilyIds || [] }); setShowNoticeModal(true); };
const handleNoticeSubmit = async (e: React.FormEvent) => { e.preventDefault(); try { const payload: Notice = { id: editingNotice ? editingNotice.id : '', ...noticeForm, targetFamilyIds: noticeTargetMode === 'all' ? [] : noticeForm.targetFamilyIds, date: editingNotice ? editingNotice.date : new Date().toISOString() }; await CondoService.saveNotice(payload); setNotices(await CondoService.getNotices(activeCondo?.id)); 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 toggleNoticeFamilyTarget = (familyId: string) => { setNoticeForm(prev => { const current = prev.targetFamilyIds; if (current.includes(familyId)) { return { ...prev, targetFamilyIds: current.filter(id => id !== familyId) }; } else { return { ...prev, targetFamilyIds: [...current, familyId] }; } }); };
const openReadDetails = (noticeId: string) => { setSelectedNoticeId(noticeId); setShowReadDetailsModal(true); };
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 toggleFeature = (key: keyof AppSettings['features']) => {
if (!globalSettings) return;
@@ -577,7 +280,7 @@ export const SettingsPage: React.FC = () => {
if (isPrivileged) {
tabs.push(
{ id: 'general', label: 'Condominio', icon: <Building className="w-4 h-4"/> },
{ id: 'storage', label: 'Cloud & Storage', icon: <HardDrive className="w-4 h-4"/> } // Moved up here
{ id: 'storage', label: 'Cloud & Storage', icon: <HardDrive className="w-4 h-4"/> }
);
if (globalSettings?.features.multiCondo) {
tabs.push({ id: 'condos', label: 'Lista Condomini', icon: <List className="w-4 h-4"/> });
@@ -597,32 +300,46 @@ export const SettingsPage: React.FC = () => {
if (loading) return <div className="p-8 text-center text-slate-400">Caricamento...</div>;
return (
<div className="max-w-5xl mx-auto space-y-6 pb-20">
{/* HEADER */}
<div>
<div className="max-w-6xl mx-auto pb-20">
<div className="mb-6">
<h2 className="text-2xl font-bold text-slate-800">Impostazioni</h2>
<p className="text-slate-500 text-sm md:text-base">{activeCondo ? `Gestione: ${activeCondo.name}` : 'Pannello di Controllo'}</p>
<p className="text-slate-500">{activeCondo ? `Gestione: ${activeCondo.name}` : 'Pannello di Controllo'}</p>
</div>
{/* TABS NAVIGATION */}
<div className="flex border-b border-slate-200 overflow-x-auto no-scrollbar pb-1 gap-1">
<div className="flex flex-col md:flex-row gap-6">
{/* NAVIGATION SIDEBAR / MOBILE SCROLL */}
<div className="md:w-64 flex-shrink-0">
<div className="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden sticky top-4">
<div className="p-4 border-b border-slate-100 md:block hidden">
<h3 className="font-bold text-slate-700 text-sm uppercase tracking-wider">Menu</h3>
</div>
{/* Mobile: Horizontal Scroll, Desktop: Vertical List */}
<div className="flex md:flex-col overflow-x-auto md:overflow-visible no-scrollbar p-2 md:p-2 gap-2">
{tabs.map(tab => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`
px-4 py-3 font-medium text-sm whitespace-nowrap flex items-center gap-2 rounded-t-lg transition-colors
${activeTab === tab.id ? 'text-blue-600 border-b-2 border-blue-600 bg-blue-50/50' : 'text-slate-500 hover:text-slate-700 hover:bg-slate-50'}
flex items-center gap-3 px-4 py-2.5 rounded-lg text-sm font-medium transition-all whitespace-nowrap flex-shrink-0
${activeTab === tab.id
? 'bg-blue-50 text-blue-700 shadow-sm'
: 'text-slate-600 hover:bg-slate-50 hover:text-slate-900'}
`}
>
{tab.icon}{tab.label}
{tab.icon}
<span>{tab.label}</span>
{activeTab === tab.id && <ChevronRight className="w-4 h-4 ml-auto hidden md:block opacity-50"/>}
</button>
))}
</div>
</div>
</div>
{/* CONTENT AREA */}
<div className="flex-1 min-w-0">
{/* PROFILE TAB */}
{activeTab === 'profile' && (
<div className="animate-fade-in bg-white rounded-xl shadow-sm border border-slate-200 p-6 max-w-2xl">
<div className="animate-fade-in bg-white rounded-xl shadow-sm border border-slate-200 p-6">
<h3 className="text-lg font-bold text-slate-800 mb-6 flex items-center gap-2"><UserIcon className="w-5 h-5 text-blue-600" /> Il Tuo Profilo</h3>
<form onSubmit={handleProfileSubmit} className="space-y-5">
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
@@ -649,9 +366,9 @@ export const SettingsPage: React.FC = () => {
</div>
)}
{/* FEATURES TAB (ADMIN ONLY) */}
{/* FEATURES TAB */}
{isSuperAdmin && activeTab === 'features' && globalSettings && (
<div className="animate-fade-in bg-white rounded-xl shadow-sm border border-slate-200 p-6 max-w-3xl">
<div className="animate-fade-in bg-white rounded-xl shadow-sm border border-slate-200 p-6">
<div className="flex items-center justify-between mb-6">
<h3 className="text-lg font-bold text-slate-800 flex items-center gap-2"><LayoutGrid className="w-5 h-5 text-blue-600" /> Funzionalità Piattaforma</h3>
</div>
@@ -704,7 +421,7 @@ export const SettingsPage: React.FC = () => {
{/* STORAGE CONFIG TAB */}
{isPrivileged && activeTab === 'storage' && (
<div className="animate-fade-in bg-white rounded-xl shadow-sm border border-slate-200 p-6 max-w-2xl">
<div className="animate-fade-in bg-white rounded-xl shadow-sm border border-slate-200 p-6">
<h3 className="text-lg font-bold text-slate-800 mb-4 flex items-center gap-2"><Cloud className="w-5 h-5 text-blue-600" /> Configurazione Storage</h3>
<p className="text-sm text-slate-500 mb-6">Scegli dove salvare i documenti caricati.</p>
@@ -773,7 +490,7 @@ export const SettingsPage: React.FC = () => {
{isPrivileged && activeTab === 'general' && (
<div className="space-y-6 animate-fade-in">
{!activeCondo ? <div className="bg-amber-50 border border-amber-200 text-amber-800 p-4 rounded-lg">Nessun condominio selezionato.</div> : (
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 md:p-8 max-w-2xl">
<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6">
<h3 className="text-lg font-bold text-slate-800 mb-4 flex items-center gap-2"><Building className="w-5 h-5 text-blue-600" /> Dati Condominio Corrente</h3>
<form onSubmit={handleGeneralSubmit} className="space-y-5">
<input type="text" value={activeCondo.name} onChange={(e) => setActiveCondo({ ...activeCondo, name: e.target.value })} className="w-full border p-2.5 rounded-lg text-slate-700" placeholder="Nome" required />
@@ -798,7 +515,7 @@ export const SettingsPage: React.FC = () => {
</form>
</div>
)}
{globalSettings && (<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 md:p-8 max-w-2xl"><h3 className="font-bold text-slate-800 mb-2">Anno Fiscale</h3><p className="text-slate-600 mb-4">Corrente: <strong>{globalSettings.currentYear}</strong></p><button type="button" onClick={handleNewYear} className="bg-slate-800 text-white px-4 py-2 rounded-lg text-sm">Chiudi Anno {globalSettings.currentYear}</button></div>)}
{globalSettings && (<div className="bg-white rounded-xl shadow-sm border border-slate-200 p-6 md:p-8"><h3 className="font-bold text-slate-800 mb-2">Anno Fiscale</h3><p className="text-slate-600 mb-4">Corrente: <strong>{globalSettings.currentYear}</strong></p><button type="button" onClick={handleNewYear} className="bg-slate-800 text-white px-4 py-2 rounded-lg text-sm">Chiudi Anno {globalSettings.currentYear}</button></div>)}
</div>
)}
@@ -806,7 +523,7 @@ export const SettingsPage: React.FC = () => {
{isPrivileged && activeTab === 'condos' && (
<div className="space-y-4 animate-fade-in">
<div className="flex justify-between items-center bg-blue-50 p-4 rounded-xl border border-blue-100"><div><h3 className="font-bold text-blue-800">I Tuoi Condomini</h3></div><button onClick={openAddCondoModal} className="bg-blue-600 text-white px-4 py-2 rounded-lg font-medium flex gap-2"><Plus className="w-4 h-4" /> Aggiungi</button></div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
{condos.map(condo => (
<div key={condo.id} className={`bg-white p-5 rounded-xl border shadow-sm relative ${activeCondo?.id === condo.id ? 'border-blue-500 ring-1 ring-blue-500' : 'border-slate-200'}`}>
{activeCondo?.id === condo.id && <div className="absolute top-3 right-3 text-xs bg-blue-100 text-blue-700 px-2 py-0.5 rounded font-bold uppercase">Attivo</div>}
@@ -923,6 +640,8 @@ export const SettingsPage: React.FC = () => {
</div>
</div>
)}
</div>
</div>
{/* Condo Modal */}
{showCondoModal && (