Spaces:
Running
Running
File size: 8,107 Bytes
afd56bc | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | import React, { useState } from 'react';
import { Building2, FileText, Settings, Plus, Sparkles, TrendingUp, Shield } from 'lucide-react';
import UsageCard from './UsageCard';
import PricingModal from './PricingModal';
import WizardModal from './WizardModal';
import { NavLink, useLocation } from 'react-router-dom';
import { UserButton, useUser } from '@clerk/clerk-react';
import { useMe } from '../../hooks/useMe';
const Sidebar: React.FC = () => {
const [showPricing, setShowPricing] = useState(false);
const [showWizard, setShowWizard] = useState(false);
const location = useLocation();
const { user } = useUser();
const { data: me } = useMe();
const isProjectWorkspace = location.pathname.startsWith('/projects/');
// tier hierarchy: me (DB) > Clerk metadata > 'free'
const tier = me?.tier ?? (user?.publicMetadata?.stripe_subscription as string) ?? 'free';
const isPro = tier === 'pro' || tier === 'business';
const tierLabel = tier.toUpperCase();
const tierColor = tier === 'business' ? '#f59e0b' : tier === 'pro' ? 'var(--accent-green)' : '#6b7280';
return (
<>
<div className="sidebar-header">
<div className="sidebar-logo" style={{ background: 'linear-gradient(135deg, var(--accent-green), var(--accent-blue))', color: '#000' }}>GF</div>
<div>
<h2 style={{ fontSize: '1.2rem', fontWeight: 800, color: 'var(--text-primary)' }}>GrantForge</h2>
<p style={{ fontSize: '0.8rem', color: 'var(--accent-green)', fontWeight: 'bold' }}>Enterprise <span style={{color:'var(--text-muted)'}}>v2.0</span></p>
</div>
</div>
<div className="sidebar-content sidebar-menu">
<UsageCard onUpgradeClick={() => setShowPricing(true)} compact={isProjectWorkspace} />
<div className="glass-card user-profile-menu" style={{ padding: isProjectWorkspace ? '1rem' : '1.8rem' }}>
<div className="card-title">
Profil Doradcy
<Settings size={14} style={{ cursor: 'pointer' }} />
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem', marginTop: '1rem' }}>
<UserButton afterSignOutUrl="/" appearance={{ elements: { avatarBox: { width: '45px', height: '45px' } } }} />
<div style={{ flex: 1, minWidth: 0 }}>
<h3 style={{ fontSize: '1rem', margin: '0 0 0.3rem 0', color: 'var(--text-primary)', overflow: 'hidden', wordWrap: 'break-word', whiteSpace: 'normal', lineHeight: '1.4' }}>
{user ? `${user.firstName || ''} ${user.lastName || ''}`.trim() || user.primaryEmailAddress?.emailAddress : 'Zaloguj się'}
</h3>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
<span style={{
color: tierColor,
fontSize: '0.7rem',
fontWeight: 700,
textTransform: 'uppercase',
letterSpacing: '0.08em',
background: `${tierColor}18`,
border: `1px solid ${tierColor}40`,
padding: '0.15rem 0.5rem',
borderRadius: '4px',
display: 'flex',
alignItems: 'center',
gap: '0.3rem',
}}
>
{isPro && <span style={{ width: '6px', height: '6px', borderRadius: '50%', background: tierColor, display: 'inline-block', boxShadow: `0 0 8px ${tierColor}` }} />}
{tierLabel}
</span>
</div>
</div>
</div>
</div>
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem', marginTop: '1rem' }}>
<div className="card-title" style={{ marginTop: '1rem' }}>Akcje i Nawigacja</div>
<button
className="btn hover-lift new-project-btn tour-step-new-project"
style={{
width: '100%',
background: 'linear-gradient(90deg, var(--accent-green), #3b82f6)',
boxShadow: '0 0 20px rgba(16,185,129,0.3)',
border: 'none',
color: '#000',
fontWeight: 800,
padding: '1rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '0.8rem',
marginBottom: '1rem'
}}
onClick={() => setShowWizard(true)}
>
<Plus size={18} /> Nowy Projekt Dotacyjny
</button>
<NavLink to="/projects" className={({isActive}) => `btn projects-list ${isActive ? 'btn-secondary' : ''}`} style={({isActive}) => ({ justifyContent: 'flex-start', background: 'transparent', border: 'none', color: isActive ? '#fff' : 'var(--text-secondary)' })}>
<FileText size={16} /> Moje Projekty
</NavLink>
<NavLink to="/nabory" className={({isActive}) => `btn ${isActive ? 'btn-secondary' : ''}`} style={({isActive}) => ({ justifyContent: 'flex-start', background: 'transparent', border: 'none', color: isActive ? '#fff' : 'var(--text-secondary)' })}>
<TrendingUp size={16} /> Aktywne Nabory
</NavLink>
<NavLink to="/about" className={({isActive}) => `btn ${isActive ? 'btn-secondary' : ''}`} style={({isActive}) => ({ justifyContent: 'flex-start', background: 'transparent', border: 'none', color: isActive ? '#fff' : 'var(--text-secondary)' })}>
<Sparkles size={16} /> O Programie
</NavLink>
<NavLink to="/help" className={({isActive}) => `btn ${isActive ? 'btn-secondary' : ''}`} style={({isActive}) => ({ justifyContent: 'flex-start', background: 'transparent', border: 'none', color: isActive ? '#fff' : 'var(--text-secondary)' })}>
<Building2 size={16} /> Pomoc
</NavLink>
<NavLink to="/settings" className={({isActive}) => `btn ${isActive ? 'btn-secondary' : ''}`} style={({isActive}) => ({ justifyContent: 'flex-start', background: 'transparent', border: 'none', color: isActive ? '#fff' : 'var(--text-secondary)' })}>
<Settings size={16} /> Ustawienia
</NavLink>
<NavLink to="/admin" className={({isActive}) => `btn ${isActive ? 'btn-secondary' : ''}`} style={({isActive}) => ({ justifyContent: 'flex-start', background: 'transparent', border: 'none', color: isActive ? '#f59e0b' : 'var(--text-secondary)' })}>
<Shield size={16} /> Admin Panel
</NavLink>
<NavLink to="/beta" className={({isActive}) => `btn ${isActive ? 'btn-secondary' : ''}`} style={({isActive}) => ({ justifyContent: 'flex-start', background: 'transparent', border: 'none', color: isActive ? '#10b981' : 'var(--text-secondary)' })}>
<Sparkles size={16} /> Beta Guide
</NavLink>
</div>
</div>
{showPricing && <PricingModal onClose={() => setShowPricing(false)} />}
{showWizard && <WizardModal onClose={() => setShowWizard(false)} />}
</>
);
};
export default Sidebar;
|