diff --git a/frontend/components/article/ArticleMeta.tsx b/frontend/components/article/ArticleMeta.tsx
index 450795e86..f51ed9a49 100644
--- a/frontend/components/article/ArticleMeta.tsx
+++ b/frontend/components/article/ArticleMeta.tsx
@@ -1,10 +1,48 @@
import React from "react";
+import Router from "next/router";
+import useSWR, { trigger } from "swr";
import ArticleActions from "./ArticleActions";
import CustomImage from "../common/CustomImage";
import CustomLink from "../common/CustomLink";
+import ArticleAPI from "../../lib/api/article";
+import checkLogin from "../../lib/utils/checkLogin";
+import { SERVER_BASE_URL } from "../../lib/utils/constant";
+import storage from "../../lib/utils/storage";
+
+const BOOKMARKED_CLASS = "btn btn-sm btn-primary";
+const NOT_BOOKMARKED_CLASS = "btn btn-sm btn-outline-primary";
const ArticleMeta = ({ article }) => {
+ const { data: currentUser } = useSWR("user", storage);
+ const isLoggedIn = checkLogin(currentUser);
+
+ const [bookmarked, setBookmarked] = React.useState(article?.bookmarked || false);
+
+ React.useEffect(() => {
+ setBookmarked(article?.bookmarked || false);
+ }, [article?.bookmarked]);
+
+ const handleBookmark = async () => {
+ if (!isLoggedIn) {
+ Router.push(`/user/login`);
+ return;
+ }
+
+ try {
+ if (bookmarked) {
+ setBookmarked(false);
+ await ArticleAPI.unbookmark(article.slug, currentUser?.token);
+ } else {
+ setBookmarked(true);
+ await ArticleAPI.bookmark(article.slug, currentUser?.token);
+ }
+ trigger(`${SERVER_BASE_URL}/articles/${article.slug}`);
+ } catch (error) {
+ setBookmarked(bookmarked);
+ }
+ };
+
if (!article) return;
return (
@@ -30,6 +68,14 @@ const ArticleMeta = ({ article }) => {
+
+
);
};
diff --git a/frontend/components/article/ArticlePreview.tsx b/frontend/components/article/ArticlePreview.tsx
index 266853203..818da69fc 100644
--- a/frontend/components/article/ArticlePreview.tsx
+++ b/frontend/components/article/ArticlePreview.tsx
@@ -8,11 +8,14 @@ import CustomLink from "../common/CustomLink";
import CustomImage from "../common/CustomImage";
import { usePageDispatch } from "../../lib/context/PageContext";
import checkLogin from "../../lib/utils/checkLogin";
+import ArticleAPI from "../../lib/api/article";
import { SERVER_BASE_URL } from "../../lib/utils/constant";
import storage from "../../lib/utils/storage";
const FAVORITED_CLASS = "btn btn-sm btn-primary";
const NOT_FAVORITED_CLASS = "btn btn-sm btn-outline-primary";
+const BOOKMARKED_CLASS = "btn btn-sm btn-primary";
+const NOT_BOOKMARKED_CLASS = "btn btn-sm btn-outline-primary";
const ArticlePreview = ({ article }) => {
const setPage = usePageDispatch();
@@ -24,6 +27,31 @@ const ArticlePreview = ({ article }) => {
const { data: currentUser } = useSWR("user", storage);
const isLoggedIn = checkLogin(currentUser);
+ const handleClickBookmark = async (slug) => {
+ if (!isLoggedIn) {
+ Router.push(`/user/login`);
+ return;
+ }
+
+ setPreview({
+ ...preview,
+ bookmarked: !preview.bookmarked,
+ });
+
+ try {
+ if (preview.bookmarked) {
+ await ArticleAPI.unbookmark(slug, currentUser?.token);
+ } else {
+ await ArticleAPI.bookmark(slug, currentUser?.token);
+ }
+ } catch (error) {
+ setPreview({
+ ...preview,
+ bookmarked: preview.bookmarked,
+ });
+ }
+ };
+
const handleClickFavorite = async (slug) => {
if (!isLoggedIn) {
Router.push(`/user/login`);
@@ -96,6 +124,15 @@ const ArticlePreview = ({ article }) => {
+