@@ -2,14 +2,18 @@ import Link from 'next/link';
22import { formatDistanceToNow } from 'date-fns' ;
33
44import { formatInferenceCost , getUserDisplayName } from '@/lib' ;
5+ import { formatAutomationLabel } from '@/lib/task-creator-filter' ;
56import { Avatar , Spinner } from '@/components/system' ;
7+ import { PullRequestBadge } from '@/components/sandbox' ;
68import { SessionStatusBadge } from '@/components/sessions/SessionStatusBadge' ;
79import { SessionSearchSnippet } from '@/components/sessions/SessionSearchSnippet' ;
810import { getSessionSurfaceLabel } from '@/components/sessions/session-surfaces' ;
911
1012type SessionCardData = {
1113 id : string ;
1214 title : string ;
15+ ownerKind : 'user' | 'automation' | 'system' ;
16+ ownerAutomation : string | null ;
1317 ownerName : string | null ;
1418 ownerEmail : string | null ;
1519 ownerImageUrl : string | null ;
@@ -21,6 +25,11 @@ type SessionCardData = {
2125 inferenceCostMicroUsd : number ;
2226 unread : boolean ;
2327 searchSnippet ?: string | null ;
28+ pullRequests : Array < {
29+ repository : string ;
30+ number : number ;
31+ url : string ;
32+ } > ;
2433 tasks : Array < {
2534 taskId : string ;
2635 workflow : string ;
@@ -37,25 +46,30 @@ export function SessionCard({
3746 viewerUserId : string ;
3847 query ?: string ;
3948} ) {
40- const owner =
41- getUserDisplayName ( {
42- name : session . ownerName ,
43- email : session . ownerEmail ,
44- } ) ?? 'Roomote' ;
49+ const actorName =
50+ session . ownerKind === 'automation' && session . ownerAutomation
51+ ? formatAutomationLabel ( session . ownerAutomation )
52+ : ( getUserDisplayName ( {
53+ name : session . ownerName ,
54+ email : session . ownerEmail ,
55+ } ) ?? 'Roomote' ) ;
4556 const status = session . cachedStatus ?? 'ready' ;
4657
4758 return (
48- < Link
49- href = { `/sessions/${ session . id } ` }
50- className = "ph-no-capture group flex w-full items-start gap-3 p-4 transition-colors hover:bg-accent-foreground/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
51- >
52- < div className = "relative mt-1 shrink-0" >
59+ < div className = "ph-no-capture group relative flex w-full items-start gap-3 p-4 transition-colors hover:bg-accent-foreground/10" >
60+ < Link
61+ href = { `/sessions/${ session . id } ` }
62+ className = "absolute inset-0 z-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
63+ >
64+ < span className = "sr-only" > { session . title } </ span >
65+ </ Link >
66+ < div className = "pointer-events-none relative z-10 mt-1 shrink-0" >
5367 < Avatar
5468 imageUrl = { session . ownerImageUrl }
55- name = { owner }
69+ name = { actorName }
5670 email = { session . ownerEmail ?? undefined }
5771 size = "md"
58- alt = { owner }
72+ alt = { actorName }
5973 />
6074 { session . unread && session . ownerUserId === viewerUserId ? (
6175 < span
@@ -64,17 +78,21 @@ export function SessionCard({
6478 />
6579 ) : null }
6680 </ div >
67- < div className = "min-w-0 flex-1 space-y-2" >
68- < div className = "flex flex-wrap items-center justify-between gap-2" >
69- < p className = "line-clamp-2 text-base font-medium group-hover:underline" >
70- { session . title }
71- </ p >
81+ < div className = "pointer-events-none relative z-10 min-w-0 flex-1" >
82+ < div className = "flex items-start justify-between gap-2 text-xs text-muted-foreground/75 md:items-center" >
83+ < div className = "flex flex-wrap items-center gap-1 text-nowrap" >
84+ < span > { actorName } </ span >
85+ < span > started a session</ span >
86+ </ div >
7287 < span className = "shrink-0 text-xs text-muted-foreground" >
7388 { formatDistanceToNow ( new Date ( session . activityAt * 1000 ) , {
7489 addSuffix : true ,
7590 } ) }
7691 </ span >
7792 </ div >
93+ < p className = "mt-1 mb-2 line-clamp-2 text-base font-medium group-hover:underline" >
94+ { session . title }
95+ </ p >
7896 < SessionSearchSnippet
7997 snippet = { session . searchSnippet }
8098 query = { query }
@@ -90,11 +108,21 @@ export function SessionCard({
90108 < SessionStatusBadge status = { status } className = "capitalize" />
91109 ) }
92110 < span > { getSessionSurfaceLabel ( session . sourceSurface ) } </ span >
111+ { session . pullRequests . map ( ( pullRequest ) => (
112+ < PullRequestBadge
113+ key = { `${ pullRequest . repository } :${ pullRequest . number } ` }
114+ repo = { pullRequest . repository }
115+ prNumber = { pullRequest . number }
116+ url = { pullRequest . url }
117+ className = "pointer-events-auto"
118+ iconClassName = "size-3"
119+ />
120+ ) ) }
93121 { session . inferenceCostMicroUsd > 0 ? (
94122 < span > ${ formatInferenceCost ( session . inferenceCostMicroUsd ) } </ span >
95123 ) : null }
96124 </ div >
97125 </ div >
98- </ Link >
126+ </ div >
99127 ) ;
100128}
0 commit comments