-
Notifications
You must be signed in to change notification settings - Fork 516
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
Project Happy Thoughts API - Kathinka #487
base: master
Are you sure you want to change the base?
Changes from all commits
35ea83a
1e32fd2
ced3399
d0e32db
14a91ae
9f5adab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,14 @@ | ||
# 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. | ||
made my own api for the happy thoughts site we built in week 7 | ||
|
||
## The problem | ||
Started working in the [template](https://github.com/kathinka/express-api-starter), and copied my work over into this repo. | ||
|
||
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? | ||
Started building the API as I have done on the last tasks | ||
wanted to add more to is as well, som made endpoint for it, but did not complete it as I rather wanted to join my team on working on the final task. So I revisit this later when I have more time! | ||
|
||
## 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. | ||
View it live: | ||
- [API](https://project-happy-thoughts-api-sw6f.onrender.com/) | ||
- [Client](https://happyhappenings.netlify.app/) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import mongoose from "mongoose"; | ||
|
||
const { Schema } = mongoose; | ||
const happyThoughtSchema = new Schema({ | ||
message: { | ||
type: String, | ||
required: true, | ||
minlength: 5, | ||
maxlength: 140, | ||
}, | ||
hearts: { | ||
type: Number, | ||
default: 0, | ||
}, | ||
createdAt: { | ||
type: Date, | ||
default: Date.now, | ||
}, | ||
}); | ||
|
||
const HappyThought = mongoose.model("HappyThought", happyThoughtSchema); | ||
|
||
export default HappyThought; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
## Netlify link | ||
Add your Netlify link here. | ||
PS. Don't forget to add it in your readme as well. | ||
[API](https://project-happy-thoughts-api-sw6f.onrender.com/) | ||
[Site](https://happyhappenings.netlify.app/) | ||
|
||
## Collaborators | ||
Add your collaborators here. Write their GitHub usernames in square brackets. If there's more than one, separate them with a comma, like this: | ||
[github-username-1, github-username-2] | ||
solo |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
import express from "express"; | ||
import listEndpoints from "express-list-endpoints"; | ||
import HappyThought from "../model/Happythoughts"; | ||
const router = express.Router(); | ||
|
||
// get 100 last happy thoughts | ||
router.get("/thoughts", async (req, res) => { | ||
try { | ||
const happyThoughts = await HappyThought.find() | ||
.sort({ createdAt: "desc" }) | ||
.limit(100) | ||
.exec(); | ||
res.json(happyThoughts); | ||
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. A status code could be nice here |
||
} catch (error) { | ||
res.status(400).json({ | ||
success: false, | ||
response: error, | ||
message: "Could not get thoughts", | ||
}); | ||
} | ||
}); | ||
|
||
//post new happy thought | ||
router.post("/thoughts", async (req, res) => { | ||
const { message } = req.body; | ||
try { | ||
const newHappyThought = await new HappyThought({ message }).save(); | ||
res.status(201).json(newHappyThought); | ||
} catch (error) { | ||
console.error(error); // Log the error | ||
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 console.logs in production |
||
res.status(400).json({ | ||
success: false, | ||
response: error, | ||
message: "Could not save thought", | ||
}); | ||
} | ||
}); | ||
|
||
//post a like to a happy thought | ||
router.post("/thoughts/:thoughtId/like", async (req, res) => { | ||
const { thoughtId } = req.params; | ||
try { | ||
const updatedThought = await HappyThought.findByIdAndUpdate( | ||
thoughtId, | ||
{ $inc: { hearts: 1 } }, | ||
{ new: true } | ||
); | ||
Comment on lines
+43
to
+47
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. 👍 |
||
if (updatedThought) { | ||
res.json(updatedThought); | ||
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. Status code could be nice here too |
||
} else { | ||
res.status(404).json({ | ||
success: false, | ||
message: "Thought not found", | ||
}); | ||
} | ||
} catch (error) { | ||
res.status(400).json({ | ||
success: false, | ||
message: "Could not save like", | ||
}); | ||
} | ||
}); | ||
|
||
//delete a happy thought | ||
router.delete("/thoughts/:thoughtId", async (req, res) => { | ||
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. Nice! Would be cool if it was reflected in your frontend as well, but since auth is not until this week, I understand you didn't want anyone to be able to delete anyone else's posts |
||
const { thoughtId } = req.params; | ||
try { | ||
const deletedThought = await HappyThought.findByIdAndDelete(thoughtId); | ||
if (deletedThought) { | ||
res.json(deletedThought); | ||
} else { | ||
res.status(404).json({ | ||
success: false, | ||
message: "Thought not found", | ||
}); | ||
} | ||
} catch (error) { | ||
res.status(400).json({ | ||
success: false, | ||
message: "Could not delete thought", | ||
}); | ||
} | ||
}); | ||
|
||
//filter happy thoughts by limit or skip or both | ||
router.get("/thoughts/q", async (req, res) => { | ||
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. This doesn't need to be its own endpoint, you can include the query in your /thoughts endpoint |
||
const { limit = 10, page = 1 } = req.query; // Provide default values for limit and page | ||
const skip = (parseInt(page) - 1) * parseInt(limit); // Correctly calculate skip | ||
|
||
try { | ||
const thoughts = await HappyThought.find() | ||
.sort({ createdAt: "desc" }) | ||
.limit(parseInt(limit)) | ||
.skip(skip) // Skip documents that have already been fetched | ||
.exec(); | ||
res.json(thoughts); | ||
} catch (error) { | ||
res.status(500).json({ message: error.message }); | ||
} | ||
}); | ||
|
||
router.get("/pages", async (req, res) => { | ||
const limit = Number(req.query.limit) || 5; // default limit to if not provided | ||
|
||
try { | ||
const count = await HappyThought.countDocuments(); // replace Thought with your model | ||
const totalPages = Math.ceil(count / limit); | ||
|
||
res.json({ totalPages }); | ||
} catch (err) { | ||
res.status(500).json({ message: err.message }); | ||
} | ||
}); | ||
|
||
// get updated documentation | ||
router.get("/", (req, res) => { | ||
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. Most generic endpoints should always come first, e.g.
|
||
try { | ||
const endpoints = listEndpoints(router); | ||
const updatedEndpoints = endpoints.map((endpoint) => { | ||
switch (endpoint.path) { | ||
case "/thoughts": | ||
return { | ||
path: endpoint.path, | ||
methods: endpoint.methods, | ||
description: | ||
"Get the last 100 happy thoughts or post a new happy thought.", | ||
}; | ||
case "/thoughts/q": | ||
return { | ||
path: endpoint.path, | ||
methods: endpoint.methods, | ||
description: "Filter happy thoughts by limit or skip or both.", | ||
queryParameters: [ | ||
{ | ||
name: "limit", | ||
description: | ||
"Limit the number of thoughts returned. Default is 5. example: /thoughts/q?limit=10. you can also use /thoughts/q?limit=5&page=2 to get the second page of 5 thoughts.", | ||
}, | ||
{ | ||
name: "page", | ||
description: | ||
"Paginate through thoughts based on limit. Default is 1. example: /thoughts/q?limit=5&page=2. ", | ||
}, | ||
], | ||
}; | ||
case "/thoughts/:thoughtId/like": | ||
return { | ||
path: endpoint.path, | ||
methods: endpoint.methods, | ||
description: "Post a like to a happy thought.", | ||
}; | ||
case "/thoughts/:thoughtId": | ||
return { | ||
path: endpoint.path, | ||
methods: ["DELETE"], | ||
description: "Delete a happy thought.", | ||
}; | ||
case "/pages": | ||
return { | ||
path: endpoint.path, | ||
methods: endpoint.methods, | ||
description: | ||
"Get the total number of pages of happy thoughts. Example: /pages.", | ||
}; | ||
default: | ||
return { | ||
path: endpoint.path, | ||
methods: endpoint.methods, | ||
}; | ||
} | ||
}); | ||
res.json(updatedEndpoints); | ||
} catch (error) { | ||
const customError = new Error( | ||
"An error occurred while fetching the endpoints" | ||
); | ||
res.status(404).json({ | ||
success: false, | ||
message: customError.message, | ||
}); | ||
} | ||
}); | ||
|
||
export default router; |
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.
File names should be kebab-case (lowercase) if nothing else is specified 😇
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.
But nice idea breaking this out 👍