-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #22 from GenerateNU/adam-post-table-and-crud
NOT YET
- Loading branch information
Showing
7 changed files
with
341 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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 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 |
---|---|---|
@@ -0,0 +1,186 @@ | ||
package controllers | ||
|
||
import ( | ||
"net/http" | ||
"strconv" | ||
|
||
"backend/src/models" | ||
"backend/src/services" | ||
|
||
"github.com/gin-gonic/gin" | ||
) | ||
|
||
type PostController struct { | ||
postService *services.PostService | ||
} | ||
|
||
func NewPostController(postService *services.PostService) *PostController { | ||
return &PostController{ | ||
postService: postService, | ||
} | ||
} | ||
|
||
// GetAllPosts godoc | ||
// | ||
// @Summary Gets all posts | ||
// @Description Returns all posts | ||
// @ID get-all-posts | ||
// @Tags post | ||
// @Produce json | ||
// @Success 200 {object} []models.Post | ||
// @Failure 404 {string} string "Failed to fetch posts" | ||
// @Router /api/posts/ [get] | ||
func (pc *PostController) GetAllPosts(c *gin.Context) { | ||
posts, err := pc.postService.GetAllPosts() | ||
if err != nil { | ||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch posts"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, posts) | ||
} | ||
|
||
// GetPostsByUserId godoc | ||
// | ||
// @Summary Gets posts by user ID | ||
// @Description Returns all posts for a specific user by user ID | ||
// @ID get-posts-by-user-id | ||
// @Tags post | ||
// @Produce json | ||
// @Param userId path uint true "User ID" | ||
// @Success 200 {object} []models.Post | ||
// @Failure 404 {string} string "Failed to fetch posts" | ||
// @Router /api/posts/user/{userId} [get] | ||
func (pc *PostController) GetPostsByUserId(c *gin.Context) { | ||
userId, err := strconv.ParseUint(c.Param("userId"), 10, 32) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) | ||
return | ||
} | ||
|
||
posts, err := pc.postService.GetPostsByUserId(uint(userId)) | ||
if err != nil { | ||
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to fetch posts"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, posts) | ||
} | ||
|
||
// CreatePost godoc | ||
// | ||
// @Summary Creates a post | ||
// @Description Creates a post | ||
// @ID create-post | ||
// @Tags post | ||
// @Accept json | ||
// @Produce json | ||
// @Param first_name body string true "First name of the post" | ||
// @Param last_name body string true "Last name of the post" | ||
// @Param postname body string true "Postname of the post" | ||
// @Param email body string true "Email of the post" | ||
// @Param password body string true "Password of the post" | ||
// @Success 201 {object} models.Post | ||
// @Failure 400 {string} string "Failed to create post" | ||
// @Router /api/posts/ [post] | ||
func (pc *PostController) CreatePost(c *gin.Context) { | ||
var post models.Post | ||
if err := c.ShouldBindJSON(&post); err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"}) | ||
return | ||
} | ||
|
||
createdPost, err := pc.postService.CreatePost(&post) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create post"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusCreated, createdPost) | ||
} | ||
|
||
// GetPostById godoc | ||
// | ||
// @Summary Gets a post by id | ||
// @Description Returns a post by id | ||
// @ID get-post-by-id | ||
// @Tags post | ||
// @Produce json | ||
// @Param id path int true "ID of the post" | ||
// @Success 200 {object} models.Post | ||
// @Failure 404 {string} string "Failed to fetch post" | ||
// @Router /api/posts/{id} [get] | ||
func (pc *PostController) GetPostById(c *gin.Context) { | ||
id := c.Param("id") | ||
postID, err := strconv.ParseUint(id, 10, 32) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid post ID"}) | ||
return | ||
} | ||
|
||
post, err := pc.postService.GetPostById(uint(postID)) | ||
if err != nil { | ||
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to fetch post"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, post) | ||
} | ||
|
||
// UpdatePostById godoc | ||
// | ||
// @Summary Updates a post by id | ||
// @Description Updates a post by id | ||
// @ID update-post-by-id | ||
// @Tags post | ||
// @Accept json | ||
// @Produce json | ||
// @Param id path int true "ID of the post" | ||
// @Param first_name body string true "First name of the post" | ||
// @Param last_name body string true "Last name of the post" | ||
// @Param postname body string true "Postname of the post" | ||
// @Param email body string true "Email of the post" | ||
// @Param password body string true "Password of the post" | ||
// @Success 200 {object} models.Post | ||
// @Failure 400 {string} string "Failed to update post" | ||
// @Router /api/posts/{id} [put] | ||
func (pc *PostController) UpdatePostById(c *gin.Context) { | ||
id := c.Param("id") | ||
postID, _ := strconv.ParseUint(id, 10, 32) | ||
var post *models.Post | ||
if err := c.ShouldBindJSON(&post); err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid input"}) | ||
return | ||
} | ||
|
||
updatedPost, err := pc.postService.UpdatePostById(uint(postID), post) | ||
if err != nil { | ||
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to update post"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, updatedPost) | ||
} | ||
|
||
// DeletePostById godoc | ||
// | ||
// @Summary Deletes a post by id | ||
// @Description Deletes a post by id | ||
// @ID delete-post-by-id | ||
// @Tags post | ||
// @Produce json | ||
// @Param id path int true "ID of the post" | ||
// @Success 200 {object} models.Post | ||
// @Failure 404 {string} string "Failed to delete post" | ||
// @Router /api/posts/{id} [delete] | ||
func (pc *PostController) DeletePostById(c *gin.Context) { | ||
id := c.Param("id") | ||
postID, _ := strconv.ParseUint(id, 10, 32) | ||
post, err := pc.postService.DeletePostById(uint(postID)) | ||
if err != nil { | ||
c.JSON(http.StatusNotFound, gin.H{"error": "Failed to delete post"}) | ||
return | ||
} | ||
|
||
c.JSON(http.StatusOK, post) | ||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,30 @@ | ||
DROP TABLE IF EXISTS post_type_enum; | ||
DROP TABLE IF EXISTS posts; | ||
|
||
--Create post type table | ||
CREATE TYPE post_type_enum AS ENUM ( | ||
'1 month summary', | ||
'Recent trade', | ||
'Share comment' | ||
); | ||
|
||
--Create post table | ||
CREATE TABLE IF NOT EXISTS posts ( | ||
id SERIAL PRIMARY KEY, | ||
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, | ||
post_type post_type_enum NOT NULL, | ||
num_data FLOAT NOT NULL, | ||
ticker_symbol VARCHAR(9), | ||
time_stamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | ||
comment TEXT NOT NULL, | ||
title VARCHAR NOT NULL | ||
); | ||
|
||
INSERT INTO posts (user_id, post_type, num_data, ticker_symbol, comment, title) | ||
VALUES | ||
(1, '1 month summary', 100, 'AAPL', 'I made a 100% return on my investment in Apple this month!', 'Apple Investment'), | ||
(1, 'Recent trade', 200, 'TSLA', 'I just bought 200 shares of Tesla!', 'Tesla Investment'), | ||
(1, 'Share comment', 150, 'MSFT', 'I think Microsoft is a great company to invest in!', 'Microsoft Comment'), | ||
(1, '1 month summary', 250, 'GOOGL', 'I made a 250% return on my investment in Google this month!', 'Google Investment'), | ||
(1, 'Recent trade', 300, 'AMZN', 'I just bought 300 shares of Amazon!', 'Amazon Investment'), | ||
(1, 'Share comment', 400, 'FB', 'I think Facebook is a great company to invest in!', 'Facebook Comment'); |
This file contains 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 |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package models | ||
|
||
import ( | ||
"backend/src/types" | ||
"time" | ||
) | ||
|
||
type PostType string | ||
|
||
const ( | ||
ONE_MONTH_SUMMARY PostType = "1 month summary" | ||
RECENT_TRADE PostType = "Recent trade" | ||
SHARE_COMMENT PostType = "Share comment" | ||
) | ||
|
||
type Post struct { | ||
types.Model | ||
UserID uint `gorm:"not null" json:"user_id"` | ||
User User `gorm:"foreignKey:UserID"` | ||
PostType PostType `gorm:"type:post_type_enum;not null" json:"post_type"` | ||
NumData float64 `gorm:"not null" json:"num_data"` | ||
TickerSymbol string `gorm:"type:varchar(9);" json:"ticker_symbol"` | ||
TimeStamp time.Time `gorm:"default:created_at" json:"time_stamp"` | ||
Comment string `gorm:"not null" json:"comment"` | ||
Title string `gorm:"not null" json:"title"` | ||
} | ||
|
This file contains 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 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 |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package routes | ||
|
||
import ( | ||
"backend/src/controllers" | ||
"backend/src/services" | ||
|
||
"github.com/gin-gonic/gin" | ||
"gorm.io/gorm" | ||
) | ||
|
||
func SetupPostRoutes(router *gin.Engine, db *gorm.DB) { | ||
postService := services.NewPostService(db) | ||
postController := controllers.NewPostController(postService) | ||
|
||
postRoutes := router.Group("/posts") | ||
{ | ||
postRoutes.GET("/", postController.GetAllPosts) | ||
postRoutes.GET("/user-posts/:userId", postController.GetPostsByUserId) | ||
postRoutes.POST("/", postController.CreatePost) | ||
postRoutes.GET("/:id", postController.GetPostById) | ||
postRoutes.PUT("/:id", postController.UpdatePostById) | ||
postRoutes.DELETE("/:id", postController.DeletePostById) | ||
} | ||
} |
This file contains 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 |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package services | ||
|
||
import ( | ||
"backend/src/models" | ||
|
||
"gorm.io/gorm" | ||
) | ||
|
||
type PostService struct { | ||
DB *gorm.DB | ||
} | ||
|
||
func NewPostService(db *gorm.DB) *PostService { | ||
return &PostService{ | ||
DB: db, | ||
} | ||
} | ||
|
||
func (ps *PostService) GetAllPosts() ([]models.Post, error) { | ||
var posts []models.Post | ||
if err := ps.DB.Find(&posts).Error; err != nil { | ||
return nil, err | ||
} | ||
return posts, nil | ||
} | ||
|
||
func (ps *PostService) GetPostsByUserId(userId uint) ([]models.Post, error) { | ||
var posts []models.Post | ||
if err := ps.DB.Where("user_id = ?", userId).Find(&posts).Error; err != nil { | ||
return nil, err | ||
} | ||
return posts, nil | ||
} | ||
|
||
//TODO: Add GetPostsFromFollowedUsers once Cam is done | ||
|
||
func (ps *PostService) CreatePost(post *models.Post) (*models.Post, error) { | ||
if err := ps.DB.Create(post).Error; err != nil { | ||
return nil, err | ||
} | ||
return post, nil | ||
} | ||
|
||
func (ps *PostService) GetPostById(id uint) (*models.Post, error) { | ||
post := &models.Post{} | ||
if err := ps.DB.First(post, id).Error; err != nil { | ||
return nil, err | ||
} | ||
return post, nil | ||
} | ||
|
||
func (ps *PostService) UpdatePostById(id uint, post *models.Post) (*models.Post, error) { | ||
// Retrieve the existing post from the database | ||
_, err := ps.GetPostById(id) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Save the updated post back to the database | ||
if err := ps.DB.Save(post).Error; err != nil { | ||
return nil, err | ||
} | ||
|
||
return post, nil | ||
} | ||
|
||
func (ps *PostService) DeletePostById(id uint) (*models.Post, error) { | ||
post := &models.Post{} | ||
if err := ps.DB.Delete(post, id).Error; err != nil { | ||
return nil, err | ||
} | ||
return post, nil | ||
} |