@@ -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,6 +29,7 @@ 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 ,
@@ -104,7 +106,7 @@ const CopilotOpportunityDetails: FC<{}> = () => {
104
106
105
107
const onApplied : ( ) => void = useCallback ( ( ) => {
106
108
mutate ( `${ copilotBaseUrl } /copilots/opportunity/${ opportunityId } /applications` )
107
- mutate ( `${ copilotBaseUrl } /copilots /opportunity/${ opportunityId } ` )
109
+ mutate ( `${ copilotBaseUrl } /copilot /opportunity/${ opportunityId } ` )
108
110
} , [ ] )
109
111
110
112
const onCloseApplyModal : ( ) => void = useCallback ( ( ) => {
@@ -120,11 +122,26 @@ const CopilotOpportunityDetails: FC<{}> = () => {
120
122
)
121
123
}
122
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
+
123
135
const applyCopilotOpportunityButton : ButtonProps = {
124
136
label : 'Apply as Copilot' ,
125
137
onClick : ( ) => setShowApplyOpportunityModal ( true ) ,
126
138
}
127
139
140
+ const cancelCopilotOpportunityButton : ButtonProps = {
141
+ label : 'Cancel opportunity' ,
142
+ onClick : cancelCopilotOpportunityHandler ,
143
+ }
144
+
128
145
const application = copilotApplications && copilotApplications [ 0 ]
129
146
130
147
const getOpportunityType = ( type : string ) : ProjectType => {
@@ -152,6 +169,10 @@ const CopilotOpportunityDetails: FC<{}> = () => {
152
169
&& opportunity ?. status === 'active'
153
170
&& opportunity ?. canApplyAsCopilot ? applyCopilotOpportunityButton : undefined
154
171
}
172
+ secondaryButtonConfig = {
173
+ opportunity ?. status === 'active'
174
+ && isAdminOrPM ? cancelCopilotOpportunityButton : undefined
175
+ }
155
176
infoComponent = { ( isCopilot && ! ( copilotApplications
156
177
&& copilotApplications . length === 0
157
178
) && opportunity ?. status === 'active' && ! ! application ) && (
@@ -171,98 +192,101 @@ const CopilotOpportunityDetails: FC<{}> = () => {
171
192
{ isValidating && ! showNotFound && (
172
193
< LoadingSpinner />
173
194
) }
174
- < h1 className = { styles . header } >
175
- { opportunity ?. projectName }
176
- </ h1 >
177
- < div className = { styles . infoRow } >
178
- < div className = { styles . infoColumn } >
179
- < IconOutline . ClipboardCheckIcon className = { styles . icon } />
180
- < div className = { styles . infoText } >
181
- < span className = { styles . infoHeading } > Status</ span >
182
- < 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 >
183
206
</ div >
184
- </ div >
185
- < div className = { styles . infoColumn } >
186
- < IconOutline . PlayIcon className = { styles . icon } />
187
- < div className = { styles . infoText } >
188
- < span className = { styles . infoHeading } > Start Date</ span >
189
- < span className = { styles . infoValue } >
190
- { moment ( opportunity ?. startDate )
191
- . format ( 'MMM D, YYYY' ) }
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' ) }
192
214
193
- </ span >
215
+ </ span >
216
+ </ div >
194
217
</ div >
195
- </ div >
196
- < div className = { styles . infoColumn } >
197
- < IconOutline . CalendarIcon className = { styles . icon } / >
198
- < div className = { styles . infoText } >
199
- < span className = { styles . infoHeading } > Duration </ span >
200
- < span className = { styles . infoValue } >
201
- { opportunity ?. numWeeks }
202
- { ' ' }
203
- weeks
204
- </ 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 >
205
228
</ div >
206
- </ div >
207
- < div className = { styles . infoColumn } >
208
- < IconOutline . ClockIcon className = { styles . icon } / >
209
- < div className = { styles . infoText } >
210
- < span className = { styles . infoHeading } > Hours </ span >
211
- < span className = { styles . infoValue } >
212
- { opportunity ?. numHoursPerWeek }
213
- { ' ' }
214
- hours/week
215
- </ 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 >
216
239
</ div >
217
- </ div >
218
- < div className = { styles . infoColumn } >
219
- < IconOutline . CogIcon className = { styles . icon } / >
220
- < div className = { styles . infoText } >
221
- < span className = { styles . infoHeading } > Type </ span >
222
- < span
223
- className = { styles . infoValue }
224
- >
225
- { opportunity ?. type && getOpportunityType ( opportunity ?. type ) }
226
- </ 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 >
227
250
</ div >
228
- </ div >
229
- < div className = { styles . infoColumn } >
230
- < IconOutline . GlobeAltIcon className = { styles . icon } / >
231
- < div className = { styles . infoText } >
232
- < span className = { styles . infoHeading } > Working Hours </ span >
233
- < 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 >
234
257
</ div >
235
258
</ div >
236
- </ div >
237
- {
238
- initialized && (
239
- < TabsNavbar
240
- defaultActive = { activeTab }
241
- onChange = { handleTabChange }
242
- 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 }
243
274
/>
244
- )
245
- }
246
- { activeTab === CopilotDetailsTabViews . details && < OpportunityDetails opportunity = { opportunity } /> }
247
- { activeTab === CopilotDetailsTabViews . applications && isAdminOrPM && opportunity && (
248
- < CopilotApplications
249
- copilotApplications = { copilotApplications }
250
- opportunity = { opportunity }
251
- members = { members }
252
- />
253
- ) }
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 >
254
289
255
- {
256
- showApplyOpportunityModal
257
- && opportunity && (
258
- < ApplyOpportunityModal
259
- copilotOpportunityId = { opportunity ?. id }
260
- onClose = { onCloseApplyModal }
261
- projectName = { opportunity ?. projectName }
262
- onApplied = { onApplied }
263
- />
264
- )
265
- }
266
290
</ ContentLayout >
267
291
)
268
292
}
0 commit comments