diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3b0049b420..7d107a6dc6 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -283,21 +283,21 @@ workflows:
filters:
branches:
only:
- - route-redirects
+ - gig-application-update
# This is alternate dev env for parallel testing
- "build-qa":
context : org-global
filters:
branches:
only:
- - tco-leaderboard-fix
+ - free
# This is beta env for production soft releases
- "build-prod-beta":
context : org-global
filters:
branches:
only:
- - free
+ - develop
# This is stage env for production QA releases
- "build-prod-staging":
context : org-global
diff --git a/src/assets/images/checkmark-green.svg b/src/assets/images/checkmark-green.svg
new file mode 100644
index 0000000000..a31e6590cf
--- /dev/null
+++ b/src/assets/images/checkmark-green.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/src/assets/images/social.jpg b/src/assets/images/social.jpg
deleted file mode 100644
index 1d33709a45..0000000000
Binary files a/src/assets/images/social.jpg and /dev/null differ
diff --git a/src/assets/images/social.png b/src/assets/images/social.png
new file mode 100644
index 0000000000..f64e599238
Binary files /dev/null and b/src/assets/images/social.png differ
diff --git a/src/server/services/recruitCRM.js b/src/server/services/recruitCRM.js
index 1320f95467..4f8ee4e2e1 100644
--- a/src/server/services/recruitCRM.js
+++ b/src/server/services/recruitCRM.js
@@ -187,7 +187,9 @@ export default class RecruitCRMService {
const { body, file } = req;
const form = JSON.parse(body.form);
const fileData = new FormData();
- fileData.append('resume', file.buffer, file.originalname);
+ if (file) {
+ fileData.append('resume', file.buffer, file.originalname);
+ }
let candidateSlug;
let referralCookie = req.cookies[config.GROWSURF_COOKIE];
if (referralCookie) referralCookie = JSON.parse(referralCookie);
@@ -272,29 +274,31 @@ export default class RecruitCRMService {
});
}
candidateData = await workCandidateResponse.json();
- // Attach resume to candidate
- const formHeaders = fileData.getHeaders();
- const fileCandidateResponse = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateData.slug}`, {
- method: 'POST',
- headers: {
- Authorization: this.private.authorization,
- ...formHeaders,
- },
- body: fileData,
- });
- if (fileCandidateResponse.status >= 300) {
- return res.send({
- error: true,
- status: fileCandidateResponse.status,
- url: `${this.private.baseUrl}/v1/candidates/${candidateData.slug}`,
- form,
- fileData,
- file,
- formHeaders,
- errObj: await fileCandidateResponse.json(),
+ // Attach resume to candidate if uploaded
+ if (file) {
+ const formHeaders = fileData.getHeaders();
+ const fileCandidateResponse = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateData.slug}`, {
+ method: 'POST',
+ headers: {
+ Authorization: this.private.authorization,
+ ...formHeaders,
+ },
+ body: fileData,
});
+ if (fileCandidateResponse.status >= 300) {
+ return res.send({
+ error: true,
+ status: fileCandidateResponse.status,
+ url: `${this.private.baseUrl}/v1/candidates/${candidateData.slug}`,
+ form,
+ fileData,
+ file,
+ formHeaders,
+ errObj: await fileCandidateResponse.json(),
+ });
+ }
+ candidateData = await fileCandidateResponse.json();
}
- candidateData = await fileCandidateResponse.json();
// Candidate ready to apply for job
const applyResponse = await fetch(`${this.private.baseUrl}/v1/candidates/${candidateData.slug}/assign?job_slug=${id}`, {
method: 'POST',
diff --git a/src/shared/actions/recruitCRM.js b/src/shared/actions/recruitCRM.js
index 1b9b127f25..cc82b1446d 100644
--- a/src/shared/actions/recruitCRM.js
+++ b/src/shared/actions/recruitCRM.js
@@ -58,47 +58,45 @@ function normalizeRecruitPayload(job, payload) {
const perJob = [
`${job.name} ->`,
`Pay Expectation: ${payload.payExpectation}`,
- `Date Available: ${new Date(payload.availFrom).toDateString()}`,
- `Heard About Gig: ${payload.reffereal}`,
- `Why fit: ${payload.whyFit}`,
`Able to work during timezone? ${payload.timezoneConfirm.filter(s => s.value).map(() => getCustomField(job.custom_fields, 'Timezone')).join(',')}`,
- `Am I ok to work the duration? ${payload.durationConfirm.filter(s => s.value).map(s => s.label).join(',')}`,
- `Notes: ${payload.notes}`,
+ `Am I ok to work the duration? ${payload.durationConfirm.filter(s => s.value).map(() => getCustomField(job.custom_fields, 'Duration')).join(',')}`,
];
- return {
+ const referral = _.find(payload.reffereal, { selected: true });
+ const normalized = {
last_name: payload.lname,
first_name: payload.fname,
email: payload.email,
contact_number: payload.phone,
city: payload.city,
locality: _.find(payload.country, { selected: true }).label,
- available_from: payload.availFrom,
salary_expectation: payload.payExpectation,
skill: payload.skills.filter(s => s.selected).map(s => s.label).join(','),
custom_fields: [
- {
- field_id: 13,
- value: payload.reffereal || '',
- },
{
field_id: 1,
- value: payload.tcProfileLink || (payload.handle ? `topcoder.com/members/${payload.handle}` : ''),
+ value: payload.tcProfileLink || (payload.handle ? `https://topcoder.com/members/${payload.handle}` : ''),
},
{
field_id: 2,
value: payload.handle || '',
},
- {
- field_id: 3,
- value: payload.whyFit || '',
- },
{
field_id: 14,
value: perJob.join(','),
},
],
- resume: payload.fileCV,
};
+ if (referral) {
+ normalized.custom_fields.push({
+ field_id: 13,
+ value: referral.label,
+ });
+ }
+ if (payload.fileCV) {
+ normalized.resume = payload.fileCV;
+ }
+
+ return normalized;
}
/**
@@ -124,6 +122,37 @@ async function applyForJobDone(job, payload) {
}
}
+/**
+ * Search for cnadidate in recruit
+ */
+function searchCandidatesInit(email) {
+ return { email };
+}
+
+/**
+ * Search for cnadidate in recruit and get profile if available
+ * @param {string} email the email to search
+ */
+async function searchCandidatesDone(email) {
+ const ss = new Service();
+ try {
+ const res = await ss.searchCandidates(email);
+
+ return {
+ email,
+ data: res,
+ };
+ } catch (error) {
+ return {
+ email,
+ data: {
+ error: true,
+ errorObj: error,
+ },
+ };
+ }
+}
+
export default redux.createActions({
RECRUIT: {
GET_JOBS_INIT: getJobsInit,
@@ -132,5 +161,7 @@ export default redux.createActions({
GET_JOB_DONE: getJobDone,
APPLY_FOR_JOB_INIT: applyForJobInit,
APPLY_FOR_JOB_DONE: applyForJobDone,
+ SEARCH_CANDIDATES_INIT: searchCandidatesInit,
+ SEARCH_CANDIDATES_DONE: searchCandidatesDone,
},
});
diff --git a/src/shared/components/GUIKit/Assets/Styles/Includes/_mixin.scss b/src/shared/components/GUIKit/Assets/Styles/Includes/_mixin.scss
index 5589e9dc31..ef6b4576f7 100644
--- a/src/shared/components/GUIKit/Assets/Styles/Includes/_mixin.scss
+++ b/src/shared/components/GUIKit/Assets/Styles/Includes/_mixin.scss
@@ -4,6 +4,7 @@ $gui-kit-gray-90: #2a2a2a;
$gui-kit-level-2: #0ab88a;
$gui-kit-level-5: #ef476f;
$gui-kit-active-label: #229174;
+$gui-kit-readonly: #d4d4d4;
@mixin textInputLabel {
font-size: 12px;
diff --git a/src/shared/components/GUIKit/DropdownTerms/index.jsx b/src/shared/components/GUIKit/DropdownTerms/index.jsx
index 1ef2c69792..74001e88bd 100644
--- a/src/shared/components/GUIKit/DropdownTerms/index.jsx
+++ b/src/shared/components/GUIKit/DropdownTerms/index.jsx
@@ -41,6 +41,9 @@ function DropdownTerms({
selectInput[0].style.borderTop = 'none';
}
}, [focused, selectedOption]);
+ useEffect(() => {
+ setInternalTerms(terms);
+ }, [terms]);
const CustomReactSelectRow = React.forwardRef(({
className,
diff --git a/src/shared/components/GUIKit/JobListCard/index.jsx b/src/shared/components/GUIKit/JobListCard/index.jsx
index 135a4845ba..6502ff43bd 100644
--- a/src/shared/components/GUIKit/JobListCard/index.jsx
+++ b/src/shared/components/GUIKit/JobListCard/index.jsx
@@ -15,6 +15,7 @@ import iconBlackSkills from 'assets/images/icon-skills.png';
export default function JobListCard({
job,
}) {
+ const duration = getCustomField(job.custom_fields, 'Duration');
let skills = getCustomField(job.custom_fields, 'Technologies Required');
if (skills !== 'n/a') {
skills = skills.split(',');
@@ -39,7 +40,7 @@ export default function JobListCard({
We have most of your information. Is there anything you would like to update to your Gig Work Profile?
+Welcome to Topcoder Gigs! We’d like to get to know you.
+ {_.isEmpty(recruitProfile) + &&Welcome to Topcoder Gigs! We’d like to get to know you.
}Your Professional Work History
+ )} +Upload Your Resume or CV
+ { + recruitProfile.resume ? ( +Upload Your Resume or CV, {recruitProfile.resume.filename}
+ ) : ( +Upload Your Resume or CV
+ ) + }Please Complete the Following Questions
Are you able to work during the specified timezone? ({`${getCustomField(job.custom_fields, 'Timezone')}`})
+Are you able to work during the specified timezone? ({`${getCustomField(job.custom_fields, 'Timezone')}`}) *
Are you ok to work with the duration of the gig? ({`${getCustomField(job.custom_fields, 'Duration')}`})
-Are you ok to work with the duration of the gig? ({/^\d+$/.test(duration) ? `${duration} Weeks` : duration}) *
+