From f0f940ec0ca65883063d23161de93956aff18388 Mon Sep 17 00:00:00 2001 From: Darren52BT Date: Tue, 19 Mar 2024 22:14:16 -0700 Subject: [PATCH 1/2] created initial article result layout --- .../ArticleResult/ArticleResult.jsx | 23 ++++++ .../ArticleResult/ArticleResult.scss | 75 +++++++++++++++++++ .../ArticleResults/ArticleResultsList.jsx | 0 frontend/src/pages/ArticleList.jsx | 66 ++++++++++------ 4 files changed, 142 insertions(+), 22 deletions(-) create mode 100644 frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx create mode 100644 frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss create mode 100644 frontend/src/Components/ArticleResults/ArticleResultsList.jsx diff --git a/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx new file mode 100644 index 0000000..e3ecc6a --- /dev/null +++ b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx @@ -0,0 +1,23 @@ +import { Image } from "react-bootstrap"; +import "./ArticleResult.scss"; +import { Bookmark, BookmarkFill } from "react-bootstrap-icons"; +export default function ArticleResult({ article }) { + return ( +
+
+ + {article.isBookmarked ? ( + + ) : ( + + )} +
+ +
+

{article.title}

+ By {article.author} + Published {article.date} +
+
+ ); +} diff --git a/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss new file mode 100644 index 0000000..ec70b28 --- /dev/null +++ b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss @@ -0,0 +1,75 @@ +@import "bootstrap/scss/bootstrap-grid.scss"; +@import "bootstrap/scss/grid"; +@import "bootstrap/scss/variables"; +@import "bootstrap/scss/mixins"; +@import "bootstrap/scss/functions"; +@import "../../../scss/variables"; + +.article-result { + display: grid; + grid-template-columns: 1fr 5fr; + height: 100px; + @include media-breakpoint-up(lg) { + grid-template-columns: 250px 5fr; + } +} + +.article-result-image-container { + width: fit-content; + position: relative; + display: flex; + height: inherit; + justify-content: center; +} + +.article-result-image { + object-fit: contain; + object-position: center top; + width: 100%; + height: 100%; +} +.article-result-bookmark { + position: absolute; + transform: rotate(-90deg); + top: 0; + right: -10px; + width: fit-content; + + &:hover { + cursor: pointer; + } + &:active { + cursor: auto; + } +} + +.article-result-text { + display: flex; + flex-direction: column; +} +.article-result-title { + font-weight: 600; +} +.article-result-author, +.article-result-date { + font-weight: 300; + font-style: italic; +} + +//COLOR MODES +@include color-mode(light) { + .article-result-text { + color: $primary-text-light; + } + .article-result-bookmark { + color: $bookmark-bg-light; + } +} +@include color-mode(dark) { + .article-result-text { + color: $primary-text-dark; + } + .article-result-bookmark { + color: $bookmark-bg-dark; + } +} diff --git a/frontend/src/Components/ArticleResults/ArticleResultsList.jsx b/frontend/src/Components/ArticleResults/ArticleResultsList.jsx new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/pages/ArticleList.jsx b/frontend/src/pages/ArticleList.jsx index dd83626..ad4b889 100644 --- a/frontend/src/pages/ArticleList.jsx +++ b/frontend/src/pages/ArticleList.jsx @@ -2,24 +2,39 @@ import { useEffect, useState } from "react"; import { Card, Stack } from "react-bootstrap"; import { useParams, useSearchParams } from "react-router-dom"; import LinkedDescriptionBox from "../Components/LinkedDescriptionBox.jsx"; +import ArticleResult from "../Components/ArticleResults/ArticleResult/ArticleResult.jsx"; -export default function ArticleList({ }) { - const [data,setData] = useState() - const [searchParams, setSearchParams] = useSearchParams() - const [specificArticle, setSpecificArticle] = useState() - const titleQuery = searchParams.get("title") +const dummmy_articles = [ + { + image: + "https://emeritus.org/in/wp-content/uploads/sites/3/2023/03/types-of-machine-learning.jpg.optimal.jpg", + title: "Machine Learning in Business and Marketing", + author: "Jeff", + date: "October 24, 2023", + }, + { + image: + "https://www.mathworks.com/solutions/machine-learning/_jcr_content/mainParsys/band_copy_1919605364/mainParsys/columns/a03cc495-1c23-4402-82ea-1c8fd4d25234/pictogram.adapt.full.medium.svg/1701252724596.svg", + title: "Machine Learning in Business and Marketing", + author: "Jeff", + date: "October 24, 2023", + }, +]; +export default function ArticleList({}) { + const [data, setData] = useState(); + const [searchParams, setSearchParams] = useSearchParams(); + const [specificArticle, setSpecificArticle] = useState(); + const titleQuery = searchParams.get("title"); //console.log(titleQuery); - useEffect(()=> - { + useEffect(() => { fetch(`http://localhost:3002/api/articles/?title=${titleQuery}`) - .then((res) => res.json() - .then(data => setData(data))) - .catch((error) =>{ + .then((res) => res.json().then((data) => setData(data))) + .catch((error) => { console.error("error fetching data"); - }) + }); - /** if(data && data.length > 0 ){ + /** if(data && data.length > 0 ){ const specificArticleId = data[0].id; fetch(`http://localhost:3002/api/articles/${specificArticleId}`) .then((res) => res.json()) @@ -31,11 +46,11 @@ export default function ArticleList({ }) { console.error("error fetching specific article"); }); } */ - },[titleQuery, setSearchParams]) + }, [titleQuery, setSearchParams]); const { id } = useParams(); - /* const fetchArticle = async () => { + /* const fetchArticle = async () => { fetch(`http://localhost:3002/api/articles/?title=${titleQuery}`) .then((res) => res.json()) .then((data) => { @@ -46,16 +61,22 @@ export default function ArticleList({ }) { console.error("Error fetching item data:", error); }); } */ - - if (data == undefined ) - { - return <>loading... + if (data == undefined) { + // return <>loading... + return ( +
+ {dummmy_articles.map((article) => { + return( ); + + })} +
+ ); } console.log(data); return ( <> -
+
@@ -67,9 +88,10 @@ export default function ArticleList({ }) { {data.map((item) => (
+ title={item.title} + id={item.id} + variant="secondary" + > {item.description}
From 47579ed62a17c1204962fab412d8c0244efa751f Mon Sep 17 00:00:00 2001 From: Darren52BT Date: Wed, 20 Mar 2024 17:12:55 -0700 Subject: [PATCH 2/2] completed article results list design --- .../ArticleResult/ArticleResult.jsx | 28 ++-- .../ArticleResult/ArticleResult.scss | 58 +++++++- .../ArticleResults/ArticleResultsList.jsx | 18 +++ frontend/src/pages/ArticleList.jsx | 140 ++++-------------- frontend/src/pages/BasePage.jsx | 1 - 5 files changed, 115 insertions(+), 130 deletions(-) diff --git a/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx index e3ecc6a..e81d665 100644 --- a/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx +++ b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.jsx @@ -1,22 +1,30 @@ import { Image } from "react-bootstrap"; import "./ArticleResult.scss"; import { Bookmark, BookmarkFill } from "react-bootstrap-icons"; -export default function ArticleResult({ article }) { +export default function ArticleResult({ article, bookmarkToggler }) { return (
-
- - {article.isBookmarked ? ( - - ) : ( - - )} +
+ + {article.isBookmarked ? ( + + ) : ( + + )}

{article.title}

- By {article.author} - Published {article.date} +
+ By {article.author} + Published {article.date} +
); diff --git a/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss index ec70b28..e4e7882 100644 --- a/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss +++ b/frontend/src/Components/ArticleResults/ArticleResult/ArticleResult.scss @@ -4,29 +4,41 @@ @import "bootstrap/scss/mixins"; @import "bootstrap/scss/functions"; @import "../../../scss/variables"; - +/*overall article result container*/ .article-result { display: grid; - grid-template-columns: 1fr 5fr; + grid-template-columns: 1fr 6fr; + gap: 20px; height: 100px; + @include media-breakpoint-up(sm) { + height: 150px; + } @include media-breakpoint-up(lg) { grid-template-columns: 250px 5fr; } } +/*image*/ .article-result-image-container { width: fit-content; position: relative; display: flex; height: inherit; justify-content: center; + margin: auto; } .article-result-image { object-fit: contain; object-position: center top; - width: 100%; height: 100%; + width: 75px; + @include media-breakpoint-up(sm) { + width: 150px; + } + @include media-breakpoint-up(md) { + width: 200px; + } } .article-result-bookmark { position: absolute; @@ -43,22 +55,54 @@ } } -.article-result-text { +/*Text*/ +.article-result-text, +.article-result-info { display: flex; flex-direction: column; } +.article-result-text { + gap: 5px; +} +.article-result-info { + gap: 2.5px; +} + .article-result-title { font-weight: 600; + margin-bottom: 0 !important; + font-size: calc(0.8rem + 0.5vw); + @include media-breakpoint-up(sm) { + font-size: calc(1.2rem + 0.5vw); + } + /*style for clicking on article title*/ + &:hover { + cursor: pointer; + text-decoration: underline; + } + &:active { + cursor: auto; + position: relative; + top: 1px; + opacity: 0.8; + } } .article-result-author, .article-result-date { font-weight: 300; font-style: italic; + padding: 0 !important; + font-size: calc(0.8rem + 0.1vw); + @include media-breakpoint-up(sm) { + font-size: calc(0.9rem + 0.1vw); + } } //COLOR MODES @include color-mode(light) { - .article-result-text { + .article-result-text, + .article-result-author, + .article-result-date { color: $primary-text-light; } .article-result-bookmark { @@ -66,7 +110,9 @@ } } @include color-mode(dark) { - .article-result-text { + .article-result-text, + .article-result-author, + .article-result-date { color: $primary-text-dark; } .article-result-bookmark { diff --git a/frontend/src/Components/ArticleResults/ArticleResultsList.jsx b/frontend/src/Components/ArticleResults/ArticleResultsList.jsx index e69de29..ed6f670 100644 --- a/frontend/src/Components/ArticleResults/ArticleResultsList.jsx +++ b/frontend/src/Components/ArticleResults/ArticleResultsList.jsx @@ -0,0 +1,18 @@ +import ArticleResult from "./ArticleResult/ArticleResult"; + +export default function ArticleResultsList({ + articles, + bookmarkTogglerCreator, +}) { + return ( +
+ {articles.map((article) => ( + + ))} +
+ ); +} diff --git a/frontend/src/pages/ArticleList.jsx b/frontend/src/pages/ArticleList.jsx index ad4b889..ab04b37 100644 --- a/frontend/src/pages/ArticleList.jsx +++ b/frontend/src/pages/ArticleList.jsx @@ -2,34 +2,48 @@ import { useEffect, useState } from "react"; import { Card, Stack } from "react-bootstrap"; import { useParams, useSearchParams } from "react-router-dom"; import LinkedDescriptionBox from "../Components/LinkedDescriptionBox.jsx"; -import ArticleResult from "../Components/ArticleResults/ArticleResult/ArticleResult.jsx"; - +import ArticleResultsList from "../Components/ArticleResults/ArticleResultsList.jsx"; const dummmy_articles = [ { + id: 1, image: "https://emeritus.org/in/wp-content/uploads/sites/3/2023/03/types-of-machine-learning.jpg.optimal.jpg", title: "Machine Learning in Business and Marketing", author: "Jeff", date: "October 24, 2023", + isBookmarked: true, }, { + id: 2, image: - "https://www.mathworks.com/solutions/machine-learning/_jcr_content/mainParsys/band_copy_1919605364/mainParsys/columns/a03cc495-1c23-4402-82ea-1c8fd4d25234/pictogram.adapt.full.medium.svg/1701252724596.svg", - title: "Machine Learning in Business and Marketing", - author: "Jeff", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS8QfYW-Re6kMIo_i9D5x4KUHVStLYWGuK4vg&usqp=CAU", + title: "Intro to Machine Learning", + author: "Darren", date: "October 24, 2023", + isBookmarked: false, }, ]; export default function ArticleList({}) { - const [data, setData] = useState(); + const [articles, setArticles] = useState(dummmy_articles); const [searchParams, setSearchParams] = useSearchParams(); const [specificArticle, setSpecificArticle] = useState(); const titleQuery = searchParams.get("title"); //console.log(titleQuery); + //bookmark toggler creator function, returns function that toggles bookmark for certain id + const bookmarkTogglerCreator = (id) => () => { + let articleIndex = articles.findIndex((article) => article.id === id); + if (articleIndex !== -1) { + const newArticles = [...articles]; + newArticles[articleIndex].isBookmarked = + !newArticles[articleIndex].isBookmarked; + setArticles(newArticles); + } + }; + useEffect(() => { fetch(`http://localhost:3002/api/articles/?title=${titleQuery}`) - .then((res) => res.json().then((data) => setData(data))) + .then((res) => res.json().then((data) => setArticles(data))) .catch((error) => { console.error("error fetching data"); }); @@ -62,112 +76,12 @@ export default function ArticleList({}) { }); } */ - if (data == undefined) { - // return <>loading... - return ( -
- {dummmy_articles.map((article) => { - return( ); - - })} -
- ); - } - console.log(data); return ( - <> -
- -
- - -

Search Results: "{titleQuery}"

-
-
-
- {data.map((item) => ( -
- - {item.description} - -
- ))} - {/*
- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum. - -
-
- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum. - -
-
- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum. - -
-
- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum. - -
-
- - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do - eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut - enim ad minim veniam, quis nostrud exercitation ullamco laboris - nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in - reprehenderit in voluptate velit esse cillum dolore eu fugiat - nulla pariatur. Excepteur sint occaecat cupidatat non proident, - sunt in culpa qui officia deserunt mollit anim id est laborum. - -
*/} -
-
- +
+ +
); } diff --git a/frontend/src/pages/BasePage.jsx b/frontend/src/pages/BasePage.jsx index 3ba7496..3635c5d 100644 --- a/frontend/src/pages/BasePage.jsx +++ b/frontend/src/pages/BasePage.jsx @@ -8,7 +8,6 @@ export default function BasePage() {
-