Skip to content
Snippets Groups Projects
Forked from meskio / cicer
198 commits behind the upstream repository.
App.js 4.41 KiB
import React from 'react';
import { BrowserRouter, Switch, Route } from 'react-router-dom';
import MemberList from './MemberList';
import ProductList from './ProductList';
import Dashboard from './Dashboard';
import Purchase from './purchase/Purchase';
import Topup from './Topup';
import ShowTransaction from './ShowTransaction';
import AuthContext from './AuthContext';
import SignIn from './SignIn';
import Head from './Head';

function Panel(props) {
    return (
        <div>
            <Head onLogout={props.onLogout} />
            <BrowserRouter>
              <Switch>
                <Route path="/members">
                    <MemberList />
                </Route>
                <Route path="/products">
                    <ProductList />
                </Route>
                <Route path="/transaction/:id">
                    <ShowTransaction />
                </Route>
                <Route path="/purchase">
                    <Purchase />
                </Route>
                <Route path="/topup">
                    <Topup />
                </Route>
                <Route path="/">
                    <Dashboard />
                </Route>
              </Switch>
            </BrowserRouter>
        </div>
    );
}

function getClaims(token) {
    const base64Url = token.split('.')[1];
    const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
    const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));

    return JSON.parse(jsonPayload);
}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            num: null,
            role: null,
            token: null
        };

        this.logout = this.logout.bind(this);
        this.login = this.login.bind(this);
    }

    componentDidMount() {
        const token = localStorage.getItem("token");
        if (token) {
            const num = localStorage.getItem("num");
            const role = localStorage.getItem("role");
            this.setState({ num, role, token });
            if (getClaims(token)["exp"] !== undefined) {
                this.timerID = setInterval(
                    () => this.renewToken(),
                    60000  // every minute
                );
            }
        }
    }

    componentWillUnmount() {
        if (this.timeID) {
            clearInterval(this.timerID);
        }
    }

    storeState(token, num, role) {
        localStorage.setItem("token", token);
        localStorage.setItem("num", num);
        localStorage.setItem("role", role);
    }

    login(token, member) {
        this.setState({
            num: member.num,
            role: member.role,
            token: token
        });
        this.storeState(token, member.num, member.role);
        if (getClaims(token)["exp"] !== undefined) {
            this.timerID = setInterval(
                () => this.renewToken(),
                60000  // every minute
            );
        }
    }

    logout() {
        if (this.timeID) {
            clearInterval(this.timerID);
        }
        this.setState({
            num: null,
            role: null,
            token: null
        });
        this.storeState("", "", "");
    }

	isLoged() {
        if (!this.state.token) {
            return false;
        }
        const claims = getClaims(this.state.token);
        if (claims["exp"] === undefined) {
            return true;
        }
        return claims["exp"] > Date.now()/1000;
	};

    renewToken() {
        fetch("/api/token")
            .then(response => {
                if (!response.ok) {
                    throw new Error(response.status.toString()+' '+response.statusText);
                }
                return response.json();
            })
            .then(data => {
                const token = data.token;
                this.setState({token});
                localStorage.setItem("token", token);
            })
            .catch(error => {
                console.log("Error renewing token: " + error.message)
            });
    }

    render() {
        let component = <Panel onLogout={this.logout} />;
        if (!this.isLoged()) {
            component = <SignIn onLogin={this.login} />;
        }

        return (
          <AuthContext.Provider value={this.state}>
            {component}
          </AuthContext.Provider>
        );
    }
}

export default App;