diff --git a/package.json b/package.json index 4e5bdec816636c2c8d74cd4f6ec6ca31ee49e36f..0ed6447efecb3a97ce948cacc122374c9b0090ac 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@capacitor-community/react-hooks": "^0.0.11", "@capacitor/android": "^2.4.4", "@capacitor/cli": "^2.4.4", "@capacitor/core": "^2.4.4", diff --git a/src/App.js b/src/App.js index e25b9eb0a4598efae5fb3f028a65e706bc895ebc..858e2cc40e873fe94f1060503a7fd1afcc2df069 100644 --- a/src/App.js +++ b/src/App.js @@ -1,88 +1,41 @@ -import React from "react"; -import { BrowserRouter, Switch, Route } from "react-router-dom"; -import { Container, Row } from "react-bootstrap"; -import MemberAdder from "./MemberAdder"; -import MemberList from "./MemberList"; -import ProductList from "./ProductList"; -import Dashboard from "./Dashboard"; -import OwnPassword from "./OwnPassword"; -import Purchase from "./purchase/Purchase"; -import Topup from "./Topup"; -import ShowTransaction from "./ShowTransaction"; -import ShowOrder from "./order/ShowOrder"; -import CreateOrder from "./order/CreateOrder"; +import React, { useEffect, useState } from "react"; +import { useStorageItem } from "@capacitor-community/react-hooks/storage"; +import Panel from "./Panel"; import AuthContext from "./AuthContext"; -import SignIn from "./SignIn"; -import ResetRequest from "./ResetRequest"; -import ResetPassword from "./ResetPassword"; -import Head from "./Head"; -import logo from "./logo.svg"; import { url } from "./util"; -function Panel(props) { - return ( - <div> - <BrowserRouter> - <Head onLogout={props.onLogout} /> - <Container> - <Switch> - <Route path="/members/add"> - <MemberAdder /> - </Route> - <Route path="/members/purchase"> - <Purchase member /> - </Route> - <Route path="/members"> - <MemberList /> - </Route> - <Route path="/products"> - <ProductList /> - </Route> - <Route path="/transaction/:id"> - <ShowTransaction /> - </Route> - <Route path="/password"> - <OwnPassword /> - </Route> - <Route path="/purchase"> - <Purchase /> - </Route> - <Route path="/topup"> - <Topup /> - </Route> - <Route path="/order/create"> - <CreateOrder /> - </Route> - <Route path="/order/:id" component={ShowOrder} /> - <Route path="/"> - <Dashboard /> - </Route> - </Switch> - </Container> - </BrowserRouter> - </div> - ); -} +function App() { + const [num, setNum] = useStorageItem("num"); + const [role, setRole] = useStorageItem("role"); + const [token, setToken] = useStorageItem("token"); + const [timerID, setTimerID] = useState(null); -function UnlogedPanel(props) { + useEffect(() => { + if (!timerID) { + startRenew(token, setToken, setTimerID); + } + return stopRenew(timerID); + }, [token, setToken, timerID, setTimerID]); + + const login = (newToken, member) => { + setNum(member.num); + setRole(member.role); + setToken(newToken); + startRenew(newToken, setToken, setTimerID); + }; + + const logout = () => { + setNum(""); + setRole(""); + setToken(""); + stopRenew(timerID); + }; + + const value = { num, role, token }; return ( - <Container> - <Row className="justify-content-center"> - <img src={logo} alt="Garbanzo Negro" /> - </Row> - <BrowserRouter> - <Switch> - <Route path="/reset/:token" component={ResetPassword} /> - <Route path="/nreset/:token"> - <ResetPassword login /> - </Route> - <Route path="/reset/" component={ResetRequest} /> - <Route path="/"> - <SignIn onLogin={props.onLogin} /> - </Route> - </Switch> - </BrowserRouter> - </Container> + <AuthContext.Provider value={value}> + <Panel onLogin={login} onLogout={logout} isLogged={isLoggedIn(token)} /> + </AuthContext.Provider> ); } @@ -101,120 +54,50 @@ function getClaims(token) { 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 - ); +function renewToken(oldToken, setToken) { + fetch(url("/api/token"), { + headers: { "x-authentication": oldToken }, + }) + .then((response) => { + if (!response.ok) { + throw new Error(response.status.toString() + " " + response.statusText); } - } - } - - 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, + return response.json(); + }) + .then((data) => { + const token = data.token; + setToken(token); + }) + .catch((error) => { + console.log("Error renewing token: " + error.message); }); - 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("", "", ""); +function startRenew(token, setToken, setTimerID) { + if (token && getClaims(token)["exp"] !== undefined) { + const timerID = setInterval( + () => renewToken(token, setToken), + 60000 // every minute + ); + setTimerID(timerID); } +} - isLoggedIn() { - if (!this.state.token) { - return false; - } - const claims = getClaims(this.state.token); - if (claims["exp"] === undefined) { - return true; - } - return claims["exp"] > Date.now() / 1000; +function stopRenew(timerID) { + if (timerID) { + clearInterval(timerID); } +} - renewToken() { - fetch(url("/api/token"), { - headers: { "x-authentication": this.state.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); - }); +function isLoggedIn(token) { + if (!token) { + return false; } - - render() { - let component; - if (!this.isLoggedIn()) { - component = <UnlogedPanel onLogin={this.login} />; - } else { - component = <Panel onLogout={this.logout} />; - } - - return ( - <AuthContext.Provider value={this.state}> - {component} - </AuthContext.Provider> - ); + const claims = getClaims(token); + if (claims["exp"] === undefined) { + return true; } + return claims["exp"] > Date.now() / 1000; } export default App; diff --git a/src/Panel.js b/src/Panel.js new file mode 100644 index 0000000000000000000000000000000000000000..2527c7221819c5566b12ba7e09ebd55d8f7b9d4f --- /dev/null +++ b/src/Panel.js @@ -0,0 +1,94 @@ +import React from "react"; +import { BrowserRouter, Switch, Route } from "react-router-dom"; +import { Container, Row } from "react-bootstrap"; +import MemberAdder from "./MemberAdder"; +import MemberList from "./MemberList"; +import ProductList from "./ProductList"; +import Dashboard from "./Dashboard"; +import OwnPassword from "./OwnPassword"; +import Purchase from "./purchase/Purchase"; +import Topup from "./Topup"; +import ShowTransaction from "./ShowTransaction"; +import ShowOrder from "./order/ShowOrder"; +import CreateOrder from "./order/CreateOrder"; +import SignIn from "./SignIn"; +import ResetRequest from "./ResetRequest"; +import ResetPassword from "./ResetPassword"; +import Head from "./Head"; +import logo from "./logo.svg"; + +function Panel(props) { + if (props.isLogged) { + return <LogedPanel onLogout={props.onLogout} />; + } + return <UnlogedPanel onLogin={props.onLogin} />; +} + +function LogedPanel(props) { + return ( + <div> + <BrowserRouter> + <Head onLogout={props.onLogout} /> + <Container> + <Switch> + <Route path="/members/add"> + <MemberAdder /> + </Route> + <Route path="/members/purchase"> + <Purchase member /> + </Route> + <Route path="/members"> + <MemberList /> + </Route> + <Route path="/products"> + <ProductList /> + </Route> + <Route path="/transaction/:id"> + <ShowTransaction /> + </Route> + <Route path="/password"> + <OwnPassword /> + </Route> + <Route path="/purchase"> + <Purchase /> + </Route> + <Route path="/topup"> + <Topup /> + </Route> + <Route path="/order/create"> + <CreateOrder /> + </Route> + <Route path="/order/:id" component={ShowOrder} /> + <Route path="/"> + <Dashboard /> + </Route> + </Switch> + </Container> + </BrowserRouter> + </div> + ); +} + +function UnlogedPanel(props) { + return ( + <Container> + <Row className="justify-content-center"> + <img src={logo} alt="Garbanzo Negro" /> + </Row> + <BrowserRouter> + <Switch> + <Route path="/reset/:token" component={ResetPassword} /> + <Route path="/nreset/:token"> + <ResetPassword login /> + </Route> + <Route path="/reset/" component={ResetRequest} /> + <Route path="/"> + <SignIn onLogin={props.onLogin} /> + </Route> + </Switch> + </BrowserRouter> + </Container> + ); +} + +export default Panel;