@@ -44,6 +44,22 @@ const yoctoToNear = (y: string | number | bigint) => utils.format.formatNearAmou
4444const nearToYocto = ( n : string ) => utils . format . parseNearAmount ( n ) || '0'
4545const nowNs = ( ) => BigInt ( Date . now ( ) ) * 1_000_000n // ms → ns
4646
47+ const formatLeft = ( endNs : bigint ) : string => {
48+ const msLeft = Number ( endNs - BigInt ( Date . now ( ) ) * 1_000_000n ) / 1e6
49+ if ( msLeft <= 0 ) return 'Ended'
50+
51+ const sec = Math . floor ( msLeft / 1_000 )
52+ const d = Math . floor ( sec / 86_400 )
53+ const h = Math . floor ( ( sec % 86_400 ) / 3_600 )
54+ const m = Math . floor ( ( sec % 3_600 ) / 60 )
55+ const s = sec % 60
56+
57+ if ( d ) return `${ d } d ${ h } h`
58+ if ( h ) return `${ h } h ${ m } m`
59+ if ( m ) return `${ m } m ${ s } s`
60+ return `${ s } s`
61+ }
62+
4763/* ─────────────────── types ─────────────────── */
4864interface Bid {
4965 bidder_id : string
@@ -218,6 +234,18 @@ const tooltip = (title: string, children: React.ReactElement) => (
218234 </ Tooltip >
219235)
220236
237+ const Countdown : React . FC < { endedAtNs : string | null } > = ( { endedAtNs } ) => {
238+ const [ text , setText ] = useState ( ( ) => ( endedAtNs ? formatLeft ( BigInt ( endedAtNs ) ) : '—' ) )
239+
240+ useEffect ( ( ) => {
241+ if ( ! endedAtNs ) return
242+ const id = setInterval ( ( ) => setText ( formatLeft ( BigInt ( endedAtNs ) ) ) , 1_000 )
243+ return ( ) => clearInterval ( id )
244+ } , [ endedAtNs ] )
245+
246+ return < > { text } </ >
247+ }
248+
221249const ConnectWalletButton = ( {
222250 accountId,
223251 onSignIn,
@@ -418,8 +446,7 @@ const ListingRow = ({
418446 < >
419447 < br />
420448 < small >
421- ⏳ { new Date ( Number ( listing . started_at ) / 1e6 ) . toLocaleString ( ) } –{ ' ' }
422- { new Date ( Number ( listing . ended_at ) / 1e6 ) . toLocaleString ( ) }
449+ ⏳ < Countdown endedAtNs = { listing . ended_at } />
423450 </ small >
424451 </ >
425452 ) }
0 commit comments