Skip to content

Commit 51e8773

Browse files
authored
Merge pull request #1181 from topcoder-platform/dev
PROD: Copilot portal CRs & Bugs V3
2 parents d920ef4 + 9e4b437 commit 51e8773

File tree

10 files changed

+80
-24
lines changed

10 files changed

+80
-24
lines changed

src/apps/copilots/src/models/CopilotApplication.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ export interface CopilotApplication {
2020
opportunityStatus: string,
2121
existingMembership?: ExistingMembership,
2222
projectName: string,
23+
onApplied: () => void,
2324
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ const CopilotOpportunityDetails: FC<{}> = () => {
296296
copilotApplications={copilotApplications}
297297
opportunity={opportunity}
298298
members={members}
299+
onApplied={onApplied}
299300
/>
300301
)}
301302

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint-disable react/jsx-no-bind */
2+
import { FC } from 'react'
3+
4+
import { BaseModal, Button } from '~/libs/ui'
5+
6+
import styles from './styles.module.scss'
7+
8+
interface ConfirmModalProps {
9+
onClose: (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
10+
onApply: () => void
11+
}
12+
13+
const ConfirmModal: FC<ConfirmModalProps> = props => (
14+
<BaseModal
15+
onClose={props.onClose as () => void}
16+
open
17+
size='lg'
18+
title='Confirm to accept as copilot'
19+
buttons={(
20+
<>
21+
<Button primary onClick={props.onApply} label='Confirm' />
22+
<Button secondary onClick={props.onClose} label='Cancel' />
23+
</>
24+
)}
25+
>
26+
<div className={styles.applyCopilotModal}>
27+
<div className={styles.info}>
28+
Click &apos;Confirm&apos; to accept by updating project role to &apos;Copilot&apos;
29+
and complete this opportunity
30+
</div>
31+
</div>
32+
</BaseModal>
33+
)
34+
35+
export default ConfirmModal

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

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { useParams } from 'react-router-dom'
22
import { toast } from 'react-toastify'
3-
import { mutate } from 'swr'
43
import { useCallback, useMemo, useState } from 'react'
54

6-
import { assignCopilotOpportunity, copilotBaseUrl } from '~/apps/copilots/src/services/copilot-opportunities'
5+
import { assignCopilotOpportunity } from '~/apps/copilots/src/services/copilot-opportunities'
76
import { CopilotApplication, CopilotApplicationStatus } from '~/apps/copilots/src/models/CopilotApplication'
87
import { IconSolid, Tooltip } from '~/libs/ui'
98

109
import AlreadyMemberModal from './AlreadyMemberModal'
10+
import ConfirmModal from './ConfirmModal'
1111
import styles from './styles.module.scss'
1212

1313
const CopilotApplicationAction = (
@@ -16,6 +16,7 @@ const CopilotApplicationAction = (
1616
): JSX.Element => {
1717
const { opportunityId }: {opportunityId?: string} = useParams<{ opportunityId?: string }>()
1818
const [showAlreadyMemberModal, setShowAlreadyMemberModal] = useState(false)
19+
const [showConfirmModal, setShowConfirmModal] = useState(false)
1920
const isInvited = useMemo(
2021
() => allCopilotApplications
2122
&& allCopilotApplications.findIndex(item => item.status === CopilotApplicationStatus.INVITED) > -1,
@@ -32,19 +33,8 @@ const CopilotApplicationAction = (
3233

3334
if (copilotApplication.existingMembership) {
3435
setShowAlreadyMemberModal(true)
35-
return
36-
}
37-
38-
if (opportunityId) {
39-
try {
40-
await assignCopilotOpportunity(opportunityId, copilotApplication.id)
41-
toast.success('Invited a copilot')
42-
mutate(`${copilotBaseUrl}/copilots/opportunity/${opportunityId}/applications`)
43-
} catch (e) {
44-
const error = e as Error
45-
toast.error(error.message)
46-
}
47-
36+
} else {
37+
setShowConfirmModal(true)
4838
}
4939
}, [opportunityId, copilotApplication])
5040

@@ -56,8 +46,9 @@ const CopilotApplicationAction = (
5646

5747
await assignCopilotOpportunity(opportunityId, copilotApplication.id)
5848
toast.success('Accepted as copilot')
59-
mutate(`${copilotBaseUrl}/copilots/opportunity/${opportunityId}/applications`)
49+
copilotApplication.onApplied()
6050
setShowAlreadyMemberModal(false)
51+
setShowConfirmModal(false)
6152
} catch (e) {
6253
const error = e as Error
6354
toast.error(error.message)
@@ -68,6 +59,7 @@ const CopilotApplicationAction = (
6859
e.preventDefault()
6960
e.stopPropagation()
7061
setShowAlreadyMemberModal(false)
62+
setShowConfirmModal(false)
7163
}, [showAlreadyMemberModal])
7264

7365
return (
@@ -84,7 +76,7 @@ const CopilotApplicationAction = (
8476
!isInvited
8577
&& copilotApplication.status === CopilotApplicationStatus.PENDING
8678
&& copilotApplication.opportunityStatus === 'active' && (
87-
<Tooltip content='Send Invitation'>
79+
<Tooltip content='Accept'>
8880
<IconSolid.UserAddIcon />
8981
</Tooltip>
9082
)
@@ -107,6 +99,13 @@ const CopilotApplicationAction = (
10799
copilotApplication={copilotApplication}
108100
/>
109101
)}
102+
103+
{showConfirmModal && (
104+
<ConfirmModal
105+
onClose={onCloseModal}
106+
onApply={onApply}
107+
/>
108+
)}
110109
</div>
111110
)
112111
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ const CopilotApplications: FC<{
7777
copilotApplications?: CopilotApplication[]
7878
members?: FormattedMembers[]
7979
opportunity: CopilotOpportunity
80+
onApplied: () => void
8081
}> = props => {
8182
const getData = (): CopilotApplication[] => (props.copilotApplications ? props.copilotApplications.map(item => {
8283
const member = props.members && props.members.find(each => each.userId === item.userId)
@@ -85,6 +86,7 @@ const CopilotApplications: FC<{
8586
activeProjects: member?.activeProjects || 0,
8687
fulfilment: member?.copilotFulfillment || 0,
8788
handle: member?.handle,
89+
onApplied: props.onApplied,
8890
opportunityStatus: props.opportunity.status,
8991
pastProjects: member?.pastProjects || 0,
9092
projectName: props.opportunity.projectName,

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ const OpportunityDetails: FC<{
1414
{props.opportunity?.skills.map(item => (<span className={styles.skillPill}>{item.name}</span>))}
1515
</div>
1616
<h2 className={styles.subHeading}> Description </h2>
17-
<p>
18-
{props.opportunity?.overview}
19-
</p>
17+
{props.opportunity?.overview && (
18+
<div dangerouslySetInnerHTML={{
19+
__html: props.opportunity.overview.replace(/\n/g, '<br />'),
20+
}}
21+
/>
22+
)}
2023
</div>
2124
<div>
2225
<h2 className={styles.subHeading}> Complexity </h2>

src/apps/copilots/src/pages/copilot-request-form/index.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const CopilotRequestForm: FC<{}> = () => {
4545
const [formErrors, setFormErrors] = useState<any>({})
4646
const [paymentType, setPaymentType] = useState<string>('')
4747
const [projectFromQuery, setProjectFromQuery] = useState<Project>()
48+
const activeProjectStatuses = ['active', 'approved', 'draft', 'new']
4849

4950
const { data: copilotRequestData }: CopilotRequestResponse = useCopilotRequest(routeParams.requestId)
5051

@@ -114,7 +115,13 @@ const CopilotRequestForm: FC<{}> = () => {
114115
label: string;
115116
value: string;
116117
}>> {
117-
const response = await getProjects(inputValue)
118+
const response = await getProjects(inputValue, {
119+
filter: {
120+
status: {
121+
$in: [activeProjectStatuses],
122+
},
123+
},
124+
})
118125
return response.map(project => ({ label: project.name, value: project.id }))
119126
}
120127

@@ -494,6 +501,7 @@ const CopilotRequestForm: FC<{}> = () => {
494501
.setFullYear(new Date()
495502
.getFullYear() + 2))}
496503
minYear={new Date()}
504+
className={styles.datepicker}
497505
/>
498506
<p className={styles.formRow}>How many weeks will you need the copilot for?</p>
499507
<InputText

src/apps/copilots/src/pages/copilot-request-form/styles.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,8 @@ $gradient: linear-gradient(
9797
margin-right: $sp-1;
9898
}
9999
}
100+
101+
.datepicker input{
102+
color: black;
103+
}
100104
}

src/apps/copilots/src/pages/copilot-requests/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ const CopilotRequestsPage: FC = () => {
200200
className: styles.opportunityTitle,
201201
label: 'Title',
202202
propertyName: 'opportunityTitle',
203-
type: 'text',
203+
renderer: (copilotRequest: CopilotRequest) => (
204+
<div className={styles.title}>{copilotRequest.opportunityTitle}</div>
205+
),
206+
type: 'element',
204207
},
205208
{
206209
label: 'Type',

src/apps/copilots/src/services/projects.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ export const getProject = (projectId: string): Promise<Project> => {
6363
return xhrGetAsync<Project>(url)
6464
}
6565

66-
export const getProjects = (search?: string, filter?: any): Promise<Project[]> => {
67-
const params = { name: `"${search}"`, ...filter }
66+
export const getProjects = (search?: string, config?: {filter: any}): Promise<Project[]> => {
67+
const params = { name: search, ...config?.filter }
6868
const url = buildUrl(baseUrl, params)
6969
return xhrGetAsync<Project[]>(url)
7070
}

0 commit comments

Comments
 (0)