feat(ui): client side private routes
This commit is contained in:
parent
ae4e54453b
commit
a30d6b76d3
|
@ -1,18 +1,29 @@
|
||||||
import React from 'react';
|
import React, { FunctionComponent, useState, useEffect } from 'react';
|
||||||
import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
|
import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
|
||||||
import { HomePage } from './HomePage/HomePage';
|
import { HomePage } from './HomePage/HomePage';
|
||||||
import { ProfilePage } from './ProfilePage/ProfilePage';
|
import { ProfilePage } from './ProfilePage/ProfilePage';
|
||||||
|
import { DashboardPage } from './DashboardPage/DashboardPage';
|
||||||
|
import { PrivateRoute } from './PrivateRoute';
|
||||||
|
import { useLoggedIn, LoggedInContext } from '../hooks/useLoggedIn';
|
||||||
|
import { useUserProfile } from '../gql/queries/user';
|
||||||
|
|
||||||
export class App extends React.Component {
|
export interface AppProps {
|
||||||
render() {
|
|
||||||
return (
|
}
|
||||||
|
|
||||||
|
export const App: FunctionComponent<AppProps> = () => {
|
||||||
|
const { user } = useUserProfile();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoggedInContext.Provider value={user.id !== ''}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/" exact component={HomePage} />
|
<Route path="/" exact component={HomePage} />
|
||||||
<Route path="/profile" exact component={ProfilePage} />
|
<PrivateRoute path="/profile" exact component={ProfilePage} />
|
||||||
|
<PrivateRoute path="/dashboard" exact component={DashboardPage} />
|
||||||
<Route component={() => <Redirect to="/" />} />
|
<Route component={() => <Redirect to="/" />} />
|
||||||
</Switch>
|
</Switch>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
);
|
</LoggedInContext.Provider>
|
||||||
}
|
);
|
||||||
}
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { EstimationPanel } from './EstimationPanel';
|
||||||
|
|
||||||
|
export function Dashboard() {
|
||||||
|
return (
|
||||||
|
<div className="container is-fluid">
|
||||||
|
<div className="columns">
|
||||||
|
<div className="column is-4">
|
||||||
|
<EstimationPanel />
|
||||||
|
</div>
|
||||||
|
<div className="column is-4">
|
||||||
|
</div>
|
||||||
|
<div className="column is-4">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Page } from '../Page';
|
||||||
|
import { Dashboard } from './Dashboard';
|
||||||
|
|
||||||
|
export function DashboardPage() {
|
||||||
|
return (
|
||||||
|
<Page title="Tableau de bord">
|
||||||
|
<section className="mt-5">
|
||||||
|
<Dashboard />
|
||||||
|
</section>
|
||||||
|
</Page>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import React, { FunctionComponent } from "react";
|
||||||
|
import { ItemPanel } from "./ItemPanel";
|
||||||
|
|
||||||
|
export interface EstimationPanelProps {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EstimationPanel: FunctionComponent<EstimationPanelProps> = () => {
|
||||||
|
return (
|
||||||
|
<ItemPanel
|
||||||
|
title="Mes estimations"
|
||||||
|
className="is-primary"
|
||||||
|
newItemUrl="/estimations/new"
|
||||||
|
items={[]}
|
||||||
|
itemKey={(item) => { return item.id }}
|
||||||
|
itemLabel={(item) => { return item.id }}
|
||||||
|
itemUrl={(item) => { return `/estimations/${item.id}` }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,15 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
export function Dashboard() {
|
|
||||||
return (
|
|
||||||
<div className="columns">
|
|
||||||
<div className="column is-6">
|
|
||||||
</div>
|
|
||||||
<div className="column is-3">
|
|
||||||
</div>
|
|
||||||
<div className="column is-3">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,20 +1,22 @@
|
||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { Page } from '../Page';
|
import { Page } from '../Page';
|
||||||
import { Dashboard } from './Dashboard';
|
|
||||||
import { useUserProfile } from '../../gql/queries/user';
|
import { useUserProfile } from '../../gql/queries/user';
|
||||||
import { WelcomeContent } from './WelcomeContent';
|
import { WelcomeContent } from './WelcomeContent';
|
||||||
|
import { useHistory } from 'react-router';
|
||||||
|
import { useLoggedIn } from '../../hooks/useLoggedIn';
|
||||||
|
|
||||||
export function HomePage() {
|
export function HomePage() {
|
||||||
const { user, loading } = useUserProfile();
|
const loggedIn = useLoggedIn();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (loggedIn) history.push('/dashboard');
|
||||||
|
}, [loggedIn]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Page title={user.id ? 'Tableau de bord' : 'Accueil'}>
|
<Page title="Accueil">
|
||||||
<section className="mt-5">
|
<section className="mt-5">
|
||||||
{
|
<WelcomeContent />
|
||||||
user.id ?
|
|
||||||
<Dashboard /> :
|
|
||||||
<WelcomeContent />
|
|
||||||
}
|
|
||||||
</section>
|
</section>
|
||||||
</Page>
|
</Page>
|
||||||
);
|
);
|
||||||
|
|
|
@ -61,7 +61,7 @@ export const WelcomeContent: FunctionComponent<WelcomeContentProps> = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="card-content">
|
<div className="card-content">
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<h4>Partager simplement vos estimations.</h4>
|
<h4>Partagez simplement vos estimations.</h4>
|
||||||
<p>Une adresse courriel et votre estimation est partagée ! Le niveau d'accès (lecture seule, écriture, vue partielle...) peut être défini pour chaque partage.</p>
|
<p>Une adresse courriel et votre estimation est partagée ! Le niveau d'accès (lecture seule, écriture, vue partielle...) peut être défini pour chaque partage.</p>
|
||||||
{/* <p><a href="#">En savoir plus</a></p> */}
|
{/* <p><a href="#">En savoir plus</a></p> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,9 +3,10 @@ import { Config } from '../config';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { useUserProfile } from '../gql/queries/user';
|
import { useUserProfile } from '../gql/queries/user';
|
||||||
import { WithLoader } from './WithLoader';
|
import { WithLoader } from './WithLoader';
|
||||||
|
import { useLoggedIn } from '../hooks/useLoggedIn';
|
||||||
|
|
||||||
export function Navbar() {
|
export function Navbar() {
|
||||||
const { user, loading } = useUserProfile();
|
const loggedIn = useLoggedIn();
|
||||||
const [ isActive, setActive ] = useState(false);
|
const [ isActive, setActive ] = useState(false);
|
||||||
|
|
||||||
const toggleMenu = () => {
|
const toggleMenu = () => {
|
||||||
|
@ -16,7 +17,7 @@ export function Navbar() {
|
||||||
<nav className="navbar is-fixed-top" role="navigation" aria-label="main navigation">
|
<nav className="navbar is-fixed-top" role="navigation" aria-label="main navigation">
|
||||||
<div className="container is-fluid">
|
<div className="container is-fluid">
|
||||||
<div className="navbar-brand">
|
<div className="navbar-brand">
|
||||||
<Link className="navbar-item" to="/">
|
<Link className="navbar-item" to={loggedIn ? '/dashboard' : '/'}>
|
||||||
<h1 className="is-size-4">
|
<h1 className="is-size-4">
|
||||||
<i className="fa fa-stopwatch mr-1"></i>
|
<i className="fa fa-stopwatch mr-1"></i>
|
||||||
Guesstimate
|
Guesstimate
|
||||||
|
@ -37,7 +38,7 @@ export function Navbar() {
|
||||||
<div className="navbar-item">
|
<div className="navbar-item">
|
||||||
<div className="buttons">
|
<div className="buttons">
|
||||||
{
|
{
|
||||||
user.id ?
|
loggedIn ?
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<Link to="/profile" className="button">
|
<Link to="/profile" className="button">
|
||||||
<span className="icon">
|
<span className="icon">
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React, { FunctionComponent, Component, ReactType } from "react"
|
||||||
|
import { Route, Redirect, RouteProps } from "react-router"
|
||||||
|
import { useLoggedIn } from "../hooks/useLoggedIn";
|
||||||
|
|
||||||
|
export interface PrivateRouteProps extends RouteProps {
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PrivateRoute: FunctionComponent<PrivateRouteProps> = ({component: Component, ...rest}) => {
|
||||||
|
const loggedIn = useLoggedIn();
|
||||||
|
return (
|
||||||
|
<Route
|
||||||
|
{...rest}
|
||||||
|
render={(props) => loggedIn === true
|
||||||
|
? <Component {...props} />
|
||||||
|
: <Redirect to={{pathname: '/', state: {from: props.location}}} />}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
|
@ -23,12 +23,14 @@ export function ProfilePage() {
|
||||||
<section className="section">
|
<section className="section">
|
||||||
<div className="columns">
|
<div className="columns">
|
||||||
<div className="column is-6 is-offset-3">
|
<div className="column is-6 is-offset-3">
|
||||||
<h2 className="is-size-2 subtitle">Mon profil</h2>
|
<div className="box">
|
||||||
<WithLoader loading={isLoading || !user}>
|
<h2 className="is-size-2 subtitle">Mon profil</h2>
|
||||||
{
|
<WithLoader loading={isLoading || !user}>
|
||||||
<UserForm onChange={onUserChange} user={user} />
|
{
|
||||||
}
|
<UserForm onChange={onUserChange} user={user} />
|
||||||
</WithLoader>
|
}
|
||||||
|
</WithLoader>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import React, { useState, useContext } from "react";
|
||||||
|
|
||||||
|
export const LoggedInContext = React.createContext(false);
|
||||||
|
|
||||||
|
export const useLoggedIn = () => {
|
||||||
|
return useContext(LoggedInContext);
|
||||||
|
};
|
Loading…
Reference in New Issue