Skip to content

Commit

Permalink
update route params based on search location
Browse files Browse the repository at this point in the history
  • Loading branch information
Gaya committed Jun 26, 2020
1 parent 8fdbf62 commit 6555704
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 31 deletions.
42 changes: 12 additions & 30 deletions src/components/App/useRouteNavigation.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import { useSetRecoilState } from 'recoil';
import { useCallback, useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';

import {
routeDistanceState,
routeFlippedState,
routeLocationState,
routeRandomSeedState,
routeTypeState,
} from '../../state/route';
import { history } from '../../utils/history';
import { randomSeed } from '../../state/utils';
import { updateRouteParameters } from '../../store/route/actions';

function hasRouteQueryParameters(search: string): boolean {
const params = new URLSearchParams(search);
Expand All @@ -21,13 +15,9 @@ function hasRouteQueryParameters(search: string): boolean {
}

function useLoadRouteFromQueryParameters(): (search: string) => void {
const setDistanceState = useSetRecoilState(routeDistanceState);
const setRouteTypeState = useSetRecoilState(routeTypeState);
const setRouteLocationState = useSetRecoilState(routeLocationState);
const setRouteRandomSeedState = useSetRecoilState(routeRandomSeedState);
const setRouteFlippedState = useSetRecoilState(routeFlippedState);
const dispatch = useDispatch();

return useCallback((search: string): boolean => {
return useCallback((search: string): void => {
const params = new URLSearchParams(search);
const distance = params.get('distance');
const routeType = params.get('routeType');
Expand All @@ -36,23 +26,15 @@ function useLoadRouteFromQueryParameters(): (search: string) => void {
const flipped = params.get('flipped');

if (distance && routeType && location) {
setDistanceState(parseInt(distance, 10));
setRouteTypeState(parseInt(routeType, 10));
setRouteLocationState(location);
setRouteRandomSeedState(r ? parseInt(r, 10) : randomSeed());
setRouteFlippedState(!!(flipped && flipped !== 'false'));

return true;
dispatch(updateRouteParameters({
distance: parseInt(distance, 10),
routeType: parseInt(routeType, 10),
randomSeed: r ? parseInt(r, 10) : randomSeed(),
flipped: !!(flipped && flipped !== 'false'),
location,
}));
}

return false;
}, [
setDistanceState,
setRouteFlippedState,
setRouteLocationState,
setRouteRandomSeedState,
setRouteTypeState,
]);
}, [dispatch]);
}

function useRouteNavigation(closeDrawer: () => void): void {
Expand Down
6 changes: 5 additions & 1 deletion src/store/createStore.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { applyMiddleware, combineReducers, createStore } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';

import { StoreState } from './types';

import app from './app/reducer';
import route from './route/reducer';

const reducers = combineReducers({
const reducers = combineReducers<StoreState>({
app,
route,
});

const store = createStore(
Expand Down
25 changes: 25 additions & 0 deletions src/store/route/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
interface RouteParameters {
distance: number;
location: string;
routeType: number;
randomSeed: number;
flipped: boolean;
}

interface UpdateRouteParameters {
type: 'ROUTE_UPDATE_PARAMETERS';
payload: RouteParameters;
}

export function updateRouteParameters(payload: RouteParameters): UpdateRouteParameters {
return {
type: 'ROUTE_UPDATE_PARAMETERS',
payload,
};
}

interface GenerateRun {
type: 'ROUTE_GENERATE_RUN';
}

export type routeActions = UpdateRouteParameters | GenerateRun;
22 changes: 22 additions & 0 deletions src/store/route/reducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { RouteState } from '../types';
import { routeActions } from './actions';

const defaultRouteState: RouteState = {
route: {
state: 'initial',
},
};

function route(state: RouteState = defaultRouteState, action: routeActions): RouteState {
switch (action.type) {
case 'ROUTE_UPDATE_PARAMETERS':
return {
...state,
...action.payload,
};
default:
return state;
}
}

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

import { Loadable, RouteState, StoreState } from '../types';

const routeState = (state: StoreState): RouteState => state.route;

const routeValueState = createSelector(routeState, (state) => state.route);

const isLoading = (item: Loadable): boolean => item.state === 'loading';
const isInitial = (item: Loadable): boolean => item.state === 'initial';
const hasError = (item: Loadable): boolean => item.state === 'error';
const getError = (item: Loadable): Error | undefined => (item.state === 'error' ? item.error : undefined);
const hasValue = (item: Loadable): boolean => item.state === 'hasValue';
const getValue = <T>(item: Loadable<T>): T | undefined => (item.state === 'hasValue' ? item.data : undefined);

const isRouteInitialSelector = createSelector(routeValueState, isLoading);
const isRouteLoadingSelector = createSelector(routeValueState, isInitial);
const hasRouteErrorSelector = createSelector(routeValueState, hasError);
const routeErrorSelector = createSelector(routeValueState, getError);
const hasRouteValueSelector = createSelector(routeValueState, hasValue);
const getRouteValueSelector = createSelector(routeValueState, getValue);
24 changes: 24 additions & 0 deletions src/store/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,34 @@
import { RoutesResponse } from '../server/types';

export type Loadable<T = unknown> = {
state: 'hasValue';
data: T;
} | {
state: 'initial';
} | {
state: 'loading';
} | {
state: 'error';
error: Error;
}

export interface AppState {
drawerOpened: boolean;
defaultDistance: number;
minimumDistance: number;
maximumDistance: number;
}

export type RouteState = {
location?: string;
distance?: number;
routeType?: number;
randomSeed?: number;
flipped?: boolean;
route: Loadable<RoutesResponse>;
};

export interface StoreState {
app: AppState;
route: RouteState;
}

0 comments on commit 6555704

Please sign in to comment.