55 TooltipContent ,
66 TooltipTrigger ,
77} from '@/components/ui/tooltip' ;
8- import { BlockRecord , getBlocks } from '@/lib/api' ;
8+ import { BlockRecord , getBlock , getBlockByHeight , getBlocks } from '@/lib/api' ;
99import { MAX_BLOCK_COST } from '@/lib/constants' ;
1010import { truncateHash } from '@/lib/conversions' ;
1111import { intlFormat , intlFormatDistance } from 'date-fns' ;
@@ -16,34 +16,67 @@ import { Link } from 'react-router-dom';
1616export function Home ( ) {
1717 const [ blocks , setBlocks ] = useState < BlockRecord [ ] > ( [ ] ) ;
1818 const [ search , setSearch ] = useState ( '' ) ;
19+ const [ searchResult , setSearchResult ] = useState < BlockRecord | null > ( null ) ;
20+ const [ error , setError ] = useState < string | null > ( null ) ;
1921
2022 useEffect ( ( ) => {
2123 getBlocks ( ) . then ( setBlocks ) ;
2224 } , [ ] ) ;
2325
26+ const handleSearch = async ( value : string ) => {
27+ setSearch ( value ) ;
28+ setError ( null ) ;
29+
30+ if ( ! value ) {
31+ setSearchResult ( null ) ;
32+ return ;
33+ }
34+
35+ try {
36+ let block : BlockRecord | null = null ;
37+
38+ // Try parsing as block height first
39+ const height = parseInt ( value ) ;
40+ if ( ! isNaN ( height ) && height < 2 ** 32 ) {
41+ block = await getBlockByHeight ( height ) ;
42+ } else {
43+ // If not a number, try as header hash
44+ block = await getBlock ( value ) ;
45+ }
46+
47+ if ( block ) {
48+ setSearchResult ( block ) ;
49+ } else {
50+ setError ( 'Block not found' ) ;
51+ }
52+ } catch {
53+ setError ( 'Failed to fetch block' ) ;
54+ }
55+ } ;
56+
57+ const displayedBlocks = searchResult ? [ searchResult ] : blocks ;
58+
2459 return (
2560 < Layout >
26- < div className = 'flex items-center justify-between mb-6' >
27- < h1 className = 'text-3xl font-semibold' > Recent Blocks</ h1 >
28- < Input
29- className = 'w-80'
30- placeholder = 'Search by height or hash...'
31- value = { search }
32- onChange = { ( e ) => setSearch ( e . target . value ) }
33- />
61+ < div className = 'flex flex-col md:flex-row md:items-center justify-between gap-4 mb-6' >
62+ < h1 className = 'text-3xl font-semibold' >
63+ { searchResult ? 'Search Result' : 'Recent Blocks' }
64+ </ h1 >
65+ < div className = 'w-full md:w-80 space-y-2' >
66+ < Input
67+ className = 'w-full'
68+ placeholder = 'Search by height or hash...'
69+ value = { search }
70+ onChange = { ( e ) => handleSearch ( e . target . value ) }
71+ />
72+ { error && < div className = 'text-sm text-red-500' > { error } </ div > }
73+ </ div >
3474 </ div >
3575
3676 < div className = 'grid gap-2' >
37- { blocks
38- . filter (
39- ( block ) =>
40- search === '' ||
41- block . height . toString ( ) . includes ( search ) ||
42- block . header_hash . toLowerCase ( ) . includes ( search . toLowerCase ( ) ) ,
43- )
44- . map ( ( block ) => (
45- < Block key = { block . height } block = { block } />
46- ) ) }
77+ { displayedBlocks . map ( ( block ) => (
78+ < Block key = { block . height } block = { block } />
79+ ) ) }
4780 </ div >
4881 </ Layout >
4982 ) ;
0 commit comments