@@ -2,13 +2,14 @@ import { formatDeadline } from '@/utils/date';
22import { CurrencyBadge } from '@/components/ui/CurrencyBadge' ;
33import { RadiatingDot } from '@/components/ui/RadiatingDot' ;
44import { ContentTypeBadge } from '@/components/ui/ContentTypeBadge' ;
5- import { Check } from 'lucide-react' ;
5+ import { Check , Clock , XCircle } from 'lucide-react' ;
66import { useCurrencyPreference } from '@/contexts/CurrencyPreferenceContext' ;
7-
7+ import { Tooltip } from '@/components/ui/Tooltip' ;
88interface BountyMetadataLineProps {
99 amount : number ;
1010 expirationDate ?: string ;
11- isOpen : boolean ;
11+ reviewPeriodEndDate ?: string ;
12+ status : 'OPEN' | 'CLOSED' | 'REVIEW_PERIOD' | 'EXPIRED' | 'CANCELLED' ;
1213 expiringSoon : boolean ;
1314 className ?: string ;
1415 solutionsCount ?: number ;
@@ -18,19 +19,61 @@ interface BountyMetadataLineProps {
1819export const BountyMetadataLine = ( {
1920 amount,
2021 expirationDate,
21- isOpen,
22+ reviewPeriodEndDate,
23+ status,
2224 expiringSoon,
2325 className = '' ,
2426 showDeadline = true ,
2527} : BountyMetadataLineProps ) => {
2628 const { showUSD } = useCurrencyPreference ( ) ;
2729
28- // Format the deadline text
29- const deadlineText = isOpen
30- ? expirationDate
31- ? formatDeadline ( expirationDate )
32- : 'No deadline'
33- : 'Completed' ;
30+ const isOpen = status === 'OPEN' ;
31+ const isActive = status === 'OPEN' || status === 'REVIEW_PERIOD' ;
32+
33+ const getDeadlineText = ( ) => {
34+ switch ( status ) {
35+ case 'OPEN' :
36+ return expirationDate ? formatDeadline ( expirationDate ) : 'No deadline' ;
37+ case 'REVIEW_PERIOD' :
38+ if ( reviewPeriodEndDate ) {
39+ const deadline = formatDeadline ( reviewPeriodEndDate ) ;
40+ // Transform deadline text for review period
41+ if ( deadline === 'Ended' ) {
42+ return 'Review ended' ;
43+ } else if ( deadline === 'Ended today' ) {
44+ return 'Review ended today' ;
45+ } else if ( deadline === 'Ends today' ) {
46+ return 'Review ends today' ;
47+ } else if ( deadline === 'Ends tomorrow' ) {
48+ return 'Review ends tomorrow' ;
49+ } else if ( deadline . includes ( 'days left' ) ) {
50+ // "10 days left" → "Review ends in 10 days"
51+ const days = deadline . match ( / ( \d + ) d a y s l e f t / ) ?. [ 1 ] ;
52+ return `Review ends in ${ days } days` ;
53+ } else if ( deadline . startsWith ( 'Ends in' ) ) {
54+ // "Ends in 5 hours" → "Review ends in 5 hours"
55+ return deadline . replace ( 'Ends in' , 'Review ends in' ) ;
56+ } else if ( deadline === 'Ends in less than an hour' ) {
57+ return 'Review ends in less than an hour' ;
58+ } else if ( deadline . startsWith ( 'Ends ' ) ) {
59+ // "Ends Dec 15, 2024" → "Review ends Dec 15, 2024"
60+ return deadline . replace ( 'Ends' , 'Review ends' ) ;
61+ }
62+ return `Review ${ deadline . toLowerCase ( ) } ` ;
63+ }
64+ return 'Under Review' ;
65+ case 'CLOSED' :
66+ return 'Completed' ;
67+ case 'EXPIRED' :
68+ return 'Bounty Ended' ;
69+ case 'CANCELLED' :
70+ return 'Cancelled' ;
71+ default :
72+ return 'Completed' ;
73+ }
74+ } ;
75+
76+ const deadlineText = getDeadlineText ( ) ;
3477
3578 return (
3679 < div className = { `space-y-3 ${ className } ` } >
@@ -49,16 +92,47 @@ export const BountyMetadataLine = ({
4992
5093 { showDeadline && (
5194 < div className = "flex items-center gap-2 text-sm" >
52- { isOpen ? (
53- < RadiatingDot size = { 12 } dotSize = { 6 } isRadiating = { isOpen } className = "flex-shrink-0" />
95+ { isActive ? (
96+ < RadiatingDot
97+ size = { 12 }
98+ dotSize = { 6 }
99+ isRadiating = { isActive }
100+ className = "flex-shrink-0"
101+ />
102+ ) : status === 'EXPIRED' ? (
103+ < XCircle size = { 14 } className = "text-gray-500 flex-shrink-0" />
54104 ) : (
55105 < Check size = { 14 } className = "text-green-600 flex-shrink-0" />
56106 ) }
57- < span
58- className = { `${ isOpen ? ( expiringSoon ? 'text-orange-600 font-medium' : 'text-gray-700' ) : 'text-green-700 font-medium' } ` }
59- >
60- { deadlineText }
61- </ span >
107+ { status === 'REVIEW_PERIOD' ? (
108+ < Tooltip
109+ content = {
110+ < div className = "flex items-start gap-3 text-left" >
111+ < div className = "bg-orange-100 p-2 rounded-md flex items-center justify-center" >
112+ < Clock className = "h-5 w-5 text-orange-600" />
113+ </ div >
114+ < div >
115+ Bounty creators get extra time after the deadline to review submissions and
116+ award funds.
117+ </ div >
118+ </ div >
119+ }
120+ position = "top"
121+ width = "w-[360px]"
122+ >
123+ < span
124+ className = { `${ isActive ? ( expiringSoon ? 'text-orange-600 font-medium' : 'text-gray-700' ) : status === 'EXPIRED' ? 'text-gray-500' : 'text-green-700 font-medium' } cursor-help underline decoration-dotted underline-offset-2` }
125+ >
126+ { deadlineText }
127+ </ span >
128+ </ Tooltip >
129+ ) : (
130+ < span
131+ className = { `${ isActive ? ( expiringSoon ? 'text-orange-600 font-medium' : 'text-gray-700' ) : status === 'EXPIRED' ? 'text-gray-500' : 'text-green-700 font-medium' } ` }
132+ >
133+ { deadlineText }
134+ </ span >
135+ ) }
62136 </ div >
63137 ) }
64138 </ div >
0 commit comments