b9316552c2
- Add logo_url column to nodes table for custom branding - Refactor bots table to use owner_id foreign key relationship with users - Add is_bot and bot_owner_id columns to users table for bot account tracking - Add bot_id foreign key to posts table for bot-generated content tracking - Create database indexes on owner_id, bot_id, is_bot, and bot_owner_id for query performance - Remove bot handle, bio, avatar_url, and cryptographic keys from bots table (moved to user accounts) - Update bot_content_sources schema and remove fetch_interval_minutes column - Fix bot_content_items foreign key constraint with set null on delete - Remove hardcoded NODE_NAME and NODE_DESCRIPTION from environment configuration - Update admin panel, bot settings, and layout components to support new schema - Add AccentColorContext and ToastContext for improved UI state management - Update PostCard, Sidebar, RightSidebar, and LayoutWrapper components for context integration
102 lines
4.5 KiB
TypeScript
102 lines
4.5 KiB
TypeScript
'use client';
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import Link from 'next/link';
|
|
import Image from 'next/image';
|
|
import { usePathname } from 'next/navigation';
|
|
import { useAuth } from '@/lib/contexts/AuthContext';
|
|
import { HomeIcon, SearchIcon, BellIcon, UserIcon, ShieldIcon, SettingsIcon, BotIcon } from './Icons';
|
|
import { formatFullHandle } from '@/lib/utils/handle';
|
|
|
|
export function Sidebar() {
|
|
const { user, isAdmin } = useAuth();
|
|
const pathname = usePathname();
|
|
const [customLogoUrl, setCustomLogoUrl] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
fetch('/api/node')
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
if (data.logoUrl) {
|
|
setCustomLogoUrl(data.logoUrl);
|
|
}
|
|
})
|
|
.catch(() => {});
|
|
}, []);
|
|
|
|
// Home is exact match
|
|
const isHome = pathname === '/';
|
|
|
|
return (
|
|
<aside className="sidebar">
|
|
<Link href="/" className="logo">
|
|
{customLogoUrl ? (
|
|
<img src={customLogoUrl} alt="Logo" style={{ maxWidth: '200px', maxHeight: '50px', objectFit: 'contain' }} />
|
|
) : (
|
|
<Image src="/logotext.png" alt="Synapsis" width={185} height={42} priority />
|
|
)}
|
|
</Link>
|
|
<nav>
|
|
<Link href="/" className={`nav-item ${isHome ? 'active' : ''}`}>
|
|
<HomeIcon />
|
|
<span>Home</span>
|
|
</Link>
|
|
<Link href="/explore" className={`nav-item ${pathname?.startsWith('/explore') ? 'active' : ''}`}>
|
|
<SearchIcon />
|
|
<span>Explore</span>
|
|
</Link>
|
|
<Link href="/notifications" className={`nav-item ${pathname?.startsWith('/notifications') ? 'active' : ''}`}>
|
|
<BellIcon />
|
|
<span>Notifications</span>
|
|
</Link>
|
|
{user && (
|
|
<Link href="/settings/bots" className={`nav-item ${pathname?.startsWith('/settings/bots') ? 'active' : ''}`}>
|
|
<BotIcon />
|
|
<span>Bots</span>
|
|
</Link>
|
|
)}
|
|
{user ? (
|
|
<Link href={`/${user.handle}`} className={`nav-item ${pathname === '/' + user.handle ? 'active' : ''}`}>
|
|
<UserIcon />
|
|
<span>Profile</span>
|
|
</Link>
|
|
) : (
|
|
<Link href="/login" className={`nav-item ${pathname === '/login' ? 'active' : ''}`}>
|
|
<UserIcon />
|
|
<span>Login</span>
|
|
</Link>
|
|
)}
|
|
{isAdmin && (
|
|
<Link href="/admin" className={`nav-item ${pathname?.startsWith('/admin') ? 'active' : ''}`}>
|
|
<ShieldIcon />
|
|
<span>Admin</span>
|
|
</Link>
|
|
)}
|
|
{user && (
|
|
<Link href="/settings" className={`nav-item ${pathname?.startsWith('/settings') ? 'active' : ''}`}>
|
|
<SettingsIcon />
|
|
<span>Settings</span>
|
|
</Link>
|
|
)}
|
|
</nav>
|
|
{user && (
|
|
<div style={{ marginTop: 'auto', paddingTop: '16px' }}>
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', minWidth: 0 }}>
|
|
<div className="avatar avatar-sm" style={{ flexShrink: 0 }}>
|
|
{user.avatarUrl ? (
|
|
<img src={user.avatarUrl} alt={user.displayName} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
|
|
) : (
|
|
(user.displayName?.charAt(0) || user.handle.charAt(0)).toUpperCase()
|
|
)}
|
|
</div>
|
|
<div style={{ minWidth: 0 }}>
|
|
<div style={{ fontWeight: 600, fontSize: '14px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{user.displayName}</div>
|
|
<div style={{ color: 'var(--foreground-tertiary)', fontSize: '13px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{formatFullHandle(user.handle)}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</aside>
|
|
);
|
|
}
|