redux to react-redux

This commit is contained in:
2022-07-26 16:11:55 +02:00
parent c0b1a35e58
commit 69f5f98b2a
11 changed files with 172 additions and 377 deletions

View File

@@ -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;
@@ -12,26 +14,36 @@ axios.interceptors.response.use(
},
(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
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)
});
resolve(response);
} else {
if (error.response && error.response.status === 403) {
store.dispatch(logout("Podany użytkownik, lub hasło nie istnieje.", "error"));
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"));
}
}
})
});
}
);
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
}
}
payload: types,
};
};

View File

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

View File

@@ -4,18 +4,17 @@ 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));
@@ -61,7 +60,9 @@ export default function Restaurant(props) {
<WorkingHours hours={restaurant.workingHours} />
{restaurant.lunchHours && <h5>Lunch menu</h5>}
{restaurant.lunchHours && (
<p style={{ color: "#bbbbbb", fontWeight: 400 }}>{restaurant.lunchHours}</p>
<p style={{ color: "#bbbbbb", fontWeight: 400 }}>
{restaurant.lunchHours}
</p>
)}
<hr />
<h5>Lokalizacja</h5>
@@ -72,9 +73,6 @@ export default function Restaurant(props) {
</div>
<div className="restaurant-content">
<div className="restaurant-dishes">
{!showDishList && <CircularProgress />}
{(showDishList && restaurant.lunchMenu) && <h3>Zestawy</h3>}
{(showDishList && restaurant.lunchMenu) && <LunchMenu restaurant={restaurant} />}
<h3>Menu</h3>
{!showDishList && <CircularProgress />}
{showDishList && <DishList />}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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),
],
};
},
},
});

View File

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

View File

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