@@ -58,8 +58,36 @@ import { List, Workspace } from '../services/api/types'
5858
5959const { Title, Paragraph, Text } = Typography
6060
61+ // Helper function to calculate remaining test time
62+ const getRemainingTestTime = ( broadcast : Broadcast , testResults ?: any ) => {
63+ if (
64+ broadcast . status !== 'testing' ||
65+ ! broadcast . test_settings . enabled ||
66+ ! broadcast . test_settings . test_duration_hours
67+ ) {
68+ return null
69+ }
70+
71+ // Use test_started_at from testResults if available, otherwise use test_sent_at from broadcast
72+ const testStartTime = testResults ?. test_started_at || broadcast . test_sent_at
73+ if ( ! testStartTime ) {
74+ return null
75+ }
76+
77+ const startTime = dayjs ( testStartTime )
78+ const endTime = startTime . add ( broadcast . test_settings . test_duration_hours , 'hours' )
79+ const now = dayjs ( )
80+
81+ if ( now . isAfter ( endTime ) ) {
82+ return null // Don't show anything if expired
83+ }
84+
85+ // Use dayjs .to() method for natural time formatting
86+ return now . to ( endTime , true ) + ' remaining'
87+ }
88+
6189// Helper function to get status badge
62- const getStatusBadge = ( status : BroadcastStatus ) => {
90+ const getStatusBadge = ( status : BroadcastStatus , remainingTime ?: string | null ) => {
6391 switch ( status ) {
6492 case 'draft' :
6593 return < Badge status = "default" text = "Draft" />
@@ -76,7 +104,16 @@ const getStatusBadge = (status: BroadcastStatus) => {
76104 case 'failed' :
77105 return < Badge status = "error" text = "Failed" />
78106 case 'testing' :
79- return < Badge status = "processing" text = "A/B Testing" />
107+ return (
108+ < Space size = "small" >
109+ < Badge status = "processing" text = "A/B Testing" />
110+ { remainingTime && (
111+ < Text type = "secondary" style = { { fontSize : '12px' } } >
112+ ({ remainingTime } )
113+ </ Text >
114+ ) }
115+ </ Space >
116+ )
80117 case 'test_completed' :
81118 return < Badge status = "success" text = "Test Completed" />
82119 case 'winner_selected' :
@@ -373,6 +410,9 @@ const BroadcastCard: React.FC<BroadcastCardProps> = ({
373410 refetchInterval : broadcast . status === 'testing' ? 10000 : false // Refetch every 10 seconds during testing
374411 } )
375412
413+ // Calculate remaining test time
414+ const remainingTestTime = getRemainingTestTime ( broadcast , testResults )
415+
376416 // Handler for selecting winner
377417 const handleSelectWinner = async ( templateId : string ) => {
378418 try {
@@ -490,7 +530,7 @@ const BroadcastCard: React.FC<BroadcastCardProps> = ({
490530 trigger = "hover"
491531 >
492532 < span className = "cursor-help" >
493- { getStatusBadge ( broadcast . status ) }
533+ { getStatusBadge ( broadcast . status , remainingTestTime ) }
494534 < FontAwesomeIcon
495535 icon = { faCircleQuestion }
496536 style = { { opacity : 0.7 } }
@@ -500,11 +540,11 @@ const BroadcastCard: React.FC<BroadcastCardProps> = ({
500540 </ Popover >
501541 ) : isTaskLoading ? (
502542 < span className = "text-gray-400" >
503- { getStatusBadge ( broadcast . status ) }
543+ { getStatusBadge ( broadcast . status , remainingTestTime ) }
504544 < FontAwesomeIcon icon = { faSpinner } spin className = "ml-2" />
505545 </ span >
506546 ) : (
507- getStatusBadge ( broadcast . status )
547+ getStatusBadge ( broadcast . status , remainingTestTime )
508548 ) }
509549 </ div >
510550 </ Space >
0 commit comments