@@ -12,6 +12,13 @@ interface SessionItem {
1212 command ?: string
1313}
1414
15+ const TYPE_LABELS : Record < string , string > = {
16+ email_review : 'Email' ,
17+ code_review : 'Code' ,
18+ action_approval : 'Approval' ,
19+ form_review : 'Form' ,
20+ selection_review : 'Selection' ,
21+ }
1522
1623function sessionPath ( s : SessionItem ) : string {
1724 if ( s . type === 'action_approval' ) return `/approval/${ s . id } `
@@ -21,6 +28,12 @@ function sessionPath(s: SessionItem): string {
2128 return `/review/${ s . id } `
2229}
2330
31+ function sessionTitle ( s : SessionItem ) : string {
32+ if ( s . subject ) return s . subject
33+ if ( s . type === 'code_review' && s . command ) return s . command
34+ return TYPE_LABELS [ s . type ] ?? s . type
35+ }
36+
2437function formatTime ( ts : number ) : string {
2538 const d = new Date ( ts )
2639 const now = Date . now ( )
@@ -59,14 +72,19 @@ function riskBadge(risk: 'danger' | 'warning' | 'normal') {
5972
6073export default function HomePage ( ) {
6174 const navigate = useNavigate ( )
62- const [ sessions , setSessions ] = useState < SessionItem [ ] > ( [ ] )
75+ const [ pending , setPending ] = useState < SessionItem [ ] > ( [ ] )
76+ const [ completedCount , setCompletedCount ] = useState ( 0 )
6377 const [ loading , setLoading ] = useState ( true )
6478 const [ prefCount , setPrefCount ] = useState < number | null > ( null )
6579
6680 useEffect ( ( ) => {
6781 fetch ( '/api/sessions' )
6882 . then ( r => r . json ( ) )
69- . then ( data => { setSessions ( data ) ; setLoading ( false ) } )
83+ . then ( ( data : SessionItem [ ] ) => {
84+ setPending ( data . filter ( s => s . status === 'pending' ) )
85+ setCompletedCount ( data . filter ( s => s . status === 'completed' ) . length )
86+ setLoading ( false )
87+ } )
7088 . catch ( ( ) => setLoading ( false ) )
7189
7290 fetch ( '/api/preferences' )
@@ -79,34 +97,49 @@ export default function HomePage() {
7997 < div className = "min-h-screen bg-gray-50 dark:bg-zinc-950" >
8098 < div className = "max-w-2xl mx-auto py-10 px-4" >
8199
82- < div className = "mb-6 " >
100+ < div className = "mb-8 " >
83101 < p className = "text-xs text-zinc-400 dark:text-slate-500 uppercase tracking-wider mb-1" > agentclick</ p >
84102 < div className = "flex items-center justify-between" >
85- < h1 className = "text-xl font-semibold text-zinc-900 dark:text-slate-100" > Recent Sessions</ h1 >
86- < button
87- onClick = { ( ) => navigate ( '/preferences' ) }
88- className = "flex items-center gap-1.5 text-sm text-blue-400 dark:text-blue-500 hover:text-blue-500 dark:hover:text-blue-400 transition-colors"
89- >
90- Preferences
91- { prefCount !== null && prefCount > 0 && (
92- < span className = "text-xs px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 text-zinc-400 dark:text-zinc-500 font-medium" > { prefCount } </ span >
93- ) }
94- < span className = "text-zinc-300 dark:text-zinc-600" > ›</ span >
95- </ button >
103+ < h1 className = "text-xl font-semibold text-zinc-900 dark:text-slate-100" > Pending</ h1 >
104+ < div className = "flex items-center gap-4" >
105+ < button
106+ onClick = { ( ) => navigate ( '/completed' ) }
107+ className = "flex items-center gap-1.5 text-sm text-zinc-400 dark:text-slate-500 hover:text-zinc-600 dark:hover:text-slate-300 transition-colors"
108+ >
109+ Completed
110+ { completedCount > 0 && (
111+ < span className = "text-xs px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 text-zinc-400 dark:text-zinc-500 font-medium" > { completedCount } </ span >
112+ ) }
113+ < span className = "text-zinc-300 dark:text-zinc-600" > ›</ span >
114+ </ button >
115+ < button
116+ onClick = { ( ) => navigate ( '/preferences' ) }
117+ className = "flex items-center gap-1.5 text-sm text-blue-400 dark:text-blue-500 hover:text-blue-500 dark:hover:text-blue-400 transition-colors"
118+ >
119+ Preferences
120+ { prefCount !== null && prefCount > 0 && (
121+ < span className = "text-xs px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 text-zinc-400 dark:text-zinc-500 font-medium" > { prefCount } </ span >
122+ ) }
123+ < span className = "text-zinc-300 dark:text-zinc-600" > ›</ span >
124+ </ button >
125+ </ div >
96126 </ div >
97127 </ div >
98128
99129 { loading && (
100130 < p className = "text-sm text-zinc-400 dark:text-slate-500" > Loading...</ p >
101131 ) }
102132
103- { ! loading && sessions . length === 0 && (
104- < p className = "text-sm text-zinc-400 dark:text-slate-500" > No sessions yet.</ p >
133+ { ! loading && pending . length === 0 && (
134+ < div className = "py-12 text-center" >
135+ < p className = "text-sm text-zinc-400 dark:text-slate-500 mb-1" > Nothing waiting for you.</ p >
136+ < p className = "text-xs text-zinc-300 dark:text-zinc-600" > Your agent will open a tab when a review is needed.</ p >
137+ </ div >
105138 ) }
106139
107- { ! loading && sessions . length > 0 && (
140+ { ! loading && pending . length > 0 && (
108141 < div className = "space-y-2" >
109- { sessions . map ( s => {
142+ { pending . map ( s => {
110143 const risk = sessionRisk ( s )
111144 const borderClass = risk === 'danger' ? 'border-l-4 border-l-red-400' :
112145 risk === 'warning' ? 'border-l-4 border-l-amber-400' : ''
@@ -116,23 +149,21 @@ export default function HomePage() {
116149 to = { sessionPath ( s ) }
117150 className = { `flex items-center justify-between p-4 bg-white dark:bg-zinc-900 border border-gray-100 dark:border-zinc-800 rounded-lg hover:border-gray-200 dark:hover:border-zinc-700 transition-colors ${ borderClass } ` }
118151 >
119- < div className = "min-w-0" >
120- < p className = "text-sm font-medium text-zinc-800 dark:text-slate-200 truncate" >
121- { s . subject ?? s . type }
122- </ p >
123- { s . to && (
124- < p className = "text-xs text-zinc-400 dark:text-slate-500 mt-0.5 truncate" > To: { s . to } </ p >
125- ) }
152+ < div className = "min-w-0 flex items-center gap-2" >
153+ < span className = "text-xs px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 text-zinc-500 dark:text-zinc-400 font-medium shrink-0" >
154+ { TYPE_LABELS [ s . type ] ?? s . type }
155+ </ span >
156+ < div className = "min-w-0" >
157+ < p className = "text-sm font-medium text-zinc-800 dark:text-slate-200 truncate" >
158+ { sessionTitle ( s ) }
159+ </ p >
160+ { s . to && (
161+ < p className = "text-xs text-zinc-400 dark:text-slate-500 mt-0.5 truncate" > To: { s . to } </ p >
162+ ) }
163+ </ div >
126164 </ div >
127165 < div className = "flex items-center gap-3 shrink-0 ml-4" >
128166 { riskBadge ( risk ) }
129- < span className = { `text-xs px-2 py-0.5 rounded font-medium ${
130- s . status === 'completed'
131- ? 'bg-green-50 dark:bg-green-950 text-green-600 dark:text-green-500'
132- : 'bg-amber-50 dark:bg-amber-950 text-amber-600 dark:text-amber-400'
133- } `} >
134- { s . status }
135- </ span >
136167 < span className = "text-xs text-zinc-400 dark:text-slate-500" > { formatTime ( s . createdAt ) } </ span >
137168 </ div >
138169 </ Link >
@@ -141,7 +172,6 @@ export default function HomePage() {
141172 </ div >
142173 ) }
143174
144-
145175 </ div >
146176 </ div >
147177 )
0 commit comments