diff --git a/backend/src/controllers/post.go b/backend/src/controllers/post.go
index dec5094c..357bd82e 100644
--- a/backend/src/controllers/post.go
+++ b/backend/src/controllers/post.go
@@ -4,8 +4,11 @@ import (
"net/http"
"strconv"
+ "fmt"
+
"backend/src/models"
"backend/src/services"
+ "backend/src/types"
"github.com/gin-gonic/gin"
)
@@ -115,36 +118,64 @@ func (pc *PostController) GetPostsFromSearch(c *gin.Context) {
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"})
+// CreateTradePost godoc
+func (pc *PostController) CreateTradePost(c *gin.Context) {
+ var req types.CreateTradePostRequest
+ if err := c.BindJSON(&req); err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request data"})
return
}
- createdPost, err := pc.postService.CreatePost(&post)
+ userId := c.Param("user_id")
+
+ fmt.Println(req.Title, req.Description)
+
+ tradePost, err := pc.postService.CreateTradePost(userId, req.PercentData, req.TickerSymbol, req.Title, req.Description)
+ if err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create post"})
+ return
+ }
+
+ c.JSON(http.StatusCreated, tradePost)
+}
+
+// CreatePortfolioPost godoc
+func (pc *PostController) CreatePortfolioPost(c *gin.Context) {
+ var req types.CreatePortfolioPostRequest
+ if err := c.BindJSON(&req); err != nil {
+ fmt.Println(err)
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request data"})
+ return
+ }
+
+ userId := c.Param("user_id")
+
+ portfolioPost, err := pc.postService.CreatePortfolioPost(userId, req.PercentData, req.SummaryType)
+ if err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create post"})
+ return
+ }
+
+ c.JSON(http.StatusCreated, portfolioPost)
+}
+
+// CreateTextPost godoc
+func (pc *PostController) CreateTextPost(c *gin.Context) {
+ var req types.CreateTextPostRequest
+ if err := c.BindJSON(&req); err != nil {
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request data"})
+ return
+ }
+
+ userId := c.Param("user_id")
+
+ textPost, err := pc.postService.CreateTextPost(userId, req.Title, req.Description)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Failed to create post"})
return
}
- c.JSON(http.StatusCreated, createdPost)
+ c.JSON(http.StatusCreated, textPost)
}
// GetPostById godoc
diff --git a/backend/src/db/migrations/7_POST_V1.sql b/backend/src/db/migrations/7_POST_V1.sql
index 1ac77eb0..a5a25beb 100644
--- a/backend/src/db/migrations/7_POST_V1.sql
+++ b/backend/src/db/migrations/7_POST_V1.sql
@@ -11,8 +11,8 @@ CREATE TYPE post_type_enum AS ENUM (
--Create post table
CREATE TABLE IF NOT EXISTS posts (
id SERIAL PRIMARY KEY,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
user_id VARCHAR(255) REFERENCES users(id) ON DELETE CASCADE,
post_type post_type_enum NOT NULL,
num_data FLOAT NOT NULL,
diff --git a/backend/src/routes/post.go b/backend/src/routes/post.go
index 934a7294..bab10416 100644
--- a/backend/src/routes/post.go
+++ b/backend/src/routes/post.go
@@ -18,7 +18,9 @@ func SetupPostRoutes(router *gin.Engine, db *gorm.DB) {
postRoutes.GET("/user-posts/:user_id", postController.GetPostsByUserId)
postRoutes.GET("/followed-posts/:user_id", postController.GetPostsFromFollowedUsers)
postRoutes.GET("/search-posts", postController.GetPostsFromSearch)
- postRoutes.POST("", postController.CreatePost)
+ postRoutes.POST("/create-trade-post/:user_id", postController.CreateTradePost)
+ postRoutes.POST("/create-portfolio-post/:user_id", postController.CreatePortfolioPost)
+ postRoutes.POST("/create-text-post/:user_id", postController.CreateTextPost)
postRoutes.GET("/:id", postController.GetPostById)
postRoutes.PUT("/:id", postController.UpdatePostById)
postRoutes.DELETE("/:id", postController.DeletePostById)
diff --git a/backend/src/services/post.go b/backend/src/services/post.go
index d81c0855..aa641758 100644
--- a/backend/src/services/post.go
+++ b/backend/src/services/post.go
@@ -69,11 +69,53 @@ func (ps *PostService) GetPostsFromSearch(postContentSearchTerm string) ([]model
return posts, nil
}
-func (ps *PostService) CreatePost(post *models.Post) (*models.Post, error) {
- if err := ps.DB.Create(post).Error; err != nil {
+func (ps *PostService) CreateTradePost(userId string, percentData float64, tickerSymbol string, title string, description string) (*models.Post, error) {
+ tradePost := &models.Post{
+ UserID: userId,
+ NumData: percentData,
+ PostType: models.RECENT_TRADE,
+ TickerSymbol: tickerSymbol,
+ Title: title,
+ Comment: description,
+ }
+
+ if err := ps.DB.Create(tradePost).Error; err != nil {
return nil, err
}
- return post, nil
+
+ return tradePost, nil
+}
+
+func (ps *PostService) CreatePortfolioPost(userId string, percentData float64, summaryType string) (*models.Post, error) {
+ portfolioPost := &models.Post{
+ UserID: userId,
+ NumData: percentData,
+ PostType: models.ONE_MONTH_SUMMARY,
+ Title: "Portfolio Summary",
+ Comment: summaryType,
+ }
+
+ if err := ps.DB.Create(portfolioPost).Error; err != nil {
+ return nil, err
+ }
+
+ return portfolioPost, nil
+}
+
+func (ps *PostService) CreateTextPost(userId string, title string, description string) (*models.Post, error) {
+ textPost := &models.Post{
+ UserID: userId,
+ NumData: 0,
+ PostType: models.SHARE_COMMENT,
+ Title: title,
+ Comment: description,
+ }
+
+ if err := ps.DB.Create(textPost).Error; err != nil {
+ return nil, err
+ }
+
+ return textPost, nil
}
func (ps *PostService) GetPostById(id uint) (*models.Post, error) {
diff --git a/backend/src/types/model.go b/backend/src/types/model.go
index 445bd0c2..77cb3293 100644
--- a/backend/src/types/model.go
+++ b/backend/src/types/model.go
@@ -118,3 +118,20 @@ type ClerkWebhookEvent struct {
Object string `json:"object"`
Type string `json:"type"`
}
+
+type CreateTradePostRequest struct {
+ PercentData float64 `json:"percent_data" binding:"required"`
+ TickerSymbol string `json:"ticker_symbol" binding:"required"`
+ Title string `json:"title" binding:"required"`
+ Description string `json:"description" binding:"required"`
+}
+
+type CreatePortfolioPostRequest struct {
+ PercentData float64 `json:"percent_data" binding:"required"`
+ SummaryType string `json:"summary_type" binding:"required"`
+}
+
+type CreateTextPostRequest struct {
+ Title string `json:"title" binding:"required"`
+ Description string `json:"description" binding:"required"`
+}
\ No newline at end of file
diff --git a/frontend/App.tsx b/frontend/App.tsx
index 6db7c355..e411770a 100644
--- a/frontend/App.tsx
+++ b/frontend/App.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import onboardingReducer from './reducers/onboarding/onboardingReducer';
+import makePostReducer from './reducers/makePost/makePostReducer';
import LayoutWrapper from './components/LayoutWrapper';
import { ClerkProvider } from '@clerk/clerk-expo';
//import 'react-native-gesture-handler';
@@ -10,6 +11,7 @@ import * as SecureStore from 'expo-secure-store';
const store = configureStore({
reducer: {
onboarding: onboardingReducer,
+ makePost: makePostReducer,
},
});
diff --git a/frontend/components/LayoutWrapper.tsx b/frontend/components/LayoutWrapper.tsx
index 28d74a11..0f8d4e21 100644
--- a/frontend/components/LayoutWrapper.tsx
+++ b/frontend/components/LayoutWrapper.tsx
@@ -4,11 +4,14 @@ import BottomNavBar from '../router/BottomNavBar';
import AuthNavigator from '../router/AuthNavigation';
import { configureStore } from '@reduxjs/toolkit';
import onboardingReducer from '../reducers/onboarding/onboardingReducer';
+import makePostReducer from '../reducers/makePost/makePostReducer';
import { useSelector } from 'react-redux';
+import MakePostNavigator from '../router/MakePostNavigation';
const store = configureStore({
reducer: {
onboarding: onboardingReducer,
+ makePost: makePostReducer,
},
});
@@ -28,7 +31,7 @@ export default function LayoutWrapper() {
{
onboarding: ,
normal: ,
- makingPost: (null),
+ makingPost: ,
}[onboarding.isOnboarding]
}
{/* {session?.user !== undefined && !onboarding.isOnboarding ? (
diff --git a/frontend/pages/FeedPage.tsx b/frontend/pages/FeedPage.tsx
index badf0b1c..a605fb4c 100644
--- a/frontend/pages/FeedPage.tsx
+++ b/frontend/pages/FeedPage.tsx
@@ -1,5 +1,6 @@
import {
TextInput,
+ TouchableOpacity,
StyleSheet,
View,
Text,
@@ -12,6 +13,8 @@ import DiscoverPeople from '../components/Feed/DiscoverPeople';
import PostNew from '../components/Feed/PostNew';
import { getPosts } from '../services/users';
import { Post } from '../types/types';
+import { useDispatch } from 'react-redux';
+import { makePost } from '../reducers/onboarding/onboardingReducer';
const AddSvg = `