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 } from 'lucide-react'; import { CondoService } from '../services/mockDb'; import { Condo, Notice, AppSettings } from '../types'; export const Layout: React.FC = () => { const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); const user = CondoService.getCurrentUser(); const isAdmin = user?.role === 'admin' || user?.role === 'poweruser'; const [condos, setCondos] = useState([]); const [activeCondo, setActiveCondo] = useState(undefined); const [showCondoDropdown, setShowCondoDropdown] = useState(false); const [settings, setSettings] = useState(null); // Notice Modal State const [activeNotice, setActiveNotice] = useState(null); const fetchContext = async () => { // Fetch global settings to check features try { const globalSettings = await CondoService.getSettings(); setSettings(globalSettings); if (isAdmin && globalSettings.features.multiCondo) { const list = await CondoService.getCondos(); setCondos(list); } else if (isAdmin) { // If multi-condo disabled, just get the one (which acts as active) const list = await CondoService.getCondos(); setCondos(list); // Store list anyway, though dropdown will be hidden } } catch(e) { console.error("Error fetching settings", e); } const active = await CondoService.getActiveCondo(); setActiveCondo(active); // Check for notices for User // ONLY if notices feature is enabled (which we check inside logic or rely on settings state) // However, `getSettings` is async. For simplicity, we fetch notices and if feature disabled at backend/UI level, it's fine. // Ideally we check `settings?.features.notices` but `settings` might not be set yet. // We'll rely on the UI hiding it, but fetching it doesn't hurt. if (!isAdmin && active && user) { try { const unread = await CondoService.getUnreadNoticesForUser(user.id, active.id); if (unread.length > 0) { // Show the most recent unread notice setActiveNotice(unread[0]); } } catch(e) {} } }; useEffect(() => { fetchContext(); // Listen for updates from Settings const handleCondoUpdate = () => fetchContext(); window.addEventListener('condo-updated', handleCondoUpdate); return () => window.removeEventListener('condo-updated', handleCondoUpdate); }, [isAdmin]); const handleCondoSwitch = (condoId: string) => { CondoService.setActiveCondo(condoId); setShowCondoDropdown(false); }; const handleReadNotice = async () => { if (activeNotice && user) { await CondoService.markNoticeAsRead(activeNotice.id, user.id); setActiveNotice(null); } }; const closeNoticeModal = () => setActiveNotice(null); const navClass = ({ isActive }: { isActive: boolean }) => `flex items-center gap-3 px-4 py-3 rounded-lg transition-all duration-200 ${ isActive ? 'bg-blue-600 text-white shadow-md' : 'text-slate-600 hover:text-slate-900 hover:bg-slate-100' }`; const closeMenu = () => setIsMobileMenuOpen(false); const NoticeIcon = ({type}: {type: string}) => { switch(type) { case 'warning': return ; case 'maintenance': return ; case 'event': return ; default: return ; } }; // Check if notices are actually enabled before showing modal const showNotice = activeNotice && settings?.features.notices; return (
{/* Active Notice Modal */} {showNotice && activeNotice && (

{activeNotice.title}

{new Date(activeNotice.date).toLocaleDateString()}

{activeNotice.content} {activeNotice.link && ( )}
)} {/* Mobile Header */}

CondoPay

{activeCondo &&

{activeCondo.name}

}
{/* Sidebar Overlay for Mobile */} {isMobileMenuOpen && (
)} {/* Sidebar Navigation */} {/* Main Content Area */}
); };