Implement session outcomes, step timing, and live timer fixes
This commit is contained in:
@@ -237,6 +237,31 @@ export function SessionDetailPage() {
|
||||
return new Date(dateString).toLocaleString()
|
||||
}
|
||||
|
||||
const formatDuration = (durationSeconds: number | null | undefined) => {
|
||||
if (durationSeconds == null || durationSeconds < 0) return null
|
||||
if (durationSeconds < 60) return `${durationSeconds}s`
|
||||
const hours = Math.floor(durationSeconds / 3600)
|
||||
const minutes = Math.floor((durationSeconds % 3600) / 60)
|
||||
const seconds = durationSeconds % 60
|
||||
if (hours > 0) return seconds > 0 ? `${hours}h ${minutes}m ${seconds}s` : `${hours}h ${minutes}m`
|
||||
return seconds > 0 ? `${minutes}m ${seconds}s` : `${minutes}m`
|
||||
}
|
||||
|
||||
const getTotalDuration = () => {
|
||||
if (!session?.completed_at) return 'In progress'
|
||||
const startedAtMs = new Date(session.started_at).getTime()
|
||||
const completedAtMs = new Date(session.completed_at).getTime()
|
||||
if (Number.isNaN(startedAtMs) || Number.isNaN(completedAtMs)) return 'Unknown'
|
||||
const seconds = Math.max(0, Math.floor((completedAtMs - startedAtMs) / 1000))
|
||||
return formatDuration(seconds) || '0s'
|
||||
}
|
||||
|
||||
const outcomeLabel = session?.outcome
|
||||
? session.outcome === 'workaround'
|
||||
? 'Workaround'
|
||||
: session.outcome.charAt(0).toUpperCase() + session.outcome.slice(1)
|
||||
: null
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex h-64 items-center justify-center">
|
||||
@@ -292,7 +317,20 @@ export function SessionDetailPage() {
|
||||
{session.completed_at ? 'Completed' : 'In Progress'}
|
||||
</span>
|
||||
{session.client_name && <span>Client: {session.client_name}</span>}
|
||||
{session.completed_at && (
|
||||
<span className="rounded-full bg-white/10 px-2 py-0.5 text-xs text-white">
|
||||
Duration: {getTotalDuration()}
|
||||
</span>
|
||||
)}
|
||||
{outcomeLabel && (
|
||||
<span className="rounded-full bg-white/10 px-2 py-0.5 text-xs text-white">
|
||||
Outcome: {outcomeLabel}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{session.outcome_notes && (
|
||||
<p className="mt-2 text-sm text-white/60">Outcome Notes: {session.outcome_notes}</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Actions */}
|
||||
@@ -401,6 +439,11 @@ export function SessionDetailPage() {
|
||||
Notes: {decision.notes}
|
||||
</p>
|
||||
)}
|
||||
{decision.duration_seconds != null && (
|
||||
<p className="mt-2 text-xs text-white/50">
|
||||
Duration: {formatDuration(decision.duration_seconds)}
|
||||
</p>
|
||||
)}
|
||||
<p className="mt-2 text-xs text-white/40">
|
||||
{formatDate(decision.timestamp)}
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user