From 64d756dbbaf69c9d113a2c4727638359c1acaff4 Mon Sep 17 00:00:00 2001 From: Mohammed Al Ameen Date: Sun, 26 Dec 2021 18:50:48 +0100 Subject: [PATCH] adds redux and connected sign in endpoint --- web/package-lock.json | 5 + web/package.json | 7 +- web/src/App.jsx | 6 +- web/src/context/actions/auth.js | 20 --- web/src/context/index.jsx | 24 ---- web/src/context/reducers/auth.js | 26 ---- web/src/context/reducers/index.js | 8 -- web/src/context/states/auth.js | 5 - web/src/context/states/common.js | 4 - web/src/context/states/index.js | 9 -- web/src/context/types.js | 4 - web/src/context/utils.js | 9 -- web/src/pages/auth/SignIn.jsx | 46 +++++-- web/src/store/actions/auth.js | 23 ++++ web/src/{context => store}/actions/common.js | 0 web/src/{context => store}/actions/index.js | 0 web/src/store/index.jsx | 16 +++ web/src/store/reducers/auth.js | 21 ++++ web/src/{context => store}/reducers/common.js | 11 +- web/src/store/reducers/index.js | 11 ++ web/src/store/types.js | 5 + web/src/store/utils.js | 51 ++++++++ web/yarn.lock | 118 +++++++++++++++++- 23 files changed, 303 insertions(+), 126 deletions(-) delete mode 100644 web/src/context/actions/auth.js delete mode 100644 web/src/context/index.jsx delete mode 100644 web/src/context/reducers/auth.js delete mode 100644 web/src/context/reducers/index.js delete mode 100644 web/src/context/states/auth.js delete mode 100644 web/src/context/states/common.js delete mode 100644 web/src/context/states/index.js delete mode 100644 web/src/context/types.js delete mode 100644 web/src/context/utils.js create mode 100644 web/src/store/actions/auth.js rename web/src/{context => store}/actions/common.js (100%) rename web/src/{context => store}/actions/index.js (100%) create mode 100644 web/src/store/index.jsx create mode 100644 web/src/store/reducers/auth.js rename web/src/{context => store}/reducers/common.js (59%) create mode 100644 web/src/store/reducers/index.js create mode 100644 web/src/store/types.js create mode 100644 web/src/store/utils.js diff --git a/web/package-lock.json b/web/package-lock.json index 12d0f32..b3ae064 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1373,6 +1373,11 @@ "picomatch": "^2.2.1" } }, + "redux-devtools-extension": { + "version": "2.13.9", + "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz", + "integrity": "sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==" + }, "regenerator-runtime": { "version": "0.13.9", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", diff --git a/web/package.json b/web/package.json index f832988..a43f697 100644 --- a/web/package.json +++ b/web/package.json @@ -8,10 +8,15 @@ }, "dependencies": { "@tailwindcss/forms": "^0.4.0", + "axios": "^0.24.0", "postcss-import": "^14.0.2", "react": "^17.0.2", "react-dom": "^17.0.2", - "react-router-dom": "6" + "react-redux": "^7.2.6", + "react-router-dom": "6", + "redux": "^4.1.2", + "redux-devtools-extension": "^2.13.9", + "redux-thunk": "^2.4.1" }, "devDependencies": { "@vitejs/plugin-react": "^1.0.7", diff --git a/web/src/App.jsx b/web/src/App.jsx index f2e6504..8fa227c 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -3,11 +3,13 @@ import React from "react"; import "./assets/scss/style.scss"; import Router from "./router"; -import { Provider } from "./context"; +import store from "./store"; + +import { Provider } from "react-redux"; export default function App() { return ( - + ); diff --git a/web/src/context/actions/auth.js b/web/src/context/actions/auth.js deleted file mode 100644 index 6f6708e..0000000 --- a/web/src/context/actions/auth.js +++ /dev/null @@ -1,20 +0,0 @@ -import { REMOVE_TEXT, CHANGE_TEXT } from "../types"; - -const removeText = (text) => (dispatch) => { - dispatch({ - action: REMOVE_TEXT, - payload: text, - }); -}; - -const changeText = (text) => (dispatch) => { - dispatch({ - type: CHANGE_TEXT, - payload: text, - }); -}; - -export default { - removeText, - changeText, -}; diff --git a/web/src/context/index.jsx b/web/src/context/index.jsx deleted file mode 100644 index 4f7f30a..0000000 --- a/web/src/context/index.jsx +++ /dev/null @@ -1,24 +0,0 @@ -import React, { createContext, useReducer } from "react"; - -import reducers from "./reducers"; -import states from "./states"; -import actions from "./actions"; - -// initial state -const initialState = states; - -// context - -export const Context = createContext(initialState); - -// provider - -export const Provider = ({ children }) => { - const [state, dispatch] = useReducer(reducers, initialState); - - return ( - - {children} - - ); -}; diff --git a/web/src/context/reducers/auth.js b/web/src/context/reducers/auth.js deleted file mode 100644 index 6c33c40..0000000 --- a/web/src/context/reducers/auth.js +++ /dev/null @@ -1,26 +0,0 @@ -import { CHANGE_TEXT, REMOVE_TEXT } from "../types"; - -export default (state, action) => { - const { auth } = state; - - switch (action.type) { - case CHANGE_TEXT: - return { - ...state, - auth: { - ...auth, - text: action.payload, - }, - }; - case REMOVE_TEXT: - return { - ...state, - auth: { - ...auth, - text: "removed", - }, - }; - default: - return state; - } -}; diff --git a/web/src/context/reducers/index.js b/web/src/context/reducers/index.js deleted file mode 100644 index 845f3ff..0000000 --- a/web/src/context/reducers/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import { combineReducers } from "../utils"; - -import auth from "./auth"; -import common from "./common"; - -const reducers = combineReducers(auth, common); - -export default reducers; diff --git a/web/src/context/states/auth.js b/web/src/context/states/auth.js deleted file mode 100644 index 5b87422..0000000 --- a/web/src/context/states/auth.js +++ /dev/null @@ -1,5 +0,0 @@ -const initialState = { - text: "Testing auth", -}; - -export default initialState; diff --git a/web/src/context/states/common.js b/web/src/context/states/common.js deleted file mode 100644 index 6e3a4b9..0000000 --- a/web/src/context/states/common.js +++ /dev/null @@ -1,4 +0,0 @@ -const initialState = { - is_loading: false, -}; -export default initialState; diff --git a/web/src/context/states/index.js b/web/src/context/states/index.js deleted file mode 100644 index 0d37fc7..0000000 --- a/web/src/context/states/index.js +++ /dev/null @@ -1,9 +0,0 @@ -import auth from "./auth"; -import common from "./common"; - -const states = { - common, - auth, -}; - -export default states; diff --git a/web/src/context/types.js b/web/src/context/types.js deleted file mode 100644 index 6188739..0000000 --- a/web/src/context/types.js +++ /dev/null @@ -1,4 +0,0 @@ -export const CHANGE_TEXT = "CHANGE_TEXT"; -export const REMOVE_TEXT = "REMOVE_TEXT"; - -export const SET_LOADING = "SET_LOADING"; diff --git a/web/src/context/utils.js b/web/src/context/utils.js deleted file mode 100644 index 537aea0..0000000 --- a/web/src/context/utils.js +++ /dev/null @@ -1,9 +0,0 @@ -export const combineReducers = - (...reducers) => - (state, action) => { - for (let i = 0; i < reducers.length; i++) { - state = reducers[i](state, action); - } - - return state; - }; diff --git a/web/src/pages/auth/SignIn.jsx b/web/src/pages/auth/SignIn.jsx index 7ce6ef5..dfa7db7 100644 --- a/web/src/pages/auth/SignIn.jsx +++ b/web/src/pages/auth/SignIn.jsx @@ -1,11 +1,43 @@ -import AuthLayout from "../../layouts/AuthLayout"; -import InputGroup from "../../components/auth/InputGroup"; +import React, { useState } from "react"; +import { connect } from "react-redux"; + +import { loginUser } from "../../store/actions/auth"; + +function SignIn({ loginUser }) { + const [username, set_username] = useState(""); + const [password, set_password] = useState(""); + + const __login_user = (username, password) => { + loginUser({ username, password }); + }; -export default function SignIn() { return ( - - - - +
+
{ + e.preventDefault(); + __login_user(username, password); + }} + > + { + set_username(e.target.value); + }} + /> + { + set_password(e.target.value); + }} + /> + + +
+
); } + +export default connect(null, { loginUser })(SignIn); diff --git a/web/src/store/actions/auth.js b/web/src/store/actions/auth.js new file mode 100644 index 0000000..0a0078a --- /dev/null +++ b/web/src/store/actions/auth.js @@ -0,0 +1,23 @@ +import { AUTH_LOGIN } from "../types"; +import { api } from "../utils"; + +export const loginUser = (user_creds) => async (dispatch) => { + await api({ + url: "/accounts/login/", + method: "POST", + data: user_creds, + }) + .then((response) => { + dispatch({ + type: AUTH_LOGIN, + payload: response.data, + }); + }) + .catch((err) => { + // dispatch({ + // action: SET_ERROR, + // payload: err.response.data + // }) + console.log(err); + }); +}; diff --git a/web/src/context/actions/common.js b/web/src/store/actions/common.js similarity index 100% rename from web/src/context/actions/common.js rename to web/src/store/actions/common.js diff --git a/web/src/context/actions/index.js b/web/src/store/actions/index.js similarity index 100% rename from web/src/context/actions/index.js rename to web/src/store/actions/index.js diff --git a/web/src/store/index.jsx b/web/src/store/index.jsx new file mode 100644 index 0000000..6604418 --- /dev/null +++ b/web/src/store/index.jsx @@ -0,0 +1,16 @@ +import { createStore, applyMiddleware } from "redux"; +import { composeWithDevTools } from "redux-devtools-extension"; +import thunk from "redux-thunk"; + +import reducers from "./reducers"; + +const initialState = {}; +const middleware = [thunk]; + +const store = createStore( + reducers, + initialState, + composeWithDevTools(applyMiddleware(...middleware)) +); + +export default store; diff --git a/web/src/store/reducers/auth.js b/web/src/store/reducers/auth.js new file mode 100644 index 0000000..a858aaa --- /dev/null +++ b/web/src/store/reducers/auth.js @@ -0,0 +1,21 @@ +import { AUTH_LOGIN } from "../types"; +import { Storage } from "../utils"; + +const storage = new Storage(); + +const initialState = { + is_authenticated: JSON.parse(storage.get("token"))?.access ? true : false, +}; + +export default (state = initialState, action) => { + switch (action.type) { + case AUTH_LOGIN: + storage.set("token", JSON.stringify(action.payload)); + return { + ...state, + is_authenticated: true, + }; + default: + return state; + } +}; diff --git a/web/src/context/reducers/common.js b/web/src/store/reducers/common.js similarity index 59% rename from web/src/context/reducers/common.js rename to web/src/store/reducers/common.js index 3513e60..e07f755 100644 --- a/web/src/context/reducers/common.js +++ b/web/src/store/reducers/common.js @@ -1,16 +1,17 @@ import { SET_LOADING } from "../types"; -export default (state, action) => { +const initialState = { + is_loading: false, +}; + +export default (state = initialState, action) => { const { common } = state; switch (action.type) { case SET_LOADING: return { ...state, - common: { - ...common, - is_loading: action.payload, - }, + is_loading: action.payload, }; default: return state; diff --git a/web/src/store/reducers/index.js b/web/src/store/reducers/index.js new file mode 100644 index 0000000..650bfa3 --- /dev/null +++ b/web/src/store/reducers/index.js @@ -0,0 +1,11 @@ +import { combineReducers } from "redux"; + +import auth from "./auth"; +import common from "./common"; + +const rootReducer = combineReducers({ + auth, + common, +}); + +export default rootReducer; diff --git a/web/src/store/types.js b/web/src/store/types.js new file mode 100644 index 0000000..5b4334d --- /dev/null +++ b/web/src/store/types.js @@ -0,0 +1,5 @@ +export const AUTH_LOGIN = "AUTH_LOGIN"; +export const AUTH_REGISTER = "AUTH_REGISTER"; +export const AUTH_LOGOUT = "AUTH_LOGOUT"; + +export const SET_LOADING = "SET_LOADING"; diff --git a/web/src/store/utils.js b/web/src/store/utils.js new file mode 100644 index 0000000..3fb0634 --- /dev/null +++ b/web/src/store/utils.js @@ -0,0 +1,51 @@ +import axios from "axios"; + +export const combineReducers = + (...reducers) => + (state, action) => { + for (let i = 0; i < reducers.length; i++) { + state = reducers[i](state, action); + } + + return state; + }; + +export function getCookie(name) { + let cookieValue = null; + if (document.cookie && document.cookie !== "") { + const cookies = document.cookie.split(";"); + for (let i = 0; i < cookies.length; i++) { + const cookie = cookies[i].trim(); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) === name + "=") { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} + +// axios settings + +var API_URL = "https://dev-47-quiz-app-api.herokuapp.com/api/v1/"; + +axios.defaults.baseURL = API_URL; +axios.defaults.xsrfHeaderName = "X-CSRFToken"; +axios.defaults.responseEncoding = "utf8"; + +export const api = axios.create({}); + +export class Storage { + set(key, value) { + localStorage.setItem(key, value); + } + + get(key) { + return localStorage.getItem(key); + } + + remove(key) { + localStorage.removeItem(key); + } +} diff --git a/web/yarn.lock b/web/yarn.lock index 48d439b..235da08 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -203,7 +203,7 @@ "@babel/plugin-syntax-jsx" "^7.16.5" "@babel/types" "^7.16.0" -"@babel/runtime@^7.7.6": +"@babel/runtime@^7.15.4", "@babel/runtime@^7.7.6", "@babel/runtime@^7.9.2": version "7.16.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.5.tgz#7f3e34bf8bdbbadf03fbb7b1ea0d929569c9487a" integrity sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA== @@ -279,11 +279,48 @@ dependencies: mini-svg-data-uri "^1.2.3" +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== +"@types/prop-types@*": + version "15.7.4" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" + integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + +"@types/react-redux@^7.1.20": + version "7.1.21" + resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.21.tgz#f32bbaf7cbc4b93f51e10d340aa54035c084b186" + integrity sha512-bLdglUiBSQNzWVVbmNPKGYYjrzp3/YDPwfOH3nLEz99I4awLlaRAPWjo6bZ2POpxztFWtDDXIPxBLVykXqBt+w== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + +"@types/react@*": + version "17.0.38" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.38.tgz#f24249fefd89357d5fa71f739a686b8d7c7202bd" + integrity sha512-SI92X1IA+FMnP3qM5m4QReluXzhcmovhZnLNm3pyeQlooi02qI7sLiepEYqT678uNiyc25XfCqxREFpy3W7YhQ== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + "@vitejs/plugin-react@^1.0.7": version "1.1.3" resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-1.1.3.tgz#0a649db2ea4637fd188adb36502b59da05ff6303" @@ -356,6 +393,13 @@ autoprefixer@^10.4.0: picocolors "^1.0.0" postcss-value-parser "^4.1.0" +axios@^0.24.0: + version "0.24.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6" + integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA== + dependencies: + follow-redirects "^1.14.4" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -491,6 +535,11 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== +csstype@^3.0.2: + version "3.0.10" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.10.tgz#2ad3a7bed70f35b965707c092e5f30b327c290e5" + integrity sha512-2u44ZG2OcNUO9HDp/Jl8C07x6pU/eTR3ncV91SiK3dhG9TWvRVsCoJw14Ckx5DgWkzGA3waZWO3d7pgqpUI/XA== + debug@^4.1.0: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" @@ -682,6 +731,11 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +follow-redirects@^1.14.4: + version "1.14.6" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.6.tgz#8cfb281bbc035b3c067d6cd975b0f6ade6e855cd" + integrity sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A== + fraction.js@^4.1.1: version "4.1.2" resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8" @@ -762,6 +816,13 @@ history@^5.1.0: dependencies: "@babel/runtime" "^7.7.6" +hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + immutable@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0.tgz#b86f78de6adef3608395efb269a91462797e2c23" @@ -870,7 +931,7 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -loose-envify@^1.1.0: +loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -1051,6 +1112,20 @@ postcss@^8.1.6, postcss@^8.3.11, postcss@^8.4.5: picocolors "^1.0.0" source-map-js "^1.0.1" +prettier@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a" + integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg== + +prop-types@^15.7.2: + version "15.8.0" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.0.tgz#d237e624c45a9846e469f5f31117f970017ff588" + integrity sha512-fDGekdaHh65eI3lMi5OnErU6a8Ighg2KjcjQxO7m8VHyWjcPyj5kiOgV1LQDOOOgVy3+5FgjXvdSSX7B8/5/4g== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.13.1" + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -1070,6 +1145,28 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" +react-is@^16.13.1, react-is@^16.7.0: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +react-is@^17.0.2: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +react-redux@^7.2.6: + version "7.2.6" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.6.tgz#49633a24fe552b5f9caf58feb8a138936ddfe9aa" + integrity sha512-10RPdsz0UUrRL1NZE0ejTkucnclYSgXp5q+tB5SWx2qeG2ZJQJyymgAhwKy73yiL/13btfB6fPr+rgbMAaZIAQ== + dependencies: + "@babel/runtime" "^7.15.4" + "@types/react-redux" "^7.1.20" + hoist-non-react-statics "^3.3.2" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^17.0.2" + react-refresh@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046" @@ -1112,6 +1209,23 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +redux-devtools-extension@^2.13.9: + version "2.13.9" + resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz#6b764e8028b507adcb75a1cae790f71e6be08ae7" + integrity sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A== + +redux-thunk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714" + integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q== + +redux@^4.0.0, redux@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" + integrity sha512-SH8PglcebESbd/shgf6mii6EIoRM0zrQyjcuQ+ojmfxjTtE0z9Y8pa62iA/OJ58qjP6j27uyW4kUF4jl/jd6sw== + dependencies: + "@babel/runtime" "^7.9.2" + regenerator-runtime@^0.13.4: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"