import { NodeViewWrapper } from '@tiptap/react' import React, { useEffect, useState } from 'react' import { useLHSession } from '@components/Contexts/LHSessionContext' import { getUserByUsername, getUser } from '@services/users/users' import { Input } from "@components/ui/input" import { Button } from "@components/ui/button" import { Label } from "@components/ui/label" import { Loader2, User, ExternalLink, Briefcase, GraduationCap, MapPin, Building2, Globe, Laptop2, Award, BookOpen, Link, Users, Calendar, Lightbulb } from 'lucide-react' import { Badge } from "@components/ui/badge" import { HoverCard, HoverCardContent, HoverCardTrigger } from "@components/ui/hover-card" import { useRouter } from 'next/navigation' import UserAvatar from '@components/Objects/UserAvatar' import { useEditorProvider } from '@components/Contexts/Editor/EditorContext' import { getUserAvatarMediaDirectory } from '@services/media/media' type UserData = { id: string user_uuid: string first_name: string last_name: string username: string bio?: string avatar_image?: string details?: { [key: string]: { id: string label: string icon: string text: string } } } const AVAILABLE_ICONS = { 'briefcase': Briefcase, 'graduation-cap': GraduationCap, 'map-pin': MapPin, 'building-2': Building2, 'speciality': Lightbulb, 'globe': Globe, 'laptop-2': Laptop2, 'award': Award, 'book-open': BookOpen, 'link': Link, 'users': Users, 'calendar': Calendar, } as const; const IconComponent = ({ iconName }: { iconName: string }) => { const IconElement = AVAILABLE_ICONS[iconName as keyof typeof AVAILABLE_ICONS] if (!IconElement) return return } function UserBlockComponent(props: any) { const session = useLHSession() as any const access_token = session?.data?.tokens?.access_token const editorState = useEditorProvider() as any const isEditable = editorState.isEditable const router = useRouter() const [username, setUsername] = useState('') const [userData, setUserData] = useState(null) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(null) useEffect(() => { if (props.node.attrs.user_id) { fetchUserById(props.node.attrs.user_id) } }, [props.node.attrs.user_id]) const fetchUserById = async (userId: string) => { setIsLoading(true) setError(null) try { const data = await getUser(userId) if (!data) { throw new Error('User not found') } setUserData(data) setUsername(data.username) } catch (err: any) { console.error('Error fetching user by ID:', err) setError(err.detail || 'User not found') // Clear the invalid user_id from the node attributes props.updateAttributes({ user_id: null }) } finally { setIsLoading(false) } } const fetchUserByUsername = async (username: string) => { setIsLoading(true) setError(null) try { const data = await getUserByUsername(username) if (!data) { throw new Error('User not found') } setUserData(data) props.updateAttributes({ user_id: data.id }) } catch (err: any) { console.error('Error fetching user by username:', err) setError(err.detail || 'User not found') } finally { setIsLoading(false) } } const handleUsernameSubmit = async (e: React.FormEvent) => { e.preventDefault() if (!username.trim()) return await fetchUserByUsername(username) } if (isEditable && !userData) { return ( Username setUsername(e.target.value)} placeholder="Enter username" className="flex-1" /> {isLoading ? ( ) : ( 'Load User' )} {error && ( {error} )} ) } if (isLoading) { return ( ) } if (error) { return ( {error} ) } if (!userData) { return ( No user selected ) } return ( {/* Header with Avatar and Name */} {/* Background gradient */} {/* Content */} {/* Avatar */} {/* Name, Bio, and Button */} {userData.first_name} {userData.last_name} {userData.username && ( @{userData.username} )} userData.username && router.push(`/user/${userData.username}`)} > {userData.bio && ( {userData.bio} )} {/* Details */} {userData.details && Object.values(userData.details).length > 0 && ( {Object.values(userData.details).map((detail) => ( {detail.label} {detail.text} ))} )} ) } export default UserBlockComponent
{error}
{userData.bio}