@@ -12,6 +12,7 @@ import {
12
12
} from 'react'
13
13
import { useLocation , useNavigate , useParams } from 'react-router-dom'
14
14
import { mutate } from 'swr'
15
+ import { toast } from 'react-toastify'
15
16
import moment from 'moment'
16
17
17
18
import {
@@ -28,13 +29,15 @@ import { textFormatDateLocaleShortString } from '~/libs/shared'
28
29
29
30
import { CopilotApplication } from '../../models/CopilotApplication'
30
31
import {
32
+ cancelCopilotOpportunity ,
31
33
copilotBaseUrl ,
32
34
CopilotOpportunityResponse ,
33
35
useCopilotApplications ,
34
36
useCopilotOpportunity ,
35
37
} from '../../services/copilot-opportunities'
36
38
import { FormattedMembers , useMembers } from '../../services/members'
37
39
import { copilotRoutesMap } from '../../copilots.routes'
40
+ import { ProjectType } from '../../constants'
38
41
39
42
import { ApplyOpportunityModal } from './apply-opportunity-modal'
40
43
import {
@@ -103,7 +106,7 @@ const CopilotOpportunityDetails: FC<{}> = () => {
103
106
104
107
const onApplied : ( ) => void = useCallback ( ( ) => {
105
108
mutate ( `${ copilotBaseUrl } /copilots/opportunity/${ opportunityId } /applications` )
106
- mutate ( `${ copilotBaseUrl } /copilots /opportunity/${ opportunityId } ` )
109
+ mutate ( `${ copilotBaseUrl } /copilot /opportunity/${ opportunityId } ` )
107
110
} , [ ] )
108
111
109
112
const onCloseApplyModal : ( ) => void = useCallback ( ( ) => {
@@ -119,13 +122,42 @@ const CopilotOpportunityDetails: FC<{}> = () => {
119
122
)
120
123
}
121
124
125
+ async function cancelCopilotOpportunityHandler ( ) : Promise < void > {
126
+ if ( opportunityId ) {
127
+ await cancelCopilotOpportunity ( opportunityId )
128
+ mutate ( `${ copilotBaseUrl } /copilots/opportunity/${ opportunityId } /applications` )
129
+ mutate ( `${ copilotBaseUrl } /copilot/opportunity/${ opportunityId } ` )
130
+ toast . success ( 'Canceled copilot opportunity successfully' )
131
+ }
132
+
133
+ }
134
+
122
135
const applyCopilotOpportunityButton : ButtonProps = {
123
136
label : 'Apply as Copilot' ,
124
137
onClick : ( ) => setShowApplyOpportunityModal ( true ) ,
125
138
}
126
139
140
+ const cancelCopilotOpportunityButton : ButtonProps = {
141
+ label : 'Cancel opportunity' ,
142
+ onClick : cancelCopilotOpportunityHandler ,
143
+ }
144
+
127
145
const application = copilotApplications && copilotApplications [ 0 ]
128
- const isAlreadyMemberOfTheProject = profile && opportunity ?. members ?. includes ( profile . userId )
146
+
147
+ const getOpportunityType = ( type : string ) : ProjectType => {
148
+ switch ( type ) {
149
+ case 'ai' :
150
+ return ProjectType . ai
151
+ case 'datascience' :
152
+ return ProjectType . datascience
153
+ case 'dev' :
154
+ return ProjectType . developement
155
+ case 'design' :
156
+ return ProjectType . design
157
+ default :
158
+ return ProjectType . qa
159
+ }
160
+ }
129
161
130
162
return (
131
163
< ContentLayout
@@ -135,7 +167,11 @@ const CopilotOpportunityDetails: FC<{}> = () => {
135
167
&& copilotApplications
136
168
&& copilotApplications . length === 0
137
169
&& opportunity ?. status === 'active'
138
- && ! isAlreadyMemberOfTheProject ? applyCopilotOpportunityButton : undefined
170
+ && opportunity ?. canApplyAsCopilot ? applyCopilotOpportunityButton : undefined
171
+ }
172
+ secondaryButtonConfig = {
173
+ opportunity ?. status === 'active'
174
+ && isAdminOrPM ? cancelCopilotOpportunityButton : undefined
139
175
}
140
176
infoComponent = { ( isCopilot && ! ( copilotApplications
141
177
&& copilotApplications . length === 0
@@ -156,94 +192,101 @@ const CopilotOpportunityDetails: FC<{}> = () => {
156
192
{ isValidating && ! showNotFound && (
157
193
< LoadingSpinner />
158
194
) }
159
- < h1 className = { styles . header } >
160
- { opportunity ?. projectName }
161
- </ h1 >
162
- < div className = { styles . infoRow } >
163
- < div className = { styles . infoColumn } >
164
- < IconOutline . ClipboardCheckIcon className = { styles . icon } />
165
- < div className = { styles . infoText } >
166
- < span className = { styles . infoHeading } > Status</ span >
167
- < span className = { styles . infoValue } > { opportunity ?. status } </ span >
195
+ < div className = { styles . wrapper } >
196
+ < h1 className = { styles . header } >
197
+ { opportunity ?. projectName }
198
+ </ h1 >
199
+ < div className = { styles . infoRow } >
200
+ < div className = { styles . infoColumn } >
201
+ < IconOutline . ClipboardCheckIcon className = { styles . icon } />
202
+ < div className = { styles . infoText } >
203
+ < span className = { styles . infoHeading } > Status</ span >
204
+ < span className = { styles . infoValue } > { opportunity ?. status } </ span >
205
+ </ div >
168
206
</ div >
169
- </ div >
170
- < div className = { styles . infoColumn } >
171
- < IconOutline . PlayIcon className = { styles . icon } / >
172
- < div className = { styles . infoText } >
173
- < span className = { styles . infoHeading } > Start Date </ span >
174
- < span className = { styles . infoValue } >
175
- { moment ( opportunity ?. startDate )
176
- . format ( 'MMM D, YYYY' ) }
177
-
178
- </ span >
207
+ < div className = { styles . infoColumn } >
208
+ < IconOutline . PlayIcon className = { styles . icon } / >
209
+ < div className = { styles . infoText } >
210
+ < span className = { styles . infoHeading } > Start Date </ span >
211
+ < span className = { styles . infoValue } >
212
+ { moment ( opportunity ?. startDate )
213
+ . format ( 'MMM D, YYYY' ) }
214
+
215
+ </ span >
216
+ </ div >
179
217
</ div >
180
- </ div >
181
- < div className = { styles . infoColumn } >
182
- < IconOutline . CalendarIcon className = { styles . icon } / >
183
- < div className = { styles . infoText } >
184
- < span className = { styles . infoHeading } > Duration </ span >
185
- < span className = { styles . infoValue } >
186
- { opportunity ?. numWeeks }
187
- { ' ' }
188
- weeks
189
- </ span >
218
+ < div className = { styles . infoColumn } >
219
+ < IconOutline . CalendarIcon className = { styles . icon } / >
220
+ < div className = { styles . infoText } >
221
+ < span className = { styles . infoHeading } > Duration </ span >
222
+ < span className = { styles . infoValue } >
223
+ { opportunity ?. numWeeks }
224
+ { ' ' }
225
+ weeks
226
+ </ span >
227
+ </ div >
190
228
</ div >
191
- </ div >
192
- < div className = { styles . infoColumn } >
193
- < IconOutline . ClockIcon className = { styles . icon } / >
194
- < div className = { styles . infoText } >
195
- < span className = { styles . infoHeading } > Hours </ span >
196
- < span className = { styles . infoValue } >
197
- { opportunity ?. numHoursPerWeek }
198
- { ' ' }
199
- hours/week
200
- </ span >
229
+ < div className = { styles . infoColumn } >
230
+ < IconOutline . ClockIcon className = { styles . icon } / >
231
+ < div className = { styles . infoText } >
232
+ < span className = { styles . infoHeading } > Hours </ span >
233
+ < span className = { styles . infoValue } >
234
+ { opportunity ?. numHoursPerWeek }
235
+ { ' ' }
236
+ hours/week
237
+ </ span >
238
+ </ div >
201
239
</ div >
202
- </ div >
203
- < div className = { styles . infoColumn } >
204
- < IconOutline . CogIcon className = { styles . icon } />
205
- < div className = { styles . infoText } >
206
- < span className = { styles . infoHeading } > Type</ span >
207
- < span className = { styles . infoValue } > { opportunity ?. type } </ span >
240
+ < div className = { styles . infoColumn } >
241
+ < IconOutline . CogIcon className = { styles . icon } />
242
+ < div className = { styles . infoText } >
243
+ < span className = { styles . infoHeading } > Type</ span >
244
+ < span
245
+ className = { styles . infoValue }
246
+ >
247
+ { opportunity ?. type && getOpportunityType ( opportunity ?. type ) }
248
+ </ span >
249
+ </ div >
208
250
</ div >
209
- </ div >
210
- < div className = { styles . infoColumn } >
211
- < IconOutline . GlobeAltIcon className = { styles . icon } / >
212
- < div className = { styles . infoText } >
213
- < span className = { styles . infoHeading } > Working Hours </ span >
214
- < span className = { styles . infoValue } > { opportunity ?. tzRestrictions } </ span >
251
+ < div className = { styles . infoColumn } >
252
+ < IconOutline . GlobeAltIcon className = { styles . icon } / >
253
+ < div className = { styles . infoText } >
254
+ < span className = { styles . infoHeading } > Working Hours </ span >
255
+ < span className = { styles . infoValue } > { opportunity ?. tzRestrictions } </ span >
256
+ </ div >
215
257
</ div >
216
258
</ div >
217
- </ div >
218
- {
219
- initialized && (
220
- < TabsNavbar
221
- defaultActive = { activeTab }
222
- onChange = { handleTabChange }
223
- tabs = { getCopilotDetailsTabsConfig ( isAdminOrPM ) }
259
+ {
260
+ initialized && (
261
+ < TabsNavbar
262
+ defaultActive = { activeTab }
263
+ onChange = { handleTabChange }
264
+ tabs = { getCopilotDetailsTabsConfig ( isAdminOrPM ) }
265
+ />
266
+ )
267
+ }
268
+ { activeTab === CopilotDetailsTabViews . details && < OpportunityDetails opportunity = { opportunity } /> }
269
+ { activeTab === CopilotDetailsTabViews . applications && isAdminOrPM && opportunity && (
270
+ < CopilotApplications
271
+ copilotApplications = { copilotApplications }
272
+ opportunity = { opportunity }
273
+ members = { members }
224
274
/>
225
- )
226
- }
227
- { activeTab === CopilotDetailsTabViews . details && < OpportunityDetails opportunity = { opportunity } /> }
228
- { activeTab === CopilotDetailsTabViews . applications && isAdminOrPM && opportunity && (
229
- < CopilotApplications
230
- copilotApplications = { copilotApplications }
231
- opportunity = { opportunity }
232
- members = { members }
233
- />
234
- ) }
275
+ ) }
276
+
277
+ {
278
+ showApplyOpportunityModal
279
+ && opportunity && (
280
+ < ApplyOpportunityModal
281
+ copilotOpportunityId = { opportunity ?. id }
282
+ onClose = { onCloseApplyModal }
283
+ projectName = { opportunity ?. projectName }
284
+ onApplied = { onApplied }
285
+ />
286
+ )
287
+ }
288
+ </ div >
235
289
236
- {
237
- showApplyOpportunityModal
238
- && opportunity && (
239
- < ApplyOpportunityModal
240
- copilotOpportunityId = { opportunity ?. id }
241
- onClose = { onCloseApplyModal }
242
- projectName = { opportunity ?. projectName }
243
- onApplied = { onApplied }
244
- />
245
- )
246
- }
247
290
</ ContentLayout >
248
291
)
249
292
}
0 commit comments