import { useState } from 'react'; import { Settings, LogOut, ExternalLink, User, Loader2, BookOpen, MessageSquare, CreditCard, } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; import { useAuth } from '@/context/AuthContext'; import { useLicense } from '@/context/LicenseContext'; import { apiFetch } from '@/lib/api'; import { toast } from '@/components/ui/toast-store'; import { cn } from '@/lib/utils'; import { TierBadge } from './TierBadge'; interface UserProfileDropdownProps { onOpenSettings: () => void; } function getInitials(username: string | undefined): string { if (!username) return ''; const trimmed = username.trim(); if (!trimmed) return ''; const parts = trimmed.split(/[\s._-]+/).filter(Boolean); if (parts.length >= 2) { return (parts[0][0] + parts[1][0]).toUpperCase(); } return trimmed.slice(0, 2).toUpperCase(); } export function UserProfileDropdown({ onOpenSettings }: UserProfileDropdownProps) { const { logout, user, isAdmin } = useAuth(); const { license } = useLicense(); const [billingLoading, setBillingLoading] = useState(false); const [open, setOpen] = useState(false); const closeMenu = () => setOpen(false); const handleOpenSettings = () => { closeMenu(); onOpenSettings(); }; const handleLogout = () => { closeMenu(); logout(); }; const openBillingPortal = async () => { setBillingLoading(true); try { const res = await apiFetch('/license/billing-portal', { localOnly: true }); const data = await res.json().catch(() => ({})); if (res.ok && data.url) { window.open(data.url, '_blank'); return; } toast.error(data?.error || data?.message || data?.data?.error || 'Something went wrong.'); } catch { toast.error('Failed to open billing portal.'); } finally { setBillingLoading(false); closeMenu(); } }; const showBilling = license?.status === 'active' && !license?.isLifetime; const initials = getInitials(user?.username); const roleLabel = user?.role; return ( {initials ? initials : } {/* Identity header */} {initials ? ( {initials} ) : ( )} {user?.username ?? 'admin'} {roleLabel ? ( {roleLabel} ) : null} {/* Navigation strip */} {showBilling ? ( ) : null} {/* Logout */} Log Out ); } interface MenuRowProps { icon: LucideIcon; label: string; onClick?: () => void; href?: string; external?: boolean; disabled?: boolean; loading?: boolean; trailingIcon?: LucideIcon; } function MenuRow({ icon: Icon, label, onClick, href, external, disabled, loading, trailingIcon, }: MenuRowProps) { const TrailingIcon = trailingIcon ?? (external ? ExternalLink : undefined); const classes = cn( 'flex w-full items-center gap-2.5 px-[var(--density-row-x)] py-[var(--density-row-y)] text-left text-sm text-stat-value transition-colors hover:bg-accent focus-visible:bg-accent focus-visible:outline-none', disabled && 'pointer-events-none opacity-50', ); const leadingIcon = loading ? ( ) : ( ); const body = ( <> {leadingIcon} {label} {TrailingIcon ? ( ) : null} > ); if (href) { return ( {body} ); } return ( {body} ); }
{user?.username ?? 'admin'}