{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"profile-dropdown","type":"registry:component","title":"Profile Dropdown","description":"Avatar button with profile, settings, and sign-out menu. Manages its own Supabase auth state.","version":"0.1.0","status":"alpha","registryDependencies":["avatar","button","dropdown-menu"],"files":[{"path":"src/components/blocks/profile-dropdown.tsx","type":"registry:component","content":"'use client'\n\nimport type { ReactNode } from 'react'\nimport Link from 'next/link'\nimport { useRouter } from 'next/navigation'\nimport { useEffect, useState } from 'react'\nimport {\n  BarChart3Icon,\n  DownloadIcon,\n  LogInIcon,\n  LogOutIcon,\n  SettingsIcon,\n  UserIcon,\n  UsersIcon,\n  WandSparklesIcon,\n} from 'lucide-react'\nimport { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'\nimport { Button } from '@/components/ui/button'\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '@/components/ui/dropdown-menu'\nimport { createClient } from '@/lib/supabase/client'\n\nfunction hasAdminAccess(user: {\n  app_metadata?: Record<string, unknown>\n  user_metadata?: Record<string, unknown>\n}): boolean {\n  const roleCandidates = [\n    user.app_metadata?.role,\n    user.user_metadata?.role,\n    user.app_metadata?.roles,\n    user.user_metadata?.roles,\n  ]\n  return roleCandidates.some((candidate) => {\n    if (typeof candidate === 'string') return candidate.toLowerCase() === 'admin'\n    if (Array.isArray(candidate)) {\n      return candidate.some((r) => typeof r === 'string' && r.toLowerCase() === 'admin')\n    }\n    return false\n  })\n}\n\ninterface ProfileDropdownProps {\n  trigger?: ReactNode\n  defaultOpen?: boolean\n  align?: 'start' | 'center' | 'end'\n  loginRedirect?: string\n}\n\nexport function ProfileDropdown({\n  trigger,\n  defaultOpen,\n  align = 'end',\n  loginRedirect,\n}: ProfileDropdownProps) {\n  const router = useRouter()\n  const [isAuthenticated, setIsAuthenticated] = useState(false)\n  const [showAdminSection, setShowAdminSection] = useState(false)\n  const [avatarUrl, setAvatarUrl] = useState('')\n  const [email, setEmail] = useState('')\n  const [displayName, setDisplayName] = useState('')\n\n  useEffect(() => {\n    let mounted = true\n\n    const loadUser = async () => {\n      const supabase = createClient()\n      const {\n        data: { user },\n      } = await supabase.auth.getUser()\n\n      if (mounted) {\n        setIsAuthenticated(Boolean(user))\n        setShowAdminSection(user ? hasAdminAccess(user) : false)\n        setAvatarUrl(\n          typeof user?.user_metadata?.avatar_url === 'string'\n            ? user.user_metadata.avatar_url\n            : '',\n        )\n        setEmail(user?.email ?? '')\n        setDisplayName(\n          typeof user?.user_metadata?.full_name === 'string'\n            ? user.user_metadata.full_name\n            : (user?.email ?? ''),\n        )\n      }\n    }\n\n    void loadUser()\n    return () => {\n      mounted = false\n    }\n  }, [])\n\n  const handleSignOut = async () => {\n    const supabase = createClient()\n    await supabase.auth.signOut()\n    router.push('/login')\n    router.refresh()\n  }\n\n  const initials = email ? email.slice(0, 2).toUpperCase() : 'U'\n\n  if (!isAuthenticated) {\n    const next = loginRedirect ? `?next=${encodeURIComponent(loginRedirect)}` : ''\n    return (\n      <Button variant=\"ghost\" size=\"sm\" asChild>\n        <Link href={`/login${next}`}>\n          <LogInIcon className=\"h-4 w-4\" />\n          Login\n        </Link>\n      </Button>\n    )\n  }\n\n  const defaultTrigger = (\n    <Button\n      variant=\"ghost\"\n      className=\"relative h-8 w-8 rounded-full\"\n      aria-label=\"Profile menu\"\n    >\n      <Avatar className=\"h-8 w-8\">\n        <AvatarImage src={avatarUrl} alt=\"User avatar\" />\n        <AvatarFallback>{initials}</AvatarFallback>\n      </Avatar>\n    </Button>\n  )\n\n  return (\n    <DropdownMenu defaultOpen={defaultOpen}>\n      <DropdownMenuTrigger asChild>{trigger ?? defaultTrigger}</DropdownMenuTrigger>\n      <DropdownMenuContent className=\"w-72\" align={align}>\n        {/* User card */}\n        <DropdownMenuLabel className=\"flex items-center gap-4 px-4 py-2.5 font-normal\">\n          <div className=\"relative\">\n            <Avatar className=\"size-10\">\n              <AvatarImage src={avatarUrl} alt=\"User avatar\" />\n              <AvatarFallback>{initials}</AvatarFallback>\n            </Avatar>\n            <span className=\"absolute bottom-0 right-0 block size-2.5 rounded-full bg-green-500 ring-2 ring-card\" />\n          </div>\n          <div className=\"flex flex-1 flex-col items-start\">\n            <span className=\"text-base font-semibold text-foreground leading-tight\">\n              {displayName}\n            </span>\n            <span className=\"text-sm text-muted-foreground\">{email}</span>\n          </div>\n        </DropdownMenuLabel>\n\n        <DropdownMenuSeparator />\n\n        {/* Account */}\n        <DropdownMenuGroup>\n          <DropdownMenuItem className=\"px-4 py-2.5 text-base\" asChild>\n            <Link href=\"/profile\">\n              <UserIcon className=\"size-5 text-foreground\" />\n              <span>My profile</span>\n            </Link>\n          </DropdownMenuItem>\n          <DropdownMenuItem className=\"px-4 py-2.5 text-base\" asChild>\n            <Link href=\"/admin/settings\">\n              <SettingsIcon className=\"size-5 text-foreground\" />\n              <span>Settings</span>\n            </Link>\n          </DropdownMenuItem>\n        </DropdownMenuGroup>\n\n        {showAdminSection && <DropdownMenuSeparator />}\n\n        {/* Brand Portal — admin only */}\n        {showAdminSection && (\n        <DropdownMenuGroup>\n          <DropdownMenuItem className=\"px-4 py-2.5 text-base\" asChild>\n            <Link href=\"/admin/users\">\n              <UsersIcon className=\"size-5 text-foreground\" />\n              <span>Manage users</span>\n            </Link>\n          </DropdownMenuItem>\n          <DropdownMenuItem className=\"px-4 py-2.5 text-base\" asChild>\n            <Link href=\"/admin/analytics\">\n              <BarChart3Icon className=\"size-5 text-foreground\" />\n              <span>Analytics</span>\n            </Link>\n          </DropdownMenuItem>\n          <DropdownMenuItem className=\"px-4 py-2.5 text-base\" asChild>\n            <Link href=\"/theme-generator\">\n              <WandSparklesIcon className=\"size-5 text-foreground\" />\n              <span>Theme generator</span>\n            </Link>\n          </DropdownMenuItem>\n          <DropdownMenuItem className=\"px-4 py-2.5 text-base\" asChild>\n            <Link href=\"/export\">\n              <DownloadIcon className=\"size-5 text-foreground\" />\n              <span>Export brand guide</span>\n            </Link>\n          </DropdownMenuItem>\n        </DropdownMenuGroup>\n        )}\n\n        <DropdownMenuSeparator />\n\n        <DropdownMenuItem\n          variant=\"destructive\"\n          className=\"px-4 py-2.5 text-base\"\n          onClick={handleSignOut}\n        >\n          <LogOutIcon className=\"size-5\" />\n          <span>Sign out</span>\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  )\n}\n"}]}