From 358ea24514748d8b6241505ca4da960b1d3f5d11 Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 5 Sep 2020 22:00:13 +0200 Subject: [PATCH] Communicate with API to authorize user --- package.json | 2 ++ src/api/index.ts | 13 +++++++++++++ src/api/user.ts | 9 +++++++++ src/app.tsx | 5 ++--- src/pages/user/login.tsx | 27 +++++++++++++++++++-------- src/state/actions/index.ts | 17 +++++++++-------- src/state/actions/student.ts | 16 ---------------- src/state/actions/user.ts | 16 ++++++++++++++++ src/state/reducer/index.ts | 4 +++- src/state/reducer/insurance.ts | 2 ++ src/state/reducer/student.ts | 8 ++++---- src/state/reducer/user.ts | 31 +++++++++++++++++++++++++++++++ src/state/store.ts | 8 ++++++-- yarn.lock | 17 +++++++++++++++++ 14 files changed, 133 insertions(+), 42 deletions(-) create mode 100644 src/api/index.ts create mode 100644 src/api/user.ts delete mode 100644 src/state/actions/student.ts create mode 100644 src/state/actions/user.ts create mode 100644 src/state/reducer/user.ts diff --git a/package.json b/package.json index c5eba09..f2da2fd 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@types/yup": "^0.29.4", "@typescript-eslint/eslint-plugin": "^2.10.0", "@typescript-eslint/parser": "^2.10.0", + "axios": "^0.20.0", "babel-core": "^6.26.3", "babel-loader": "^8.1.0", "babel-plugin-import": "^1.13.0", @@ -56,6 +57,7 @@ "redux": "^4.0.5", "redux-devtools-extension": "^2.13.8", "redux-persist": "^6.0.0", + "redux-thunk": "^2.3.0", "sass-loader": "8.0.2", "style-loader": "0.23.1", "ts-loader": "^7.0.5", diff --git a/src/api/index.ts b/src/api/index.ts new file mode 100644 index 0000000..2d1e182 --- /dev/null +++ b/src/api/index.ts @@ -0,0 +1,13 @@ +import Axios from "axios"; +import * as user from "./user"; + +export const axios = Axios.create({ + baseURL: "https://system-praktyk.stg.kadet.net/api", +}) + +const api = { + user, +} + +export default api; + diff --git a/src/api/user.ts b/src/api/user.ts new file mode 100644 index 0000000..ba70d5f --- /dev/null +++ b/src/api/user.ts @@ -0,0 +1,9 @@ +import { axios } from "@/api/index"; + +const AUTHORIZE_ENDPOINT = "/access/login" + +export async function authorize(code: string): Promise { + const response = await axios.get(AUTHORIZE_ENDPOINT, { params: { code }}); + + return response.data; +} diff --git a/src/app.tsx b/src/app.tsx index 1758fdb..d879206 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -3,7 +3,6 @@ import { Link, Route, Switch } from "react-router-dom" import { route, routes } from "@/routing"; import { useSelector } from "react-redux"; import { AppState, isReady } from "@/state/reducer"; -import { StudentActions } from "@/state/actions/student"; import { Trans, useTranslation } from "react-i18next"; import { Student } from "@/data"; import '@/styles/overrides.scss' @@ -14,7 +13,7 @@ import { EditionActions } from "@/state/actions/edition"; import { sampleEdition } from "@/provider/dummy/edition"; import { Edition } from "@/data/edition"; import { SettingActions } from "@/state/actions/settings"; -import { useDispatch } from "@/state/actions"; +import { useDispatch, UserActions } from "@/state/actions"; import { getLocale, Locale } from "@/state/reducer/settings"; import i18n from "@/i18n"; import moment from "moment"; @@ -26,7 +25,7 @@ const UserMenu = (props: HTMLProps) => { const { t } = useTranslation(); const handleUserLogout = () => { - dispatch({ type: StudentActions.Logout }) + dispatch({ type: UserActions.Logout }) } return
    diff --git a/src/pages/user/login.tsx b/src/pages/user/login.tsx index d9cfe8c..89fa966 100644 --- a/src/pages/user/login.tsx +++ b/src/pages/user/login.tsx @@ -1,21 +1,32 @@ -import React from "react"; +import React, { Dispatch } from "react"; import { Page } from "@/pages/base"; import { Button, Container, Typography } from "@material-ui/core"; -import { StudentActions, useDispatch } from "@/state/actions"; -import { sampleStudent } from "@/provider/dummy"; +import { Action, useDispatch } from "@/state/actions"; import { useHistory } from "react-router-dom"; import { route } from "@/routing"; import { useVerticalSpacing } from "@/styles"; +import { AppState } from "@/state/reducer"; + +import api from "@/api"; +import { UserActions } from "@/state/actions/user"; +import { sampleStudent } from "@/provider/dummy"; + +const authorizeUser = async (dispatch: Dispatch, getState: () => AppState): Promise => { + const token = await api.user.authorize("test"); + + dispatch({ + type: UserActions.Login, + token, + student: sampleStudent, + }) +} export const UserLoginPage = () => { const dispatch = useDispatch(); const history = useHistory(); - const handleSampleLogin = () => { - dispatch({ - type: StudentActions.Login, - student: sampleStudent, - }) + const handleSampleLogin = async () => { + await dispatch(authorizeUser); history.push(route("home")); } diff --git a/src/state/actions/index.ts b/src/state/actions/index.ts index 54ac996..a629b04 100644 --- a/src/state/actions/index.ts +++ b/src/state/actions/index.ts @@ -1,25 +1,26 @@ -import { StudentAction, StudentActions } from "@/state/actions/student"; +import { useDispatch as useReduxDispatch } from "react-redux"; + import { EditionAction, EditionActions } from "@/state/actions/edition"; import { SettingActions, SettingsAction } from "@/state/actions/settings"; import { InternshipProposalAction, InternshipProposalActions } from "@/state/actions/proposal"; -import { Dispatch } from "react"; - -import { useDispatch as useReduxDispatch } from "react-redux"; import { InternshipPlanAction, InternshipPlanActions } from "@/state/actions/plan"; import { InsuranceAction, InsuranceActions } from "@/state/actions/insurance"; +import { UserAction, UserActions } from "@/state/actions/user"; +import { ThunkDispatch } from "redux-thunk"; +import { AppState } from "@/state/reducer"; export * from "./base" export * from "./edition" export * from "./settings" -export * from "./student" export * from "./proposal" export * from "./plan" +export * from "./user" -export type Action = StudentAction | EditionAction | SettingsAction | InternshipProposalAction | InternshipPlanAction | InsuranceAction; +export type Action = UserAction | EditionAction | SettingsAction | InternshipProposalAction | InternshipPlanAction | InsuranceAction; -export const Actions = { ...StudentActions, ...EditionActions, ...SettingActions, ...InternshipProposalActions, ...InternshipPlanActions, ...InsuranceActions } +export const Actions = { ...UserActions, ...EditionActions, ...SettingActions, ...InternshipProposalActions, ...InternshipPlanActions, ...InsuranceActions } export type Actions = typeof Actions; -export const useDispatch = () => useReduxDispatch>() +export const useDispatch = () => useReduxDispatch>() export default Actions; diff --git a/src/state/actions/student.ts b/src/state/actions/student.ts deleted file mode 100644 index 29c6ae0..0000000 --- a/src/state/actions/student.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Action } from "@/state/actions/base"; -import { Student } from "@/data"; - -export enum StudentActions { - Login = 'LOGIN', - Logout = 'LOGOUT' -} - -export interface LoginAction extends Action { - student: Student -} - -export type LogoutAction = Action; - -export type StudentAction = LoginAction | LogoutAction; - diff --git a/src/state/actions/user.ts b/src/state/actions/user.ts new file mode 100644 index 0000000..6ee23f1 --- /dev/null +++ b/src/state/actions/user.ts @@ -0,0 +1,16 @@ +import { Action } from "@/state/actions/base"; +import { Student } from "@/data"; + +export enum UserActions { + Login = 'LOGIN', + Logout = 'LOGOUT' +} + +export interface LoginAction extends Action { + token: string; + student: Student; +} + +export type LogoutAction = Action; + +export type UserAction = LoginAction | LogoutAction; diff --git a/src/state/reducer/index.ts b/src/state/reducer/index.ts index ca5d238..6374056 100644 --- a/src/state/reducer/index.ts +++ b/src/state/reducer/index.ts @@ -5,7 +5,8 @@ import editionReducer from "@/state/reducer/edition"; import settingsReducer from "@/state/reducer/settings"; import internshipProposalReducer from "@/state/reducer/proposal"; import internshipPlanReducer from "@/state/reducer/plan"; -import { insuranceReducer } from "@/state/reducer/insurance"; +import insuranceReducer from "@/state/reducer/insurance"; +import userReducer from "@/state/reducer/user"; const rootReducer = combineReducers({ student: studentReducer, @@ -14,6 +15,7 @@ const rootReducer = combineReducers({ proposal: internshipProposalReducer, plan: internshipPlanReducer, insurance: insuranceReducer, + user: userReducer, }) export type AppState = ReturnType; diff --git a/src/state/reducer/insurance.ts b/src/state/reducer/insurance.ts index fded761..61cabc9 100644 --- a/src/state/reducer/insurance.ts +++ b/src/state/reducer/insurance.ts @@ -37,3 +37,5 @@ export const insuranceReducer: Reducer { +const studentReducer = (state: StudentState = initialStudentState, action: UserAction): StudentState => { switch (action.type) { - case StudentActions.Login: + case UserActions.Login: return action.student; - case StudentActions.Logout: + case UserActions.Logout: return null; } diff --git a/src/state/reducer/user.ts b/src/state/reducer/user.ts new file mode 100644 index 0000000..ae868a6 --- /dev/null +++ b/src/state/reducer/user.ts @@ -0,0 +1,31 @@ +import { Reducer } from "react"; +import { UserAction, UserActions } from "@/state/actions/user"; + +export type UserState = { + loggedIn: boolean; + token?: string; +} + +const initialUserState: UserState = { + loggedIn: false, +} + +const userReducer: Reducer = (state = initialUserState, action) => { + switch (action.type) { + case UserActions.Login: + return { + ...state, + loggedIn: true, + token: action.token, + } + + case UserActions.Logout: + return { + loggedIn: false + }; + } + + return state; +} + +export default userReducer; diff --git a/src/state/store.ts b/src/state/store.ts index d3f3095..935b3b2 100644 --- a/src/state/store.ts +++ b/src/state/store.ts @@ -1,8 +1,9 @@ -import { createStore } from "redux"; +import { applyMiddleware, compose, createStore } from "redux"; import rootReducer from "@/state/reducer"; import { devToolsEnhancer } from "redux-devtools-extension"; import { persistReducer, persistStore } from "redux-persist" import sessionStorage from "redux-persist/lib/storage/session" +import thunk from "redux-thunk"; const store = createStore( persistReducer( @@ -13,7 +14,10 @@ const store = createStore( }, rootReducer ), - devToolsEnhancer({}) + compose( + applyMiddleware(thunk), + devToolsEnhancer({}) + ) ); export const persistor = persistStore(store); diff --git a/yarn.lock b/yarn.lock index 634fa14..f385c39 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1816,6 +1816,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== +axios@^0.20.0: + version "0.20.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.20.0.tgz#057ba30f04884694993a8cd07fa394cff11c50bd" + integrity sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA== + dependencies: + follow-redirects "^1.10.0" + babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" @@ -3943,6 +3950,11 @@ follow-redirects@^1.0.0: dependencies: debug "^3.0.0" +follow-redirects@^1.10.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -7613,6 +7625,11 @@ redux-persist@*, redux-persist@^6.0.0: resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-6.0.0.tgz#b4d2972f9859597c130d40d4b146fecdab51b3a8" integrity sha512-71LLMbUq2r02ng2We9S215LtPu3fY0KgaGE0k8WRgl6RkqxtGfl7HUozz1Dftwsb0D/5mZ8dwAaPbtnzfvbEwQ== +redux-thunk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622" + integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== + redux@*, redux@^4.0.0, redux@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f"