feat: Implement routing
This commit is contained in:
parent
297d2e50f9
commit
6734e59a1b
@ -4,7 +4,15 @@ import AppBar from "@material-ui/core/AppBar";
|
||||
import Toolbar from "@material-ui/core/Toolbar";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
|
||||
import { BrowserRouter, Route, Redirect } from "react-router-dom";
|
||||
|
||||
import AuthRoute from "../security/AuthRoute";
|
||||
|
||||
import Dashboard from "../pages/dashboard";
|
||||
import LoginPage from "../pages/login";
|
||||
import LessonsPage from "../pages/lessons";
|
||||
|
||||
import { ILesson } from "../models/lesson";
|
||||
|
||||
interface IState {
|
||||
loggedIn: boolean;
|
||||
@ -19,26 +27,62 @@ export default class Application extends React.Component<{}, IState> {
|
||||
};
|
||||
|
||||
this.login = this.login.bind(this);
|
||||
this.isAuthenticated = this.isAuthenticated.bind(this);
|
||||
}
|
||||
|
||||
lessons(): ILesson[] {
|
||||
const lessons = [{
|
||||
name: "Der Bauer auf dem Feld",
|
||||
desc: "So fängt alles an: Du bist ein einfacher Bauer und musst dich die Karriereleiter mit deinen freshen Latein-Skills hinaufarbeiten",
|
||||
level: 1,
|
||||
done: true,
|
||||
}, {
|
||||
name: "???",
|
||||
desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd",
|
||||
level: 2,
|
||||
done: false,
|
||||
}];
|
||||
|
||||
return lessons;
|
||||
}
|
||||
|
||||
login(username: string, password: string): Promise<boolean> {
|
||||
return new Promise((res, rej) => {
|
||||
// TODO
|
||||
this.setState({
|
||||
loggedIn: true
|
||||
});
|
||||
res();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
return <div className="flex">
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<Typography className="flex" variant="title" color="inherit">
|
||||
Lateinicus
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
// Checks whether the user is logged in
|
||||
isAuthenticated() {
|
||||
// TODO: Security?
|
||||
return this.state.loggedIn === true;
|
||||
}
|
||||
|
||||
<LoginPage login={this.login} />
|
||||
</div>;
|
||||
render() {
|
||||
return <BrowserRouter
|
||||
basename="/">
|
||||
<div className="flex">
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<Typography className="flex" variant="title" color="inherit">
|
||||
Lateinicus
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
|
||||
<div className="content">
|
||||
<Route exact path="/" component={() => <Redirect to="/login" />} />
|
||||
<Route exact path="/login" component={() => {
|
||||
return <LoginPage loggedIn={this.state.loggedIn} login={this.login} />
|
||||
}} />
|
||||
<AuthRoute isAuth={this.isAuthenticated} path="/dashboard" component={() => <Dashboard lessons={this.lessons()} />} />
|
||||
<AuthRoute isAuth={this.isAuthenticated} path="/lessons" component={() => <LessonsPage lessons={this.lessons()} />} />
|
||||
</div>
|
||||
</div>
|
||||
</BrowserRouter>;
|
||||
}
|
||||
};
|
||||
|
7
src/models/lesson.ts
Normal file
7
src/models/lesson.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export interface ILesson {
|
||||
name: string;
|
||||
desc: string;
|
||||
level: number;
|
||||
|
||||
done: boolean;
|
||||
}
|
52
src/pages/dashboard.tsx
Normal file
52
src/pages/dashboard.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import * as React from "react";
|
||||
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
|
||||
import { ILesson } from "../models/lesson";
|
||||
|
||||
interface IProps {
|
||||
lessons: ILesson[];
|
||||
}
|
||||
|
||||
export default class Dashboard extends React.Component<{}> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const small = window.matchMedia("(max-width: 700px)").matches;
|
||||
const cName = small ? "lesson-card-xs" : "lesson-card-lg";
|
||||
|
||||
let key = 0;
|
||||
const lessonToCard = (lesson: ILesson) => {
|
||||
return <Grid item key={key++}>
|
||||
<Card style={{
|
||||
width: small ? window.width - 32 : "300px"
|
||||
}}>
|
||||
<CardContent className={cName}>
|
||||
<Typography variant="title">{`Level ${lesson.level}`}</Typography>
|
||||
<Typography variant="title" component="p">{lesson.name}</Typography>
|
||||
<br />
|
||||
<Typography component="p">
|
||||
{lesson.desc}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button className="lesson-card-btn">
|
||||
Zum Level
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>;
|
||||
};
|
||||
|
||||
return <Grid container spacing={16} direction="row">
|
||||
{this.props.lessons.map(lessonToCard)}
|
||||
</Grid>
|
||||
}
|
||||
};
|
52
src/pages/lessons.tsx
Normal file
52
src/pages/lessons.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import * as React from "react";
|
||||
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Button from "@material-ui/core/Button";
|
||||
import Card from '@material-ui/core/Card';
|
||||
import CardActions from '@material-ui/core/CardActions';
|
||||
import CardContent from '@material-ui/core/CardContent';
|
||||
|
||||
import { ILesson } from "../models/lesson";
|
||||
|
||||
interface IProps {
|
||||
lessons: ILesson[];
|
||||
}
|
||||
|
||||
export default class Dashboard extends React.Component<{}> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const small = window.matchMedia("(max-width: 700px)").matches;
|
||||
const cName = small ? "lesson-card-xs" : "lesson-card-lg";
|
||||
|
||||
let key = 0;
|
||||
const lessonToCard = (lesson: ILesson) => {
|
||||
return <Grid item key={key++}>
|
||||
<Card style={{
|
||||
width: small ? window.width - 32 : "300px"
|
||||
}}>
|
||||
<CardContent className={cName}>
|
||||
<Typography variant="title">{`Level ${lesson.level}`}</Typography>
|
||||
<Typography variant="title" component="p">{lesson.name}</Typography>
|
||||
<br />
|
||||
<Typography component="p">
|
||||
{lesson.desc}
|
||||
</Typography>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
<Button className="lesson-card-btn">
|
||||
Zum Level
|
||||
</Button>
|
||||
</CardActions>
|
||||
</Card>
|
||||
</Grid>;
|
||||
};
|
||||
|
||||
return <Grid container spacing={16} direction="row">
|
||||
{this.props.lessons.map(lessonToCard)}
|
||||
</Grid>
|
||||
}
|
||||
};
|
@ -8,8 +8,11 @@ import Button from "@material-ui/core/Button";
|
||||
import LinearProgress from "@material-ui/core/LinearProgress";
|
||||
import Snackbar from "@material-ui/core/Snackbar";
|
||||
|
||||
import { Redirect } from "react-router-dom";
|
||||
|
||||
interface IProps {
|
||||
login: (username: string, password: string) => Promise<boolean>;
|
||||
loggedIn: boolean;
|
||||
}
|
||||
|
||||
interface IState {
|
||||
@ -63,7 +66,7 @@ export default class LoginPage extends React.Component<{}, IState> {
|
||||
|
||||
const { username, password } = this.state;
|
||||
this.props.login(username, password).then((res) => {
|
||||
load(false);
|
||||
// Don't even do anything here!
|
||||
}, (err) => {
|
||||
load(false);
|
||||
showSnackbar("Failed to log in");
|
||||
@ -121,6 +124,11 @@ export default class LoginPage extends React.Component<{}, IState> {
|
||||
onClose={snackbarClose}
|
||||
message={this.state.snack}
|
||||
autoHideDuration={6000} />
|
||||
{
|
||||
this.props.loggedIn ? (
|
||||
<Redirect to="/dashboard" />
|
||||
) : undefined
|
||||
}
|
||||
</div>;
|
||||
}
|
||||
};
|
||||
|
18
src/security/AuthRoute.tsx
Normal file
18
src/security/AuthRoute.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { Route, Redirect } from "react-router-dom";
|
||||
|
||||
interface IAuthRouteProps {
|
||||
path: string;
|
||||
component: any;
|
||||
isAuth: () => boolean;
|
||||
}
|
||||
|
||||
export default class AuthRoute extends React.Component<IAuthRouteProps, {}> {
|
||||
render() {
|
||||
const auth = this.props.isAuth();
|
||||
return <Route path={this.props.path} component={
|
||||
() => auth ? <this.props.component /> : <Redirect to="/login" />
|
||||
} />;
|
||||
}
|
||||
};
|
Reference in New Issue
Block a user