feat: implement federation for inter-instance meeting invitations with dedicated API, UI, and configuration.
This commit is contained in:
@@ -1,18 +1,36 @@
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { LayoutDashboard, Settings, Shield, X, Palette } from 'lucide-react';
|
||||
import { LayoutDashboard, Settings, Shield, X, Palette, Globe } from 'lucide-react';
|
||||
import BrandLogo from './BrandLogo';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { useLanguage } from '../contexts/LanguageContext';
|
||||
import ThemeSelector from './ThemeSelector';
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import api from '../services/api';
|
||||
|
||||
export default function Sidebar({ open, onClose }) {
|
||||
const { user } = useAuth();
|
||||
const { t } = useLanguage();
|
||||
const [themeOpen, setThemeOpen] = useState(false);
|
||||
const [federationCount, setFederationCount] = useState(0);
|
||||
|
||||
// Fetch pending federation invitation count
|
||||
useEffect(() => {
|
||||
const fetchCount = async () => {
|
||||
try {
|
||||
const res = await api.get('/federation/invitations/pending-count');
|
||||
setFederationCount(res.data.count || 0);
|
||||
} catch {
|
||||
// Ignore — federation may not be enabled
|
||||
}
|
||||
};
|
||||
fetchCount();
|
||||
const interval = setInterval(fetchCount, 30000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const navItems = [
|
||||
{ to: '/dashboard', icon: LayoutDashboard, label: t('nav.dashboard') },
|
||||
{ to: '/federation/inbox', icon: Globe, label: t('nav.federation'), badge: federationCount },
|
||||
{ to: '/settings', icon: Settings, label: t('nav.settings') },
|
||||
];
|
||||
|
||||
@@ -21,10 +39,9 @@ export default function Sidebar({ open, onClose }) {
|
||||
}
|
||||
|
||||
const linkClasses = ({ isActive }) =>
|
||||
`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ${
|
||||
isActive
|
||||
? 'bg-th-accent text-th-accent-t shadow-sm'
|
||||
: 'text-th-text-s hover:text-th-text hover:bg-th-hover'
|
||||
`flex items-center gap-3 px-3 py-2.5 rounded-lg text-sm font-medium transition-all duration-200 ${isActive
|
||||
? 'bg-th-accent text-th-accent-t shadow-sm'
|
||||
: 'text-th-text-s hover:text-th-text hover:bg-th-hover'
|
||||
}`;
|
||||
|
||||
return (
|
||||
@@ -60,6 +77,11 @@ export default function Sidebar({ open, onClose }) {
|
||||
>
|
||||
<item.icon size={18} />
|
||||
{item.label}
|
||||
{item.badge > 0 && (
|
||||
<span className="ml-auto px-1.5 py-0.5 rounded-full bg-th-accent text-th-accent-t text-xs font-bold">
|
||||
{item.badge}
|
||||
</span>
|
||||
)}
|
||||
</NavLink>
|
||||
))}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user