Update Layout.tsx
This commit is contained in:
@@ -3,14 +3,17 @@ 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, ReceiptEuro, FileText } from 'lucide-react';
|
||||
import { CondoService } from '../services/mockDb';
|
||||
import { Condo, Notice, AppSettings } from '../types';
|
||||
import { Condo, Notice, AppSettings, BrandingConfig } from '../types';
|
||||
|
||||
export const Layout: React.FC = () => {
|
||||
interface LayoutProps {
|
||||
branding?: BrandingConfig;
|
||||
}
|
||||
|
||||
export const Layout: React.FC<LayoutProps> = ({ branding }) => {
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||
const user = CondoService.getCurrentUser();
|
||||
|
||||
// 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[]>([]);
|
||||
@@ -26,7 +29,6 @@ export const Layout: React.FC = () => {
|
||||
const [ticketBadgeCount, setTicketBadgeCount] = useState(0);
|
||||
|
||||
const fetchContext = async () => {
|
||||
// Fetch global settings to check features
|
||||
try {
|
||||
const globalSettings = await CondoService.getSettings();
|
||||
setSettings(globalSettings);
|
||||
@@ -49,7 +51,7 @@ export const Layout: React.FC = () => {
|
||||
|
||||
// 1. Tickets Badge Logic
|
||||
try {
|
||||
if (settings?.features.tickets || true) { // Check features if available or default
|
||||
if (settings?.features.tickets || true) {
|
||||
const tickets = await CondoService.getTickets();
|
||||
let count = 0;
|
||||
|
||||
@@ -59,7 +61,6 @@ export const Layout: React.FC = () => {
|
||||
const isArchived = t.status === 'RESOLVED' || t.status === 'CLOSED';
|
||||
|
||||
if (isPrivileged) {
|
||||
// Admin/PowerUser: Count new unarchived tickets OR tickets with new comments from users
|
||||
if (isTicketNew && !isArchived) {
|
||||
count++;
|
||||
} else {
|
||||
@@ -71,7 +72,6 @@ export const Layout: React.FC = () => {
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
@@ -85,21 +85,17 @@ export const Layout: React.FC = () => {
|
||||
} catch(e) { console.error("Error calc ticket badges", e); }
|
||||
|
||||
|
||||
// Check for notices & expenses for User (non-privileged mostly, but logic works for all if needed)
|
||||
if (!isPrivileged && active && user) {
|
||||
try {
|
||||
// 2. Check Notices
|
||||
const unread = await CondoService.getUnreadNoticesForUser(user.id, active.id);
|
||||
if (unread.length > 0) {
|
||||
setActiveNotice(unread[0]);
|
||||
}
|
||||
|
||||
// 3. Check New Extraordinary Expenses
|
||||
const myExpenses = await CondoService.getMyExpenses();
|
||||
const lastViewed = localStorage.getItem('lastViewedExpensesTime');
|
||||
const lastViewedTime = lastViewed ? parseInt(lastViewed) : 0;
|
||||
|
||||
// Count expenses created AFTER the last visit
|
||||
const count = myExpenses.filter((e: any) => new Date(e.createdAt).getTime() > lastViewedTime).length;
|
||||
setNewExpensesCount(count);
|
||||
|
||||
@@ -109,12 +105,10 @@ export const Layout: React.FC = () => {
|
||||
|
||||
useEffect(() => {
|
||||
fetchContext();
|
||||
|
||||
// Listen for updates from Settings or Expense views
|
||||
const handleUpdate = () => fetchContext();
|
||||
window.addEventListener('condo-updated', handleUpdate);
|
||||
window.addEventListener('expenses-viewed', handleUpdate);
|
||||
window.addEventListener('tickets-viewed', handleUpdate); // Listen for ticket view
|
||||
window.addEventListener('tickets-viewed', handleUpdate);
|
||||
return () => {
|
||||
window.removeEventListener('condo-updated', handleUpdate);
|
||||
window.removeEventListener('expenses-viewed', handleUpdate);
|
||||
@@ -134,8 +128,6 @@ export const Layout: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
@@ -154,9 +146,12 @@ export const Layout: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Check if notices are actually enabled before showing modal
|
||||
const showNotice = activeNotice && settings?.features.notices;
|
||||
|
||||
// Use props passed from App.tsx directly
|
||||
const appName = branding?.appName || 'CondoPay';
|
||||
const logoUrl = branding?.logoUrl;
|
||||
|
||||
return (
|
||||
<div className="flex h-screen bg-slate-50 overflow-hidden">
|
||||
|
||||
@@ -195,11 +190,15 @@ export const Layout: React.FC = () => {
|
||||
{/* Mobile Header */}
|
||||
<div className="lg:hidden fixed top-0 left-0 right-0 h-16 bg-white border-b border-slate-200 flex items-center justify-between px-4 z-40 shadow-sm">
|
||||
<div className="flex items-center gap-2 overflow-hidden">
|
||||
<div className="bg-blue-600 p-1.5 rounded-lg flex-shrink-0">
|
||||
<Building className="text-white w-5 h-5" />
|
||||
</div>
|
||||
{logoUrl ? (
|
||||
<img src={logoUrl} alt="Logo" className="w-8 h-8 object-contain rounded-lg" />
|
||||
) : (
|
||||
<div className="bg-blue-600 p-1.5 rounded-lg flex-shrink-0">
|
||||
<Building className="text-white w-5 h-5" />
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col min-w-0">
|
||||
<h1 className="font-bold text-slate-800 leading-tight truncate">CondoPay</h1>
|
||||
<h1 className="font-bold text-slate-800 leading-tight truncate">{appName}</h1>
|
||||
{activeCondo && <p className="text-xs text-slate-500 truncate">{activeCondo.name}</p>}
|
||||
</div>
|
||||
</div>
|
||||
@@ -221,10 +220,14 @@ export const Layout: React.FC = () => {
|
||||
{/* Desktop Logo & Condo Switcher */}
|
||||
<div className="p-6 hidden lg:flex flex-col gap-4 border-b border-slate-100">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="bg-blue-600 p-2 rounded-lg">
|
||||
<Building className="text-white w-6 h-6" />
|
||||
</div>
|
||||
<h1 className="font-bold text-xl text-slate-800 tracking-tight">CondoPay</h1>
|
||||
{logoUrl ? (
|
||||
<img src={logoUrl} alt="Logo" className="w-10 h-10 object-contain rounded-xl" />
|
||||
) : (
|
||||
<div className="bg-blue-600 p-2 rounded-lg">
|
||||
<Building className="text-white w-6 h-6" />
|
||||
</div>
|
||||
)}
|
||||
<h1 className="font-bold text-xl text-slate-800 tracking-tight">{appName}</h1>
|
||||
</div>
|
||||
|
||||
{/* Condo Switcher (Privileged Only & MultiCondo Enabled) */}
|
||||
|
||||
Reference in New Issue
Block a user