From 8d0d38977a30bb769ce718a8b04b624eb10745c1 Mon Sep 17 00:00:00 2001
From: StephBerg86
Date: Thu, 27 Aug 2020 12:16:10 +0200
Subject: [PATCH 1/4] added authentication on homepage
---
src/App.js | 5 +++--
src/components/Navigation/index.js | 2 --
src/components/Navigation/protectedRoute.js | 9 +++++++++
src/pages/Exercise/index.js | 4 +++-
src/pages/Homepage/index.js | 3 ++-
src/store/exercise/actions.js | 15 ++++++++-------
6 files changed, 25 insertions(+), 13 deletions(-)
create mode 100644 src/components/Navigation/protectedRoute.js
diff --git a/src/App.js b/src/App.js
index 29e0892..7b7b3b6 100644
--- a/src/App.js
+++ b/src/App.js
@@ -10,6 +10,7 @@ import Login from "./pages/Login";
import Welcome from "./pages/Welcome";
import Homepage from "./pages/Homepage";
import Exercise from "./pages/Exercise";
+import ProtectedRoute from "./components/Navigation/protectedRoute";
import { useDispatch, useSelector } from "react-redux";
import { selectAppLoading } from "./store/appState/selectors";
@@ -30,10 +31,10 @@ function App() {
{isLoading ? : null}
-
-
+
+
);
diff --git a/src/components/Navigation/index.js b/src/components/Navigation/index.js
index aa4780c..00799e7 100644
--- a/src/components/Navigation/index.js
+++ b/src/components/Navigation/index.js
@@ -10,7 +10,6 @@ import LoggedOut from "./LoggedOut";
export default function Navigation() {
const token = useSelector(selectToken);
-
const loginLogoutControls = token ? : ;
return (
@@ -25,7 +24,6 @@ export default function Navigation() {
diff --git a/src/components/Navigation/protectedRoute.js b/src/components/Navigation/protectedRoute.js
new file mode 100644
index 0000000..56a974a
--- /dev/null
+++ b/src/components/Navigation/protectedRoute.js
@@ -0,0 +1,9 @@
+import React from "react";
+import { Redirect } from "react-router-dom";
+
+export default function protectedRoute({ component }) {
+ const Component = component;
+ const isAuthenticated = localStorage.getItem("token");
+
+ return isAuthenticated ? : ;
+}
diff --git a/src/pages/Exercise/index.js b/src/pages/Exercise/index.js
index 616bc96..357cfa7 100644
--- a/src/pages/Exercise/index.js
+++ b/src/pages/Exercise/index.js
@@ -15,6 +15,7 @@ export default function Exercise() {
const allCurrentExercises = useSelector(selectExercise);
const completedExercises = useSelector(selectCompletedExercises);
const [currentExercise, setCurrentExercise] = useState("");
+ console.log("all ex", allCurrentExercises);
useEffect(() => {
completedExercises.forEach((item) => {
@@ -40,7 +41,7 @@ export default function Exercise() {
dispatch(getCompletedExercises());
dispatch(getExerciseById(exerciseId));
}, [dispatch, exerciseId]);
- // console.log("current exercise", currentExercise)
+ console.log("current exercise", currentExercise);
const questionFormat = () => {
if (currentExercise && currentExercise.level === "level 1") {
@@ -49,6 +50,7 @@ export default function Exercise() {
return ;
} else {
//return some loading indicator would be better
+ console.log("test");
return null;
}
};
diff --git a/src/pages/Homepage/index.js b/src/pages/Homepage/index.js
index c733f91..54dda10 100644
--- a/src/pages/Homepage/index.js
+++ b/src/pages/Homepage/index.js
@@ -16,7 +16,7 @@ export default function Homepage() {
useEffect(() => {
dispatch(getExercises());
- }, [dispatch]);
+ }, []);
useEffect(() => {
if (!searchTerm) {
@@ -26,6 +26,7 @@ export default function Homepage() {
exercise.name.toLowerCase().includes(searchTerm.toLowerCase())
);
setSearchResults(results);
+ }
}, [searchTerm]);
const handleChange = (event) => {
diff --git a/src/store/exercise/actions.js b/src/store/exercise/actions.js
index b0502f1..fc1ec18 100644
--- a/src/store/exercise/actions.js
+++ b/src/store/exercise/actions.js
@@ -4,14 +4,15 @@ import { appLoading, appDoneLoading, setMessage } from "../appState/actions";
import { selectToken } from "../user/selectors";
export const GET_EXERCISE_SUCCESS = "GET_EXERCISE_SUCCESS";
+
export const SET_QUIZ_QUESTIONS = "SET_QUIZ_QUESTIONS";
export const setQuizQuestions = (data) => {
return {
type: SET_QUIZ_QUESTIONS,
- payload: data
- }
-}
+ payload: data,
+ };
+};
export const getExerciseSuccess = (exercise) => {
return {
@@ -22,11 +23,11 @@ export const getExerciseSuccess = (exercise) => {
export const getExercises = () => {
return async (dispatch, getState) => {
- const tokenNeeded = getState().user.token
- const response = await axios.get(`${apiUrl}/exercises/list`,{
+ const tokenNeeded = getState().user.token;
+ const response = await axios.get(`${apiUrl}/exercises/list`, {
headers: {
- Authorization: `Bearer ${tokenNeeded}`
- }
+ Authorization: `Bearer ${tokenNeeded}`,
+ },
});
// console.log("response.data", response.data);
dispatch(getExerciseSuccess(response.data));
From 8a32441a1eca1454f54aa8a8e536400670b8fd1c Mon Sep 17 00:00:00 2001
From: StephBerg86
Date: Thu, 27 Aug 2020 12:35:17 +0200
Subject: [PATCH 2/4] changed the colors of the buttons and links
---
src/components/Navigation/LoggedIn.js | 18 ++++++++++++++--
src/pages/Login/index.js | 26 +++++++++++++++++------
src/pages/SignUp/index.js | 30 ++++++++++++++++++++-------
src/pages/Welcome/index.js | 16 +++++++-------
4 files changed, 67 insertions(+), 23 deletions(-)
diff --git a/src/components/Navigation/LoggedIn.js b/src/components/Navigation/LoggedIn.js
index 35410ea..8ceb58f 100644
--- a/src/components/Navigation/LoggedIn.js
+++ b/src/components/Navigation/LoggedIn.js
@@ -1,7 +1,6 @@
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { logOut } from "../../store/user/actions";
-import Button from "react-bootstrap/Button";
import { selectUser } from "../../store/user/selectors";
import Nav from "react-bootstrap/Nav";
@@ -11,7 +10,22 @@ export default function LoggedIn() {
return (
<>
{user.email}
-
+
>
);
}
diff --git a/src/pages/Login/index.js b/src/pages/Login/index.js
index d35d780..3f9f97f 100644
--- a/src/pages/Login/index.js
+++ b/src/pages/Login/index.js
@@ -1,7 +1,6 @@
import React, { useState, useEffect } from "react";
import Form from "react-bootstrap/Form";
import Container from "react-bootstrap/Container";
-import Button from "react-bootstrap/Button";
import { login } from "../../store/user/actions";
import { selectToken } from "../../store/user/selectors";
import { useDispatch, useSelector } from "react-redux";
@@ -39,7 +38,7 @@ export default function SignUp() {
Email address
setEmail(event.target.value)}
+ onChange={(event) => setEmail(event.target.value)}
type="email"
placeholder="Enter email"
required
@@ -50,18 +49,33 @@ export default function SignUp() {
Password
setPassword(event.target.value)}
+ onChange={(event) => setPassword(event.target.value)}
type="password"
placeholder="Password"
required
/>
-
-
+
Click here to sign up
diff --git a/src/pages/SignUp/index.js b/src/pages/SignUp/index.js
index 9e7b90f..888f583 100644
--- a/src/pages/SignUp/index.js
+++ b/src/pages/SignUp/index.js
@@ -1,7 +1,6 @@
import React, { useState, useEffect } from "react";
import Form from "react-bootstrap/Form";
import Container from "react-bootstrap/Container";
-import Button from "react-bootstrap/Button";
import { signUp } from "../../store/user/actions";
import { selectToken } from "../../store/user/selectors";
import { useDispatch, useSelector } from "react-redux";
@@ -40,7 +39,7 @@ export default function SignUp() {
Name
setName(event.target.value)}
+ onChange={(event) => setName(event.target.value)}
type="text"
placeholder="Enter name"
required
@@ -50,7 +49,7 @@ export default function SignUp() {
Email address
setEmail(event.target.value)}
+ onChange={(event) => setEmail(event.target.value)}
type="email"
placeholder="Enter email"
required
@@ -64,18 +63,35 @@ export default function SignUp() {
Password
setPassword(event.target.value)}
+ onChange={(event) => setPassword(event.target.value)}
type="password"
placeholder="Password"
required
/>
-
+
Sign up
-
+
- Click here to log in
+
+ Click here to log in
+
);
diff --git a/src/pages/Welcome/index.js b/src/pages/Welcome/index.js
index 2ab1c56..0bd3974 100644
--- a/src/pages/Welcome/index.js
+++ b/src/pages/Welcome/index.js
@@ -17,14 +17,14 @@ export default function Welcome() {
You will start as a code monkey but if you complete all the exercises
you can become the ultimate code master!
-
-
-
-
- Register
- {" "}
- for free and start your code challenge now!
-
+
+
+
+
+ Sign up
+ {" "}
+ for free and start your code challenge now!
+
>
From 0f3f455757973c11f487fdf667cdff4c4229cb78 Mon Sep 17 00:00:00 2001
From: StephBerg86
Date: Thu, 27 Aug 2020 13:57:38 +0200
Subject: [PATCH 3/4] fixed the fetching issue of homepage
---
src/pages/Homepage/index.js | 22 ++++++++++++----------
src/store/exercise/reducer.js | 6 +++---
src/store/user/actions.js | 33 ++++++++++++++++++---------------
3 files changed, 33 insertions(+), 28 deletions(-)
diff --git a/src/pages/Homepage/index.js b/src/pages/Homepage/index.js
index 54dda10..a9be66d 100644
--- a/src/pages/Homepage/index.js
+++ b/src/pages/Homepage/index.js
@@ -15,7 +15,9 @@ export default function Homepage() {
const [searchResults, setSearchResults] = useState([]);
useEffect(() => {
- dispatch(getExercises());
+ if (exercises.length === 0) {
+ dispatch(getExercises());
+ }
}, []);
useEffect(() => {
@@ -48,16 +50,16 @@ export default function Homepage() {
{data.map((exercise) => {
return (
-
-
-
+
+
+
{exercise.name}
-
-
- Exercises:
- MonkeyMaster:
-
-
+
+ Exercises: 3
+ MonkeyMaster:
+
+
+
);
})}
diff --git a/src/store/exercise/reducer.js b/src/store/exercise/reducer.js
index c8cfe07..b413d02 100644
--- a/src/store/exercise/reducer.js
+++ b/src/store/exercise/reducer.js
@@ -13,12 +13,12 @@ export default (state = initialState, action) => {
case SET_QUIZ_QUESTIONS:
return {
...state,
- questions: [...state.questions, ...action.payload]
- }
+ questions: [...state.questions, ...action.payload],
+ };
case GET_EXERCISE_SUCCESS:
return {
...state,
- exercises: [...state.exercises, ...action.payload],
+ exercises: [...action.payload],
};
default:
diff --git a/src/store/user/actions.js b/src/store/user/actions.js
index 5f9bc1f..278ef14 100644
--- a/src/store/user/actions.js
+++ b/src/store/user/actions.js
@@ -169,22 +169,25 @@ export const updateCompletedExercise = (exerciseId, quizId, timeTaken, exp) => {
};
};
-export function sendCompletedQuiz(exerciseId, quizId){
- return async(dispatch, getState) => {
- const tokenNeeded = getState().user.token
- try{
- const infoUpdated = await axios.patch(`${apiUrl}/exercises/${exerciseId}/quiz/completed/${quizId}`,{},{
- headers: {
- Authorization: `Bearer ${tokenNeeded}`
+export function sendCompletedQuiz(exerciseId, quizId) {
+ return async (dispatch, getState) => {
+ const tokenNeeded = getState().user.token;
+ try {
+ const infoUpdated = await axios.patch(
+ `${apiUrl}/exercises/${exerciseId}/quiz/completed/${quizId}`,
+ {},
+ {
+ headers: {
+ Authorization: `Bearer ${tokenNeeded}`,
+ },
}
- })
- console.log("updated info test", infoUpdated.data.user)
-
- dispatch(getCompletedExercisesSuccess(infoUpdated.data.completedQuiz))
- dispatch(tokenStillValid(infoUpdated.data.user))
+ );
+ console.log("updated info test", infoUpdated.data.user);
- } catch(error){
- console.log(error.message)
+ dispatch(getCompletedExercisesSuccess(infoUpdated.data.completedQuiz));
+ dispatch(tokenStillValid(infoUpdated.data.user));
+ } catch (error) {
+ console.log(error.message);
}
- }
+ };
}
From ed2905d6fb2ab142dad0ab8fcf4f4039c6d45074 Mon Sep 17 00:00:00 2001
From: StephBerg86
Date: Thu, 27 Aug 2020 15:30:46 +0200
Subject: [PATCH 4/4] first round of testing
---
package-lock.json | 61 +++++++++++++++++----
package.json | 1 +
src/App.js | 22 ++++++--
src/components/Navigation/LoggedIn.js | 8 ++-
src/components/Navigation/protectedRoute.js | 9 ---
src/pages/Exercise/index.js | 2 +
src/pages/Homepage/index.js | 2 +-
7 files changed, 80 insertions(+), 25 deletions(-)
delete mode 100644 src/components/Navigation/protectedRoute.js
diff --git a/package-lock.json b/package-lock.json
index e188120..89e1b34 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8322,13 +8322,12 @@
"integrity": "sha1-z8RcN+nsDY8KDsPdTvf3w6vjklY="
},
"mini-create-react-context": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz",
- "integrity": "sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz",
+ "integrity": "sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA==",
"requires": {
- "@babel/runtime": "^7.4.0",
- "gud": "^1.0.0",
- "tiny-warning": "^1.0.2"
+ "@babel/runtime": "^7.5.5",
+ "tiny-warning": "^1.0.3"
}
},
"mini-css-extract-plugin": {
@@ -10787,15 +10786,15 @@
}
},
"react-router": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz",
- "integrity": "sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz",
+ "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==",
"requires": {
"@babel/runtime": "^7.1.2",
"history": "^4.9.0",
"hoist-non-react-statics": "^3.1.0",
"loose-envify": "^1.3.1",
- "mini-create-react-context": "^0.3.0",
+ "mini-create-react-context": "^0.4.0",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.2",
"react-is": "^16.6.0",
@@ -10830,6 +10829,48 @@
"react-router": "5.1.2",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
+ },
+ "mini-create-react-context": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz",
+ "integrity": "sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw==",
+ "requires": {
+ "@babel/runtime": "^7.4.0",
+ "gud": "^1.0.0",
+ "tiny-warning": "^1.0.2"
+ }
+ },
+ "path-to-regexp": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+ "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+ "requires": {
+ "isarray": "0.0.1"
+ }
+ },
+ "react-router": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.1.2.tgz",
+ "integrity": "sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==",
+ "requires": {
+ "@babel/runtime": "^7.1.2",
+ "history": "^4.9.0",
+ "hoist-non-react-statics": "^3.1.0",
+ "loose-envify": "^1.3.1",
+ "mini-create-react-context": "^0.3.0",
+ "path-to-regexp": "^1.7.0",
+ "prop-types": "^15.6.2",
+ "react-is": "^16.6.0",
+ "tiny-invariant": "^1.0.2",
+ "tiny-warning": "^1.0.0"
+ }
+ }
}
},
"react-scripts": {
diff --git a/package.json b/package.json
index ada209b..0f8aeb7 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
"react-dom": "^16.13.0",
"react-motion": "^0.5.2",
"react-redux": "^7.2.0",
+ "react-router": "^5.2.0",
"react-router-dom": "^5.1.2",
"react-scripts": "^3.4.3",
"redux": "^4.0.5",
diff --git a/src/App.js b/src/App.js
index 7b7b3b6..b7d9f39 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,7 +1,7 @@
import React, { useEffect } from "react";
import "./App.css";
-import { Switch, Route } from "react-router-dom";
+import { Switch, Route, Redirect } from "react-router-dom";
import Navigation from "./components/Navigation";
import Loading from "./components/Loading";
import MessageBox from "./components/MessageBox";
@@ -10,7 +10,6 @@ import Login from "./pages/Login";
import Welcome from "./pages/Welcome";
import Homepage from "./pages/Homepage";
import Exercise from "./pages/Exercise";
-import ProtectedRoute from "./components/Navigation/protectedRoute";
import { useDispatch, useSelector } from "react-redux";
import { selectAppLoading } from "./store/appState/selectors";
@@ -24,6 +23,15 @@ function App() {
dispatch(getUserWithStoredToken());
}, [dispatch]);
+ const protectedRoutes = (Component, routerProps) => {
+ const isAuthenticated = localStorage.getItem("token");
+ return isAuthenticated ? (
+
+ ) : (
+
+ );
+ };
+
return (
@@ -33,8 +41,14 @@ function App() {
-
-
+
protectedRoutes(Homepage, routerProps)}
+ />
+ protectedRoutes(Exercise, routerProps)}
+ />
);
diff --git a/src/components/Navigation/LoggedIn.js b/src/components/Navigation/LoggedIn.js
index 8ceb58f..2b2d016 100644
--- a/src/components/Navigation/LoggedIn.js
+++ b/src/components/Navigation/LoggedIn.js
@@ -1,11 +1,14 @@
import React from "react";
import { useDispatch, useSelector } from "react-redux";
+// import { useHistory } from "react-router";
import { logOut } from "../../store/user/actions";
import { selectUser } from "../../store/user/selectors";
import Nav from "react-bootstrap/Nav";
+import Homepage from "../../pages/Homepage";
export default function LoggedIn() {
const dispatch = useDispatch();
+ // const history = useHistory();
const user = useSelector(selectUser);
return (
<>
@@ -22,7 +25,10 @@ export default function LoggedIn() {
fontSize: "16px",
borderRadius: "8px",
}}
- onClick={() => dispatch(logOut())}
+ onClick={() => {
+ dispatch(logOut());
+ // history.push(Homepage);
+ }}
>
Logout
diff --git a/src/components/Navigation/protectedRoute.js b/src/components/Navigation/protectedRoute.js
deleted file mode 100644
index 56a974a..0000000
--- a/src/components/Navigation/protectedRoute.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from "react";
-import { Redirect } from "react-router-dom";
-
-export default function protectedRoute({ component }) {
- const Component = component;
- const isAuthenticated = localStorage.getItem("token");
-
- return isAuthenticated ? : ;
-}
diff --git a/src/pages/Exercise/index.js b/src/pages/Exercise/index.js
index 357cfa7..2799641 100644
--- a/src/pages/Exercise/index.js
+++ b/src/pages/Exercise/index.js
@@ -10,7 +10,9 @@ import QuizCode from "../../components/QuizCode";
export default function Exercise() {
const param = useParams();
+ console.log("param", param);
const exerciseId = param.id;
+ console.log("ex id test", exerciseId);
const dispatch = useDispatch();
const allCurrentExercises = useSelector(selectExercise);
const completedExercises = useSelector(selectCompletedExercises);
diff --git a/src/pages/Homepage/index.js b/src/pages/Homepage/index.js
index a9be66d..32579d5 100644
--- a/src/pages/Homepage/index.js
+++ b/src/pages/Homepage/index.js
@@ -29,7 +29,7 @@ export default function Homepage() {
);
setSearchResults(results);
}
- }, [searchTerm]);
+ }, [searchTerm, exercises]);
const handleChange = (event) => {
setSearchTerm(event.target.value);