diff --git a/components/Layout.tsx b/components/Layout.tsx index 382a5c1..660278b 100644 --- a/components/Layout.tsx +++ b/components/Layout.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import { NavLink, Outlet } from 'react-router-dom'; import { Users, Settings, Building, LogOut, Menu, X, ChevronDown, Check, LayoutDashboard, Megaphone, Info, AlertTriangle, Hammer, Calendar, MessageSquareWarning, PieChart, Briefcase } from 'lucide-react'; -import { CondoService } from '../services/mockDb'; +import { CondoService } from '../services/api'; import { Condo, Notice, AppSettings } from '../types'; export const Layout: React.FC = () => { @@ -18,6 +18,9 @@ export const Layout: React.FC = () => { // Notifications const [activeNotice, setActiveNotice] = useState(null); const [hasNewExpenses, setHasNewExpenses] = useState(false); + + // Ticket Badges + const [ticketBadgeCount, setTicketBadgeCount] = useState(0); const fetchContext = async () => { // Fetch global settings to check features @@ -37,16 +40,63 @@ export const Layout: React.FC = () => { const active = await CondoService.getActiveCondo(); setActiveCondo(active); + // --- NOTIFICATION LOGIC --- + const lastViewedTicketsStr = localStorage.getItem('lastViewedTickets'); + const lastViewedTickets = lastViewedTicketsStr ? parseInt(lastViewedTicketsStr) : 0; + + // 1. Tickets Badge Logic + try { + if (settings?.features.tickets || true) { // Check features if available or default + const tickets = await CondoService.getTickets(); + let count = 0; + + for (const t of tickets) { + const ticketDate = new Date(t.createdAt).getTime(); + const isTicketNew = ticketDate > lastViewedTickets; + const isArchived = t.status === 'RESOLVED' || t.status === 'CLOSED'; + + if (isAdmin) { + // Admin: Count new unarchived tickets OR tickets with new comments from users + if (isTicketNew && !isArchived) { + count++; + } 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(); + if (updatedDate > lastViewedTickets) { + // Deep check: fetch comments only if recently updated + const comments = await CondoService.getTicketComments(t.id); + const hasNewUserReply = comments.some(c => new Date(c.createdAt).getTime() > lastViewedTickets && c.userId !== user?.id); + if (hasNewUserReply) count++; + } + } + } else { + // User: Count tickets with new comments from Admin (or others) + const updatedDate = new Date(t.updatedAt).getTime(); + if (updatedDate > lastViewedTickets) { + const comments = await CondoService.getTicketComments(t.id); + const hasNewReply = comments.some(c => new Date(c.createdAt).getTime() > lastViewedTickets && c.userId !== user?.id); + if (hasNewReply) count++; + } + } + } + setTicketBadgeCount(count); + } + } catch(e) { console.error("Error calc ticket badges", e); } + + // Check for notices & expenses for User if (!isAdmin && active && user) { try { - // 1. Check Notices + // 2. Check Notices const unread = await CondoService.getUnreadNoticesForUser(user.id, active.id); if (unread.length > 0) { setActiveNotice(unread[0]); } - // 2. Check New Extraordinary Expenses + // 3. Check New Extraordinary Expenses const myExpenses = await CondoService.getMyExpenses(); const lastViewed = localStorage.getItem('lastViewedExpensesTime'); const lastViewedTime = lastViewed ? parseInt(lastViewed) : 0; @@ -65,10 +115,12 @@ export const Layout: React.FC = () => { // Listen for updates from Settings or Expense views const handleUpdate = () => fetchContext(); window.addEventListener('condo-updated', handleUpdate); - window.addEventListener('expenses-viewed', handleUpdate); // Listen for manual trigger when user views page + window.addEventListener('expenses-viewed', handleUpdate); + window.addEventListener('tickets-viewed', handleUpdate); // Listen for ticket view return () => { window.removeEventListener('condo-updated', handleUpdate); window.removeEventListener('expenses-viewed', handleUpdate); + window.removeEventListener('tickets-viewed', handleUpdate); }; }, [isAdmin]); @@ -276,8 +328,17 @@ export const Layout: React.FC = () => { {/* Hide Tickets if disabled */} {settings?.features.tickets && ( - - Segnalazioni +
+
+ + Segnalazioni +
+ {ticketBadgeCount > 0 && ( + + {ticketBadgeCount > 99 ? '99+' : ticketBadgeCount} + + )} +
)}