Update Layout.tsx
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user