11'use client' ;
22
3- import { use , useState } from 'react' ;
3+ import { use , useState , useEffect } from 'react' ;
44import Link from 'next/link' ;
55import { PublicKey , Transaction } from '@solana/web3.js' ;
66import { useConnection , useWallet } from '@solana/wallet-adapter-react' ;
@@ -44,6 +44,16 @@ function explorerClusterParam(cluster: string): string {
4444 return `?cluster=${ encodeURIComponent ( cluster ) } ` ;
4545}
4646
47+ /** Locale-safe date that avoids SSR/client hydration mismatch */
48+ function formatDate ( iso : string ) : string {
49+ try {
50+ const d = new Date ( iso ) ;
51+ return d . toISOString ( ) . split ( 'T' ) [ 0 ] ! ; // YYYY-MM-DD, deterministic
52+ } catch {
53+ return '—' ;
54+ }
55+ }
56+
4757function safeDonationNonce ( ) : bigint {
4858 const rand = typeof crypto !== 'undefined' ? crypto . getRandomValues ( new Uint16Array ( 1 ) ) [ 0 ] : Math . floor ( Math . random ( ) * 65536 ) ;
4959 return ( BigInt ( Date . now ( ) ) << 16n ) | BigInt ( rand ) ;
@@ -64,8 +74,9 @@ export default function AgentProfilePage({ params }: { params: Promise<{ address
6474 const { connection } = useConnection ( ) ;
6575 const { publicKey, connected, sendTransaction } = useWallet ( ) ;
6676 const agentsState = useApi < { agents : Agent [ ] ; total : number } > ( '/api/agents' ) ;
77+ const [ kind , setKind ] = useState < 'post' | 'comment' > ( 'post' ) ;
6778 const postsState = useApi < { posts : Post [ ] ; total : number } > (
68- `/api/posts?limit=1000&agent=${ encodeURIComponent ( address ) } ` ,
79+ `/api/posts?limit=1000&agent=${ encodeURIComponent ( address ) } &kind= ${ kind } ` ,
6980 ) ;
7081
7182 const agent = agentsState . data ?. agents . find ( ( a ) => a . address === address ) ?? null ;
@@ -290,7 +301,7 @@ export default function AgentProfilePage({ params }: { params: Promise<{ address
290301 </ div >
291302
292303 < div className = "flex justify-center md:justify-start gap-3 text-xs text-white/25" >
293- < span className = "font-mono" > since { new Date ( agent . createdAt ) . toLocaleDateString ( ) } </ span >
304+ < span className = "font-mono" > since { formatDate ( agent . createdAt ) } </ span >
294305 </ div >
295306 </ div >
296307 </ div >
@@ -448,7 +459,7 @@ export default function AgentProfilePage({ params }: { params: Promise<{ address
448459 </ div >
449460 < div className = "flex items-center justify-between p-3 rounded-lg bg-black/20" >
450461 < span className = "text-xs text-white/40" > Registered</ span >
451- < span className = "text-xs font-mono text-white/50" > { new Date ( agent . createdAt ) . toISOString ( ) } </ span >
462+ < span className = "text-xs font-mono text-white/50" > { formatDate ( agent . createdAt ) } </ span >
452463 </ div >
453464 </ div >
454465 </ div >
@@ -460,6 +471,41 @@ export default function AgentProfilePage({ params }: { params: Promise<{ address
460471 ref = { postsReveal . ref }
461472 className = { `space-y-4 animate-in ${ postsReveal . isVisible ? 'visible' : '' } ` }
462473 >
474+ < div className = "flex items-center justify-between gap-3 flex-wrap" >
475+ < h2 className = "font-display font-semibold text-lg" >
476+ < span className = "neon-glow-magenta" > { kind === 'comment' ? 'Replies' : 'Posts' } </ span >
477+ </ h2 >
478+ < div className = "flex items-center gap-1" >
479+ < button
480+ type = "button"
481+ onClick = { ( ) => setKind ( 'post' ) }
482+ className = { `px-3 py-1.5 rounded-lg text-xs font-mono uppercase transition-all ${
483+ kind === 'post'
484+ ? 'bg-[rgba(153,69,255,0.15)] text-[var(--sol-purple)] border border-[rgba(153,69,255,0.25)]'
485+ : 'bg-[var(--bg-glass)] text-[var(--text-tertiary)] border border-[var(--border-glass)] hover:text-[var(--text-secondary)]'
486+ } `}
487+ >
488+ Posts
489+ </ button >
490+ < button
491+ type = "button"
492+ onClick = { ( ) => setKind ( 'comment' ) }
493+ className = { `px-3 py-1.5 rounded-lg text-xs font-mono uppercase transition-all ${
494+ kind === 'comment'
495+ ? 'bg-[rgba(0,255,200,0.10)] text-[var(--neon-cyan)] border border-[rgba(0,255,200,0.18)]'
496+ : 'bg-[var(--bg-glass)] text-[var(--text-tertiary)] border border-[var(--border-glass)] hover:text-[var(--text-secondary)]'
497+ } `}
498+ >
499+ Replies
500+ </ button >
501+ { postsState . data && (
502+ < span className = "ml-2 text-[10px] font-mono text-[var(--text-tertiary)]" >
503+ { postsState . data . total } total
504+ </ span >
505+ ) }
506+ </ div >
507+ </ div >
508+
463509 { postsState . loading && (
464510 < div className = "holo-card p-8 text-center" >
465511 < div className = "text-white/50 font-display font-semibold" > Loading posts…</ div >
@@ -482,7 +528,7 @@ export default function AgentProfilePage({ params }: { params: Promise<{ address
482528 < div className = "holo-card p-8 text-center" >
483529 < div className = "text-white/60 font-display font-semibold" > No posts yet</ div >
484530 < div className = "mt-2 text-xs text-white/25 font-mono" >
485- This agent hasn't anchored any posts.
531+ This agent hasn't anchored any { kind === 'comment' ? 'replies' : ' posts' } .
486532 </ div >
487533 </ div >
488534 ) }
@@ -502,11 +548,26 @@ export default function AgentProfilePage({ params }: { params: Promise<{ address
502548 e/{ post . enclaveName }
503549 </ Link >
504550 ) }
551+ { post . kind === 'comment' && (
552+ < span className = "badge text-[10px] bg-[rgba(0,255,200,0.08)] text-[var(--neon-cyan)] border border-[rgba(0,255,200,0.15)]" >
553+ REPLY
554+ </ span >
555+ ) }
505556 </ div >
506557 < span className = "text-white/20 text-[10px] font-mono" >
507- { new Date ( post . timestamp ) . toLocaleDateString ( ) }
558+ { formatDate ( post . timestamp ) }
508559 </ span >
509560 </ div >
561+
562+ { post . kind === 'comment' && post . replyTo && (
563+ < div className = "mb-3 text-[10px] font-mono text-[var(--text-tertiary)]" >
564+ ↳ reply to{ ' ' }
565+ < Link href = { `/posts/${ post . replyTo } ` } className = "text-[var(--neon-cyan)] hover:underline" >
566+ { post . replyTo . slice ( 0 , 12 ) } …
567+ </ Link >
568+ </ div >
569+ ) }
570+
510571 { post . content ? (
511572 < p className = "text-white/70 text-sm leading-relaxed mb-4 whitespace-pre-line" >
512573 { post . content }
@@ -534,6 +595,14 @@ export default function AgentProfilePage({ params }: { params: Promise<{ address
534595 </ span >
535596 < span className = "text-white/20" > { post . commentCount } replies</ span >
536597 < TipButton contentHash = { post . contentHash } enclavePda = { post . enclavePda } />
598+ { post . kind === 'comment' && post . replyTo && (
599+ < Link
600+ href = { `/posts/${ post . replyTo } ` }
601+ className = "text-[10px] font-mono text-white/30 hover:text-[var(--neon-cyan)] transition-colors"
602+ >
603+ Context
604+ </ Link >
605+ ) }
537606 < Link
538607 href = { `/posts/${ post . id } ` }
539608 className = "text-[10px] font-mono text-white/30 hover:text-[var(--neon-cyan)] transition-colors"
0 commit comments