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 { HomePage } from './HomePage/HomePage';
|
||||
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 {
|
||||
render() {
|
||||
return (
|
||||
export interface AppProps {
|
||||
|
||||
}
|
||||
|
||||
export const App: FunctionComponent<AppProps> = () => {
|
||||
const { user } = useUserProfile();
|
||||
|
||||
return (
|
||||
<LoggedInContext.Provider value={user.id !== ''}>
|
||||
<BrowserRouter>
|
||||
<Switch>
|
||||
<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="/" />} />
|
||||
</Switch>
|
||||
</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 { Dashboard } from './Dashboard';
|
||||
import { useUserProfile } from '../../gql/queries/user';
|
||||
import { WelcomeContent } from './WelcomeContent';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useLoggedIn } from '../../hooks/useLoggedIn';
|
||||
|
||||
export function HomePage() {
|
||||
const { user, loading } = useUserProfile();
|
||||
const loggedIn = useLoggedIn();
|
||||
const history = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
if (loggedIn) history.push('/dashboard');
|
||||
}, [loggedIn]);
|
||||
|
||||
return (
|
||||
<Page title={user.id ? 'Tableau de bord' : 'Accueil'}>
|
||||
<Page title="Accueil">
|
||||
<section className="mt-5">
|
||||
{
|
||||
user.id ?
|
||||
<Dashboard /> :
|
||||
<WelcomeContent />
|
||||
}
|
||||
<WelcomeContent />
|
||||
</section>
|
||||
</Page>
|
||||
);
|
||||
|
|
|
@ -61,7 +61,7 @@ export const WelcomeContent: FunctionComponent<WelcomeContentProps> = () => {
|
|||
</div>
|
||||
<div className="card-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><a href="#">En savoir plus</a></p> */}
|
||||
</div>
|
||||
|
|
|
@ -3,9 +3,10 @@ import { Config } from '../config';
|
|||
import { Link } from 'react-router-dom';
|
||||
import { useUserProfile } from '../gql/queries/user';
|
||||
import { WithLoader } from './WithLoader';
|
||||
import { useLoggedIn } from '../hooks/useLoggedIn';
|
||||
|
||||
export function Navbar() {
|
||||
const { user, loading } = useUserProfile();
|
||||
const loggedIn = useLoggedIn();
|
||||
const [ isActive, setActive ] = useState(false);
|
||||
|
||||
const toggleMenu = () => {
|
||||
|
@ -16,7 +17,7 @@ export function Navbar() {
|
|||
<nav className="navbar is-fixed-top" role="navigation" aria-label="main navigation">
|
||||
<div className="container is-fluid">
|
||||
<div className="navbar-brand">
|
||||
<Link className="navbar-item" to="/">
|
||||
<Link className="navbar-item" to={loggedIn ? '/dashboard' : '/'}>
|
||||
<h1 className="is-size-4">
|
||||
<i className="fa fa-stopwatch mr-1"></i>
|
||||
Guesstimate
|
||||
|
@ -37,7 +38,7 @@ export function Navbar() {
|
|||
<div className="navbar-item">
|
||||
<div className="buttons">
|
||||
{
|
||||
user.id ?
|
||||
loggedIn ?
|
||||
<Fragment>
|
||||
<Link to="/profile" className="button">
|
||||
<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">
|
||||
<div className="columns">
|
||||
<div className="column is-6 is-offset-3">
|
||||
<h2 className="is-size-2 subtitle">Mon profil</h2>
|
||||
<WithLoader loading={isLoading || !user}>
|
||||
{
|
||||
<UserForm onChange={onUserChange} user={user} />
|
||||
}
|
||||
</WithLoader>
|
||||
<div className="box">
|
||||
<h2 className="is-size-2 subtitle">Mon profil</h2>
|
||||
<WithLoader loading={isLoading || !user}>
|
||||
{
|
||||
<UserForm onChange={onUserChange} user={user} />
|
||||
}
|
||||
</WithLoader>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</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