Skip to content

Commit

Permalink
store distance settings in redux
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaya committed Jun 24, 2020
1 parent ff4de0f commit 6a82e7d
Show file tree
Hide file tree
Showing 8 changed files with 140 additions and 33 deletions.
19 changes: 12 additions & 7 deletions src/components/App/AppWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React from 'react';
import { Provider } from 'react-redux';
import { RecoilRoot } from 'recoil';

import { createMuiTheme, ThemeProvider } from '@material-ui/core/styles';
import teal from '@material-ui/core/colors/teal';
import deepOrange from '@material-ui/core/colors/deepOrange';

import store from '../../store/createStore';

import ErrorProvider from '../Error/ErrorProvider';

import './App.css';
Expand All @@ -18,13 +21,15 @@ const theme = createMuiTheme({
});

const AppWrapper: React.FC = ({ children }) => (
<ThemeProvider theme={theme}>
<ErrorProvider>
<RecoilRoot>
{children}
</RecoilRoot>
</ErrorProvider>
</ThemeProvider>
<Provider store={store}>
<ThemeProvider theme={theme}>
<ErrorProvider>
<RecoilRoot>
{children}
</RecoilRoot>
</ErrorProvider>
</ThemeProvider>
</Provider>
);

export default AppWrapper;
54 changes: 33 additions & 21 deletions src/components/Settings/DistanceSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,62 @@ import {
InputLabel,
Typography,
} from '@material-ui/core';
import { useRecoilState } from 'recoil';
import { useDispatch, useSelector } from 'react-redux';

import { defaultDistanceState, maximumDistanceState, minimumDistanceState } from '../../state/app';
import { storeDistanceSettings } from '../../utils/localStorage';
import { updateDistanceSettings, UpdateDistanceSettingsPayload } from '../../store/app/actions';
import {
defaultDistanceSelector,
maximumDistanceSelector,
minimumDistanceSelector,
} from '../../store/app/selectors';

const DistanceSettings: React.FC = () => {
const [defaultState, setDefaultState] = useRecoilState(defaultDistanceState);
const [minState, setMinState] = useRecoilState(minimumDistanceState);
const [maxState, setMaxState] = useRecoilState(maximumDistanceState);
const dispatch = useDispatch();

const defaultDistanceState = useSelector(defaultDistanceSelector);
const minimumDistanceState = useSelector(minimumDistanceSelector);
const maximumDistanceState = useSelector(maximumDistanceSelector);

const [defaultDistance, setDefaultDistance] = useState<number>(defaultState);
const [minDistance, setMinDistance] = useState<number>(minState);
const [maxDistance, setMaxDistance] = useState<number>(maxState);
const [defaultDistance, setDefaultDistance] = useState<number>(defaultDistanceState);
const [minDistance, setMinDistance] = useState<number>(minimumDistanceState);
const [maxDistance, setMaxDistance] = useState<number>(maximumDistanceState);

useEffect(
() => {
if (defaultState !== defaultDistance) {
setDefaultState(defaultDistance);
const payload: UpdateDistanceSettingsPayload = {};

if (defaultDistanceState !== defaultDistance) {
payload.defaultDistance = defaultDistance;
}

if (minState !== minDistance) {
setMinState(minDistance);
if (maximumDistanceState !== maxDistance) {
payload.maximumDistance = maxDistance;
}

if (maxState !== maxDistance) {
setMaxState(maxDistance);
if (minimumDistanceState !== minDistance) {
payload.minimumDistance = minDistance;
}

if (Object.keys(payload).length > 0) {
dispatch(updateDistanceSettings(payload));
}

// @todo SIDE EFFECT
storeDistanceSettings({
defaultDistance,
min: minDistance,
max: maxDistance,
min: minDistance,
});
},
[
defaultDistance,
defaultState,
defaultDistanceState,
dispatch,
maxDistance,
maxState,
maximumDistanceState,
minDistance,
minState,
setDefaultState,
setMaxState,
setMinState,
minimumDistanceState,
],
);

Expand Down
5 changes: 0 additions & 5 deletions src/state/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@ import { atom } from 'recoil';

import { safeStoredDistance } from '../utils/localStorage';

export const errorState = atom<string | undefined>({
key: 'ErrorState',
default: undefined,
});

export const drawerOpenState = atom<boolean>({
key: 'DrawerOpenState',
default: true,
Expand Down
21 changes: 21 additions & 0 deletions src/store/app/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export interface UpdateDistanceSettingsPayload {
defaultDistance?: number;
minimumDistance?: number;
maximumDistance?: number;
}

interface UpdateDistanceSettings {
type: 'APP_UPDATE_DISTANCE_SETTINGS';
payload: UpdateDistanceSettingsPayload;
}

export function updateDistanceSettings(
payload: UpdateDistanceSettingsPayload,
): UpdateDistanceSettings {
return {
type: 'APP_UPDATE_DISTANCE_SETTINGS',
payload,
};
}

export type AppActions = UpdateDistanceSettings;
26 changes: 26 additions & 0 deletions src/store/app/reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { AppState } from '../types';
import { safeStoredDistance } from '../../utils/localStorage';
import { AppActions } from './actions';

const storedDistanceSettings = safeStoredDistance();

const initialState: AppState = {
drawerOpened: true,
defaultDistance: storedDistanceSettings?.defaultDistance || 10,
minimumDistance: storedDistanceSettings?.min || 1,
maximumDistance: storedDistanceSettings?.max || 50,
};

function app(state = initialState, action: AppActions): AppState {
switch (action.type) {
case 'APP_UPDATE_DISTANCE_SETTINGS':
return {
...state,
...action.payload,
};
default:
return state;
}
}

export default app;
20 changes: 20 additions & 0 deletions src/store/app/selectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createSelector } from 'reselect';

import { AppState, StoreState } from '../types';

const appState = (state: StoreState): AppState => state.app;

export const defaultDistanceSelector = createSelector(
appState,
(state) => state.defaultDistance,
);

export const maximumDistanceSelector = createSelector(
appState,
(state) => state.maximumDistance,
);

export const minimumDistanceSelector = createSelector(
appState,
(state) => state.minimumDistance,
);
18 changes: 18 additions & 0 deletions src/store/createStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { applyMiddleware, combineReducers, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';

import app from './app/reducer';

const reducers = combineReducers({
app,
});

const store = createStore(
reducers,
undefined,
composeWithDevTools(
applyMiddleware(),
),
);

export default store;
10 changes: 10 additions & 0 deletions src/store/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export interface AppState {
drawerOpened: boolean;
defaultDistance: number;
minimumDistance: number;
maximumDistance: number;
}

export interface StoreState {
app: AppState;
}

0 comments on commit 6a82e7d

Please sign in to comment.