1
+ import React , { useCallback , useEffect , useState } from 'react' ;
2
+ import clsx from "clsx" ;
3
+ import { BountyTileData , ContestSchedule , ContestTileData , ContestTileProps , ContestTileVariant } from "./ContestTile.types" ;
4
+ import { Status } from '../types' ;
5
+ import { ContestStatus } from '../ContestStatus' ;
6
+ import { Countdown } from './ContestTile' ;
7
+ import { getDates } from '../../utils/time' ;
8
+
9
+ export default function CompactTemplate ( {
10
+ variant,
11
+ htmlId,
12
+ title,
13
+ sponsorImage,
14
+ sponsorUrl,
15
+ contestData,
16
+ bountyData
17
+ } : ContestTileProps ) {
18
+ const variantClasses = clsx ( {
19
+ "compact--light" : variant === ContestTileVariant . COMPACT_LIGHT ,
20
+ "compact--dark" : variant === ContestTileVariant . COMPACT_DARK ,
21
+ } ) ;
22
+
23
+ const tileClasses = clsx ( {
24
+ c4contesttile : true ,
25
+ compact : true
26
+ } ) ;
27
+
28
+ return < div className = { clsx ( "c4tilewrapper" , variantClasses ) } >
29
+ < div id = { htmlId ?? undefined } className = { clsx ( variantClasses , tileClasses ) } >
30
+ < div className = "container--inner compact-content" >
31
+ { contestData && < IsContest
32
+ title = { title }
33
+ contestData = { contestData }
34
+ sponsorUrl = { sponsorUrl }
35
+ sponsorImage = { sponsorImage } /> }
36
+ { bountyData && < IsBounty
37
+ title = { title }
38
+ bountyData = { bountyData }
39
+ sponsorUrl = { sponsorUrl }
40
+ sponsorImage = { sponsorImage }
41
+ /> }
42
+ </ div >
43
+ </ div >
44
+ </ div >
45
+ }
46
+
47
+
48
+ const IsContest = ( { title, contestData, sponsorUrl, sponsorImage} : {
49
+ title : string ;
50
+ contestData : ContestTileData ;
51
+ sponsorUrl : string | undefined ;
52
+ sponsorImage : string | undefined ;
53
+ } ) => {
54
+ const { startDate, endDate, amount, contestUrl, contestType } = contestData ;
55
+ const [ contestTimelineObject , setContestTimelineObject ] = useState < ContestSchedule | undefined > ( ) ;
56
+
57
+ const updateContestTileStatus = useCallback ( ( ) => {
58
+ if ( contestData ) {
59
+ const { updateContestStatus } = contestData ;
60
+ if ( updateContestStatus ) {
61
+ updateContestStatus ( ) ;
62
+ }
63
+
64
+ if ( startDate && endDate ) {
65
+ const newTimelineObject = getDates ( contestData . startDate , contestData . endDate ) ;
66
+ setContestTimelineObject ( newTimelineObject ) ;
67
+ }
68
+ }
69
+ } , [ contestData ] ) ;
70
+
71
+ useEffect ( ( ) => {
72
+ if ( contestData && startDate && endDate ) {
73
+ const newTimelineObject = getDates ( startDate , endDate ) ;
74
+ setContestTimelineObject ( newTimelineObject ) ;
75
+ }
76
+ } , [ contestData ] )
77
+
78
+ return (
79
+ < div className = "body--contest" >
80
+ < header >
81
+ < div className = "header--status" >
82
+ { contestData && contestTimelineObject && < span >
83
+ < ContestStatus className = { clsx ( 'status' , contestTimelineObject . contestStatus === Status . ENDED && 'ended' ) }
84
+ status = { contestTimelineObject . contestStatus } />
85
+ { contestTimelineObject . contestStatus !== Status . ENDED && (
86
+ < div className = "timer" >
87
+ < Countdown
88
+ start = { startDate }
89
+ end = { endDate }
90
+ updateContestStatus = { updateContestTileStatus }
91
+ text = { contestTimelineObject . contestStatus === Status . UPCOMING ? 'Starts in ' : 'Ends in ' }
92
+ />
93
+ </ div >
94
+ ) }
95
+ </ span > }
96
+ < p className = "type" > { contestType } </ p >
97
+ </ div >
98
+ </ header >
99
+ < div className = "content--wrapper" >
100
+ { sponsorUrl ? (
101
+ < a
102
+ href = { sponsorUrl }
103
+ target = "_blank"
104
+ rel = "noreferrer noopener"
105
+ className = "logo"
106
+ >
107
+ < img
108
+ alt = "Sponsor logo"
109
+ src = { sponsorImage ?? "/" }
110
+ width = { 88 }
111
+ height = { 88 }
112
+ />
113
+ </ a >
114
+ ) : (
115
+ < img
116
+ alt = "Sponsor logo"
117
+ className = "logo"
118
+ src = { sponsorImage ?? "/" }
119
+ width = { 88 }
120
+ height = { 88 }
121
+ />
122
+ ) }
123
+ < div className = "content" >
124
+ < h2 className = "title" >
125
+ < a href = { `${ contestUrl } #top` } > { title } </ a >
126
+ </ h2 >
127
+ </ div >
128
+ < p className = "amount" > { amount } </ p >
129
+ </ div >
130
+ </ div >
131
+ ) }
132
+
133
+ const IsBounty = ( { title, bountyData, sponsorUrl, sponsorImage} : {
134
+ title : string ;
135
+ bountyData : BountyTileData ;
136
+ sponsorUrl : string | undefined ;
137
+ sponsorImage : string | undefined ;
138
+ } ) => {
139
+ const { amount, bountyUrl } = bountyData ;
140
+
141
+ return (
142
+ < div className = "body--bounty" >
143
+ < header >
144
+ { sponsorUrl ? (
145
+ < a
146
+ href = { sponsorUrl }
147
+ target = "_blank"
148
+ rel = "noreferrer noopener"
149
+ className = "logo"
150
+ >
151
+ < img
152
+ alt = "Sponsor logo"
153
+ src = { sponsorImage ?? "/" }
154
+ width = { 88 }
155
+ height = { 88 }
156
+ />
157
+ </ a >
158
+ ) : (
159
+ < img
160
+ alt = "Sponsor logo"
161
+ className = "logo"
162
+ src = { sponsorImage ?? "/" }
163
+ width = { 88 }
164
+ height = { 88 }
165
+ />
166
+ ) }
167
+ < h2 className = "title" >
168
+ < a href = { bountyUrl ? `${ bountyUrl } #top` : '#' } > { title } </ a >
169
+ </ h2 >
170
+ < p className = "type" > Bug Bounty</ p >
171
+ </ header >
172
+ < div className = "content--wrapper" >
173
+ < strong > Max Bounty</ strong >
174
+ < p className = "amount" > { amount } </ p >
175
+ </ div >
176
+ </ div >
177
+ ) }
0 commit comments