diff --git a/bfrontend/package-lock.json b/bfrontend/package-lock.json index d9edd22..af36251 100644 --- a/bfrontend/package-lock.json +++ b/bfrontend/package-lock.json @@ -12201,6 +12201,11 @@ "whatwg-fetch": "^3.4.1" } }, + "react-content-loader": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/react-content-loader/-/react-content-loader-5.1.4.tgz", + "integrity": "sha512-hTq7pZi2GKCK6a9d3u6XStozm0QGCEjw8cSqQReiWnh2up6IwCha5R5TF0o6SY5qUDpByloEZEZtnFxpJyENFw==" + }, "react-dev-utils": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.1.tgz", @@ -12314,6 +12319,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-media-hook": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/react-media-hook/-/react-media-hook-0.4.9.tgz", + "integrity": "sha512-FZr/2xA1+23vDJ1IZ794yLqMRRkBoCNOiJATdtTfB5GyVc5djf8FL2qEB/68pSkiNgHdHsmKknMSDr0sC4zBKQ==" + }, "react-redux": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.2.tgz", diff --git a/bfrontend/package.json b/bfrontend/package.json index 469e59d..3e858d1 100644 --- a/bfrontend/package.json +++ b/bfrontend/package.json @@ -8,7 +8,9 @@ "@testing-library/user-event": "^12.6.0", "nord": "^0.2.1", "react": "^17.0.1", + "react-content-loader": "^5.1.4", "react-dom": "^17.0.1", + "react-media-hook": "^0.4.9", "react-redux": "^7.2.2", "react-router-dom": "^5.2.0", "react-scripts": "4.0.1", @@ -22,7 +24,7 @@ "test": "react-scripts test", "eject": "react-scripts eject" }, - "proxy": "http://localhost:3002", + "proxy": "http://localhost:3005", "eslintConfig": { "extends": [ "react-app", diff --git a/bfrontend/src/Components/App.js b/bfrontend/src/Components/App.js index c9fd0db..fdc1989 100644 --- a/bfrontend/src/Components/App.js +++ b/bfrontend/src/Components/App.js @@ -3,6 +3,9 @@ import Root from './Root'; import Authenticator from './../Authenticator'; import Notification from './Notification'; import './../Styles/App.scss'; +import { couldNotReach } from '../Errors'; +import CategoryView from './Categories/CategoryView'; +import Sidebar from './UI/Sidebar'; import { useEffect, useState } from 'react'; import { useDispatch, connect } from 'react-redux' @@ -20,7 +23,7 @@ function App({ user }) { dispatch({ type: 'authenticator/updatelocaluserobject', user: res }) }) .catch(() => { - setNotificationText('An error has occoured.'); + setNotificationText(couldNotReach); setHasError(true); }); }, [dispatch]); @@ -28,16 +31,22 @@ function App({ user }) { if (!hasError) { return (
- - - - - - - - - - +
+ + + + + + + + + + + + + + +
); } else { @@ -51,7 +60,7 @@ function App({ user }) { const stateToProps = (state) => { return { - user: state?.user + user: state?.user, }; }; diff --git a/bfrontend/src/Components/Categories/CategoryButton.js b/bfrontend/src/Components/Categories/CategoryButton.js new file mode 100644 index 0000000..ba4adbc --- /dev/null +++ b/bfrontend/src/Components/Categories/CategoryButton.js @@ -0,0 +1,11 @@ +import { useHistory } from 'react-router-dom'; + +export default function CategoryButton({ category }) { + const history = useHistory(); + + return ( + + ) +} \ No newline at end of file diff --git a/bfrontend/src/Components/Categories/CategoryList.js b/bfrontend/src/Components/Categories/CategoryList.js new file mode 100644 index 0000000..2ca7ea2 --- /dev/null +++ b/bfrontend/src/Components/Categories/CategoryList.js @@ -0,0 +1,53 @@ +import CategoryListLoader from './CategoryListLoader'; +import CategoryButton from './CategoryButton'; +import APIRequest from '../../APIRequest'; +import { couldNotReach } from '../../Errors'; + +import { useDispatch } from 'react-redux' +import { useState, useEffect } from 'react'; + +export default function CategoryList() { + const [ categoryList, setCategoryList ] = useState(); + const [ error, setError ] = useState(); + + const dispatch = useDispatch(); + + useEffect(() => { + APIRequest.authenticated('/api/v1/content/category/list?count=50') + .then(({ isOK, json }) => { + if (!isOK) return setError(true); + setCategoryList(json.categories || []); + + dispatch({ type: 'categories/updatecategorylist', categories: json.categories }); + }) + .catch(() => { + setError(true); + }); + }, [dispatch]); + + if (!categoryList) { + if (error) { + return ( +
+

+ { couldNotReach } +

+
+ ); + } else { + return ( +
+ +
+ ); + } + } else { + return ( +
+ {categoryList.map((category) => + + )} +
+ ); + } +} \ No newline at end of file diff --git a/bfrontend/src/Components/Categories/CategoryListLoader.js b/bfrontend/src/Components/Categories/CategoryListLoader.js new file mode 100644 index 0000000..50ce706 --- /dev/null +++ b/bfrontend/src/Components/Categories/CategoryListLoader.js @@ -0,0 +1,44 @@ +import ContentLoader from "react-content-loader" +import { useMediaPredicate } from "react-media-hook"; + +export default function CategoryListLoader(props) { + const lessThan600 = useMediaPredicate("(max-width: 600px)"); + + if (lessThan600) { + return ( + + + + + + + + ); + } else { + return ( + + + + + + + + ); + } +} \ No newline at end of file diff --git a/bfrontend/src/Components/Categories/CategoryProfile.js b/bfrontend/src/Components/Categories/CategoryProfile.js new file mode 100644 index 0000000..e69de29 diff --git a/bfrontend/src/Components/Categories/CategoryView.js b/bfrontend/src/Components/Categories/CategoryView.js new file mode 100644 index 0000000..6be9092 --- /dev/null +++ b/bfrontend/src/Components/Categories/CategoryView.js @@ -0,0 +1,55 @@ +import CategoryViewLoader from './CategoryViewLoader'; + +import { useParams } from 'react-router-dom'; +import { connect } from 'react-redux' + +function CategoryView({ categories }) { + const { id } = useParams(); + + let category; + + if (categories) { + category = categories.find(x => x._id === id); + } + + if (category) { + return ( +
+
+ { category.title } +
+
+ In terms of development, the first year of a cat’s life is equal to the first 15 years of a human life. After its second year, a cat is 25 in human years. And after that, each year of a cat’s life is equal to about 7 human years. + Cats can rotate their ears 180 degrees. +
+
+ The hearing of the average cat is at least five times keener than that of a human adult. + In the largest cat breed, the average male weighs approximately 20 pounds. +
+
+ ) + } else { + return ( +
+
+ +
+
+ +
+
+ +
+
+ ) + } + +} + +const stateToProps = (state) => { + return { + categories: state?.categories + }; +}; + +export default connect(stateToProps)(CategoryView); \ No newline at end of file diff --git a/bfrontend/src/Components/Categories/CategoryViewLoader.js b/bfrontend/src/Components/Categories/CategoryViewLoader.js new file mode 100644 index 0000000..ed113af --- /dev/null +++ b/bfrontend/src/Components/Categories/CategoryViewLoader.js @@ -0,0 +1,17 @@ +import ContentLoader from "react-content-loader" + +export default function CategoryViewLoader(props) { + return ( + + + + ) +} \ No newline at end of file diff --git a/bfrontend/src/Components/Root.js b/bfrontend/src/Components/Root.js index 4de4e52..19e0415 100644 --- a/bfrontend/src/Components/Root.js +++ b/bfrontend/src/Components/Root.js @@ -1,22 +1,16 @@ import { useHistory } from 'react-router-dom'; +import Sidebar from './UI/Sidebar'; export default function Root(props) { const history = useHistory(); if (props.user) { return ( -
-
- hhhhhhhhhhhhhhhhhhhhhh -
-
- sdfsdfsdf -
-
+ ); } else { return ( -
+

Welcome, - nevermind, you aren't logged in

diff --git a/bfrontend/src/Components/UI/Sidebar.js b/bfrontend/src/Components/UI/Sidebar.js new file mode 100644 index 0000000..8e1f1c1 --- /dev/null +++ b/bfrontend/src/Components/UI/Sidebar.js @@ -0,0 +1,9 @@ +import CategoryList from '../Categories/CategoryList'; + +export default function Sidebar() { + return ( +
+ +
+ ) +} \ No newline at end of file diff --git a/bfrontend/src/Errors.js b/bfrontend/src/Errors.js index c6c81a2..d5b0c4f 100644 --- a/bfrontend/src/Errors.js +++ b/bfrontend/src/Errors.js @@ -110,4 +110,6 @@ const getCreateCategoryError = (json) => { } }; -module.exports = { getLoginMessageFromError, getSignupMessageFromError, getCreatePostError, getCreateCategoryError } \ No newline at end of file +const couldNotReach = "Whoops! We couldn't reach Brainlet." + +module.exports = { couldNotReach, getLoginMessageFromError, getSignupMessageFromError, getCreatePostError, getCreateCategoryError } \ No newline at end of file diff --git a/bfrontend/src/Images/defaultprofile_256px-256px.png b/bfrontend/src/Images/defaultprofile_256px-256px.png new file mode 100644 index 0000000..0ace865 Binary files /dev/null and b/bfrontend/src/Images/defaultprofile_256px-256px.png differ diff --git a/bfrontend/src/Styles/App.scss b/bfrontend/src/Styles/App.scss index ffdd468..bce94a8 100644 --- a/bfrontend/src/Styles/App.scss +++ b/bfrontend/src/Styles/App.scss @@ -1,28 +1,159 @@ @import "../../node_modules/nord/src/sass/nord.scss"; +:root { + --background-color: #{$nord0}; + + --default-main-card-color: #{$nord1}; + --card-box-shadow-color:rgba(0, 0, 0, 0.25); + + --default-text-color: #{$nord5}; + + --accent-color-dark: #{$nord2}; + --accent-color-light: #{$nord3}; + + --default-transition-duration: 200ms; + --default-border-radius: 0px; + --default-button-border-radius: 0px; +} + +::-webkit-scrollbar { + width: 0px; +} +::-webkit-scrollbar-track { + background: var(--accent-color-light); +} + +::-webkit-scrollbar-thumb { + background: var(--default-main-card-color); +} + +@mixin card { + padding: 0px; + margin: 0px; + background-color: var(--default-main-card-color); + border-radius: var(--default-border-radius); + box-shadow: 0px 3px 5px var(--card-box-shadow-color); +} + +@mixin fancy-scrollbar-firefox { + scrollbar-width: none; + scrollbar-color: var(--default-main-card-color) var(--accent-color-light); +} + body { margin: 0px; padding: 0px; + + color: var(--default-text-color); + font-family: Noto Sans,-apple-system,BlinkMacSystemFont,sans-serif; } .main-display { padding: 0px; margin: 0px; display: flex; - background-color: $nord0; + background-color: var(--background-color); min-height: 100vh; + max-height: 100vh; flex-direction: row; } +.card { + @include card; + + &.bar-card { + background-color: var(--accent-color-dark); + min-height: 40px; + + border-radius: var(--default-button-border-radius) var(--default-button-border-radius) 0px 0px; + display: flex; + align-items: center; + justify-content: left; + + font-size: large; + } + + &.bar-card-bottom { + background-color: var(--accent-color-dark); + min-height: 30px; + + border-radius: 0px 0px var(--default-button-border-radius) var(--default-button-border-radius); + } + + &.message-list-card { + border-radius: 0px; + flex-grow: 1; + box-shadow: none; + } +} + .main-card { - padding: 0px; - margin: 0px; - background-color: $nord1; - border-radius: 10px; - box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.25); + @include card; + margin: 12px; &.main-content-card { flex-grow: 1; + display: flex; + flex-direction: column; + } +} + +.button { + @include card; + + padding: 5px; + margin: 5px; + border: 0px; + background-color: var(--accent-color-dark); + color: var(--default-text-color); + cursor: pointer; + transition: background-color, var(--default-transition-duration); + border-radius: var(--default-button-border-radius); + min-height: 25px; + + &.category-button { + min-width: 100px; + max-width: 100px; + } + + &.pressed { + background-color: var(--accent-color-light); + } +} + +.button:hover { + background-color: var(--accent-color-light); +} + +.category-list { + display: flex; + flex-direction: column; + word-wrap: break-word; +} + +.category-list-container { + @include fancy-scrollbar-firefox; + + overflow: auto; + overflow-x: hidden; + + min-width: 110px; + max-width: 110px; +} + +@media only screen and (max-width: 600px) { + .button.category-button { + min-width: 50px; + max-width: 50px; + } + + .category-list-container { + min-width: 60px; + max-width: 60px; + } + + .main-card { + margin: 6px; } } \ No newline at end of file diff --git a/bfrontend/src/store.js b/bfrontend/src/store.js index 885e684..e5e33fa 100644 --- a/bfrontend/src/store.js +++ b/bfrontend/src/store.js @@ -9,6 +9,13 @@ const reducer = (state, payload) => { } } + case 'categories/updatecategorylist': { + return { + ...state, + categories: payload.categories + } + } + default: { return state; }