Update Layout.tsx

This commit is contained in:
2025-12-11 22:27:46 +01:00
committed by GitHub
parent 669f55a14d
commit ffebddaf33

View File

@@ -8,7 +8,10 @@ import { Condo, Notice, AppSettings } from '../types';
export const Layout: React.FC = () => { export const Layout: React.FC = () => {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const user = CondoService.getCurrentUser(); const user = CondoService.getCurrentUser();
const isAdmin = user?.role === 'admin' || user?.role === 'poweruser';
// Logic: "isPrivileged" includes Admin AND PowerUser.
// This allows PowerUsers to see Reports and other admin-like features.
const isPrivileged = user?.role === 'admin' || user?.role === 'poweruser';
const [condos, setCondos] = useState<Condo[]>([]); const [condos, setCondos] = useState<Condo[]>([]);
const [activeCondo, setActiveCondo] = useState<Condo | undefined>(undefined); const [activeCondo, setActiveCondo] = useState<Condo | undefined>(undefined);
@@ -28,10 +31,10 @@ export const Layout: React.FC = () => {
const globalSettings = await CondoService.getSettings(); const globalSettings = await CondoService.getSettings();
setSettings(globalSettings); setSettings(globalSettings);
if (isAdmin && globalSettings.features.multiCondo) { if (isPrivileged && globalSettings.features.multiCondo) {
const list = await CondoService.getCondos(); const list = await CondoService.getCondos();
setCondos(list); setCondos(list);
} else if (isAdmin) { } else if (isPrivileged) {
const list = await CondoService.getCondos(); const list = await CondoService.getCondos();
setCondos(list); setCondos(list);
} }
@@ -55,18 +58,13 @@ export const Layout: React.FC = () => {
const isTicketNew = ticketDate > lastViewedTickets; const isTicketNew = ticketDate > lastViewedTickets;
const isArchived = t.status === 'RESOLVED' || t.status === 'CLOSED'; const isArchived = t.status === 'RESOLVED' || t.status === 'CLOSED';
if (isAdmin) { if (isPrivileged) {
// Admin: Count new unarchived tickets OR tickets with new comments from users // Admin/PowerUser: Count new unarchived tickets OR tickets with new comments from users
if (isTicketNew && !isArchived) { if (isTicketNew && !isArchived) {
count++; count++;
} else { } else {
// Check for new comments from users
// Optimization: In a real app we'd need a lighter query.
// Here we iterate because we have the data or fetch lightly.
// Assuming getTickets includes basic info or we need to check updatedAt
const updatedDate = new Date(t.updatedAt).getTime(); const updatedDate = new Date(t.updatedAt).getTime();
if (updatedDate > lastViewedTickets) { if (updatedDate > lastViewedTickets) {
// Deep check: fetch comments only if recently updated
const comments = await CondoService.getTicketComments(t.id); const comments = await CondoService.getTicketComments(t.id);
const hasNewUserReply = comments.some(c => new Date(c.createdAt).getTime() > lastViewedTickets && c.userId !== user?.id); const hasNewUserReply = comments.some(c => new Date(c.createdAt).getTime() > lastViewedTickets && c.userId !== user?.id);
if (hasNewUserReply) count++; if (hasNewUserReply) count++;
@@ -87,8 +85,8 @@ export const Layout: React.FC = () => {
} catch(e) { console.error("Error calc ticket badges", e); } } catch(e) { console.error("Error calc ticket badges", e); }
// Check for notices & expenses for User // Check for notices & expenses for User (non-privileged mostly, but logic works for all if needed)
if (!isAdmin && active && user) { if (!isPrivileged && active && user) {
try { try {
// 2. Check Notices // 2. Check Notices
const unread = await CondoService.getUnreadNoticesForUser(user.id, active.id); const unread = await CondoService.getUnreadNoticesForUser(user.id, active.id);
@@ -122,7 +120,7 @@ export const Layout: React.FC = () => {
window.removeEventListener('expenses-viewed', handleUpdate); window.removeEventListener('expenses-viewed', handleUpdate);
window.removeEventListener('tickets-viewed', handleUpdate); window.removeEventListener('tickets-viewed', handleUpdate);
}; };
}, [isAdmin]); }, [isPrivileged]);
const handleCondoSwitch = (condoId: string) => { const handleCondoSwitch = (condoId: string) => {
CondoService.setActiveCondo(condoId); CondoService.setActiveCondo(condoId);
@@ -229,8 +227,8 @@ export const Layout: React.FC = () => {
<h1 className="font-bold text-xl text-slate-800 tracking-tight">CondoPay</h1> <h1 className="font-bold text-xl text-slate-800 tracking-tight">CondoPay</h1>
</div> </div>
{/* Condo Switcher (Admin Only & MultiCondo Enabled) */} {/* Condo Switcher (Privileged Only & MultiCondo Enabled) */}
{isAdmin && settings?.features.multiCondo && ( {isPrivileged && settings?.features.multiCondo && (
<div className="relative mt-2"> <div className="relative mt-2">
<div className="flex items-center gap-1.5 mb-2 text-xs font-bold text-slate-400 uppercase tracking-wider"> <div className="flex items-center gap-1.5 mb-2 text-xs font-bold text-slate-400 uppercase tracking-wider">
<LayoutDashboard className="w-3 h-3" /> <LayoutDashboard className="w-3 h-3" />
@@ -260,8 +258,8 @@ export const Layout: React.FC = () => {
)} )}
</div> </div>
)} )}
{/* Static info if not multi-condo or not admin */} {/* Static info if not multi-condo or not privileged */}
{(!isAdmin || (isAdmin && !settings?.features.multiCondo)) && activeCondo && ( {(!isPrivileged || (isPrivileged && !settings?.features.multiCondo)) && activeCondo && (
<div className="px-3 py-2 bg-slate-50 border border-slate-100 rounded-lg text-sm text-slate-500 truncate"> <div className="px-3 py-2 bg-slate-50 border border-slate-100 rounded-lg text-sm text-slate-500 truncate">
{activeCondo.name} {activeCondo.name}
</div> </div>
@@ -275,7 +273,7 @@ export const Layout: React.FC = () => {
</div> </div>
{/* Mobile Condo Switcher */} {/* Mobile Condo Switcher */}
{isAdmin && settings?.features.multiCondo && ( {isPrivileged && settings?.features.multiCondo && (
<div className="lg:hidden px-4 py-2 border-b border-slate-100"> <div className="lg:hidden px-4 py-2 border-b border-slate-100">
<p className="text-xs font-semibold text-slate-400 uppercase tracking-wider mb-2 flex items-center gap-2"> <p className="text-xs font-semibold text-slate-400 uppercase tracking-wider mb-2 flex items-center gap-2">
<LayoutDashboard className="w-3 h-3" /> <LayoutDashboard className="w-3 h-3" />
@@ -301,8 +299,8 @@ export const Layout: React.FC = () => {
<span className="font-medium">Famiglie</span> <span className="font-medium">Famiglie</span>
</NavLink> </NavLink>
{/* Condo Financials - Admin or Enabled User */} {/* Condo Financials - Admin/PowerUser or Enabled User */}
{(isAdmin || settings?.features.condoFinancialsView) && ( {(isPrivileged || settings?.features.condoFinancialsView) && (
<NavLink to="/financials" className={navClass} onClick={closeMenu}> <NavLink to="/financials" className={navClass} onClick={closeMenu}>
<ReceiptEuro className="w-5 h-5" /> <ReceiptEuro className="w-5 h-5" />
<span className="font-medium">Spese Condominio</span> <span className="font-medium">Spese Condominio</span>
@@ -315,7 +313,7 @@ export const Layout: React.FC = () => {
<div className="flex items-center justify-between w-full"> <div className="flex items-center justify-between w-full">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Briefcase className="w-5 h-5" /> <Briefcase className="w-5 h-5" />
<span className="font-medium">{isAdmin ? 'Spese Straordinarie' : 'Le Mie Spese Extra'}</span> <span className="font-medium">{isPrivileged ? 'Spese Straordinarie' : 'Le Mie Spese Extra'}</span>
</div> </div>
{newExpensesCount > 0 && ( {newExpensesCount > 0 && (
<span className="bg-red-500 text-white text-[10px] font-bold px-1.5 h-5 min-w-[20px] rounded-full flex items-center justify-center shadow-sm"> <span className="bg-red-500 text-white text-[10px] font-bold px-1.5 h-5 min-w-[20px] rounded-full flex items-center justify-center shadow-sm">
@@ -326,8 +324,8 @@ export const Layout: React.FC = () => {
</NavLink> </NavLink>
)} )}
{/* Privileged Links */} {/* Privileged Links (Admin & PowerUser) */}
{isAdmin && settings?.features.reports && ( {isPrivileged && settings?.features.reports && (
<NavLink to="/reports" className={navClass} onClick={closeMenu}> <NavLink to="/reports" className={navClass} onClick={closeMenu}>
<PieChart className="w-5 h-5" /> <PieChart className="w-5 h-5" />
<span className="font-medium">Reportistica</span> <span className="font-medium">Reportistica</span>