From 69f5f98b2a70ee1444f52a8e0e0eec66814e4e54 Mon Sep 17 00:00:00 2001 From: Jonasz Bigda Date: Tue, 26 Jul 2022 16:11:55 +0200 Subject: [PATCH] redux to react-redux --- src/actions/index.js | 259 +++++-------------------- src/actions/toggles.js | 43 +--- src/components/Output/Restaurant.js | 18 +- src/reducers/data.js | 71 ++----- src/redux/slices/notificationsSlice.ts | 19 +- src/redux/slices/restaurantSlice.ts | 21 ++ src/redux/slices/tempDataSlice.ts | 29 --- src/redux/slices/togglesSlice.ts | 42 ++++ src/redux/slices/userSlice.ts | 16 +- src/redux/slices/viewportSlice.ts | 21 -- src/redux/store.ts | 10 +- 11 files changed, 172 insertions(+), 377 deletions(-) create mode 100644 src/redux/slices/restaurantSlice.ts delete mode 100644 src/redux/slices/tempDataSlice.ts create mode 100644 src/redux/slices/togglesSlice.ts delete mode 100644 src/redux/slices/viewportSlice.ts diff --git a/src/actions/index.js b/src/actions/index.js index 57a1aa4..70e321c 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -1,8 +1,10 @@ import axios from "axios"; -import * as toggles from "./toggles"; import { push } from "connected-react-router"; import { backend } from "../config.js"; import store from "../index.js"; +import * as restaurant from "../redux/slices/restaurantSlice"; +import * as toggle from "../redux/slices/togglesSlice"; +import * as notifications from "../redux/slices/notificationsSlice"; axios.defaults.withCredentials = true; @@ -11,27 +13,37 @@ axios.interceptors.response.use( return response; }, (error) => { - return new Promise((resolve) => { - if (error.response && error.response.status === 401 && error.config && !error.config.__isRetryRequest) { - const response = axios.post(backend + "user/refreshtoken", {withCredentials: true}).then((res) => { - const jwt = res.headers['x-auth-token']; - store.dispatch(setNewToken(jwt)) - error.config.__isRetryRequest = true - error.config.headers['x-auth-token'] = jwt - return axios(error.config); - }) - resolve(response) + return new Promise((resolve) => { + if ( + error.response && + error.response.status === 401 && + error.config && + !error.config.__isRetryRequest + ) { + const response = axios + .post(backend + "user/refreshtoken", { withCredentials: true }) + .then((res) => { + const jwt = res.headers["x-auth-token"]; + store.dispatch(setNewToken(jwt)); + error.config.__isRetryRequest = true; + error.config.headers["x-auth-token"] = jwt; + return axios(error.config); + }); + resolve(response); + } else { + if (error.response && error.response.status === 403) { + store.dispatch( + logout("Podany użytkownik, lub hasło nie istnieje.", "error") + ); + } else if (error.response && error.response.status === 400) { + store.dispatch(logout("Dane nieprawidłowe.", "error")); } else { - if(error.response && error.response.status === 403){ - store.dispatch(logout("Podany użytkownik, lub hasło nie istnieje.", "error")); - } else if(error.response && error.response.status === 400) { - store.dispatch(logout("Dane nieprawidłowe.", "error")); - } else { - store.dispatch(logout("Sesja wygasła", "info")); - } + store.dispatch(logout("Sesja wygasła", "info")); } - }) - }); + } + }); + } +); const autocomplete = (input) => { return { @@ -49,9 +61,9 @@ export const clearAutocomplete = () => { export const setNewToken = (token) => { return { type: "SET_NEW_TOKEN", - payload: token - } -} + payload: token, + }; +}; export const fetchAutocomplete = (input) => { return function (dispatch) { @@ -100,20 +112,13 @@ export const setSearchQuery = (input) => { }; }; -export const setRestaurant = (restaurant) => { - return { - type: "SET_RESTAURANT", - payload: restaurant, - }; -}; - export const fetchRestaurant = (id) => { return function (dispatch) { axios .get(backend + "restaurant?restaurantId=" + id) .then((response) => { - dispatch(setRestaurant(response.data)); - dispatch(toggles.hideDishes()); + dispatch(restaurant.setRestaurant(response.data)); + dispatch(toggle.hideDishes()); dispatch(fetchAllDishes(id)); }) .catch((err) => @@ -142,7 +147,7 @@ export const fetchAllDishes = (id) => { .get(backend + "restaurant/dishes?restaurantId=" + id) .then((response) => { dispatch(setDishes(response.data)); - dispatch(toggles.showDishes()); + dispatch(toggle.showDishes()); }); }; }; @@ -163,7 +168,7 @@ export const fetchDish = (id) => { export const refreshUserData = () => { return function (dispatch) { - const state = store.getState() + const state = store.getState(); axios({ url: backend + "user/refresh", method: "POST", @@ -173,7 +178,7 @@ export const refreshUserData = () => { }) .then((response) => { dispatch( - toggles.setLoggedIn( + toggle.setLoggedIn( response.data.firstname, response.data.lastname, state.data.userData.jwt, @@ -195,180 +200,10 @@ export const refreshUserData = () => { }; }; -export const tryLogin = (username, password) => { - const data = { email: username, password: password }; - - return function (dispatch) { - dispatch(toggles.showBackdrop()); - axios - .post(backend + "user/login", data) - .then((response) => { - if(response.data.isRestaurant === true){ - const jwt = response.headers["x-auth-token"]; - dispatch( - toggles.setLoggedIn( - response.data.firstname, - response.data.lastname, - jwt, - response.data.id, - response.data.email, - "", - response.data.NIP, - response.data.adress, - response.data.companyName, - response.data.restaurants, - response.data.isRestaurant - ) - ); - dispatch(toggles.hideBackdrop()); - dispatch(notification(`Witaj ${response.data.firstname}!`, "success")); - dispatch(push("/")); - } else { - const jwt = response.headers["x-auth-token"]; - dispatch( - toggles.setLoggedIn( - "", - "", - jwt, - response.data.id, - response.data.email, - response.data.login, - "", - "", - "", - [], - response.data.isRestaurant - ) - ); - dispatch(toggles.hideBackdrop()); - dispatch(notification(`Witaj ${response.data.login}!`, "success")); - dispatch(push("/")); - } - }) - .catch((err) => { - if (!err.response) { - console.log(err); - } else if (err.response.status === 404) { - dispatch(toggles.hideBackdrop()); - dispatch(notification("Użytkownik nie istnieje :(", "error")); - } else if (err.response.status === 403) { - dispatch(toggles.hideBackdrop()); - dispatch(notification("Błędne dane logowania :(", "error")); - } else { - dispatch(toggles.hideBackdrop()); - dispatch(notification("Błąd serwera :(", "error")); - } - }); - }; -}; - -export const remindPassword = (email) => { - return function (dispatch) { - const data = { email: email }; - dispatch(toggles.showBackdrop()); - axios - .post(backend + "user/forgotpassword", data) - .then((response) => { - dispatch(toggles.hideBackdrop()); - dispatch(notification(response.data, "info")); - }) - .catch((e) => { - dispatch(toggles.hideBackdrop()); - dispatch(notification(e.response.data, "error")); - }); - }; -}; - -export const changePassword = (email, password, token) => { - return function (dispatch) { - const data = { - token: token, - email: email, - newPass: password, - }; - dispatch(toggles.showBackdrop()); - axios - .post(backend + "user/resetpass", data) - .then((response) => { - dispatch(toggles.hideBackdrop()); - dispatch(notification(response.data, "info")); - }) - .catch((e) => { - dispatch(toggles.hideBackdrop()); - dispatch(notification(e.response.data, "error")); - }); - }; -}; - -export const logout = (message, type) => { - return function (dispatch) { - if(message && type){ - dispatch(notification(message, type)); - } else { - dispatch(notification("Wylogowano.", "info")); - } - dispatch(toggles.hideBackdrop()); - dispatch(toggles.setLoggedOut()); - dispatch(push("/")); - }; -}; - -export const tryRegister = (data) => { - return function (dispatch) { - dispatch(toggles.showBackdrop()); - axios - .post(backend + "user/register", data) - .then((response) => { - if (response.status === 201) { - dispatch( - notification( - "Rejestracja przebiegła pomyślnie, możesz teraz zalogować się do swojego konta.", - "success" - ) - ); - dispatch(toggles.hideBackdrop()); - dispatch(push("/")) - } - }) - .catch((err) => { - if (err.response.status === 500) { - dispatch( - notification( - "Wystąpił nieoczekiwany błąd serwera, przepraszamy...", - "error" - ) - ); - dispatch(toggles.hideBackdrop()); - } else if (err.response.status === 409) { - dispatch( - notification( - "Adres email jest już zajęty, proszę użyć innego.", - "error" - ) - ); - dispatch(toggles.hideBackdrop()); - } - }); - }; -}; - -export const setTempData = (data) => { - return { - type: "SET_TEMP_DATA", - payload: data, - }; -}; - -export const clearTempData = () => { - return { - type: "CLEAR_TEMP_DATA", - }; -}; - export const notification = (message, type) => { return function (dispatch) { dispatch( - toggles.enqueueSnackbar({ + toggle.enqueueSnackbar({ message: message, options: { key: new Date().getTime() + Math.random(), @@ -389,13 +224,13 @@ export const updateRestaurant = (restaurant) => { export const setTags = (tags) => { return { type: "SET_TAGS", - payload: tags - } -} + payload: tags, + }; +}; export const setTypes = (types) => { return { type: "SET_TYPES", - payload: types - } -} \ No newline at end of file + payload: types, + }; +}; diff --git a/src/actions/toggles.js b/src/actions/toggles.js index 93ea2ad..66bb2d8 100644 --- a/src/actions/toggles.js +++ b/src/actions/toggles.js @@ -1,15 +1,3 @@ -export const showDishes = () => { - return { - type: "SET_DISHLIST_VISIBLE", - }; -}; - -export const hideDishes = () => { - return { - type: "SET_DISHLIST_HIDDEN", - }; -}; - export const setLoggedIn = ( firstname, lastname, @@ -36,7 +24,7 @@ export const setLoggedIn = ( adress: adress, companyName: companyName, restaurants: restaurants, - isRestaurant: isRestaurant + isRestaurant: isRestaurant, }, }; }; @@ -47,18 +35,6 @@ export const setLoggedOut = () => { }; }; -export const hideRegulamin = () => { - return { - type: "DIALOG_REGULAMIN_HIDE", - }; -}; - -export const showRegulamin = () => { - return { - type: "DIALOG_REGULAMIN_SHOW", - }; -}; - export const enqueueSnackbar = (notification) => { const key = notification.options && notification.options.key; @@ -70,20 +46,3 @@ export const enqueueSnackbar = (notification) => { }, }; }; - -export const removeSnackbar = (key) => ({ - type: "REMOVE_SNACKBAR", - key, -}); - -export const showBackdrop = () => { - return { - type: "SHOW_BACKDROP", - }; -}; - -export const hideBackdrop = () => { - return { - type: "HIDE_BACKDROP", - }; -}; diff --git a/src/components/Output/Restaurant.js b/src/components/Output/Restaurant.js index e2286ea..dc2272e 100644 --- a/src/components/Output/Restaurant.js +++ b/src/components/Output/Restaurant.js @@ -4,21 +4,20 @@ import DishList from "./DishList"; import CircularProgress from "@material-ui/core/CircularProgress"; import { useParams } from "react-router-dom"; import { extractTags } from "../../Services"; -import { useSelector, useDispatch } from "react-redux"; +import { useAppDispatch, useAppSelector } from "../../redux/hooks"; import { fetchRestaurant } from "../../actions"; import GoogleMapStatic from "./GoogleMapStatic"; import WorkingHours from "./WorkingHours"; import Social from "./Social"; -import LunchMenu from "./LunchMenu"; export default function Restaurant(props) { - const restaurant = useSelector((state) => state.restaurant); + const restaurant = useAppSelector((state) => state.restaurant); const { id } = useParams(); - const dispatch = useDispatch(); - const showDishList = useSelector((state) => state.data.showDishList); + const dispatch = useAppDispatch(); + const showDishList = useAppSelector((state) => state.toggles.showDishList); useEffect(() => { - dispatch(fetchRestaurant(id)); + dispatch(fetchRestaurant(id)); }, [dispatch, id]); if (restaurant.name) document.title = restaurant.name; @@ -61,7 +60,9 @@ export default function Restaurant(props) { {restaurant.lunchHours &&
Lunch menu
} {restaurant.lunchHours && ( -

{restaurant.lunchHours}

+

+ {restaurant.lunchHours} +

)}
Lokalizacja
@@ -72,9 +73,6 @@ export default function Restaurant(props) {
- {!showDishList && } - {(showDishList && restaurant.lunchMenu) &&

Zestawy

} - {(showDishList && restaurant.lunchMenu) && }

Menu

{!showDishList && } {showDishList && } diff --git a/src/reducers/data.js b/src/reducers/data.js index 71a86d7..9a3943f 100644 --- a/src/reducers/data.js +++ b/src/reducers/data.js @@ -1,37 +1,5 @@ -const initialState = { - showDishList: false, - loggedIn: false, - userData: { - jwt: "", - firstname: "", - lastname: "", - userId: "", - userEmail: "", - billing: { - NIP: "", - adress: "", - companyName: "", - }, - restaurants: [], - isRestaurant: false - }, - dialogs: { - regulamin: false, - }, - backdrop: false, - tempData: {}, - filters: { - types: [], - tags: [] - } -}; - const data = (state = initialState, action) => { switch (action.type) { - case "SET_DISHLIST_VISIBLE": - return (state = { ...state, showDishList: true }); - case "SET_DISHLIST_HIDDEN": - return (state = { ...state, showDishList: false }); case "SET_LOGGEDIN": return (state = { ...state, @@ -49,7 +17,7 @@ const data = (state = initialState, action) => { companyName: action.payload.companyName, }, restaurants: action.payload.restaurants, - isRestaurant: action.payload.isRestaurant + isRestaurant: action.payload.isRestaurant, }, }); case "SET_LOGGEDOUT": @@ -68,29 +36,17 @@ const data = (state = initialState, action) => { companyName: "", }, restaurants: [], - isRestaurant: false + isRestaurant: false, }, }); - case "DIALOG_REGULAMIN_SHOW": - return (state = { - ...state, - dialogs: { ...state.dialogs, regulamin: true }, - }); - case "DIALOG_REGULAMIN_HIDE": - return (state = { - ...state, - dialogs: { ...state.dialogs, regulamin: false }, - }); case "SET_TEMP_DATA": return (state = { ...state, tempData: action.payload }); case "CLEAR_TEMP_DATA": return (state = { ...state, tempData: {} }); - case "SHOW_BACKDROP": - return (state = { ...state, backdrop: true }); - case "HIDE_BACKDROP": - return (state = { ...state, backdrop: false }); case "UPDATE_RESTAURANT": - const index = state.userData.restaurants.findIndex((restaurant) => restaurant._id === action.payload._id); + const index = state.userData.restaurants.findIndex( + (restaurant) => restaurant._id === action.payload._id + ); return (state = { ...state, userData: { @@ -98,16 +54,25 @@ const data = (state = initialState, action) => { restaurants: [ ...state.userData.restaurants.slice(0, index), action.payload, - ...state.userData.restaurants.slice(index + 1) + ...state.userData.restaurants.slice(index + 1), ], }, }); case "SET_NEW_TOKEN": - return (state = {...state, userData: {...state.userData, jwt: action.payload}}) + return (state = { + ...state, + userData: { ...state.userData, jwt: action.payload }, + }); case "SET_TYPES": - return (state = {...state, filters: {...state.filters, types: action.payload}}) + return (state = { + ...state, + filters: { ...state.filters, types: action.payload }, + }); case "SET_TAGS": - return (state = {...state, filters: {...state.filters, tags: action.payload}}) + return (state = { + ...state, + filters: { ...state.filters, tags: action.payload }, + }); default: return state; } diff --git a/src/redux/slices/notificationsSlice.ts b/src/redux/slices/notificationsSlice.ts index 894ea5f..38679da 100644 --- a/src/redux/slices/notificationsSlice.ts +++ b/src/redux/slices/notificationsSlice.ts @@ -1,16 +1,25 @@ import { createSlice } from "@reduxjs/toolkit"; -const initialState = []; +const initialState: any[] = []; -export const userSlice = createSlice({ +export const notificationsSlice = createSlice({ name: "notifications", initialState: initialState, reducers: { addNotification: (state, action) => { - state = [...state, { key: action.key }]; + state = [ + ...state, + { key: action.payload.key, ...action.payload.notification }, + ]; + }, + removeNotification: (state, action) => { + state = state.filter( + (notification) => notification.key != action.payload.key + ); }, }, }); -export const { clearUserData } = userSlice.actions; -export default userSlice.reducer; +export const { addNotification, removeNotification } = + notificationsSlice.actions; +export default notificationsSlice.reducer; diff --git a/src/redux/slices/restaurantSlice.ts b/src/redux/slices/restaurantSlice.ts new file mode 100644 index 0000000..6c7fc73 --- /dev/null +++ b/src/redux/slices/restaurantSlice.ts @@ -0,0 +1,21 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { Restaurant } from "../../typescript/interfaces"; +import axios from "axios"; + +const initialState: Restaurant = {} as Restaurant; + +export const restaurantSlice = createSlice({ + name: "restaurant", + initialState: initialState, + reducers: { + clearRestaurant: (state) => { + state = initialState; + }, + setRestaurant: (state, action) => { + state = action.payload; + }, + }, +}); + +export const { clearRestaurant, setRestaurant } = restaurantSlice.actions; +export default restaurantSlice.reducer; diff --git a/src/redux/slices/tempDataSlice.ts b/src/redux/slices/tempDataSlice.ts deleted file mode 100644 index b9dc1d0..0000000 --- a/src/redux/slices/tempDataSlice.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { User } from "../../typescript/interfaces"; -import { createSlice } from "@reduxjs/toolkit"; - -const initialState: User = { - id: "", - username: "", - email: "", - isRestaurant: true, - trialUsed: false, - billing: { - NIP: "", - adress: "", - companyName: "", - }, - restaurants: [], -}; - -export const tempDataSlice = createSlice({ - name: "tempData", - initialState: initialState, - reducers: { - clearTempData: (state) => { - state = initialState; - }, - }, -}); - -export const { clearTempData } = tempDataSlice.actions; -export default tempDataSlice.reducer; diff --git a/src/redux/slices/togglesSlice.ts b/src/redux/slices/togglesSlice.ts new file mode 100644 index 0000000..e65bf11 --- /dev/null +++ b/src/redux/slices/togglesSlice.ts @@ -0,0 +1,42 @@ +import { createSlice } from "@reduxjs/toolkit"; + +const initialState = { + backdrop: false, + showDishList: false, + regulamin: false, +}; + +export const togglesSlice = createSlice({ + name: "toggles", + initialState: initialState, + reducers: { + showBackdrop: (state) => { + state = { ...state, backdrop: true }; + }, + hideBackdrop: (state) => { + state = { ...state, backdrop: false }; + }, + showDishes: (state) => { + state = { ...state, showDishList: true }; + }, + hideDishes: (state) => { + state = { ...state, showDishList: false }; + }, + showRegulamin: (state) => { + state = { ...state, showDishList: true }; + }, + hideRegulamin: (state) => { + state = { ...state, showDishList: false }; + }, + }, +}); + +export const { + showBackdrop, + hideBackdrop, + showDishes, + hideDishes, + showRegulamin, + hideRegulamin, +} = togglesSlice.actions; +export default togglesSlice.reducer; diff --git a/src/redux/slices/userSlice.ts b/src/redux/slices/userSlice.ts index bccfb75..e113ba3 100644 --- a/src/redux/slices/userSlice.ts +++ b/src/redux/slices/userSlice.ts @@ -1,4 +1,4 @@ -import { User } from "../../typescript/interfaces"; +import { Restaurant, User } from "../../typescript/interfaces"; import { createSlice } from "@reduxjs/toolkit"; const initialState: User = { @@ -22,6 +22,20 @@ export const userSlice = createSlice({ clearUserData: (state) => { state = initialState; }, + updateRestaurant: (state, action) => { + const index = state.restaurants?.findIndex( + (restaurant) => restaurant.id === action.payload.id + ); + let restaurants: Restaurant[] = state.restaurants || []; + state = { + ...state, + restaurants: [ + ...restaurants.slice(0, index), + action.payload, + ...restaurants.slice(index + 1), + ], + }; + }, }, }); diff --git a/src/redux/slices/viewportSlice.ts b/src/redux/slices/viewportSlice.ts deleted file mode 100644 index 3f0867f..0000000 --- a/src/redux/slices/viewportSlice.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { createSlice } from "@reduxjs/toolkit"; - -const initialState = { - backdrop: false, -}; - -export const viewportSlice = createSlice({ - name: "viewport", - initialState: initialState, - reducers: { - showBackdrop: (state) => { - state = { ...state, backdrop: true }; - }, - hideBackdrop: (state) => { - state = { ...state, backdrop: false }; - }, - }, -}); - -export const { showBackdrop, hideBackdrop } = viewportSlice.actions; -export default viewportSlice.reducer; diff --git a/src/redux/store.ts b/src/redux/store.ts index c99e09e..38e8199 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -1,13 +1,15 @@ import { configureStore } from "@reduxjs/toolkit"; import userReducer from "./slices/userSlice"; -import tempDataReducer from "./slices/tempDataSlice"; -import viewportReducer from "./slices/viewportSlice"; +import restaurantReducer from "./slices/restaurantSlice"; +import togglesReducer from "./slices/togglesSlice"; +import notificationsReducer from "./slices/notificationsSlice"; const store = configureStore({ reducer: { user: userReducer, - tempData: tempDataReducer, - viewport: viewportReducer, + restaurant: restaurantReducer, + toggles: togglesReducer, + notifications: notificationsReducer, }, });