1+ import { Link } from '@tanstack/react-router' ;
2+ import { LuMapPin , LuMail , LuGlobe , LuTwitter , LuGithub , LuMessageSquare , LuSend } from "react-icons/lu" ;
3+ import { ChainIcon } from './ChainIcon' ;
4+ import { getChainIconUrl } from '../utils/chainIcons' ;
5+ import { useFollowers } from '../hooks/useFollowers' ;
6+
7+ interface Profile {
8+ name : string ;
9+ display : string ;
10+ address ?: string ;
11+ avatar ?: string ;
12+ header ?: string ;
13+ records ?: {
14+ header ?: string ;
15+ avatar ?: string ;
16+ description ?: string ;
17+ location ?: string ;
18+ email ?: string ;
19+ url ?: string ;
20+ 'com.twitter' ?: string ;
21+ 'com.github' ?: string ;
22+ 'com.discord' ?: string ;
23+ 'org.telegram' ?: string ;
24+ } ;
25+ chains ?: Record < string , string > ;
26+ }
27+
28+ interface SearchResultProps {
29+ profile : Profile ;
30+ }
31+
32+ export function SearchResult ( { profile } : SearchResultProps ) {
33+ const { data : followersData } = useFollowers ( profile . name ) ;
34+
35+ return (
36+ < div className = "bg-white rounded-lg overflow-hidden shadow-sm hover:shadow-md transition-all duration-200" >
37+ < Link
38+ to = "/$profileId"
39+ params = { { profileId : profile . name } }
40+ className = "block h-full"
41+ >
42+ < div className = "relative h-full flex flex-col" >
43+ { /* Header/Banner image */ }
44+ { profile . header || profile . records ?. header ? (
45+ < div className = "w-full aspect-[3/1] overflow-hidden" >
46+ < img
47+ src = { profile . header || profile . records ?. header }
48+ alt = { `${ profile . display } banner` }
49+ className = "w-full h-full object-cover"
50+ />
51+ </ div >
52+ ) : (
53+ < div className = "w-full aspect-[3/1] bg-gradient-to-r from-blue-500 to-purple-600" > </ div >
54+ ) }
55+
56+ { /* Profile information with avatar */ }
57+ < div className = "p-2 flex-1" >
58+ < div className = "flex items-start space-x-2 pr-2 pb-1 h-full" >
59+ { /* Avatar */ }
60+ < div className = { `${ profile . header || profile . records ?. header ? '-mt-7' : '' } flex-shrink-0` } >
61+ { profile . avatar ? (
62+ < img
63+ src = { profile . avatar }
64+ alt = { profile . display }
65+ className = "h-14 w-14 rounded-full border-2 border-white shadow-md object-cover"
66+ />
67+ ) : (
68+ < div className = "h-14 w-14 rounded-full bg-gray-200 flex items-center justify-center text-gray-500 text-xl font-bold" >
69+ { profile . display . charAt ( 0 ) . toUpperCase ( ) }
70+ </ div >
71+ ) }
72+ </ div >
73+
74+ { /* Profile details */ }
75+ < div className = "flex-1 min-w-0 h-full flex flex-col" >
76+ < h3 className = "text-base font-semibold text-blue-600 truncate" >
77+ { profile . display }
78+ </ h3 >
79+ { profile . address && (
80+ < p className = "text-xs text-gray-500 truncate" >
81+ { profile . address }
82+ </ p >
83+ ) }
84+ < p className = "mt-1 text-xs text-gray-600 whitespace-pre-line line-clamp-2" >
85+ { profile . records ?. description || '' }
86+ </ p >
87+
88+ { /* Chain addresses */ }
89+ { profile . chains && Object . keys ( profile . chains ) . length > 0 && (
90+ < div className = "mt-1.5 flex flex-wrap gap-x-2 gap-y-1" >
91+ { Object . entries ( profile . chains ) . map ( ( [ chain , address ] ) => (
92+ < div key = { chain } className = "flex items-center text-xs text-gray-500" title = { `${ chain . toUpperCase ( ) } : ${ address } ` } >
93+ < ChainIcon
94+ chain = { chain }
95+ iconUrl = { getChainIconUrl ( chain ) }
96+ className = "mr-1"
97+ />
98+ < span className = "truncate max-w-[100px]" > { address } </ span >
99+ </ div >
100+ ) ) }
101+ </ div >
102+ ) }
103+
104+ { /* Profile metadata */ }
105+ < div className = "mt-1.5 flex flex-wrap gap-x-3 gap-y-1 text-xs text-gray-500" >
106+ { profile . records ?. location && (
107+ < div className = "flex items-center" >
108+ < LuMapPin className = "mr-1 h-4 w-4" />
109+ < span > { profile . records . location } </ span >
110+ </ div >
111+ ) }
112+ { profile . records ?. email && (
113+ < div className = "flex items-center" >
114+ < LuMail className = "mr-1 h-4 w-4" />
115+ < span > { profile . records . email } </ span >
116+ </ div >
117+ ) }
118+ { profile . records ?. url && (
119+ < div className = "flex items-center" >
120+ < LuGlobe className = "mr-1 h-4 w-4" />
121+ < span > { profile . records . url } </ span >
122+ </ div >
123+ ) }
124+ </ div >
125+
126+ { /* Social links and followers */ }
127+ < div className = "mt-1.5 flex justify-between items-center flex-1" >
128+ < div className = "flex space-x-2" >
129+ { profile . records ?. [ 'com.twitter' ] && (
130+ < div className = "text-blue-400 hover:text-blue-600" >
131+ < LuTwitter className = "h-4 w-4" title = { `Twitter: ${ profile . records [ 'com.twitter' ] } ` } />
132+ </ div >
133+ ) }
134+ { profile . records ?. [ 'com.github' ] && (
135+ < div className = "text-gray-700 hover:text-gray-900" >
136+ < LuGithub className = "h-4 w-4" title = { `GitHub: ${ profile . records [ 'com.github' ] } ` } />
137+ </ div >
138+ ) }
139+ { profile . records ?. [ 'com.discord' ] && (
140+ < div className = "text-indigo-500 hover:text-indigo-700" >
141+ < LuMessageSquare className = "h-4 w-4" title = { `Discord: ${ profile . records [ 'com.discord' ] } ` } />
142+ </ div >
143+ ) }
144+ { profile . records ?. [ 'org.telegram' ] && (
145+ < div className = "text-blue-500 hover:text-blue-700" >
146+ < LuSend className = "h-4 w-4" title = { `Telegram: ${ profile . records [ 'org.telegram' ] } ` } />
147+ </ div >
148+ ) }
149+ </ div >
150+
151+ { /* Followers data */ }
152+ { followersData && (
153+ < div className = "flex gap-3 items-center self-end" onClick = { ( e ) => e . stopPropagation ( ) } >
154+ < a href = { `https://ethfollow.xyz/${ profile . name } ?tab=following` } target = "_blank" rel = "noopener noreferrer" className = "text-xs text-gray-500 flex gap-1 items-center hover:underline cursor-pointer" >
155+ < span className = "font-bold" > { followersData . following_count } </ span >
156+ < span className = "text-gray-500" > Following</ span >
157+ </ a >
158+ < a href = { `https://ethfollow.xyz/${ profile . name } ?tab=followers` } target = "_blank" rel = "noopener noreferrer" className = "text-xs text-gray-500 flex gap-1 items-center hover:underline cursor-pointer" >
159+ < span className = "font-bold" > { followersData . followers_count } </ span >
160+ < span className = "text-gray-500" > Followers</ span >
161+ </ a >
162+ </ div >
163+ ) }
164+ </ div >
165+ </ div >
166+ </ div >
167+ </ div >
168+ </ div >
169+ </ Link >
170+ </ div >
171+ ) ;
172+ }
0 commit comments