Skip to content

Commit 2001031

Browse files
committed
feat: added cancel opportunity button and some design changes
1 parent 0393ba4 commit 2001031

File tree

5 files changed

+118
-86
lines changed

5 files changed

+118
-86
lines changed

src/apps/copilots/src/pages/copilot-opportunity-details/index.tsx

Lines changed: 98 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { textFormatDateLocaleShortString } from '~/libs/shared'
2828

2929
import { CopilotApplication } from '../../models/CopilotApplication'
3030
import {
31+
cancelCopilotOpportunity,
3132
copilotBaseUrl,
3233
CopilotOpportunityResponse,
3334
useCopilotApplications,
@@ -119,11 +120,25 @@ const CopilotOpportunityDetails: FC<{}> = () => {
119120
)
120121
}
121122

123+
async function cancelCopilotOpportunityHandler() {
124+
if (opportunityId) {
125+
await cancelCopilotOpportunity(opportunityId)
126+
mutate(`${copilotBaseUrl}/copilots/opportunity/${opportunityId}/applications`)
127+
mutate(`${copilotBaseUrl}/copilots/opportunity/${opportunityId}`)
128+
}
129+
130+
}
131+
122132
const applyCopilotOpportunityButton: ButtonProps = {
123133
label: 'Apply as Copilot',
124134
onClick: () => setShowApplyOpportunityModal(true),
125135
}
126136

137+
const cancelCopilotOpportunityButton: ButtonProps = {
138+
label: 'Cancel opportunity',
139+
onClick: cancelCopilotOpportunityHandler,
140+
}
141+
127142
const application = copilotApplications && copilotApplications[0]
128143

129144
return (
@@ -136,6 +151,7 @@ const CopilotOpportunityDetails: FC<{}> = () => {
136151
&& opportunity?.status === 'active'
137152
&& opportunity?.canApplyAsCopilot ? applyCopilotOpportunityButton : undefined
138153
}
154+
secondaryButtonConfig={opportunity?.status === 'active' && isAdminOrPM ? cancelCopilotOpportunityButton : undefined}
139155
infoComponent={(isCopilot && !(copilotApplications
140156
&& copilotApplications.length === 0
141157
) && opportunity?.status === 'active' && !!application) && (
@@ -155,94 +171,97 @@ const CopilotOpportunityDetails: FC<{}> = () => {
155171
{isValidating && !showNotFound && (
156172
<LoadingSpinner />
157173
) }
158-
<h1 className={styles.header}>
159-
{opportunity?.projectName}
160-
</h1>
161-
<div className={styles.infoRow}>
162-
<div className={styles.infoColumn}>
163-
<IconOutline.ClipboardCheckIcon className={styles.icon} />
164-
<div className={styles.infoText}>
165-
<span className={styles.infoHeading}>Status</span>
166-
<span className={styles.infoValue}>{opportunity?.status}</span>
174+
<div className={styles.wrapper}>
175+
<h1 className={styles.header}>
176+
{opportunity?.projectName}
177+
</h1>
178+
<div className={styles.infoRow}>
179+
<div className={styles.infoColumn}>
180+
<IconOutline.ClipboardCheckIcon className={styles.icon} />
181+
<div className={styles.infoText}>
182+
<span className={styles.infoHeading}>Status</span>
183+
<span className={styles.infoValue}>{opportunity?.status}</span>
184+
</div>
167185
</div>
168-
</div>
169-
<div className={styles.infoColumn}>
170-
<IconOutline.PlayIcon className={styles.icon} />
171-
<div className={styles.infoText}>
172-
<span className={styles.infoHeading}>Start Date</span>
173-
<span className={styles.infoValue}>
174-
{moment(opportunity?.startDate)
175-
.format('MMM D, YYYY')}
176-
177-
</span>
186+
<div className={styles.infoColumn}>
187+
<IconOutline.PlayIcon className={styles.icon} />
188+
<div className={styles.infoText}>
189+
<span className={styles.infoHeading}>Start Date</span>
190+
<span className={styles.infoValue}>
191+
{moment(opportunity?.startDate)
192+
.format('MMM D, YYYY')}
193+
194+
</span>
195+
</div>
178196
</div>
179-
</div>
180-
<div className={styles.infoColumn}>
181-
<IconOutline.CalendarIcon className={styles.icon} />
182-
<div className={styles.infoText}>
183-
<span className={styles.infoHeading}>Duration</span>
184-
<span className={styles.infoValue}>
185-
{opportunity?.numWeeks}
186-
{' '}
187-
weeks
188-
</span>
197+
<div className={styles.infoColumn}>
198+
<IconOutline.CalendarIcon className={styles.icon} />
199+
<div className={styles.infoText}>
200+
<span className={styles.infoHeading}>Duration</span>
201+
<span className={styles.infoValue}>
202+
{opportunity?.numWeeks}
203+
{' '}
204+
weeks
205+
</span>
206+
</div>
189207
</div>
190-
</div>
191-
<div className={styles.infoColumn}>
192-
<IconOutline.ClockIcon className={styles.icon} />
193-
<div className={styles.infoText}>
194-
<span className={styles.infoHeading}>Hours</span>
195-
<span className={styles.infoValue}>
196-
{opportunity?.numHoursPerWeek}
197-
{' '}
198-
hours/week
199-
</span>
208+
<div className={styles.infoColumn}>
209+
<IconOutline.ClockIcon className={styles.icon} />
210+
<div className={styles.infoText}>
211+
<span className={styles.infoHeading}>Hours</span>
212+
<span className={styles.infoValue}>
213+
{opportunity?.numHoursPerWeek}
214+
{' '}
215+
hours/week
216+
</span>
217+
</div>
200218
</div>
201-
</div>
202-
<div className={styles.infoColumn}>
203-
<IconOutline.CogIcon className={styles.icon} />
204-
<div className={styles.infoText}>
205-
<span className={styles.infoHeading}>Type</span>
206-
<span className={styles.infoValue}>{opportunity?.type}</span>
219+
<div className={styles.infoColumn}>
220+
<IconOutline.CogIcon className={styles.icon} />
221+
<div className={styles.infoText}>
222+
<span className={styles.infoHeading}>Type</span>
223+
<span className={styles.infoValue}>{opportunity?.type}</span>
224+
</div>
207225
</div>
208-
</div>
209-
<div className={styles.infoColumn}>
210-
<IconOutline.GlobeAltIcon className={styles.icon} />
211-
<div className={styles.infoText}>
212-
<span className={styles.infoHeading}>Working Hours</span>
213-
<span className={styles.infoValue}>{opportunity?.tzRestrictions}</span>
226+
<div className={styles.infoColumn}>
227+
<IconOutline.GlobeAltIcon className={styles.icon} />
228+
<div className={styles.infoText}>
229+
<span className={styles.infoHeading}>Working Hours</span>
230+
<span className={styles.infoValue}>{opportunity?.tzRestrictions}</span>
231+
</div>
214232
</div>
215233
</div>
216-
</div>
217-
{
218-
initialized && (
219-
<TabsNavbar
220-
defaultActive={activeTab}
221-
onChange={handleTabChange}
222-
tabs={getCopilotDetailsTabsConfig(isAdminOrPM)}
234+
{
235+
initialized && (
236+
<TabsNavbar
237+
defaultActive={activeTab}
238+
onChange={handleTabChange}
239+
tabs={getCopilotDetailsTabsConfig(isAdminOrPM)}
240+
/>
241+
)
242+
}
243+
{activeTab === CopilotDetailsTabViews.details && <OpportunityDetails opportunity={opportunity} />}
244+
{activeTab === CopilotDetailsTabViews.applications && isAdminOrPM && opportunity && (
245+
<CopilotApplications
246+
copilotApplications={copilotApplications}
247+
opportunity={opportunity}
248+
members={members}
223249
/>
224-
)
225-
}
226-
{activeTab === CopilotDetailsTabViews.details && <OpportunityDetails opportunity={opportunity} />}
227-
{activeTab === CopilotDetailsTabViews.applications && isAdminOrPM && opportunity && (
228-
<CopilotApplications
229-
copilotApplications={copilotApplications}
230-
opportunity={opportunity}
231-
members={members}
232-
/>
233-
)}
250+
)}
234251

235-
{
236-
showApplyOpportunityModal
237-
&& opportunity && (
238-
<ApplyOpportunityModal
239-
copilotOpportunityId={opportunity?.id}
240-
onClose={onCloseApplyModal}
241-
projectName={opportunity?.projectName}
242-
onApplied={onApplied}
243-
/>
244-
)
245-
}
252+
{
253+
showApplyOpportunityModal
254+
&& opportunity && (
255+
<ApplyOpportunityModal
256+
copilotOpportunityId={opportunity?.id}
257+
onClose={onCloseApplyModal}
258+
projectName={opportunity?.projectName}
259+
onApplied={onApplied}
260+
/>
261+
)
262+
}
263+
</div>
264+
246265
</ContentLayout>
247266
)
248267
}

src/apps/copilots/src/pages/copilot-opportunity-details/styles.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
@import '@libs/ui/styles/includes';
22

3+
.wrapper {
4+
min-height: 800px;
5+
}
6+
37
.header {
48
display: flex;
59
align-items: center;

src/apps/copilots/src/pages/copilot-opportunity-details/tabs/copilot-applications/CopilotApplicationAction.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const CopilotApplicationAction = (
1515
): JSX.Element => {
1616
const { opportunityId }: {opportunityId?: string} = useParams<{ opportunityId?: string }>()
1717
const isInvited = useMemo(
18-
() => allCopilotApplications.findIndex(item => item.status === CopilotApplicationStatus.INVITED) > -1,
18+
() => allCopilotApplications && allCopilotApplications.findIndex(item => item.status === CopilotApplicationStatus.INVITED) > -1,
1919
[allCopilotApplications],
2020
)
2121
const onClick = useCallback(async () => {

src/apps/copilots/src/pages/copilot-opportunity-details/tabs/opportunity-details/OpportunityDetails.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ const OpportunityDetails: FC<{
1111
<div>
1212
<h2 className={styles.subHeading}> Required skills </h2>
1313
<div className={styles.skillsContainer}>
14-
{props.opportunity?.skills.map((skill: any) => (
15-
<div key={skill.id} className={styles.skillPill}>
16-
{skill.name}
17-
</div>
18-
))}
14+
{props.opportunity?.skills.map(item => item.name).join(",")}
1915
</div>
2016
<h2 className={styles.subHeading}> Description </h2>
2117
<p>

src/apps/copilots/src/services/copilot-opportunities.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import useSWR, { SWRResponse } from 'swr'
22
import useSWRInfinite, { SWRInfiniteResponse } from 'swr/infinite'
33

44
import { EnvironmentConfig } from '~/config'
5-
import { xhrGetAsync, xhrPostAsync } from '~/libs/core'
5+
import { xhrDeleteAsync, xhrGetAsync, xhrPostAsync } from '~/libs/core'
66
import { buildUrl } from '~/libs/shared/lib/utils/url'
77

88
import { CopilotOpportunity } from '../models/CopilotOpportunity'
@@ -120,6 +120,19 @@ export const assignCopilotOpportunity = async (
120120
return xhrPostAsync(url, { applicationId: applicationId.toString() }, {})
121121
}
122122

123+
/**
124+
* cancel copilot opportunity
125+
* @param opportunityId
126+
* @returns
127+
*/
128+
export const cancelCopilotOpportunity = async (
129+
opportunityId: string,
130+
): Promise<{applicationId: number}> => {
131+
const url = `${copilotBaseUrl}/copilots/opportunity/${opportunityId}/cancel`
132+
133+
return xhrDeleteAsync(url)
134+
}
135+
123136
/**
124137
* Custom hook to fetch copilot applications by opportunity id.
125138
*

0 commit comments

Comments
 (0)