diff --git a/package.json b/package.json
index 049ff641..a6897e35 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-icons": "^4.1.0",
+ "short-number": "^1.0.7",
"validator": "^13.5.2"
},
"devDependencies": {
diff --git a/pages/[username]/[post_id].tsx b/pages/[username]/[post_id].tsx
index 25bc29b7..c8a03ca6 100644
--- a/pages/[username]/[post_id].tsx
+++ b/pages/[username]/[post_id].tsx
@@ -1,4 +1,4 @@
-import { Box, chakra, Divider, Flex, Heading, HStack, IconButton, Image, VStack } from "@chakra-ui/react"
+import { Box, chakra, Divider, Flex, Heading, HStack, IconButton, Image, storageKey, VStack } from "@chakra-ui/react"
import Comments from "components/comments/comments"
import Container from "components/container"
import LikeButton from "components/posts/unicorn-like"
@@ -23,13 +23,14 @@ import { Tag } from "src/types/tag"
import { requestApi } from "utils/axios/request"
import UnicornLike from "components/posts/unicorn-like"
import SvgButton from "components/svg-button"
+import Bookmark from "components/posts/bookmark"
+import PostSidebar from "components/posts/post-sidebar"
const PostPage = () => {
const router = useRouter()
const id = router.query.post_id
const [post, setPost]: [Post, any] = useState(null)
- const [comments,setComments]: [Comment[],any] = useState([])
- const session = useSession()
+ const [comments, setComments]: [Comment[], any] = useState([])
useEffect(() => {
if (id) {
getData()
@@ -41,9 +42,9 @@ const PostPage = () => {
if (router && router.asPath.indexOf("#comments") > -1) {
setTimeout(() => {
location.href = "#comments"
- },100)
+ }, 100)
}
- },[router])
+ }, [router])
const getData = async () => {
const res = await requestApi.get(`/post/${id}`)
@@ -52,20 +53,6 @@ const PostPage = () => {
getComments(res.data.id)
}
- const onLike = async () => {
- await requestApi.post(`/story/like/${post.id}`)
- const p = cloneDeep(post)
-
- if (post.liked) {
- p.likes += -1
- p.liked = false
- } else {
- p.likes += 1
- p.liked = true
- }
- setPost(p)
- }
-
const getComments = async (id) => {
const res = await requestApi.get(`/story/comments/${id}`)
setComments(res.data)
@@ -81,7 +68,7 @@ const PostPage = () => {
{post &&
<>
-
+
{post.title}
@@ -92,84 +79,12 @@ const PostPage = () => {
- {post.rawTags.map(tag => )}
+ {post.rawTags.map(tag => )}
-
-
- {/* */}
-
-
-
- }
- />
- }
- />
-
-
-
- getComments(post.id)}/>
+ getComments(post.id)} />
-
-
-
- {/* */}
- {/* */}
-
- {/* */}
-
-
-
-
- location.href="#comments"}
- />
-
-
- {post.creatorId === session?.user.id &&
- router.push(`${ReserveUrls.Editor}/post/${post.id}`)}
- icon="edit"
- />
- }
-
-
-
-
-
+
+
@@ -182,3 +97,4 @@ const PostPage = () => {
export default PostPage
+
diff --git a/pages/[username]/index.tsx b/pages/[username]/index.tsx
index 3572ddea..f1449e0e 100644
--- a/pages/[username]/index.tsx
+++ b/pages/[username]/index.tsx
@@ -21,6 +21,7 @@ import userCustomTheme from "theme/user-custom"
import Posts from "components/posts/posts"
import Link from "next/link"
import Empty from "components/empty"
+import Count from "components/count"
const UserPage = () => {
const router = useRouter()
@@ -60,8 +61,8 @@ const UserPage = () => {
{user.nickname}
{user.tagline && {user.tagline}}
- Followers 0
- Following 0
+ Followers
+ Following
{session?.user.id === user.id ?
: }
diff --git a/server/internal/api/editor.go b/server/internal/api/editor.go
deleted file mode 100644
index fc76cb28..00000000
--- a/server/internal/api/editor.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package api
-
-import (
- "net/http"
-
- "github.com/gin-gonic/gin"
- "github.com/imdotdev/im.dev/server/internal/story"
- "github.com/imdotdev/im.dev/server/internal/user"
- "github.com/imdotdev/im.dev/server/pkg/common"
- "github.com/imdotdev/im.dev/server/pkg/e"
-)
-
-func GetEditorPosts(c *gin.Context) {
- user := user.CurrentUser(c)
- ars, err := story.UserPosts(int64(user.ID))
- if err != nil {
- c.JSON(err.Status, common.RespError(err.Message))
- return
- }
-
- c.JSON(http.StatusOK, common.RespSuccess(ars))
-}
-
-func GetEditorPost(c *gin.Context) {
- id := c.Param("id")
- if id == "" {
- c.JSON(http.StatusBadRequest, common.RespError(e.ParamInvalid))
- return
- }
-
- user := user.CurrentUser(c)
- creator, err := story.GetPostCreator(id)
- if err != nil {
- c.JSON(err.Status, common.RespError(err.Message))
- return
- }
-
- if user.ID != creator {
- c.JSON(http.StatusForbidden, common.RespError(e.NoPermission))
- return
- }
-
- ar, err := story.GetPost(id, "")
- if err != nil {
- c.JSON(err.Status, common.RespError(err.Message))
- return
- }
-
- c.JSON(http.StatusOK, common.RespSuccess(ar))
-}
diff --git a/server/internal/api/posts.go b/server/internal/api/posts.go
new file mode 100644
index 00000000..60dd522e
--- /dev/null
+++ b/server/internal/api/posts.go
@@ -0,0 +1,60 @@
+package api
+
+import (
+ "net/http"
+ "strconv"
+
+ "github.com/gin-gonic/gin"
+ "github.com/imdotdev/im.dev/server/internal/story"
+ "github.com/imdotdev/im.dev/server/internal/user"
+ "github.com/imdotdev/im.dev/server/pkg/common"
+)
+
+func GetEditorPosts(c *gin.Context) {
+ user := user.CurrentUser(c)
+ ars, err := story.UserPosts(user, int64(user.ID))
+ if err != nil {
+ c.JSON(err.Status, common.RespError(err.Message))
+ return
+ }
+
+ c.JSON(http.StatusOK, common.RespSuccess(ars))
+}
+
+func GetUserPosts(c *gin.Context) {
+ userID, _ := strconv.ParseInt(c.Param("userID"), 10, 64)
+
+ user := user.CurrentUser(c)
+
+ posts, err := story.UserPosts(user, userID)
+ if err != nil {
+ c.JSON(err.Status, common.RespError(err.Message))
+ return
+ }
+
+ c.JSON(http.StatusOK, common.RespSuccess(posts))
+}
+
+func GetTagPosts(c *gin.Context) {
+ tagID, _ := strconv.ParseInt(c.Param("id"), 10, 64)
+ user := user.CurrentUser(c)
+ posts, err := story.TagPosts(user, tagID)
+ if err != nil {
+ c.JSON(err.Status, common.RespError(err.Message))
+ return
+ }
+
+ c.JSON(http.StatusOK, common.RespSuccess(posts))
+}
+
+func GetHomePosts(c *gin.Context) {
+ filter := c.Param("filter")
+ user := user.CurrentUser(c)
+ posts, err := story.HomePosts(user, filter)
+ if err != nil {
+ c.JSON(err.Status, common.RespError(err.Message))
+ return
+ }
+
+ c.JSON(http.StatusOK, common.RespSuccess(posts))
+}
diff --git a/server/internal/api/story.go b/server/internal/api/story.go
index f3195d34..fa68817b 100644
--- a/server/internal/api/story.go
+++ b/server/internal/api/story.go
@@ -2,7 +2,6 @@ package api
import (
"net/http"
- "strconv"
"github.com/gin-gonic/gin"
"github.com/imdotdev/im.dev/server/internal/story"
@@ -51,18 +50,16 @@ func DeletePost(c *gin.Context) {
func GetPost(c *gin.Context) {
id := c.Param("id")
+ user := user.CurrentUser(c)
ar, err := story.GetPost(id, "")
if err != nil {
c.JSON(err.Status, common.RespError(err.Message))
return
}
- user := user.CurrentUser(c)
- if user == nil {
- ar.Liked = false
- } else {
+ if user != nil {
ar.Liked = story.GetLiked(ar.ID, user.ID)
-
+ ar.Bookmarked, _ = story.Bookmarked(user.ID, ar.ID)
}
c.JSON(http.StatusOK, common.RespSuccess(ar))
@@ -85,59 +82,44 @@ func LikeStory(c *gin.Context) {
c.JSON(http.StatusOK, common.RespSuccess(nil))
}
-func GetUserPosts(c *gin.Context) {
- userID, _ := strconv.ParseInt(c.Param("userID"), 10, 64)
+func Bookmark(c *gin.Context) {
+ storyID := c.Param("storyID")
- posts, err := story.UserPosts(userID)
+ user := user.CurrentUser(c)
+
+ err := story.Bookmark(user.ID, storyID)
if err != nil {
c.JSON(err.Status, common.RespError(err.Message))
return
}
- user := user.CurrentUser(c)
- if user != nil {
- for _, post := range posts {
- post.Liked = story.GetLiked(post.ID, user.ID)
- }
- }
-
- c.JSON(http.StatusOK, common.RespSuccess(posts))
+ c.JSON(http.StatusOK, common.RespSuccess(nil))
}
-func GetTagPosts(c *gin.Context) {
- tagID, _ := strconv.ParseInt(c.Param("id"), 10, 64)
+func GetEditorPost(c *gin.Context) {
+ id := c.Param("id")
+ if id == "" {
+ c.JSON(http.StatusBadRequest, common.RespError(e.ParamInvalid))
+ return
+ }
- posts, err := story.TagPosts(tagID)
+ user := user.CurrentUser(c)
+ creator, err := story.GetPostCreator(id)
if err != nil {
c.JSON(err.Status, common.RespError(err.Message))
return
}
- user := user.CurrentUser(c)
- if user != nil {
- for _, post := range posts {
- post.Liked = story.GetLiked(post.ID, user.ID)
- }
+ if user.ID != creator {
+ c.JSON(http.StatusForbidden, common.RespError(e.NoPermission))
+ return
}
- c.JSON(http.StatusOK, common.RespSuccess(posts))
-}
-
-func GetHomePosts(c *gin.Context) {
- filter := c.Param("filter")
-
- posts, err := story.HomePosts(filter)
+ ar, err := story.GetPost(id, "")
if err != nil {
c.JSON(err.Status, common.RespError(err.Message))
return
}
- user := user.CurrentUser(c)
- if user != nil {
- for _, post := range posts {
- post.Liked = story.GetLiked(post.ID, user.ID)
- }
- }
-
- c.JSON(http.StatusOK, common.RespSuccess(posts))
+ c.JSON(http.StatusOK, common.RespSuccess(ar))
}
diff --git a/server/internal/server.go b/server/internal/server.go
index 2659c196..b489b1d0 100644
--- a/server/internal/server.go
+++ b/server/internal/server.go
@@ -79,6 +79,9 @@ func (s *Server) Start() error {
r.GET("/home/posts/:filter", api.GetHomePosts)
r.GET("/session", IsLogin(), api.GetSession)
+
+ r.POST("/bookmark/:storyID", IsLogin(), api.Bookmark)
+
err := router.Run(config.Data.Server.Addr)
if err != nil {
logger.Crit("start backend server error", "error", err)
diff --git a/server/internal/storage/sql_tables.go b/server/internal/storage/sql_tables.go
index bc09474e..27241a82 100644
--- a/server/internal/storage/sql_tables.go
+++ b/server/internal/storage/sql_tables.go
@@ -141,4 +141,13 @@ var sqlTables = map[string]string{
count INTEGER DEFAULT 0
);
`,
+
+ "bookmarks": `CREATE TABLE IF NOT EXISTS bookmarks (
+ user_id INTEGER,
+ story_id VARCHAR(255),
+ created DATETIME
+ );
+ CREATE INDEX IF NOT EXISTS bookmarks_userid
+ ON bookmarks (user_id);
+ `,
}
diff --git a/server/internal/story/bookmark.go b/server/internal/story/bookmark.go
new file mode 100644
index 00000000..55d482fd
--- /dev/null
+++ b/server/internal/story/bookmark.go
@@ -0,0 +1,52 @@
+package story
+
+import (
+ "database/sql"
+ "net/http"
+
+ "github.com/imdotdev/im.dev/server/pkg/db"
+ "github.com/imdotdev/im.dev/server/pkg/e"
+)
+
+func Bookmark(userID int64, storyID string) *e.Error {
+ storyExist := Exist(storyID)
+ if !storyExist {
+ return e.New(http.StatusNotFound, e.NotFound)
+ }
+
+ bookmarked, err := Bookmarked(userID, storyID)
+ if err != nil {
+ return e.New(http.StatusInternalServerError, e.Internal)
+ }
+
+ if !bookmarked {
+ _, err = db.Conn.Exec("insert into bookmarks (user_id,story_id) values (?,?)", userID, storyID)
+ if err != nil {
+ logger.Warn("add bookmark error", "error", err)
+ return e.New(http.StatusInternalServerError, e.Internal)
+ }
+ } else {
+ _, err = db.Conn.Exec("delete from bookmarks where user_id=? and story_id=?", userID, storyID)
+ if err != nil {
+ logger.Warn("delete bookmark error", "error", err)
+ return e.New(http.StatusInternalServerError, e.Internal)
+ }
+ }
+
+ return nil
+}
+
+func Bookmarked(userID int64, storyID string) (bool, error) {
+ var nid string
+ err := db.Conn.QueryRow("select story_id from bookmarks where user_id=? and story_id=?", userID, storyID).Scan(&nid)
+ if err != nil && err != sql.ErrNoRows {
+ logger.Warn("get bookmarked error", "error", err)
+ return false, err
+ }
+
+ if err == sql.ErrNoRows {
+ return false, nil
+ }
+
+ return true, nil
+}
diff --git a/server/internal/story/post.go b/server/internal/story/post.go
index c53f3cdf..c7081284 100644
--- a/server/internal/story/post.go
+++ b/server/internal/story/post.go
@@ -4,7 +4,6 @@ import (
"database/sql"
"fmt"
"net/http"
- "sort"
"strings"
"time"
"unicode/utf8"
@@ -20,81 +19,6 @@ import (
"github.com/imdotdev/im.dev/server/pkg/utils"
)
-func UserPosts(uid int64) (models.Posts, *e.Error) {
- ars := make(models.Posts, 0)
- rows, err := db.Conn.Query("select id,slug,title,url,cover,brief,likes,views,created,updated from posts where creator=?", uid)
- if err != nil && err != sql.ErrNoRows {
- logger.Warn("get user posts error", "error", err)
- return ars, e.New(http.StatusInternalServerError, e.Internal)
- }
-
- creator := &models.UserSimple{ID: uid}
- creator.Query()
- for rows.Next() {
- ar := &models.Post{}
- err := rows.Scan(&ar.ID, &ar.Slug, &ar.Title, &ar.URL, &ar.Cover, &ar.Brief, &ar.Likes, &ar.Views, &ar.Created, &ar.Updated)
- if err != nil {
- logger.Warn("scan post error", "error", err)
- continue
- }
-
- ar.Creator = creator
-
- ar.Comments = GetCommentCount(ar.ID)
- ars = append(ars, ar)
- }
-
- sort.Sort(ars)
- return ars, nil
-}
-
-func TagPosts(tagID int64) (models.Posts, *e.Error) {
- ars := make(models.Posts, 0)
-
- // get post ids
- rows, err := db.Conn.Query("select post_id from tag_post where tag_id=?", tagID)
- if err != nil {
- logger.Warn("get user posts error", "error", err)
- return ars, e.New(http.StatusInternalServerError, e.Internal)
- }
-
- postIDs := make([]string, 0)
- for rows.Next() {
- var id string
- rows.Scan(&id)
- postIDs = append(postIDs, id)
- }
-
- ids := strings.Join(postIDs, "','")
-
- q := fmt.Sprintf("select id,slug,title,url,cover,brief,likes,views,creator,created,updated from posts where id in ('%s')", ids)
- rows, err = db.Conn.Query(q)
- if err != nil && err != sql.ErrNoRows {
- logger.Warn("get user posts error", "error", err)
- return ars, e.New(http.StatusInternalServerError, e.Internal)
- }
-
- for rows.Next() {
- ar := &models.Post{}
- err := rows.Scan(&ar.ID, &ar.Slug, &ar.Title, &ar.URL, &ar.Cover, &ar.Brief, &ar.Likes, &ar.Views, &ar.CreatorID, &ar.Created, &ar.Updated)
- if err != nil {
- logger.Warn("scan post error", "error", err)
- continue
- }
-
- creator := &models.UserSimple{ID: ar.CreatorID}
- creator.Query()
-
- ar.Creator = creator
-
- ar.Comments = GetCommentCount(ar.ID)
- ars = append(ars, ar)
- }
-
- sort.Sort(ars)
- return ars, nil
-}
-
func SubmitPost(c *gin.Context) (map[string]string, *e.Error) {
user := user.CurrentUser(c)
@@ -249,6 +173,7 @@ func GetPost(id string, slug string) (*models.Post, *e.Error) {
logger.Warn("update post view count error", "error", err)
}
+ //get bookmared
return ar, nil
}
@@ -266,35 +191,6 @@ func GetPostCreator(id string) (int64, *e.Error) {
return uid, nil
}
-func HomePosts(filter string) (models.Posts, *e.Error) {
- ars := make(models.Posts, 0)
- rows, err := db.Conn.Query("select id,slug,title,url,cover,brief,likes,views,creator,created,updated from posts")
- if err != nil && err != sql.ErrNoRows {
- logger.Warn("get user posts error", "error", err)
- return ars, e.New(http.StatusInternalServerError, e.Internal)
- }
-
- for rows.Next() {
- ar := &models.Post{}
- err := rows.Scan(&ar.ID, &ar.Slug, &ar.Title, &ar.URL, &ar.Cover, &ar.Brief, &ar.Likes, &ar.Views, &ar.CreatorID, &ar.Created, &ar.Updated)
- if err != nil {
- logger.Warn("scan post error", "error", err)
- continue
- }
-
- creator := &models.UserSimple{ID: ar.CreatorID}
- creator.Query()
-
- ar.Creator = creator
-
- ar.Comments = GetCommentCount(ar.ID)
- ars = append(ars, ar)
- }
-
- sort.Sort(ars)
- return ars, nil
-}
-
func postExist(id string) bool {
var nid string
err := db.Conn.QueryRow("SELECT id from posts WHERE id=?", id).Scan(&nid)
diff --git a/server/internal/story/posts.go b/server/internal/story/posts.go
new file mode 100644
index 00000000..f150e402
--- /dev/null
+++ b/server/internal/story/posts.go
@@ -0,0 +1,101 @@
+package story
+
+import (
+ "database/sql"
+ "fmt"
+ "net/http"
+ "sort"
+ "strings"
+
+ "github.com/imdotdev/im.dev/server/pkg/db"
+ "github.com/imdotdev/im.dev/server/pkg/e"
+ "github.com/imdotdev/im.dev/server/pkg/models"
+)
+
+func HomePosts(user *models.User, filter string) (models.Posts, *e.Error) {
+
+ rows, err := db.Conn.Query("select id,slug,title,url,cover,brief,likes,views,creator,created,updated from posts")
+ if err != nil && err != sql.ErrNoRows {
+ logger.Warn("get user posts error", "error", err)
+ return nil, e.New(http.StatusInternalServerError, e.Internal)
+ }
+
+ posts := getPosts(user, rows)
+ sort.Sort(posts)
+
+ return posts, nil
+}
+
+func UserPosts(user *models.User, uid int64) (models.Posts, *e.Error) {
+ rows, err := db.Conn.Query("select id,slug,title,url,cover,brief,likes,views,creator,created,updated from posts where creator=?", uid)
+ if err != nil && err != sql.ErrNoRows {
+ logger.Warn("get user posts error", "error", err)
+ return nil, e.New(http.StatusInternalServerError, e.Internal)
+ }
+
+ posts := getPosts(user, rows)
+
+ sort.Sort(posts)
+ return posts, nil
+}
+
+func TagPosts(user *models.User, tagID int64) (models.Posts, *e.Error) {
+ // get post ids
+ rows, err := db.Conn.Query("select post_id from tag_post where tag_id=?", tagID)
+ if err != nil {
+ logger.Warn("get user posts error", "error", err)
+ return nil, e.New(http.StatusInternalServerError, e.Internal)
+ }
+
+ postIDs := make([]string, 0)
+ for rows.Next() {
+ var id string
+ rows.Scan(&id)
+ postIDs = append(postIDs, id)
+ }
+
+ ids := strings.Join(postIDs, "','")
+
+ q := fmt.Sprintf("select id,slug,title,url,cover,brief,likes,views,creator,created,updated from posts where id in ('%s')", ids)
+ rows, err = db.Conn.Query(q)
+ if err != nil && err != sql.ErrNoRows {
+ logger.Warn("get user posts error", "error", err)
+ return nil, e.New(http.StatusInternalServerError, e.Internal)
+ }
+
+ posts := getPosts(user, rows)
+
+ sort.Sort(posts)
+ return posts, nil
+}
+
+func getPosts(user *models.User, rows *sql.Rows) models.Posts {
+ posts := make(models.Posts, 0)
+ for rows.Next() {
+ ar := &models.Post{}
+ err := rows.Scan(&ar.ID, &ar.Slug, &ar.Title, &ar.URL, &ar.Cover, &ar.Brief, &ar.Likes, &ar.Views, &ar.CreatorID, &ar.Created, &ar.Updated)
+ if err != nil {
+ logger.Warn("scan post error", "error", err)
+ continue
+ }
+
+ // 获取作者信息
+ creator := &models.UserSimple{ID: ar.CreatorID}
+ creator.Query()
+ ar.Creator = creator
+
+ // 获取评论信息
+ ar.Comments = GetCommentCount(ar.ID)
+
+ // 获取当前登录用户的like
+ if user != nil {
+ ar.Liked = GetLiked(ar.ID, user.ID)
+ }
+
+ // 获取当前登录用户的bookmark
+ ar.Bookmarked, _ = Bookmarked(user.ID, ar.ID)
+ posts = append(posts, ar)
+ }
+
+ return posts
+}
diff --git a/server/pkg/models/post.go b/server/pkg/models/post.go
index 481a5950..88e8bb5a 100644
--- a/server/pkg/models/post.go
+++ b/server/pkg/models/post.go
@@ -9,24 +9,25 @@ const (
)
type Post struct {
- ID string `json:"id"`
- Creator *UserSimple `json:"creator"`
- CreatorID int64 `json:"creatorId"`
- Title string `json:"title"`
- Slug string `json:"slug"`
- Md string `json:"md"`
- URL string `json:"url"`
- Cover string `json:"cover"`
- Brief string `json:"brief"`
- Tags []int64 `json:"tags"`
- RawTags []*Tag `json:"rawTags"`
- Likes int `json:"likes"`
- Liked bool `json:"liked"`
- Comments int `json:"comments"`
- Views int `json:"views"`
- Status int `json:"status"`
- Created time.Time `json:"created"`
- Updated time.Time `json:"updated"`
+ ID string `json:"id"`
+ Creator *UserSimple `json:"creator"`
+ CreatorID int64 `json:"creatorId"`
+ Title string `json:"title"`
+ Slug string `json:"slug"`
+ Md string `json:"md"`
+ URL string `json:"url"`
+ Cover string `json:"cover"`
+ Brief string `json:"brief"`
+ Tags []int64 `json:"tags"`
+ RawTags []*Tag `json:"rawTags"`
+ Likes int `json:"likes"`
+ Liked bool `json:"liked"`
+ Comments int `json:"comments"`
+ Views int `json:"views"`
+ Bookmarked bool `json:"bookmarked"`
+ Status int `json:"status"`
+ Created time.Time `json:"created"`
+ Updated time.Time `json:"updated"`
}
type Posts []*Post
diff --git a/src/components/comments/comment.tsx b/src/components/comments/comment.tsx
index 645fe20d..9efcb953 100644
--- a/src/components/comments/comment.tsx
+++ b/src/components/comments/comment.tsx
@@ -5,7 +5,7 @@ import Card from "components/card"
import { getUserName } from "utils/user"
import moment from 'moment'
import { MarkdownRender } from "components/markdown-editor/render"
-import HeartLike from "components/posts/heart-like"
+import Like from "components/posts/like"
import { FaRegEdit, FaRegFlag, FaRegTrashAlt, FaReply, FaTrash } from "react-icons/fa"
import { User } from "src/types/session"
import CommentEditor from "./editor"
@@ -40,11 +40,6 @@ export const CommentCard = (props: Props) => {
onChange()
}
- const likeComment = async (id) => {
- await requestApi.post(`/story/like/${id}`)
- onChange()
- }
-
return (
<>{
editorVisible ? (user && {setEditorVisible(false);changeComment(md)}} onCancel={() => setEditorVisible(false)} menu={false}/>) :
@@ -66,7 +61,7 @@ export const CommentCard = (props: Props) => {
- likeComment(comment.id)} />
+
{user && {
- likeReply(comment.id)} />
+
{user && {
+ return (
+ {shortNumber(props.count)}
+ )
+}
+
+export default Count
diff --git a/src/components/posts/bookmark.tsx b/src/components/posts/bookmark.tsx
new file mode 100644
index 00000000..96c22020
--- /dev/null
+++ b/src/components/posts/bookmark.tsx
@@ -0,0 +1,35 @@
+import { chakra, HStack, IconButton, Image, Tooltip, useColorMode, useColorModeValue } from "@chakra-ui/react";
+import SvgButton from "components/svg-button";
+import { useState } from "react";
+import { FaHeart, FaRegHeart } from "react-icons/fa";
+import { requestApi } from "utils/axios/request";
+
+interface Props {
+ storyID: string
+ bookmarked: boolean
+ height?: string
+}
+
+const Bookmark = (props: Props) => {
+ const {storyID, height="1.4rem"} = props
+
+ const [bookmarked,setBookmarked] = useState(props.bookmarked)
+ const bookmark = async () => {
+ await requestApi.post(`/bookmark/${storyID}`)
+ setBookmarked(!bookmarked)
+ }
+
+ return (
+
+ )
+}
+
+export default Bookmark
\ No newline at end of file
diff --git a/src/components/posts/heart-like.tsx b/src/components/posts/heart-like.tsx
deleted file mode 100644
index 4f953d41..00000000
--- a/src/components/posts/heart-like.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { chakra, HStack, IconButton, Image, Tooltip, useColorMode, useColorModeValue } from "@chakra-ui/react";
-import { FaHeart, FaRegHeart } from "react-icons/fa";
-
-interface Props {
- count: number
- onClick: any
- liked: boolean
-}
-const UnicornLike = (props: Props) => {
- const label = "I like it"
- return (
-
-
- {props.liked? }
- onClick={props.onClick}
- fontSize="20px"
- /> :
- }
- onClick={props.onClick}
- fontSize="20px"
- />}
-
-
- {props.count}
-
- )
-}
-
-export default UnicornLike
\ No newline at end of file
diff --git a/src/components/posts/like.tsx b/src/components/posts/like.tsx
new file mode 100644
index 00000000..145dc297
--- /dev/null
+++ b/src/components/posts/like.tsx
@@ -0,0 +1,61 @@
+import { chakra, HStack, IconButton, Tooltip} from "@chakra-ui/react";
+import Count from "components/count";
+import { useState } from "react";
+import { FaHeart, FaRegHeart } from "react-icons/fa";
+import { requestApi } from "utils/axios/request";
+
+interface Props {
+ storyID: string
+ count: number
+ liked: boolean
+ fontSize?: string
+ spacing?: string
+}
+const Like = (props: Props) => {
+ const {fontSize="20px",spacing="0"} = props
+ const label = "I like it"
+
+ const [liked,setLiked] = useState(props.liked)
+ const [count,setCount] = useState(props.count)
+ const like = async () => {
+ await requestApi.post(`/story/like/${props.storyID}`)
+
+
+ if (liked) {
+ setCount(count-1)
+ } else {
+ setCount(count+1)
+ }
+
+ setLiked(!liked)
+ }
+
+ return (
+
+
+ {liked? }
+ onClick={like}
+ fontSize={fontSize}
+ /> :
+ }
+ onClick={like}
+ fontSize={fontSize}
+ />}
+
+
+
+
+ )
+}
+
+export default Like
\ No newline at end of file
diff --git a/src/components/posts/no-more-posts.tsx b/src/components/posts/no-more-posts.tsx
new file mode 100644
index 00000000..e69de29b
diff --git a/src/components/posts/post-card.tsx b/src/components/posts/post-card.tsx
index db117c09..980808f7 100644
--- a/src/components/posts/post-card.tsx
+++ b/src/components/posts/post-card.tsx
@@ -3,9 +3,11 @@ import { Box, chakra, Flex, Heading, HStack, Image, Text, useMediaQuery, VStack
import { Post } from "src/types/posts"
import PostAuthor from "./post-author"
import Link from "next/link"
-import UnicornLike from "./heart-like"
-import { FaHeart, FaRegBookmark, FaRegComment, FaRegHeart } from "react-icons/fa"
-import SvgButton from "components/svg-button"
+import Like from "./like"
+import { FaHeart, FaRegHeart } from "react-icons/fa"
+import Bookmark from "./bookmark"
+import { getSvgIcon } from "components/svg-icon"
+import Count from "components/count"
interface Props {
post: Post
@@ -30,24 +32,17 @@ export const PostCard = (props: Props) => {
-
- {post.liked ?
-
- :
- }
- {post.likes}
-
-
+
-
-
- {post.comments}
-
+
+ {getSvgIcon("comments", "1.3rem")}
+
+
-
+
)
diff --git a/src/components/posts/post-sidebar.tsx b/src/components/posts/post-sidebar.tsx
new file mode 100644
index 00000000..83960e92
--- /dev/null
+++ b/src/components/posts/post-sidebar.tsx
@@ -0,0 +1,57 @@
+import React from "react"
+import { Box, BoxProps, useColorModeValue, VStack } from "@chakra-ui/react"
+import { Post } from "src/types/posts"
+import useSession from "hooks/use-session"
+import Like from "./like"
+import Bookmark from "./bookmark"
+import SvgButton from "components/svg-button"
+import { useRouter } from "next/router"
+import { ReserveUrls } from "src/data/reserve-urls"
+
+interface Props {
+ post: Post
+ vertical?: boolean
+}
+
+export const PostSidebar = (props: Props) => {
+ const {post,vertical = true} = props
+ const session = useSession()
+ const router = useRouter()
+ return (
+
+
+
+
+
+
+
+
+
+ location.href = "#comments"}
+ />
+
+
+ {post.creatorId === session?.user.id &&
+ router.push(`${ReserveUrls.Editor}/post/${post.id}`)}
+ icon="edit"
+ />
+ }
+
+
+ )
+}
+
+export default PostSidebar
diff --git a/src/components/svg-button.tsx b/src/components/svg-button.tsx
index 9b773109..5ec8cbbe 100644
--- a/src/components/svg-button.tsx
+++ b/src/components/svg-button.tsx
@@ -2,25 +2,28 @@ import React from "react"
import {chakra, PropsOf, IconButton } from "@chakra-ui/react"
type Props = PropsOf & {
- icon: 'bookmark' | 'edit' | 'share'
+ icon: any
onClick: any
height?: string
}
export const SvgButton= (props:Props) =>{
- const {icon,height="1.7rem",...rest} = props
+ const {icon,height="1.6rem",...rest} = props
let iconSvg
switch (icon) {
+ case "bookmarked":
+ iconSvg =
+ break;
case "bookmark":
iconSvg =
break;
case "share":
- iconSvg =
+ iconSvg =
break
case "edit":
- iconSvg =
+ iconSvg =
break
default:
break;
diff --git a/src/components/svg-icon.tsx b/src/components/svg-icon.tsx
index 2e9871e5..c8828c23 100644
--- a/src/components/svg-icon.tsx
+++ b/src/components/svg-icon.tsx
@@ -1,6 +1,9 @@
export function getSvgIcon(name,height="1.4rem") {
let svg
switch (name) {
+ case "comments":
+ svg =
+ break
case "hot":
svg =
break
diff --git a/src/types/posts.ts b/src/types/posts.ts
index f16f591c..15872510 100644
--- a/src/types/posts.ts
+++ b/src/types/posts.ts
@@ -23,4 +23,5 @@ export interface Post {
likes? : number
liked? : boolean
comments? : number
+ bookmarked?: boolean
}
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 7a6842fc..cd0f790b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3735,6 +3735,11 @@ shell-quote@1.7.2:
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
+short-number@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/short-number/-/short-number-1.0.7.tgz#5ab8021b86f20a4bdd1bbe01a85c22ff1cd15514"
+ integrity sha512-e3cb811QXHiAH2H5rgZwXHsmg2+aG6XK0QyKF/+pyDIZFBSz/G8bkr8avdBrL5PVIfhIq8rlohjFvSB3azzpEQ==
+
signal-exit@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"