Skip to content

Commit

Permalink
ft<Job>:implemented job application through form
Browse files Browse the repository at this point in the history
  • Loading branch information
Timothy-py committed May 4, 2024
1 parent 5d3941e commit e013c19
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 20 deletions.
90 changes: 87 additions & 3 deletions controllers/jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ const {
validateJobStatus,
validateJobTimeRange,
validateCreateJob,
joiErrorMessage
joiErrorMessage,
validateApplyJobSchema
} = require('../middleware/validators');
const { UserJobType } = require('../utils/enum');

Expand Down Expand Up @@ -499,7 +500,7 @@ exports.getApplicants = asyncHandler(async (req, res, next) => {
* @description Applied For A New Job `Candidate Account Only`
* @route `/api/v1/job/a/:id`
* @access Private
* @type GET
* @type POST
*/
exports.applyJob = asyncHandler(async (req, res, next) => {
const isExist = await Jobs.exists({ _id: req.params.id });
Expand All @@ -526,7 +527,7 @@ exports.applyJob = asyncHandler(async (req, res, next) => {
_user: req.user._id,
date: Date.now(),
rejected: false,
accpected: false
accepted: false
}
}
},
Expand Down Expand Up @@ -582,6 +583,89 @@ exports.applyJob = asyncHandler(async (req, res, next) => {
res.end();
});

/**
* @author Timothy <adeyeyetimothy33@gmail.com>
* @description Applied For A Job through form`
* @route `/api/v1/job/form-apply/:id`
* @access Public
* @type POST
*/
exports.formJobApply = async (req, res) => {
try {
const { error, value } = validateApplyJobSchema(req.body);
if (error) return res.status(400).send(errorMessage);

const jobId = req.params.jobId;
const job = await Jobs.findById(jobId).select({
external_applicants: 1
});
if (!job)
return res
.status(404)
.json({ status: 'fail', message: 'Job no longer exists' });

const applicants = job.external_applicants;
// check if appliant already exists
applicants.forEach((applicant) => {
if (applicant.email === req.body.email) {
return res.status(409).json({
status: 'false',
message: 'User already applied for this job'
});
}
});

// apply for job
await Jobs.findOneAndUpdate(
{ _id: jobId },
{
$push: {
external_applicants: { ...value }
}
}
);

// TODO: Send email notification
return res
.status(200)
.json({ status: 'success', message: 'Application sent successfully' });
} catch (error) {
return res.status(500).json({
status: 'error',
message: 'Unable to send application',
error: error
});
}
};

/**
* @author Timothy <adeyeyetimothy33@gmail.com>
* @description Get applicants that applied through form`
* @route `/api/v1/job/form-applicants/:id`
* @access Private
* @type GET
*/
exports.formJobApplicants = async (req, res) => {
try {
const jobId = req.params.jobId;
const applicants = await Jobs.findById(jobId).select({
external_applicants: 1
});

return res.status(200).json({
status: 'success',
message: 'Job form applicants retrieved successfully',
data: applicants
});
} catch (error) {
return res.status(500).json({
status: 'error',
message: 'An error occurred while retrieving applicants',
error: error
});
}
};

/**
* @author Timothy Adeyeye <adeyeyetimothy33@gmail.com>
* @description Change the status of a job
Expand Down
14 changes: 13 additions & 1 deletion middleware/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ const jobSchema = Joi.object({
// }).required()
}).options({ allowUnknown: true });

const applyJobSchema = Joi.object({
firstName: Joi.string().required(),
lastName: Joi.string().required(),
email: Joi.string().required(),
jobTitle: Joi.string().optional(),
country: Joi.string().required(),
phoneNumber: Joi.string().optional(),
resumeURL: Joi.string().required()
});

const validateAdminInvite = validator(inviteAdminSchema);
const validateAdminLogin = validator(loginAdminSchema);
const validateJobStatus = validator(jobStatus);
Expand All @@ -107,6 +117,7 @@ const validateSendEmail = validator(sendEmailSchema);
const validateReportSchema = validator(createReportSchema);
const validatePasswordSchema = validator(passwordSchema);
const validateCreateJob = validator(jobSchema);
const validateApplyJobSchema = validator(applyJobSchema);

const joiErrorMessage = (error) => {
return error.details.map((detail) => {
Expand All @@ -125,5 +136,6 @@ module.exports = {
validateSendEmail,
validateReportSchema,
validatePasswordSchema,
validateCreateJob
validateCreateJob,
validateApplyJobSchema
};
32 changes: 17 additions & 15 deletions model/content.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
const mongoose = require("mongoose");
const mongoose = require('mongoose');

const contentSchema = new mongoose.Schema({
_post: {
type: mongoose.SchemaTypes.ObjectId,
required: [true, "a Content can't be created without a post ID"],
ref: "post",
unique:true
const contentSchema = new mongoose.Schema(
{
_post: {
type: mongoose.SchemaTypes.ObjectId,
required: [true, "a Content can't be created without a post ID"],
ref: 'post',
unique: true
},
message: {
type: String,
required: false
}
},
message: {
type: String,
required: false,
{
timestamps: true
}
},
{
timestamps: true
});
);

module.exports = mongoose.model("content", contentSchema);
module.exports = mongoose.model('content', contentSchema);
3 changes: 2 additions & 1 deletion model/jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ const jobSchema = new mongoose.Schema(
rejected: Boolean,
accepted: Boolean
}
]
],
external_applicants: []
},
{
timestamps: true
Expand Down
4 changes: 4 additions & 0 deletions routes/jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const {
closeJob,
openJob,
applyJob,
formJobApply,
formJobApplicants,
getApplicants,
updateStatus,
jobsByCompany,
Expand All @@ -40,6 +42,8 @@ router.get('/p/', R_protect, getMyJobs);

// Apply For A job
router.post('/a/:id', C_protect, applyJob);
router.post('/form-apply/:jobId', formJobApply);
router.get('/form-applicants/:jobId', R_protect, formJobApplicants);

// Veiw all applicants
router.get('/applicants/:id', R_protect, getApplicants);
Expand Down
62 changes: 62 additions & 0 deletions swagger/doc.job.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,36 @@
* $ref: '#/components/schemas/Job'
*/

// *************************UPDATE JOB DETAILS******************************
/**
* @openapi
* /jobs/form-apply/{jobId}:
* post:
* tags:
* - Job
* summary: Apply to job through form submission
* parameters:
* - in: path
* name: jobId
* schema:
* type: string
* required: true
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type:
* $ref: '#/components/schemas/JobForm'
* responses:
* 404:
* description: Job no longer exists
* 200:
* description: Application sent successfully
* 409:
* description: User already applied for this job
*/

// *************************VIEW JOBS PRIVATE ONLY TO COMPANY MEMBERS******************************
/**
* @openapi
Expand Down Expand Up @@ -257,6 +287,38 @@
* type: array
*/

// *************************VIEW ALL FORM APPLICANTS FOR A JOB**********************
/**
* @openapi
* /jobs/form-applicants/{jobId}:
* get:
* tags:
* - Job
* summary: Get all form applicants for a job
* parameters:
* - in: path
* name: jobId
* schema:
* type: string
* required: true
* responses:
* 401:
* description: Not Authorized
* 200:
* description: All job's applicants
* content:
* application/json:
* schema:
* type: object
* properties:
* success:
* example: true
* status:
* example: success
* data:
* type: array
*/

// *************************CLOSE A JOB******************************
/**
* @openapi
Expand Down
31 changes: 31 additions & 0 deletions swagger/doc.schemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -1046,3 +1046,34 @@
* - deals_access
* - forum_access
*/

// *************JOB APPLICATION FORM SCHEMA***********************************
/**
* @openapi
* components:
* schemas:
* JobForm:
* type: object
* required:
* - firstName
* - lastName
* - email
* - country
* - phoneNumber
* - resumeURL
* properties:
* firstName:
* type: string
* lastName:
* type: string
* email:
* type: string
* jobTitle:
* type: string
* country:
* type: string
* phoneNumber:
* type: string
* resumeURL:
* type: string
*/

0 comments on commit e013c19

Please sign in to comment.