Skip to content

Toggle bookmark hook #52

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

Open
wants to merge 31 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b488d75
Create ImageStorage
plexin123 Mar 22, 2024
6e7d1b8
created basic hooks for bookmarks
Darren52BT Jun 10, 2024
eb17014
added a hook called useBookmark to keep track of bookmark status and …
davidgit3000 Jun 13, 2024
5acab0f
Make some changes about .env and connection refused
plexin123 Jun 18, 2024
02b7ecc
login/signup 90%
plexin123 Jun 19, 2024
4fbea69
fixed the fetch link between DELETE and POST methods in useBookmark hook
davidgit3000 Jun 20, 2024
4bcedba
added useBookmark hook to handle bookmark toggling logic
davidgit3000 Jun 20, 2024
d8c67be
added signup logic using useSignup hook
davidgit3000 Jun 20, 2024
b82e3a6
added Signup logic and modified RecentArticles, SavedArticles, and us…
davidgit3000 Jun 20, 2024
edee848
fixed bug allowing user to be empty by restricting no white spacesl, …
Darren52BT Jun 20, 2024
f92c075
fixed bug with moving on to login even if there are errors
Darren52BT Jun 20, 2024
99120a0
fixed bug with fieldnames in sign up
Darren52BT Jun 20, 2024
74734c0
small change
plexin123 Jun 23, 2024
73c2609
Merge remote-tracking branch 'origin/dev' into ImageStorage
plexin123 Jun 24, 2024
e2adb96
added login logic on client side and modified the padding of menu opt…
davidgit3000 Jun 27, 2024
a39b75d
add authorizeArticle
plexin123 Jun 27, 2024
ea0ad4b
Merge remote-tracking branch 'origin/ImageStorage' into toggle-bookma…
davidgit3000 Jun 27, 2024
393d4ee
modifed SigninCard and SignupCard
davidgit3000 Jun 27, 2024
25db2b0
fixed duplicate imports in SigninCard and SignupCard
davidgit3000 Jun 27, 2024
11dd502
Changed articleID to article_id
plexin123 Jul 1, 2024
95696d9
small testing fixes
pv-nguyen Jul 6, 2024
dfb62b9
added JWT to GET article endpoint in ArticleView.jsx and changed the …
davidgit3000 Jul 7, 2024
6a9c727
bookmarked articles display correctly now
pv-nguyen Jul 7, 2024
31a4788
allow user to see article even if not logged in
pv-nguyen Jul 7, 2024
620a4a0
integrated Settings Saved Articles
Darren52BT Jul 7, 2024
3c7844c
modified loading state of bookmark icon - removed page reloading for …
davidgit3000 Jul 9, 2024
1c353fc
modified the avatar menu and showed username once logged in
davidgit3000 Jul 9, 2024
a9c1056
fixed username error when not logged in
davidgit3000 Jul 9, 2024
cb4c93e
fixed loading and no results states
Darren52BT Jul 9, 2024
03457f1
Merge branch 'toggle-bookmark-hook' of github.com:cppsea/CS-Catalog i…
Darren52BT Jul 9, 2024
4283c7c
Change to env
plexin123 Aug 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"react-bootstrap-icons": "^1.10.3",
"react-bootstrap-typeahead": "^6.3.2",
"react-dom": "^18.2.0",
"react-hot-toast": "^2.4.1",
"react-icons": "^5.2.1",
"react-router-dom": "^6.18.0",
"web-vitals": "^2.1.4"
},
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import ProfileEdit from "./Components/Settings/Profile/ProfileEdit.jsx";
import SavedArticles from "./Components/Settings/SavedArticles/SavedArticles.jsx";
import CustomizationsEdit from "./Components/Settings/Customizations/CustomizationsEdit.jsx";
import SignWelcome from "./pages/SignPages/SignWelcome.jsx";
import { Toaster } from "react-hot-toast";

function App() {
return (
Expand Down Expand Up @@ -42,6 +43,7 @@ function App() {
/>
</Route>
</Routes>
<Toaster />
</>
);
}
Expand Down
43 changes: 39 additions & 4 deletions frontend/src/Components/Article/Article.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import { Container, Row, Col, Stack } from "react-bootstrap";
import "./ArticleComponents.scss";
import "./Article.scss";
import { useEffect, useState } from "react";
import useBookmark from "../../hooks/useBookmark.jsx";
import { AiOutlineLoading3Quarters } from "react-icons/ai";
import { toast } from "react-hot-toast";

//dummy data for table of contents
const tableOfContents = [
"Introduction to Machine Learning",
Expand Down Expand Up @@ -74,11 +78,15 @@ const relatedTopicsList = [

//this component accepts an article object and displays the corresponding article
export default function Article({ article }) {
const { isLoading, error, updateBookmark } = useBookmark();

// keep track of a specific article's bookmark toggling process
const [isPendingArticle, setIsPendingArticle] = useState(false);

//extracts article data pieces from provided article

//these properties that i'm defining aside from title don't exist in the database yet,
//mostly made up so feel free to change later on

//will display default data from figma for now

const [articleData, setArticleData] = useState({
Expand All @@ -90,7 +98,7 @@ export default function Article({ article }) {
: "Embark on a journey through the basics; explore what machine learning entails and how one can apply it in the real world.",
author: article.author ? article.author : "David Lam",
date: article.date ? article.date : "October 29, 2023",
isBookmarked: false,
isBookmarked: article.isBookmarked,
headers:
article.headers && Array.isArray(article.headers)
? article.headers
Expand Down Expand Up @@ -118,9 +126,35 @@ export default function Article({ article }) {
};
}
);

//handler for toggling bookmark
const toggleBookmark = () =>
const toggleBookmark = () => {
setArticleData({ ...articleData, isBookmarked: !articleData.isBookmarked });

// set pending state of an article being bookmarked to true
setIsPendingArticle(true);

// reset pending state to false
setTimeout(() => {
setIsPendingArticle(false);
}, 500);
};

// toggleBookmark() function will be called only if there is a successful response from the server
const handleToggleBookmark = async () => {
await updateBookmark(
articleData.id,
articleData.isBookmarked,
toggleBookmark
);
};

useEffect(() => {
if (error) {
toast.error(error);
}
}, [error]);

return (
<>
<Container fluid className="h-100">
Expand All @@ -132,7 +166,8 @@ export default function Article({ article }) {
author={articleData.author}
date={articleData.date}
isBookmarked={articleData.isBookmarked}
bookmarkToggler={toggleBookmark}
isPending={isPendingArticle}
bookmarkToggler={handleToggleBookmark}
/>
</Col>
</Row>
Expand Down
14 changes: 14 additions & 0 deletions frontend/src/Components/Article/Article.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@
}
}

@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

.loading {
font-size: 1.2rem;
animation: spin 500ms linear infinite;
}

@include color-mode(light) {
.rel-topics-container {
border-color: $divider-light;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,19 @@ export default function ArticleHeader({
author,
date,
isBookmarked,
isPending,
bookmarkToggler,
}) {
return (
<Stack gap={2}>
<ArticleHeaderTitle
title={title}
isBookmarked={isBookmarked}
isPending={isPending}
bookmarkToggler={bookmarkToggler}
/>
<ArticleHeaderDesc desc={description} />
<ArticleHeaderAuthorDate
author={author}
date={date}
bookmarkToggler={bookmarkToggler}
isBookmarked={isBookmarked}
/>
<ArticleHeaderAuthorDate author={author} date={date} />
</Stack>
);
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { Stack } from "react-bootstrap";

import { Bookmark, BookmarkFill } from "react-bootstrap-icons";
import { AiOutlineLoading3Quarters } from "react-icons/ai";

//component for article title
export default function ArticleHeaderTitle({
title,
isBookmarked,
isPending,
bookmarkToggler,
}) {
return (
<Stack direction="horizontal" gap={2}>
{isBookmarked ? (
{isPending ? (
<AiOutlineLoading3Quarters className="loading fs-2" />
) : isBookmarked ? (
<BookmarkFill className="article-bookmark" onClick={bookmarkToggler} />
) : (
<Bookmark className="article-bookmark" onClick={bookmarkToggler} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@ import { Image } from "react-bootstrap";
import "./ArticleResult.scss";
import { Bookmark, BookmarkFill } from "react-bootstrap-icons";
import { useNavigate } from "react-router-dom";
export default function ArticleResult({ article, bookmarkToggler }) {
import { AiOutlineLoading3Quarters } from "react-icons/ai";
export default function ArticleResult({ article, isPending, bookmarkToggler }) {
const navigate = useNavigate();

const articleNavigate = () => {
navigate(`/article_view/${article.id}`);
};
return (
<div className="article-result">
<div className="article-result-image-container">
<div className="article-result-image-container" onClick={articleNavigate}>
<Image src={article.image} className="article-result-image" />
</div>
<div>
{article.isBookmarked ? (
{isPending ? (
<AiOutlineLoading3Quarters className="loading" />
) : article.isBookmarked ? (
<BookmarkFill
className="article-result-bookmark"
onClick={bookmarkToggler}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@
.article-result {
display: flex;
gap: 10px;
height: 100px;
height: 100%;
padding: 0.5rem;
cursor: pointer;

&:hover {
border: 1px solid $primary;
border-radius: 10px;
}

@include media-breakpoint-up(sm) {
height: 150px;
}
Expand Down
78 changes: 40 additions & 38 deletions frontend/src/Components/Header/Header.jsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
import logo from "../../assets/logo.png";
import avatar from "../../assets/avatar.jpg";
import {
Button,
Container,
Image,
Nav,
Navbar,
Image,
Stack,
NavDropdown,
OverlayTrigger,
Popover,
Button,
DropdownButton,
ButtonGroup,
Dropdown,
Stack
} from "react-bootstrap";
import avatar from "../../assets/avatar.jpg";
import SearchBar from "../SearchBar";
import { SunFill, MoonFill } from "react-bootstrap-icons";

import { useAuthContext } from "../../hooks/useAuthContext";
import { useLogout } from "../../hooks/useLogout";
import "./Header.scss";
import { useState } from "react";

export default function Header() {
const [isDark, setIsDark] = useState(false);
const { user } = useAuthContext();
const { logout } = useLogout();
const storedUser = localStorage.getItem("user");
let username = null;
if (storedUser) {
username = JSON.parse(storedUser).username;
}

const handleLogout = () => {
logout();
};

return (
<>
Expand Down Expand Up @@ -80,28 +86,12 @@ export default function Header() {
as="h3"
className="text-center bg-primary"
>
Hello John!
{username
? username.charAt(0).toUpperCase() + username.slice(1)
: "Guest"}
</Popover.Header>
<Popover.Body className="py-2">
<Nav>
<Nav.Item>
<Nav.Link
className="fw-medium"
href="/settings/profile-settings"
id="dropdown_items"
>
My Profile
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
className="fw-medium"
href="/settings/saved-articles"
id="dropdown_items"
>
Saved Articles
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
className="fw-medium"
Expand All @@ -113,14 +103,26 @@ export default function Header() {
</Nav.Item>
<div id="profile_menu_divider"></div>
<Nav.Item>
<Nav.Link
className="fw-medium"
href="/signin"
id="dropdown_items"
style={{ color: "red" }}
>
Sign out
</Nav.Link>
{user ? (
<Nav.Link
className="fw-medium"
href="/signin"
id="dropdown_items"
style={{ color: "red" }}
onClick={handleLogout}
>
Sign out
</Nav.Link>
) : (
<Nav.Link
className="fw-bold"
href="/signin"
id="dropdown_items"
style={{ color: "lightblue" }}
>
Sign in
</Nav.Link>
)}
</Nav.Item>
</Nav>
</Popover.Body>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Components/Header/Header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

#dropdown_items {
color: $link-text;
padding-left: 10px;
padding: 8px 10px;
font-size: 1.2em;
&:hover {
font-weight: 600 !important;
Expand Down
Loading