As part of our group final project, my team and I were tasked with implementing the ideas behind Toaster Oven Lovin’. We used the Meteor-Application-Template-React template as the starting point for the application. The application uses Meteor with MongoDB, React, Bootstrap 5 to implement the functionality and design.
Taste Technologists was designed to give students (on-campus or off) a variety of easy and delicious recipes that:
For this project, each member of the team was responsible for both front-end and back-end (server side) code. Some of my responsibilities included:
You can view the Admin Panel in action here:
This project was a challenging experience since it was the first time that I was involved in writing code for both the front-end and back-end of a web application.
In carrying out my responsibilities, I learned about:
The following is a sample of the code used to render and implement the rating/review feature.
The rating/reviews form and comments appear in an Offcanvas Bootstrap component that is accessed via the recipe page by pressing on the “Reviews” button at the bottom of the page.
This code renders the Review Menu.
<>
<Button variant="secondary" id="review-button" onClick={handleShow} className="me-2">
Reviews
</Button>
<Offcanvas show={show} onHide={handleClose} placement="end" className="bg-img">
<Offcanvas.Header closeButton>
<Offcanvas.Title>Reviews</Offcanvas.Title>
</Offcanvas.Header>
<Offcanvas.Body>
<AddReview name={name} recipeId={recipeId} userID={userID} user={user} />
<h3>Reviews: {reviewCount}</h3>
<Accordion>
{currentItems.map((rev, idx) => (
<RecReviewItem key={idx} idx={idx} review={rev} />
))}
</Accordion>
<Pagination className="my-3">
{paginationItems}
</Pagination>
</Offcanvas.Body>
</Offcanvas>
</>
The AddReview component contains the form for users to submit their review for a recipe.
When a user submits a recipe review, they only need to provide a rating on a scale of 1 to 5 and a comment. After completing the form and hitting ‘submit,’ the submit function initiates a Meteor call to the Review.add Meteor method. Because users are logged in when creating a review, their identifying information can be easily accessed and passed along with the review to the Meteor method.
The following code executes once the user has correctly filled out the form and pressed the submit button:
const submit = (data, formRef) => {
const { rating, comment } = data.review[0];
const reviewInfo = { userID, user, rating: Number(rating), comment, created: new Date() };
Meteor.call(addReviewMethod, { recipeId, reviewInfo }, (error) => {
if (error) {
swal('Error', error.message, 'error');
} else {
swal('Success', 'Review added successfully', 'success');
formRef.reset();
}
});
};
When the Review.add method is called, it removes the old review if one exists, and adds the new review.
Meteor.methods({
'Review.add'({ recipeId, reviewInfo }) {
// Pulls the old review
RecReviews.collection.update(
{ recipeId: recipeId },
{ $pull: { review: { userID: reviewInfo.userID } } },
);
// Add the new review
RecReviews.collection.update(
{ recipeId: recipeId },
{ $addToSet: { review: reviewInfo } },
);
console.log('Successfully added into RecipesReviews');
},
});
If a recipe has one or more reviews, then they are rendered in the Review Menu as an accordion item.
/** Renders a single Accordion Item in the ReviewMenu Component. See components/ReviewMenu.jsx. */
const RecReviewItem = ({ review, idx }) => (
<Accordion.Item eventKey={idx}>
<Accordion.Header>
<Row className="w-100">
<Col md={6} lg={6} className="text-start">
Reviewer: {review.user}
</Col>
<Col md={6} lg={6} className="text-end text-lg-center">
{new Date(review.created).toLocaleDateString('en-US', {year: 'numeric',month: 'long',day: 'numeric',})}
</Col>
<Col md={12} lg={12} className="text-start">
Rating: {review.rating}/5
</Col>
</Row>
</Accordion.Header>
<Accordion.Body>
<h6>Comment: </h6>
<p className="review-comment">{review.comment}</p>
</Accordion.Body>
</Accordion.Item>
);
You can learn more about Taste Technologists at https://taste-technologists.github.io/.