summaryrefslogtreecommitdiffhomepage
path: root/app/routes.js
blob: 5440027c6bcb22ce9cf6ae2d61570f2a3e5193be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import React from 'react';
import { Switch, Route, Redirect } from 'react-router';
import { CSSTransitionGroup } from 'react-transition-group';
import WindowChrome from './components/WindowChrome';
import LoginPage from './containers/LoginPage';
import ConnectPage from './containers/ConnectPage';
import SettingsPage from './containers/SettingsPage';
import AccountPage from './containers/AccountPage';
import SelectLocationPage from './containers/SelectLocationPage';
import { getTransitionProps } from './transitions';

/**
 * Create routes
 *
 * @export
 * @param {function} getState       - function to get redux state
 * @param {object}   componentProps - extra props to propagate across components
 * @returns {React.element}
 */
export default function makeRoutes(getState, componentProps) {

  /**
   * Merge props and render component
   * @param {React.Component} component - component class
   * @param {...}             rest      - props
   * @private
   */
  const renderMergedProps = (component, ...rest) => {
    const finalProps = Object.assign({}, componentProps, ...rest);
    return (
      React.createElement(component, finalProps)
    );
  };

  /**
   * Renders public route
   * Example: <PublicRoute path="/" component={ MyComponent } />
   * @private
   */
  const PublicRoute = ({ component, ...rest }) => {
    return (
      <Route {...rest} render={ (routeProps) => {
        return renderMergedProps(component, routeProps, ...rest);
      }} />
    );
  };

  /**
   * Renders protected route that requires authentication, otherwise redirects to /
   * Example: <PrivateRoute path="/protected" component={ MyComponent } />
   * @private
   */
  const PrivateRoute = ({ component, ...rest }) => {
    return (
      <Route {...rest} render={ (routeProps) => {
        const { account } = getState();
        const isLoggedIn = account.status === 'ok';

        if(isLoggedIn) {
          return renderMergedProps(component, routeProps, ...rest);
        } else {
          return (<Redirect to={ '/' } />);
        }
      }} />
    );
  };

  /**
   * Renders login route that is only available to non-authenticated
   * users. Otherwise this route redirects user to /connect.
   * Example: <LoginRoute path="/login" component={ MyComponent } />
   * @private
   */
  const LoginRoute = ({ component, ...rest }) => {
    return (
      <Route {...rest} render={ (routeProps) => {
        const { account } = getState();
        const isLoggedIn = account.status === 'ok';

        if(isLoggedIn) {
          return (<Redirect to={ '/connect' } />);
        } else {
          return renderMergedProps(component, routeProps, ...rest);
        }
      }} />
    );
  };

  // store previous route
  let previousRoute;

  return (
    <Route render={({location}) => {
      const toRoute = location.pathname;
      const fromRoute = previousRoute;
      const transitionProps = getTransitionProps(fromRoute, toRoute);
      previousRoute = toRoute;

      return (
        <WindowChrome>
          <CSSTransitionGroup component="div" className="transition-container" { ...transitionProps }>
            <Switch key={ location.key } location={ location }>
              <LoginRoute exact path="/" component={ LoginPage } />
              <PrivateRoute exact path="/connect" component={ ConnectPage } />
              <PublicRoute exact path="/settings" component={ SettingsPage } />
              <PrivateRoute path="/settings/account" component={ AccountPage } />
              <PrivateRoute path="/select-location" component={ SelectLocationPage } />
            </Switch>
          </CSSTransitionGroup>
        </WindowChrome>
      );
    }} />
  );
}