11"use client" ;
22
33import { formatDistanceToNow } from "date-fns" ;
4- import { ExternalLink , Users , Target , TrendingUp } from "lucide-react" ;
4+ import { Users , Target , TrendingUp , Calendar , ArrowRight , Activity , Clock } from "lucide-react" ;
55import Link from "next/link" ;
6- import { Card , CardContent , CardHeader , CardTitle , CardDescription } from "@/components/ui/card" ;
6+ import { Badge } from "@/components/ui/badge" ;
7+ import { Tooltip , TooltipContent , TooltipTrigger } from "@/components/ui/tooltip" ;
78
89interface SessionSummary {
910 roomId : string ;
@@ -13,6 +14,7 @@ interface SessionSummary {
1314 issuesCompleted : number ;
1415 totalStoryPoints : number | null ;
1516 averageAgreement : number | null ;
17+ participantCount : number ;
1618}
1719
1820interface SessionHistoryProps {
@@ -23,103 +25,152 @@ interface SessionHistoryProps {
2325export function SessionHistory ( { sessions, isLoading } : SessionHistoryProps ) {
2426 if ( isLoading ) {
2527 return (
26- < Card className = "flex flex-col h-full" >
27- < CardHeader >
28- < CardTitle className = "text-base font-semibold" > Session History</ CardTitle >
29- < CardDescription > Recent planning rooms joined</ CardDescription >
30- </ CardHeader >
31- < CardContent className = "flex-1" >
32- < div className = "space-y-3" >
33- { [ 1 , 2 , 3 ] . map ( ( i ) => (
34- < div key = { i } className = "animate-pulse" >
35- < div className = "h-16 rounded-lg bg-muted" />
28+ < div className = "space-y-4" >
29+ < div >
30+ < h2 className = "text-xl font-semibold tracking-tight" > Recent Sessions</ h2 >
31+ < p className = "text-sm text-muted-foreground" > Continue where you left off or review past estimates.</ p >
32+ </ div >
33+ < div className = "grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4" >
34+ { [ 1 , 2 , 3 , 4 ] . map ( ( i ) => (
35+ < div key = { i } className = "animate-pulse rounded-2xl border bg-card p-5 h-[200px]" >
36+ < div className = "h-6 w-2/3 bg-muted rounded-md mb-4" />
37+ < div className = "space-y-3" >
38+ < div className = "h-4 w-1/2 bg-muted rounded-md" />
39+ < div className = "h-4 w-3/4 bg-muted rounded-md" />
3640 </ div >
37- ) ) }
38- </ div >
39- </ CardContent >
40- </ Card >
41+ </ div >
42+ ) ) }
43+ </ div >
44+ </ div >
4145 ) ;
4246 }
4347
4448 if ( sessions . length === 0 ) {
4549 return (
46- < Card className = "flex flex-col h-full" >
47- < CardHeader >
48- < CardTitle className = "text-base font-semibold" > Session History</ CardTitle >
49- < CardDescription > Recent planning rooms joined</ CardDescription >
50- </ CardHeader >
51- < CardContent className = "flex-1" >
52- < div className = "flex h-full min-h-[200px] flex-col items-center justify-center text-muted-foreground" >
53- < Users className = "mb-2 h-8 w-8 opacity-50" />
54- < p > No sessions yet</ p >
55- < p className = "text-sm" >
56- Join a planning room to start tracking your sessions
57- </ p >
58- </ div >
59- </ CardContent >
60- </ Card >
50+ < div className = "flex flex-col items-center justify-center min-h-[300px] rounded-2xl border border-dashed p-8 text-center bg-muted/20" >
51+ < div className = "flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 mb-4" >
52+ < Activity className = "h-6 w-6 text-primary" />
53+ </ div >
54+ < h2 className = "text-xl font-semibold mb-2" > No active sessions</ h2 >
55+ < p className = "text-sm text-muted-foreground max-w-sm mb-6" >
56+ You haven't joined any planning rooms yet. Create or join a room to start estimating with your team.
57+ </ p >
58+ </ div >
6159 ) ;
6260 }
6361
6462 return (
65- < Card className = "flex flex-col h-full" >
66- < CardHeader >
67- < CardTitle className = "text-base font-semibold" > Session History</ CardTitle >
68- < CardDescription > Recent planning rooms joined</ CardDescription >
69- </ CardHeader >
70- < CardContent className = "flex-1" >
71- < div className = "space-y-2" >
72- { sessions . map ( ( session ) => (
63+ < div className = "space-y-6" >
64+ < div className = "flex items-center justify-between" >
65+ < div >
66+ < h2 className = "text-xl font-semibold tracking-tight" > Recent Sessions</ h2 >
67+ < p className = "text-sm text-muted-foreground mt-1" > Pick up where you left off or review past estimates.</ p >
68+ </ div >
69+ </ div >
70+
71+ < div className = "grid gap-5 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4" >
72+ { sessions . map ( ( session ) => {
73+ const isHighConsensus = session . averageAgreement !== null && session . averageAgreement >= 80 ;
74+ const isMedConsensus = session . averageAgreement !== null && session . averageAgreement >= 60 && session . averageAgreement < 80 ;
75+
76+ return (
7377 < Link
7478 key = { session . roomId }
7579 href = { `/room/${ session . roomId } ` }
76- className = "group flex items-center justify-between rounded-lg border p-3 transition-colors hover:bg-muted/50 "
80+ className = "group relative flex flex-col justify-between overflow-hidden rounded-2xl border bg-card p-5 transition-all duration-300 hover:shadow-md hover:border-primary/30 "
7781 >
78- < div className = "min-w-0 flex-1" >
79- < div className = "flex items-center gap-2" >
80- < span className = "truncate font-medium" >
81- { session . roomName }
82- </ span >
83- < ExternalLink className = "h-3 w-3 opacity-0 transition-opacity group-hover:opacity-50" />
84- </ div >
85- < div className = "mt-1 text-xs text-muted-foreground" >
86- { formatDistanceToNow ( session . lastActivityAt , {
87- addSuffix : true ,
88- } ) }
82+ < div className = "absolute inset-0 bg-linear-to-br from-primary/5 via-transparent to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100" />
83+
84+ < div className = "relative z-10 mb-6" >
85+ < div className = "flex items-start justify-between mb-4" >
86+ < div className = "flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-primary/10 text-primary" >
87+ < Activity className = "h-5 w-5" />
88+ </ div >
89+ { session . averageAgreement !== null && (
90+ < Tooltip >
91+ < TooltipTrigger render = { < div className = "cursor-default" onClick = { ( e ) => e . preventDefault ( ) } /> } >
92+ < Badge
93+ variant = { isHighConsensus ? "default" : isMedConsensus ? "secondary" : "destructive" }
94+ className = "font-medium"
95+ >
96+ < Users className = "h-3 w-3 mr-1" />
97+ { session . averageAgreement } % Match
98+ </ Badge >
99+ </ TooltipTrigger >
100+ < TooltipContent >
101+ < p > Average team consensus matching</ p >
102+ </ TooltipContent >
103+ </ Tooltip >
104+ ) }
89105 </ div >
106+
107+ < h3 className = "line-clamp-2 text-lg font-semibold leading-tight group-hover:text-primary transition-colors" >
108+ { session . roomName }
109+ </ h3 >
90110 </ div >
91111
92- < div className = "flex items-center gap-4 text-sm" >
93- < div className = "flex items-center gap-1 text-muted-foreground" >
94- < Target className = "h-4 w-4" />
95- < span > { session . issuesCompleted } </ span >
96- </ div >
112+ < div className = "relative z-10 mt-auto" >
113+ < div className = { `grid gap-4 mb-5 pb-5 border-b border-border/50 ${ session . totalStoryPoints !== null ? "grid-cols-3" : "grid-cols-2" } ` } >
114+ < Tooltip >
115+ < TooltipTrigger render = { < div className = "text-left cursor-default" onClick = { ( e ) => e . preventDefault ( ) } /> } >
116+ < p className = "text-xs text-muted-foreground flex items-center mb-1 whitespace-nowrap" >
117+ < Target className = "h-3 w-3 mr-1 shrink-0" /> Issues
118+ </ p >
119+ < p className = "text-base font-medium" > { session . issuesCompleted } </ p >
120+ </ TooltipTrigger >
121+ < TooltipContent >
122+ < p > Total issues estimated</ p >
123+ </ TooltipContent >
124+ </ Tooltip >
97125
98- { session . totalStoryPoints !== null && (
99- < div className = "flex items-center gap-1 text-muted-foreground" >
100- < TrendingUp className = "h-4 w-4" />
101- < span > { session . totalStoryPoints } pts</ span >
102- </ div >
103- ) }
126+ < Tooltip >
127+ < TooltipTrigger render = { < div className = "text-left cursor-default" onClick = { ( e ) => e . preventDefault ( ) } /> } >
128+ < p className = "text-xs text-muted-foreground flex items-center mb-1 whitespace-nowrap" >
129+ < Users className = "h-3 w-3 mr-1 shrink-0" /> Members
130+ </ p >
131+ < p className = "text-base font-medium" > { session . participantCount } </ p >
132+ </ TooltipTrigger >
133+ < TooltipContent >
134+ < p > Total room participants</ p >
135+ </ TooltipContent >
136+ </ Tooltip >
137+
138+ { session . totalStoryPoints !== null && (
139+ < Tooltip >
140+ < TooltipTrigger render = { < div className = "text-left cursor-default" onClick = { ( e ) => e . preventDefault ( ) } /> } >
141+ < p className = "text-xs text-muted-foreground flex items-center mb-1 whitespace-nowrap" >
142+ < TrendingUp className = "h-3 w-3 mr-1 shrink-0" /> Points
143+ </ p >
144+ < p className = "text-base font-medium" > { session . totalStoryPoints } </ p >
145+ </ TooltipTrigger >
146+ < TooltipContent >
147+ < p > Total story points estimated</ p >
148+ </ TooltipContent >
149+ </ Tooltip >
150+ ) }
151+ </ div >
104152
105- { session . averageAgreement !== null && (
106- < div
107- className = { `rounded-full px-2 py-0.5 text-xs font-medium ${
108- session . averageAgreement >= 80
109- ? "bg-green-100 text-green-700 dark:bg-status-success-bg dark:text-status-success-fg"
110- : session . averageAgreement >= 60
111- ? "bg-amber-100 text-amber-700 dark:bg-status-warning-bg dark:text-status-warning-fg"
112- : "bg-red-100 text-red-700 dark:bg-status-error-bg dark:text-status-error-fg"
113- } `}
114- >
115- { session . averageAgreement } %
153+ < div className = "flex items-center justify-between" >
154+ < Tooltip >
155+ < TooltipTrigger render = { < div className = "flex items-center text-xs text-muted-foreground cursor-default" onClick = { ( e ) => e . preventDefault ( ) } /> } >
156+ < Clock className = "h-3.5 w-3.5 mr-1.5" />
157+ < time dateTime = { new Date ( session . lastActivityAt ) . toISOString ( ) } >
158+ { formatDistanceToNow ( session . lastActivityAt , { addSuffix : true } ) }
159+ </ time >
160+ </ TooltipTrigger >
161+ < TooltipContent >
162+ < p > Time since last activity</ p >
163+ </ TooltipContent >
164+ </ Tooltip >
165+ < div className = "flex h-7 w-7 items-center justify-center rounded-full bg-primary text-primary-foreground opacity-0 transition-all duration-300 transform translate-x-[-10px] group-hover:translate-x-0 group-hover:opacity-100" >
166+ < ArrowRight className = "h-4 w-4" />
116167 </ div >
117- ) }
168+ </ div >
118169 </ div >
119170 </ Link >
120- ) ) }
121- </ div >
122- </ CardContent >
123- </ Card >
171+ ) ;
172+ } ) }
173+ </ div >
174+ </ div >
124175 ) ;
125176}
0 commit comments