Skip to content

Commit

Permalink
fix: added the thesis request view and added the check that a student…
Browse files Browse the repository at this point in the history
… can make only one thesis request at time
  • Loading branch information
MagliariElio committed Jan 15, 2024
1 parent f838cdd commit 0c0e7bf
Show file tree
Hide file tree
Showing 7 changed files with 342 additions and 146 deletions.
34 changes: 27 additions & 7 deletions backend/controllers/proposals.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,9 @@ module.exports = {
const teacher = await getTeacherById(req.body.supervisor);
if (!teacher?.data) {
console.error("[BACKEND-SERVER] This teacher doesn't exist");
res
.status(404)
.json({
error: "This teacher doesn't exist, enter a valid teacher!",
});
res.status(404).json({
error: "This teacher doesn't exist, enter a valid teacher!",
});
return;
}

Expand All @@ -161,13 +159,35 @@ module.exports = {
supervisor_id: req.body.supervisor,
student_id: req.user.id,
});
res.status(201).json({ response: thesisRequest });
res.status(thesisRequest.status).json({ response: thesisRequest.data });
} catch (err) {
console.error("[BACKEND-SERVER] Cannot insert new thesis request", err);
res.status(500).json({ error: "Internal server error has occurred" });
res.status(err.status).json({ error: err.data });
}
},

/**
* Get the thesis request of the autenticated user
*
* @params none
* @body none
* @returns { proposal: { request_id: number, title: string, ... } }
* @status 201 Success status
* @error 401 Unauthorized - if the user is not logged in
* @error 500 Internal Server Error - if something went wrong
*
* @note Refer to the official documentation for more details
*/
getThesisRequest: async (req, res) => {
proposalsService.getThesisRequest(req.user.id)
.then((result) => {
res.status(result.status).json({ response: result.data });
})
.catch((err) => {
res.status(err.status).json({ error: err.data });
});
},

/**
* Get all active proposals by a professor
*
Expand Down
20 changes: 20 additions & 0 deletions backend/routes/proposals.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ const isArrayOfStrings = (array) => {
* Route /api/proposals
*/

/**
* GET /api/proposals/requests
*
* @params none
* @body none
* @returns { proposal: { request_id: number, title: string, ... } }
* @status 201 Success status
* @error 401 Unauthorized - if the user is not logged in
* @error 500 Internal Server Error - if something went wrong
*
* @note Refer to the official documentation for more details
*/
router.get(
"/requests",
isLoggedIn,
isStudent,
proposalsController.getThesisRequest
);

/**
* GET /api/proposals
*
Expand Down Expand Up @@ -221,6 +240,7 @@ router.delete(
* @returns { proposal: { request_id: number, title: string, ... } }
* @status 201 Success status
* @error 401 Unauthorized - if the user is not logged in
* @error 403 Unauthorized - there is already a thesis request for the authenticated student
* @error 404 Invalid teacher - teacher not found in the db
* @error 422 Invalid body - invalid fields in request body
* @error 500 Internal Server Error - if something went wrong
Expand Down
92 changes: 74 additions & 18 deletions backend/service/proposals.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const db = require("./db");
const Proposal = require("../model/Proposal");
const ThesisRequest = require("../model/ThesisRequest.js");
const { getTeacherById } = require("./teachers.service.js");

exports.rowToProposal = (row) => {
return new Proposal(
Expand Down Expand Up @@ -37,26 +38,81 @@ exports.rowToThesisRequest = (row) => {
};

exports.insertThesisRequest = async (request) => {
try {
const result = await db.query(
`INSERT INTO thesis_request
return new Promise(async (resolve, reject) => {
try {
const thesis = await this.getThesisRequest(request.student_id);
if (thesis) {
console.error("[BACKEND-SERVER] Error in insertThesisRequest");
const alreadyExistsError = new Error("There is already a thesis request!");
alreadyExistsError.status = 403;
alreadyExistsError.data = "There is already a thesis request!";
reject(alreadyExistsError);
return;
}
} catch (err) {
if (err.status != 404) {
console.error("[BACKEND-SERVER] Error in insertThesisRequest", err);
reject(err);
return;
}
}

try {
const result = await db.query(
`INSERT INTO thesis_request
(request_id, title, description, supervisor_id, student_id, status)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING *;`,
[
request.request_id,
request.title,
request.description,
request.supervisor_id,
request.student_id,
"pending"
]
);
return this.rowToThesisRequest(result.rows[0]);
} catch (err) {
console.log(err);
throw err;
}
[
request.request_id,
request.title,
request.description,
request.supervisor_id,
request.student_id,
"pending"
]
);
resolve({ status: 201, data: this.rowToThesisRequest(result.rows[0]) });
} catch (err) {
console.error("[BACKEND-SERVER] Error in insertThesisRequest", err);
let error = new Error("Internal Server Error");
error.status = 500;
error.data = "Internal Server Error";
reject(error);
}
})
};

exports.getThesisRequest = async (student_id) => {
return new Promise((resolve, reject) => {
db.query(
`SELECT request_id, title, description, supervisor_id, student_id, status
FROM thesis_request
WHERE student_id = $1;`,
[student_id]
)
.then(async (rows) => {
if (rows.rows.length == 0) {
console.error("[BACKEND-SERVER] Error in getThesisRequest");
const notFoundError = new Error("Thesis request not found!");
notFoundError.status = 404;
notFoundError.data = "Thesis request not found!";
reject(notFoundError);
return;
}
let thesisRequest = this.rowToThesisRequest(rows.rows[0]);
thesisRequest.supervisor = (await getTeacherById(thesisRequest.supervisor_id)).data;
delete thesisRequest.supervisor_id;
resolve({ status: 200, data: thesisRequest });
})
.catch((err) => {
console.error("[BACKEND-SERVER] Error in getThesisRequest", err);
const error = new Error("Internal Server Error");
error.status = 500;
error.data = "Internal Server Error";
reject(error);
});
});
};

exports.getMaxThesisRequestIdNumber = async () => {
Expand Down Expand Up @@ -267,7 +323,7 @@ exports.getProposalById = (proposal_id) => {
const error4 = new Error("Internal Server Error");
error4.status = 500;
error4.data = "Internal Server Error";
reject(error4);
reject(error4);
});
});
};
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ function Main() {
<Route path="new" element={loggedUser && loggedUser.role === 0 ? <ProposalDetailsPage mode="add" /> : <UnAuthorizationPage isLoadingUser={isLoadingUser}/>} />
<Route path=":proposal_id/update" element={loggedUser && loggedUser.role === 0 ? <ProposalDetailsPage mode="update" /> : <UnAuthorizationPage isLoadingUser={isLoadingUser}/>} />
<Route path=":proposal_id/copy" element={loggedUser && loggedUser.role === 0 ? <ProposalDetailsPage mode="copy" /> : <UnAuthorizationPage isLoadingUser={isLoadingUser}/>} />
<Route path="requests/new" element={loggedUser && loggedUser.role === 1 ? <ThesisRequestDetailsPage /> : <UnAuthorizationPage isLoadingUser={isLoadingUser}/>} />
<Route path="requests" element={loggedUser && loggedUser.role === 1 ? <ThesisRequestDetailsPage /> : <UnAuthorizationPage isLoadingUser={isLoadingUser}/>} />
</Route>
</Route>
<Route path='*' element={<NotFoundPage />} />
Expand Down
29 changes: 29 additions & 0 deletions frontend/src/api/ProposalsAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,35 @@ module.exports = {
}
},

/**
* Get all the thesis request for the authenticated user
*
* GET /api/proposals/requests
*/
getThesisRequest: async () => {
try {
const response = await fetch(ProposalsAPIURL + "/requests", {
method: "GET",
headers: APIConfig.API_REQUEST_HEADERS,
credentials: "include"
});

if (response.ok) {
const resObject = await response.json();
return resObject.response;
} else {
if (response.status == 404) {
return undefined;
} else {
const res = await response.json();
throw new Error(res.error);
}
}
} catch (err) {
throw new Error(err);
}
},

/**
* Get all the teachers
*
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/TitleBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function TitleBar() {
</Col>
{loggedUser?.role === 1 &&
<Col xs={12} md="auto" className="my-1">
<Button type="button" id="add-thesis-request-btn" as={Link} to="/proposals/requests/new" className="title-bar-btn w-100">
<Button type="button" id="add-thesis-request-btn" as={Link} to="/proposals/requests" className="title-bar-btn w-100">
<span className="d-flex align-items-center">
<FaPen className="me-1" />
Thesis Request
Expand Down
Loading

0 comments on commit 0c0e7bf

Please sign in to comment.