Skip to content

Commit 2abb10c

Browse files
Merge pull request #5515 from topcoder-platform/gig-apply-restrict
Gig apply restrict
2 parents 6a46fd5 + f696f4d commit 2abb10c

File tree

3 files changed

+97
-56
lines changed

3 files changed

+97
-56
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ workflows:
297297
filters:
298298
branches:
299299
only:
300-
- free
300+
- gig-apply-restrict
301301
# This is stage env for production QA releases
302302
- "build-prod-staging":
303303
context : org-global

src/server/services/recruitCRM.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -308,15 +308,29 @@ export default class RecruitCRMService {
308308
error: true,
309309
status: candidateResponse.status,
310310
url: `${this.private.baseUrl}/v1/candidates/search?email=${form.email}`,
311-
errObj: await candidateResponse.json(),
311+
errorObj: await candidateResponse.json(),
312312
};
313313
notifyKirilAndNick(error);
314314
return res.send(error);
315315
}
316316
let candidateData = await candidateResponse.json();
317317
if (candidateData.data) {
318-
// Candidate exists we will update profile fields
319-
// otherwise we create it
318+
// Candidate exists in recruitCRM
319+
// We will update profile fields, otherwise we create new candidate below
320+
// Check if candidate is placed in gig currently
321+
const candStatusIndex = _.findIndex(
322+
candidateData.data[0].custom_fields, { field_id: 12 },
323+
);
324+
if (candStatusIndex !== -1 && candidateData.data[0].custom_fields[candStatusIndex].value === 'Placed') {
325+
// reject application
326+
return res.send({
327+
error: true,
328+
errorObj: {
329+
notAllowed: true,
330+
message: 'Apologies, you are not allowed to apply to gigs if you are already placed on a gig.',
331+
},
332+
});
333+
}
320334
candidateSlug = candidateData.data[0].slug;
321335
const fieldIndexProfile = _.findIndex(
322336
candidateData.data[0].custom_fields, { field_id: 14 },
@@ -345,7 +359,7 @@ export default class RecruitCRMService {
345359
status: workCandidateResponse.status,
346360
url: `${this.private.baseUrl}/v1/candidates${candidateSlug ? `/${candidateSlug}` : ''}`,
347361
form,
348-
errObj: await workCandidateResponse.json(),
362+
errorObj: await workCandidateResponse.json(),
349363
};
350364
notifyKirilAndNick(error);
351365
return res.send(error);
@@ -371,7 +385,7 @@ export default class RecruitCRMService {
371385
fileData,
372386
file,
373387
formHeaders,
374-
errObj: await fileCandidateResponse.json(),
388+
errorObj: await fileCandidateResponse.json(),
375389
};
376390
notifyKirilAndNick(error);
377391
return res.send(error);
@@ -399,7 +413,7 @@ export default class RecruitCRMService {
399413
url: `${this.private.baseUrl}/v1/candidates/${candidateData.slug}/assign?job_slug=${id}`,
400414
form,
401415
candidateData,
402-
errObj,
416+
errorObj: errObj,
403417
};
404418
notifyKirilAndNick(error);
405419
return res.send(error);
@@ -423,7 +437,7 @@ export default class RecruitCRMService {
423437
status: hireStageResponse.status,
424438
url: `$${this.private.baseUrl}/v1/candidates/${candidateData.slug}/hiring-stages/${id}`,
425439
form,
426-
errObj: await hireStageResponse.json(),
440+
errorObj: await hireStageResponse.json(),
427441
};
428442
notifyKirilAndNick(error);
429443
return res.send(error);

src/shared/components/Gigs/GigApply/index.jsx

Lines changed: 75 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export default function GigApply(props) {
2929
} = props;
3030
const retUrl = window.location.href;
3131
const duration = getCustomField(job.custom_fields, 'Duration');
32+
const isPlaced = _.find(_.isEmpty(recruitProfile) ? [] : recruitProfile.custom_fields, { field_id: 12 });
3233

3334
return user ? (
3435
<div styleName="container">
@@ -45,10 +46,24 @@ export default function GigApply(props) {
4546
<h2>{job.name}</h2>
4647
<Link to={`${config.GIGS_PAGES_PATH}/${job.slug}`} styleName="back-link"><BackArrowGig /> GIG DETAILS</Link>
4748
<div styleName="separator" />
49+
{
50+
isPlaced && isPlaced.value === 'Placed' ? (
51+
<div styleName="apply-state">
52+
<SadFace />
53+
<h2>One Gig Limit!</h2>
54+
<React.Fragment>
55+
<p>Apologies, you are not allowed to apply to gigs if you are already placed on a gig.<br /><br />You can however refer a friend to this gig and receive $500 if they get placed in that gig. To do that, you can enter their email on the right side of the Gigs Description page.<br /><br />If you have any questions or feel this is an error, please email <a href="mailto:gigwork@topcoder.com">gigwork@topcoder.com</a>.</p>
56+
</React.Fragment>
57+
<div styleName="cta-buttons">
58+
<Link to={`${config.GIGS_PAGES_PATH}/${job.slug}`} styleName="primaryBtn">Back To Gig</Link>
59+
</div>
60+
</div>
61+
) : null
62+
}
4863
{
4964
application ? (
5065
<div styleName="apply-state">
51-
{ application.error ? <SadFace /> : <img src={bigCheckmark} alt="bigCheckmark OK" /> }
66+
{ application.error ? <SadFace /> : <img src={bigCheckmark} alt="bigCheckmark OK" />}
5267
<h2>{application.error ? 'OOPS!' : 'APPLICATION SUBMITTED'}</h2>
5368
{
5469
application.error ? (
@@ -58,8 +73,16 @@ export default function GigApply(props) {
5873
<p styleName="error-text">{application.errorObj.message || JSON.stringify(application.errorObj)}</p>
5974
) : null
6075
}
61-
<p>Looks like there is a problem on our end. Please try again.<br />If this persists please contact <a href="mailto:support@topcoder.com">support@topcoder.com</a>.</p>
62-
<p>Please send us an email at <a href="mailto:gigwork@topcoder.com">gigwork@topcoder.com</a> with the subject ‘Gig Error’<br />and paste the URL for the gig you are attempting to apply for so that we know of your interest.</p>
76+
{
77+
application.errorObj && application.errorObj.notAllowed ? (
78+
<p>If you have any questions or feel this is an error, please email <a href="mailto:gigwork@topcoder.com">gigwork@topcoder.com</a>.</p>
79+
) : (
80+
<React.Fragment>
81+
<p>Looks like there is a problem on our end. Please try again.<br />If this persists please contact <a href="mailto:support@topcoder.com">support@topcoder.com</a>.</p>
82+
<p>Please send us an email at <a href="mailto:gigwork@topcoder.com">gigwork@topcoder.com</a> with the subject ‘Gig Error’<br />and paste the URL for the gig you are attempting to apply for so that we know of your interest.</p>
83+
</React.Fragment>
84+
)
85+
}
6386
</React.Fragment>
6487
) : (
6588
<p>We will contact you via email if it seems like a fit!</p>
@@ -69,15 +92,19 @@ export default function GigApply(props) {
6992
{
7093
application.error ? (
7194
<React.Fragment>
72-
<a
73-
href="#"
74-
styleName="primaryBtn"
75-
onClick={(e) => {
76-
e.preventDefault();
77-
window.location.reload();
78-
}}
79-
>APPLY AGAIN
80-
</a>
95+
{
96+
!application.errorObj.notAllowed ? (
97+
<a
98+
href="#"
99+
styleName="primaryBtn"
100+
onClick={(e) => {
101+
e.preventDefault();
102+
window.location.reload();
103+
}}
104+
>APPLY AGAIN
105+
</a>
106+
) : null
107+
}
81108
<Link to={`${config.GIGS_PAGES_PATH}`}>VIEW OTHER GIGS</Link>
82109
</React.Fragment>
83110
) : (
@@ -97,18 +124,18 @@ export default function GigApply(props) {
97124
) : null
98125
}
99126
{
100-
!application && !applying ? (
127+
!application && !applying && (!isPlaced || isPlaced.value !== 'Placed') ? (
101128
<div styleName="form-wrap">
102129
{!_.isEmpty(recruitProfile)
103-
&& (
104-
<div styleName="info-text">
105-
<h6>It looks like you have applied to a gig previously. Perfect!<CheckmarkGreen /></h6>
106-
<p>We have most of your information. Is there anything you would like to update to your Gig Work Profile?</p>
107-
</div>
108-
)}
130+
&& (
131+
<div styleName="info-text">
132+
<h6>It looks like you have applied to a gig previously. Perfect!<CheckmarkGreen /></h6>
133+
<p>We have most of your information. Is there anything you would like to update to your Gig Work Profile?</p>
134+
</div>
135+
)}
109136
<h4>PERSONAL INFORMATION</h4>
110137
{_.isEmpty(recruitProfile)
111-
&& <p>Welcome to Topcoder Gigs! We’d like to get to know you.</p>}
138+
&& <p>Welcome to Topcoder Gigs! We’d like to get to know you.</p>}
112139
<div styleName="form-section">
113140
<div styleName="form-row">
114141
<TextInput
@@ -170,26 +197,26 @@ export default function GigApply(props) {
170197
</div>
171198
{_.isEmpty(recruitProfile) && <h4>TOPCODER INFORMATION</h4>}
172199
{_.isEmpty(recruitProfile) && (
173-
<div styleName="form-section">
174-
<div styleName="form-row">
175-
<TextInput
176-
placeholder="Topcoder Username"
177-
label="Topcoder Username"
178-
onChange={val => onFormInputChange('handle', val)}
179-
errorMsg={formErrors.handle}
180-
value={formData.handle}
181-
readonly
182-
/>
183-
<TextInput
184-
placeholder="Topcoder Profile (topcoder.com/members/[username])"
185-
label="Topcoder Profile"
186-
onChange={val => onFormInputChange('tcProfileLink', val)}
187-
errorMsg={formErrors.tcProfileLink}
188-
value={formData.handle ? `https://topcoder.com/members/${formData.handle}` : null}
189-
readonly
190-
/>
200+
<div styleName="form-section">
201+
<div styleName="form-row">
202+
<TextInput
203+
placeholder="Topcoder Username"
204+
label="Topcoder Username"
205+
onChange={val => onFormInputChange('handle', val)}
206+
errorMsg={formErrors.handle}
207+
value={formData.handle}
208+
readonly
209+
/>
210+
<TextInput
211+
placeholder="Topcoder Profile (topcoder.com/members/[username])"
212+
label="Topcoder Profile"
213+
onChange={val => onFormInputChange('tcProfileLink', val)}
214+
errorMsg={formErrors.tcProfileLink}
215+
value={formData.handle ? `https://topcoder.com/members/${formData.handle}` : null}
216+
readonly
217+
/>
218+
</div>
191219
</div>
192-
</div>
193220
)}
194221
<h4>SHARE YOUR WEEKLY PAY EXPECTATIONS</h4>
195222
<div styleName="form-section">
@@ -236,14 +263,14 @@ export default function GigApply(props) {
236263
<h4>FINAL QUESTIONS</h4>
237264
<div styleName="form-section">
238265
{_.isEmpty(recruitProfile) && (
239-
<Dropdown
240-
placeholder="How did you find out about Topcoder Gig Work?"
241-
label="How did you find out about Topcoder Gig Work?"
242-
onChange={val => onFormInputChange('reffereal', val)}
243-
errorMsg={formErrors.reffereal}
244-
options={formData.reffereal}
245-
required
246-
/>
266+
<Dropdown
267+
placeholder="How did you find out about Topcoder Gig Work?"
268+
label="How did you find out about Topcoder Gig Work?"
269+
onChange={val => onFormInputChange('reffereal', val)}
270+
errorMsg={formErrors.reffereal}
271+
options={formData.reffereal}
272+
required
273+
/>
247274
)}
248275
<div styleName="input-bot-margin" />
249276
<p>Are you able to work during the specified timezone? (<strong>{`${getCustomField(job.custom_fields, 'Timezone')}`}</strong>) *</p>
@@ -283,7 +310,7 @@ export default function GigApply(props) {
283310
</button>
284311
</div>
285312
) : null
286-
}
313+
}
287314
</div>
288315
)
289316
}

0 commit comments

Comments
 (0)