diff --git a/package-lock.json b/package-lock.json index 20cc105..f639521 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3639,6 +3639,16 @@ "q": "^1.1.2" } }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "codemirror": { + "version": "5.57.0", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.57.0.tgz", + "integrity": "sha512-WGc6UL7Hqt+8a6ZAsj/f1ApQl3NPvHY/UQSzG6fB6l4BjExgVdhFaxd7mRTw1UCiYe/6q86zHP+kfvBQcZGvUg==" + } "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -10447,6 +10457,11 @@ "warning": "^4.0.3" } }, + "react-codemirror2": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/react-codemirror2/-/react-codemirror2-7.2.1.tgz", + "integrity": "sha512-t7YFmz1AXdlImgHXA9Ja0T6AWuopilub24jRaQdPVbzUJVNKIYuy3uCFZYa7CE5S3UW6SrSa5nAqVQvtzRF9gw==" + }, "react-dev-utils": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.1.tgz", diff --git a/package.json b/package.json index 850ee9e..0a31a9e 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,10 @@ "@testing-library/user-event": "^7.1.2", "axios": "^0.19.2", "bootstrap": "^4.4.1", + "codemirror": "^5.57.0", "react": "^16.13.0", "react-bootstrap": "^1.0.0-beta.17", + "react-codemirror2": "^7.2.1", "react-dom": "^16.13.0", "react-redux": "^7.2.0", "react-router-dom": "^5.1.2", diff --git a/src/components/CodeMirror/index.js b/src/components/CodeMirror/index.js new file mode 100644 index 0000000..dd631fe --- /dev/null +++ b/src/components/CodeMirror/index.js @@ -0,0 +1,71 @@ +import React, { useState, useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { selectCorrectAnswer } from "../../store/exercise/selectors"; +import { getExerciseById } from "../../store/exercise/actions"; + +import { Controlled as CodeMirror } from "react-codemirror2"; +import "codemirror/lib/codemirror.css"; +import "codemirror/mode/javascript/javascript"; +import "codemirror/theme/material.css"; + +export default function CodeMirrorComponent() { + const dispatch = useDispatch(); + const correctAnswer = useSelector(selectCorrectAnswer); + const [code, setCode] = useState(""); + const [message, setMessage] = useState(""); + + //this is something we should do in the parent component I think + useEffect(() => { + dispatch(getExerciseById(1)); + }, []); + + const codeMirrorOptions = { + theme: "material", + lineNumbers: true, + scrollbarStyle: null, + lineWrapping: true, + }; + + function equal(a, b) { + const condition2 = typeof a === "string" && typeof b === "string"; + if (condition2) return a === b; + } + + function submitAnswer() { + const result = equal(correctAnswer, code); + if (!result) { + setMessage({ + backgroundColor: "red", + text: "oeh-oeh-ahh-ahh monkey want banana? - This answer is incorrect!", + }); + } + if (result) { + setMessage({ + backgroundColor: "green", + text: "Long live the master! - This answer is correct!", + }); + } + } + + return ( +
+ { + setCode(js); + }} + /> + + {message && ( +

+ {message.text} +

+ )} + + +
+ ); +} diff --git a/src/store/exercise/actions.js b/src/store/exercise/actions.js new file mode 100644 index 0000000..297afcf --- /dev/null +++ b/src/store/exercise/actions.js @@ -0,0 +1,41 @@ +import { apiUrl } from "../../config/constants"; +import axios from "axios"; +import { appLoading, appDoneLoading, setMessage } from "../appState/actions"; +import { selectToken } from "../user/selectors"; + +export const GET_EXERCISE_SUCCESS = "GET_EXERCISE_SUCCESS"; + +const getExerciseSuccess = (exercise) => { + return { + type: GET_EXERCISE_SUCCESS, + payload: exercise, + }; +}; + +export const getExerciseById = (id) => { + console.log("what is id in actions", id); + return async (dispatch, getState) => { + const token = selectToken(getState()); + if (token === null) return; + + dispatch(appLoading()); + try { + const response = axios.get(`${apiUrl}/exercises/${id}/quiz`, { + headers: { Authorization: `Bearer ${token}` }, + }); + + dispatch(getExerciseSuccess(response.data)); + + dispatch(appDoneLoading()); + } catch (error) { + if (error.response) { + console.log(error.response.data.message); + dispatch(setMessage("danger", true, error.response.data.message)); + } else { + console.log(error.message); + dispatch(setMessage("danger", true, error.message)); + } + dispatch(appDoneLoading()); + } + }; +}; diff --git a/src/store/exercise/reducer.js b/src/store/exercise/reducer.js new file mode 100644 index 0000000..e697a42 --- /dev/null +++ b/src/store/exercise/reducer.js @@ -0,0 +1,16 @@ +import { GET_EXERCISE_SUCCESS } from "./actions"; + +const initialState = { + name: "", + content: "", + correctAnswer: "", +}; + +export default (state = initialState, action) => { + switch (action.type) { + case GET_EXERCISE_SUCCESS: + return { ...state, ...action.payload }; + default: + return state; + } +}; diff --git a/src/store/exercise/selectors.js b/src/store/exercise/selectors.js new file mode 100644 index 0000000..7954ed5 --- /dev/null +++ b/src/store/exercise/selectors.js @@ -0,0 +1 @@ +export const selectCorrectAnswer = (state) => state.exercise.correctAnswer; diff --git a/src/store/rootReducer.js b/src/store/rootReducer.js index 03483da..9d95d10 100644 --- a/src/store/rootReducer.js +++ b/src/store/rootReducer.js @@ -1,8 +1,10 @@ import { combineReducers } from "redux"; import appState from "./appState/reducer"; import user from "./user/reducer"; +import exercise from "./exercise/reducer"; export default combineReducers({ appState, - user + user, + exercise, });