Commit f4129b48 authored by IT20613686's avatar IT20613686

Job posting endpoint and integration

parent 9a21a2a1
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const jobSchema = new Schema({
jobID: {
type: String,
},
title: {
type: String,
required: true,
},
company: {
type: String,
required: true,
},
location: {
type: String,
required: true,
},
workType: {
type: String,
required: true,
},
term: {
type: String,
required: true,
},
salary: {
type: Number,
required: true,
},
duration: {
type: String,
required: true,
},
deadline: {
type: Date,
required: true,
},
logo: {
type: String,
required: true,
},
responsibilities: {
type: String,
required: true,
},
qualifications: {
type: String,
required: true,
},
aboutJob: {
type: String,
required: true,
},
});
const Job = mongoose.model("Job", jobSchema);
module.exports = Job;
const router = require("express").Router();
const multer = require("multer");
let Job = require("../models/job");
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, "uploads");
},
filename: (req, file, cb) => {
cb(null, Date.now() + file.originalname);
},
});
const upload = multer({
storage: storage,
}).single("logo");
router.post("/add", upload, async (req, res) => {
const newJob = new Job({
jobID: req.body,
title: req.body.title,
company: req.body.company,
location: req.body.location,
workType: req.body.workType,
term: req.body.term,
salary: req.body.salary,
duration: req.body.duration,
deadline: req.body.deadline,
logo: req.file.filename,
responsibilities: req.body.responsibilities,
qualifications: req.body.qualifications,
aboutJob: req.body.aboutJob,
});
const totalNumberOfJobInDb = await Job.countDocuments();
// convert number to string, so we can concatenate 0s easily...
let numberToString = totalNumberOfJobInDb.toString();
// If length of number string is less than 5 then add leading 0s in nuberToString
if (numberToString.length < 3) {
for (let i = numberToString.length; i < 3; i++) {
numberToString = "0" + numberToString;
}
}
newJob.jobID = `JID${numberToString}`;
newJob
.save()
.then(() => {
res.status(200).send({ status: "Job added" });
})
.catch((err) => {
console.log(err);
res
.status(500)
.send({ status: "Error with adding job", error: err.message });
});
});
module.exports = router;
\ No newline at end of file
...@@ -5,8 +5,7 @@ const cors = require("cors"); ...@@ -5,8 +5,7 @@ const cors = require("cors");
const connectDB = require("./config/db"); const connectDB = require("./config/db");
const dotenv = require("dotenv"); const dotenv = require("dotenv");
const userRoutes = require("./routes/userRoutes"); const userRoutes = require("./routes/userRoutes");
// const hardwareRouter = require("./routes/hardwares.js"); const jobRoutes = require("./routes/jobs")
// const hardwareItemRouter = require("./routes/hardwareItems.js");
const { notFound, errorHandler } = require("./middlewares/errorMiddleware"); const { notFound, errorHandler } = require("./middlewares/errorMiddleware");
const app = express(); const app = express();
...@@ -21,8 +20,7 @@ app.use(bodyparser.urlencoded({ extended: true })); ...@@ -21,8 +20,7 @@ app.use(bodyparser.urlencoded({ extended: true }));
app.use('/uploads', express.static('./uploads')); app.use('/uploads', express.static('./uploads'));
app.use("/api/users", userRoutes); app.use("/api/users", userRoutes);
// app.use("/hardware", hardwareRouter); app.use("/job", jobRoutes)
// app.use("/hardwareItem", hardwareItemRouter);
app.use(notFound); app.use(notFound);
app.use(errorHandler); app.use(errorHandler);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
"name": "pro-hire", "name": "pro-hire",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@redux-devtools/extension": "^3.2.6",
"@testing-library/jest-dom": "^5.17.0", "@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
...@@ -18,8 +19,11 @@ ...@@ -18,8 +19,11 @@
"react-datepicker": "^4.21.0", "react-datepicker": "^4.21.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-quill": "^2.0.0", "react-quill": "^2.0.0",
"react-redux": "^8.1.3",
"react-router-dom": "^6.17.0", "react-router-dom": "^6.17.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
} }
}, },
...@@ -3261,6 +3265,18 @@ ...@@ -3261,6 +3265,18 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@redux-devtools/extension": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.2.6.tgz",
"integrity": "sha512-fWrqYAoFFKc5+78P/xWj+3NcoiJ07ak5qdiPTbO5CAuM5vE3dKk5fajpJyuOab+hLNEUJMTklCBYm+WTFcWWxA==",
"dependencies": {
"@babel/runtime": "^7.23.2",
"immutable": "^4.3.4"
},
"peerDependencies": {
"redux": "^3.1.0 || ^4.0.0"
}
},
"node_modules/@remix-run/router": { "node_modules/@remix-run/router": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz",
...@@ -4034,6 +4050,15 @@ ...@@ -4034,6 +4050,15 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
"integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/html-minifier-terser": { "node_modules/@types/html-minifier-terser": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
...@@ -4464,6 +4489,11 @@ ...@@ -4464,6 +4489,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.4.tgz",
"integrity": "sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ==" "integrity": "sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ=="
}, },
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.7", "version": "8.5.7",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz",
...@@ -9022,6 +9052,19 @@ ...@@ -9022,6 +9052,19 @@
"he": "bin/he" "he": "bin/he"
} }
}, },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/hoopy": { "node_modules/hoopy": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
...@@ -9313,6 +9356,11 @@ ...@@ -9313,6 +9356,11 @@
"url": "https://opencollective.com/immer" "url": "https://opencollective.com/immer"
} }
}, },
"node_modules/immutable": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
"integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA=="
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
...@@ -14940,6 +14988,49 @@ ...@@ -14940,6 +14988,49 @@
"react-dom": "^16 || ^17 || ^18" "react-dom": "^16 || ^17 || ^18"
} }
}, },
"node_modules/react-redux": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz",
"integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4 || ^5.0.0-beta.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
...@@ -15105,6 +15196,22 @@ ...@@ -15105,6 +15196,22 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/redux": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"peerDependencies": {
"redux": "^4"
}
},
"node_modules/reflect.getprototypeof": { "node_modules/reflect.getprototypeof": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
...@@ -17109,6 +17216,14 @@ ...@@ -17109,6 +17216,14 @@
"requires-port": "^1.0.0" "requires-port": "^1.0.0"
} }
}, },
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
...@@ -20301,6 +20416,15 @@ ...@@ -20301,6 +20416,15 @@
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
}, },
"@redux-devtools/extension": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/@redux-devtools/extension/-/extension-3.2.6.tgz",
"integrity": "sha512-fWrqYAoFFKc5+78P/xWj+3NcoiJ07ak5qdiPTbO5CAuM5vE3dKk5fajpJyuOab+hLNEUJMTklCBYm+WTFcWWxA==",
"requires": {
"@babel/runtime": "^7.23.2",
"immutable": "^4.3.4"
}
},
"@remix-run/router": { "@remix-run/router": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz",
...@@ -20862,6 +20986,15 @@ ...@@ -20862,6 +20986,15 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/hoist-non-react-statics": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
"integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/html-minifier-terser": { "@types/html-minifier-terser": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
...@@ -21239,6 +21372,11 @@ ...@@ -21239,6 +21372,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.4.tgz", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.4.tgz",
"integrity": "sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ==" "integrity": "sha512-IDaobHimLQhjwsQ/NMwRVfa/yL7L/wriQPMhw1ZJall0KX6E1oxk29XMDeilW5qTIg5aoiqf5Udy8U/51aNoQQ=="
}, },
"@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@types/ws": { "@types/ws": {
"version": "8.5.7", "version": "8.5.7",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz",
...@@ -24541,6 +24679,21 @@ ...@@ -24541,6 +24679,21 @@
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
}, },
"hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"requires": {
"react-is": "^16.7.0"
},
"dependencies": {
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}
}
},
"hoopy": { "hoopy": {
"version": "0.1.4", "version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz", "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
...@@ -24751,6 +24904,11 @@ ...@@ -24751,6 +24904,11 @@
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="
}, },
"immutable": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
"integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA=="
},
"import-fresh": { "import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
...@@ -28649,6 +28807,26 @@ ...@@ -28649,6 +28807,26 @@
"quill": "^1.3.7" "quill": "^1.3.7"
} }
}, },
"react-redux": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz",
"integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==",
"requires": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"dependencies": {
"react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}
}
},
"react-refresh": { "react-refresh": {
"version": "0.11.0", "version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
...@@ -28769,6 +28947,20 @@ ...@@ -28769,6 +28947,20 @@
"strip-indent": "^3.0.0" "strip-indent": "^3.0.0"
} }
}, },
"redux": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
"requires": {
"@babel/runtime": "^7.9.2"
}
},
"redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"requires": {}
},
"reflect.getprototypeof": { "reflect.getprototypeof": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
...@@ -30233,6 +30425,12 @@ ...@@ -30233,6 +30425,12 @@
"requires-port": "^1.0.0" "requires-port": "^1.0.0"
} }
}, },
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"requires": {}
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@redux-devtools/extension": "^3.2.6",
"@testing-library/jest-dom": "^5.17.0", "@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
...@@ -13,8 +14,11 @@ ...@@ -13,8 +14,11 @@
"react-datepicker": "^4.21.0", "react-datepicker": "^4.21.0",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-quill": "^2.0.0", "react-quill": "^2.0.0",
"react-redux": "^8.1.3",
"react-router-dom": "^6.17.0", "react-router-dom": "^6.17.0",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"redux": "^4.2.1",
"redux-thunk": "^2.4.2",
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {
......
import React, {useState} from 'react' import React, {useState, useCallback} from 'react'
import DatePicker from "react-datepicker"; import DatePicker from "react-datepicker";
import ReactQuill from "react-quill"; import ReactQuill from "react-quill";
import axios from 'axios';
import "react-datepicker/dist/react-datepicker.css"; import "react-datepicker/dist/react-datepicker.css";
import "react-quill/dist/quill.snow.css"; import "react-quill/dist/quill.snow.css";
import './JobPosting.css' import './JobPosting.css'
function JobPosting() { function JobPosting() {
const [selectedDate, setSelectedDate] = useState(new Date()); const [title, setTitle] = useState("");
const [company, setCompany] = useState("");
const [location, setLocation] = useState("");
const [workType, setWorkType] = useState("");
const [term, setTerm] = useState("");
const [salary, setSalary] = useState("");
const [duration, setDuration] = useState("");
const [deadline, setDeadline] = useState(new Date());
const [logo, setLogo] = useState("");
const [responsibilities, setResponsibilities] = useState(""); const [responsibilities, setResponsibilities] = useState("");
const [qualifications, setQualifications] = useState(""); const [qualifications, setQualifications] = useState("");
const [aboutJob, setAboutJob] = useState(""); const [aboutJob, setAboutJob] = useState("");
const handleQuillChange = (content, setContent) => {
// Remove <p> tags from the content
const strippedContent = content.replace(/<p><\/p>/g, ""); // Remove empty <p> tags
const finalContent = strippedContent.replace(/<p>(.*?)<\/p>/g, "$1\n"); // Preserve content structure
setContent(finalContent.trim());
};
function sendData(e) {
e.preventDefault();
const formData = new FormData();
formData.append("title", title);
formData.append("company", company);
formData.append("location", location);
formData.append("workType", workType);
formData.append("term", term);
formData.append("salary", salary);
formData.append("duration", duration);
formData.append("deadline", deadline);
formData.append("logo", logo);
formData.append("responsibilities", responsibilities);
formData.append("qualifications", qualifications);
formData.append("aboutJob", aboutJob);
axios
.post("http://localhost:8070/job/add", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then(() => {
alert("Job posted successfully");
window.location.reload();
})
.catch((err) => {
alert(err);
});
}
return ( return (
<div className="jobPosting"> <div className="jobPosting">
<form className="form-jobPosting"> <form className="form-jobPosting" onSubmit={sendData}>
<div className="form-group"> <div className="form-group">
<label htmlFor="jobTitle">Job Title</label> <label htmlFor="jobTitle">Job Title</label>
<input type="text" className="form-control" id="jobTitle" /> <input
type="text"
className="form-control"
id="jobTitle"
required
onChange={(e) => {
setTitle(e.target.value);
}}
/>
</div> </div>
<div className="form-group"> <div className="form-group">
<label htmlFor="companyName">Company Name</label> <label htmlFor="companyName">Company Name</label>
<select className="form-control" id="companyName"> <select
className="form-control"
id="companyName"
required
onChange={(e) => {
setCompany(e.target.value);
}}
>
<option value="" disabled selected> <option value="" disabled selected>
Select Company Select Company
</option> </option>
<option value="company1">Company 1</option> <option>InstaHire</option>
<option value="company2">Company 2</option>
</select> </select>
</div> </div>
<div className="form-group"> <div className="form-group">
<label htmlFor="location">Location</label> <label htmlFor="location">Location</label>
<select className="form-control" id="location"> <select
className="form-control"
id="location"
required
onChange={(e) => {
setLocation(e.target.value);
}}
>
<option value="" disabled selected> <option value="" disabled selected>
Select location Select location
</option> </option>
<option value="location1">Location 1</option> <option>No:365, Galle Road, Colombo 03</option>
<option value="location2">Location 2</option>
</select> </select>
</div> </div>
<div className="d-flex"> <div className="d-flex">
<div className="form-group col-md-6"> <div className="form-group col-md-6">
<label htmlFor="workType">Work Type</label> <label htmlFor="workType">Work Type</label>
<select className="form-control" id="workType"> <select
className="form-control"
id="workType"
required
onChange={(e) => {
setWorkType(e.target.value);
}}
>
<option value="" disabled selected> <option value="" disabled selected>
Select work type Select work type
</option> </option>
<option value="workType1">Work Type 1</option> <option>On-site</option>
<option value="workType2">Work Type 2</option> <option>Hybrid</option>
<option>Online</option>
</select> </select>
</div> </div>
<div className="form-group col-md-6" style={{ paddingLeft: "5px" }}> <div className="form-group col-md-6" style={{ paddingLeft: "5px" }}>
<label htmlFor="term">Term</label> <label htmlFor="term">Term</label>
<select className="form-control" id="term"> <select
className="form-control"
id="term"
required
onChange={(e) => {
setTerm(e.target.value);
}}
>
<option value="" disabled selected> <option value="" disabled selected>
Select term Select term
</option> </option>
<option value="term1">Term 1</option> <option>Full-time</option>
<option value="term2">Term 2</option> <option>Part-time</option>
</select> </select>
</div> </div>
</div> </div>
<div className="d-flex"> <div className="d-flex">
<div className="form-group col-md-6"> <div className="form-group col-md-6">
<label htmlFor="salary">Salary</label> <label htmlFor="salary">Salary</label>
<input type="number" className="form-control" id="salary" /> <input
type="number"
className="form-control"
id="salary"
required
onChange={(e) => {
setSalary(e.target.value);
}}
/>
</div> </div>
<div className="form-group col-md-6" style={{ paddingLeft: "5px" }}> <div className="form-group col-md-6" style={{ paddingLeft: "5px" }}>
<label htmlFor="duration">Duration</label> <label htmlFor="duration">Duration</label>
<select className="form-control" id="duration"> <select
className="form-control"
id="duration"
required
onChange={(e) => {
setDuration(e.target.value);
}}
>
<option value="" disabled selected> <option value="" disabled selected>
Select duration Select duration
</option> </option>
<option value="duration1">Duration 1</option> <option>6 months</option>
<option value="duration2">Duration 2</option> <option>1 year</option>
<option>2 year</option>
</select> </select>
</div> </div>
</div> </div>
...@@ -83,8 +183,8 @@ function JobPosting() { ...@@ -83,8 +183,8 @@ function JobPosting() {
<DatePicker <DatePicker
className="form-control" className="form-control"
id="deadline" id="deadline"
selected={selectedDate} selected={deadline}
onChange={(date) => setSelectedDate(date)} onChange={(date) => setDeadline(date)}
/> />
</div> </div>
</div> </div>
...@@ -95,9 +195,13 @@ function JobPosting() { ...@@ -95,9 +195,13 @@ function JobPosting() {
<label htmlFor="logo">Logo</label> <label htmlFor="logo">Logo</label>
<input <input
type="file" type="file"
name="logo"
className="form-control-file" className="form-control-file"
id="logo" id="logo"
accept="image/*" required
onChange={(e) => {
setLogo(e.target.files[0]);
}}
/> />
</div> </div>
</div> </div>
...@@ -106,7 +210,9 @@ function JobPosting() { ...@@ -106,7 +210,9 @@ function JobPosting() {
<ReactQuill <ReactQuill
theme="snow" theme="snow"
value={responsibilities} value={responsibilities}
onChange={setResponsibilities} onChange={(content) =>
handleQuillChange(content, setResponsibilities)
}
/> />
</div> </div>
...@@ -115,16 +221,24 @@ function JobPosting() { ...@@ -115,16 +221,24 @@ function JobPosting() {
<ReactQuill <ReactQuill
theme="snow" theme="snow"
value={qualifications} value={qualifications}
onChange={setQualifications} onChange={(content) =>
handleQuillChange(content, setQualifications)
}
/> />
</div> </div>
<div className="form-group"> <div className="form-group">
<label htmlFor="aboutJob">About the Job</label> <label htmlFor="aboutJob">About the Job</label>
<ReactQuill theme="snow" value={aboutJob} onChange={setAboutJob} /> <ReactQuill
theme="snow"
value={aboutJob}
onChange={(content) => handleQuillChange(content, setAboutJob)}
/>
</div> </div>
<div style={{ paddingTop: "10px" }}> <div style={{ paddingTop: "10px" }}>
<button className='btn btn-primary' type="submit">Post Job</button> <button className="btn btn-primary" type="submit">
Post Job
</button>
</div> </div>
</form> </form>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment