-
Notifications
You must be signed in to change notification settings - Fork 510
Happy thoughts API - Emelie Nyberg #501
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
EmelieNyberg
wants to merge
4
commits into
Technigo:master
Choose a base branch
from
EmelieNyberg:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
bb7b8a8
was afraid to push too early due to the env file
EmelieNyberg 5a76a89
trying out two diffrent post codes, one from the material and one fro…
EmelieNyberg 061124f
trying out the second post code
EmelieNyberg 5b218d5
updated the readme file
EmelieNyberg File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,39 @@ | ||
| # Project Happy Thoughts API | ||
|
|
||
| Replace this readme with your own information about your project. | ||
|
|
||
| Start by briefly describing the assignment in a sentence or two. Keep it short and to the point. | ||
| This project involves creating an API for a "Happy Thoughts" platform, a positivity-focused version of Twitter. The assignment is to build a backend API that serves as a replacement for the Technigo-provided API, allowing a React frontend to interact with it seamlessly. The API will handle features like posting new thoughts, listing recent thoughts, and updating the number of likes (hearts) for each thought. | ||
|
|
||
| ## The problem | ||
|
|
||
| Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next? | ||
| To complete this project, I needed to design and implement a fully functional RESTful API using Node.js, Express, and MongoDB. The primary challenge was to ensure the API followed the specific requirements, such as input validation, endpoint functionality, and seamless integration with the existing frontend. | ||
|
|
||
| ### Approach and Tools: | ||
|
|
||
| - **Planning:** I broke down the project into key functionalities, starting with creating the Thought model, then implementing and testing each endpoint. | ||
| - **Technologies:** | ||
| - Backend Framework: Express.js to manage API routes and middleware. | ||
| - Database: MongoDB with Mongoose for data modeling and validation. | ||
| - Deployment: Deployed the API on Render to make it accessible for frontend integration. | ||
| - Validation: Used Mongoose schema validation and manual checks to ensure user input met all requirements. | ||
|
|
||
| ### Key Steps: | ||
|
|
||
| - **Thought Model:** | ||
| Defined a Mongoose schema with properties: | ||
| - message (required, 5-140 characters). | ||
| - hearts (default to 0, unassignable during creation). | ||
| - createdAt (default to current timestamp, unassignable during creation). | ||
| Endpoints: | ||
| - GET /thoughts: Returned up to 20 recent thoughts, sorted by creation date. | ||
| - POST /thoughts: Allowed new thoughts to be submitted, with proper validation and error handling. | ||
| - POST /thoughts/:thoughtId/like: Incremented the hearts property for a specific thought. | ||
| Validation and Error Handling: | ||
| - Ensured invalid input resulted in clear error messages and a 400 Bad Request status. | ||
| - Checked for non-existent thought IDs in the POST /thoughts/:thoughtId/like endpoint. | ||
| Frontend Integration: | ||
| - Updated the React app to use the new API by replacing the Technigo URL with the deployed API URL. | ||
|
|
||
| ## View it live | ||
|
|
||
| Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about. | ||
| Frontend Netlify: https://happy-thoughts-project-technigo.netlify.app/ | ||
| Frontend GitHub: https://github.com/EmelieNyberg/project-happy-thoughts-vite-ek | ||
| Backend Render: https://project-happy-thoughts-api-ek.onrender.com/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,24 +1,117 @@ | ||
| import cors from "cors"; | ||
| import express from "express"; | ||
| import mongoose from "mongoose"; | ||
| import dotenv from "dotenv"; | ||
| import expressListEndpoints from "express-list-endpoints"; | ||
|
|
||
| const mongoUrl = process.env.MONGO_URL || "mongodb://localhost/project-mongo"; | ||
| dotenv.config(); | ||
|
|
||
| const mongoUrl = process.env.MONGO_URL; //|| "mongodb://localhost/project-mongo"; | ||
| mongoose.connect(mongoUrl); | ||
| mongoose.Promise = Promise; | ||
|
|
||
| // Defines the port the app will run on. Defaults to 8080, but can be overridden | ||
| // when starting the server. Example command to overwrite PORT env variable value: | ||
| // PORT=9000 npm start | ||
| const port = process.env.PORT || 8080; | ||
| const port = process.env.PORT || 3000; | ||
| const app = express(); | ||
|
|
||
| // Add middlewares to enable cors and json body parsing | ||
| app.use(cors()); | ||
| app.use(express.json()); | ||
|
|
||
| const { Schema, model } = mongoose; | ||
|
|
||
| // Define mongoose Schema since more complex than just using mongoose model | ||
| const thoughtSchema = new Schema({ | ||
| message: { | ||
| type: String, | ||
| required: true, | ||
| minlength: 5, | ||
| maxlength: 140 | ||
| }, | ||
| hearts: { | ||
| type: Number, | ||
| default: 0 | ||
| }, | ||
| createdAt: { | ||
| type: Date, | ||
| default: Date.now | ||
| } | ||
| }); | ||
|
|
||
| const Thought = model('Thought', thoughtSchema); | ||
|
|
||
| // Start defining your routes here | ||
| app.get("/", (req, res) => { | ||
| res.send("Hello Technigo!"); | ||
| res.json(expressListEndpoints(app)); | ||
| }); | ||
|
|
||
| app.get("/thoughts", async (req, res) => { | ||
| const thoughts = await Thought.find().sort({ createdAt: 'desc' }).limit(20).exec(); | ||
| res.json(thoughts); | ||
| }); | ||
|
|
||
| app.post("/thoughts", async (req, res) => { | ||
| //Retrieve info that is sent by the user to our API endpoint | ||
| // I use {} around message to make sure ONLY message can be sent in by the user, not hearts and createdAt. | ||
| const { message } = req.body; | ||
| // Use our mongoose model to create the database entry | ||
| const thought = new Thought({ message }); | ||
|
|
||
| try { | ||
| // Success | ||
| const savedThought = await thought.save(); | ||
| res.status(201).json(savedThought); | ||
| } catch (err) { | ||
| res.status(400).json({ message: "Could not save thought to database", error: err.errors }); | ||
| } | ||
| }); | ||
|
|
||
| // app.post("/thoughts", async (req, res) => { | ||
| // //Retrieve info that is sent by the user to our API endpoint | ||
| // // I use {} around message to make sure ONLY message can be sent in by the user, not hearts and createdAt. | ||
| // const { message } = req.body; | ||
|
|
||
| // try { | ||
| // // Use our mongoose model to create the database entry | ||
| // const thought = await new Thought({ message }).save(); | ||
|
|
||
| // res.status(201).json({ | ||
| // success: true, | ||
| // response: thought, | ||
| // message: "thought is created" | ||
| // }); | ||
| // } catch (err) { | ||
| // res.status(400).json({ | ||
| // success: false, | ||
| // response: err.errors, | ||
| // message: "Could not save thought to database" | ||
| // }); | ||
| // } | ||
| // }); | ||
|
Comment on lines
+71
to
+92
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused code |
||
|
|
||
| app.post("/thoughts/:thoughtId/like", async (req, res) => { | ||
| // Get thoughtId from URL-param | ||
| // Could also do like this: const thoughtId = req.params.thoughtId; | ||
| const { thoughtId } = req.params; | ||
|
|
||
| try { | ||
| // Find a thought with right ID and increase hearts by 1 | ||
| const updatedThought = await Thought.findByIdAndUpdate( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⭐ |
||
| thoughtId, // Find thought based on ID | ||
| { $inc: { hearts: 1 } }, // Increments hearts with 1 | ||
| { new: true } // Return the updated thought | ||
| ); | ||
|
|
||
| if (updatedThought) { | ||
| res.status(200).json(updatedThought); // Send back the updated thought | ||
| } else { | ||
| res.status(404).json({ message: "Thought not found" }); // If no thought found | ||
| } | ||
| } catch (err) { | ||
| res.status(400).json({ message: "Could not update hearts", error: err.message }); | ||
| } | ||
| }); | ||
|
|
||
| // Start the server | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be consistent with double quotes