Communicate with API to authorize user

This commit is contained in:
Kacper Donat 2020-09-05 22:00:13 +02:00
parent c7fa02d588
commit 358ea24514
14 changed files with 133 additions and 42 deletions

View File

@ -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",

13
src/api/index.ts Normal file
View File

@ -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;

9
src/api/user.ts Normal file
View File

@ -0,0 +1,9 @@
import { axios } from "@/api/index";
const AUTHORIZE_ENDPOINT = "/access/login"
export async function authorize(code: string): Promise<string> {
const response = await axios.get<string>(AUTHORIZE_ENDPOINT, { params: { code }});
return response.data;
}

View File

@ -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<HTMLUListElement>) => {
const { t } = useTranslation();
const handleUserLogout = () => {
dispatch({ type: StudentActions.Logout })
dispatch({ type: UserActions.Logout })
}
return <ul { ...props }>

View File

@ -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<Action>, getState: () => AppState): Promise<void> => {
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"));
}

View File

@ -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<Dispatch<Action>>()
export const useDispatch = () => useReduxDispatch<ThunkDispatch<AppState, any, Action>>()
export default Actions;

View File

@ -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<StudentActions.Login> {
student: Student
}
export type LogoutAction = Action<StudentActions.Logout>;
export type StudentAction = LoginAction | LogoutAction;

16
src/state/actions/user.ts Normal file
View File

@ -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<UserActions.Login> {
token: string;
student: Student;
}
export type LogoutAction = Action<UserActions.Logout>;
export type UserAction = LoginAction | LogoutAction;

View File

@ -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<typeof rootReducer>;

View File

@ -37,3 +37,5 @@ export const insuranceReducer: Reducer<InsuranceState, InsuranceAction | Interns
return state;
}
}
export default insuranceReducer;

View File

@ -1,16 +1,16 @@
import { Student } from "@/data";
import { StudentAction, StudentActions } from "@/state/actions/student";
import { UserAction, UserActions } from "@/state/actions/user";
export type StudentState = Student | null;
const initialStudentState: StudentState = null;
const studentReducer = (state: StudentState = initialStudentState, action: StudentAction): StudentState => {
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;
}

31
src/state/reducer/user.ts Normal file
View File

@ -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<UserState, UserAction> = (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;

View File

@ -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);

View File

@ -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"