refactor: Move the LevelPage to Redux

This commit is contained in:
Alexander Polynomdivision
2018-09-18 20:20:26 +02:00
parent 95fc93f690
commit 3136c92687
5 changed files with 227 additions and 55 deletions

View File

@@ -5,8 +5,11 @@ import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import CircularProgress from "@material-ui/core/CircularProgress";
import { Redirect } from "react-router-dom";
@@ -14,35 +17,42 @@ import { IVocab } from "../models/vocab";
interface IProps {
id: string;
levelVocab: (id: string) => Promise<IVocab[]>;
levelVocab: (id: string) => IVocab[];
loading: boolean;
setLoading: (state: boolean) => void;
vocab: IVocab[];
setVocab: (vocab: IVocab[]) => void;
setLookedAt: (ids: number[]) => void;
setCurrentVocab: (vocab: IVocab) => void;
setReview: (state: boolean) => void;
drawerButtonState: (state: boolean) => void;
};
interface IState {
currentVocab: IVocab;
lookedAt: number[];
toReview: boolean;
};
export default class LevelPage extends React.Component<IProps, IState> {
export default class LevelPage extends React.Component<IProps> {
private uid = 0;
// To prevent React from redrawing the vocabulary list and prematurely
// cancelling the animation
private uids: { [key: string]: string } = {};
constructor(props: any) {
super(props);
componentDidMount() {
// Hide the drawer
this.props.drawerButtonState(false);
this.state = {
currentVocab: this.props.levelVocab(this.props.id)[0],
lookedAt: [0],
toReview: false,
};
// Fetch the vocabulary
this.props.setLoading(true);
// TODO: Error handling
this.props.levelVocab(this.props.id).then(vocab => {
this.props.setVocab(vocab);
this.props.setCurrentVocab(vocab[0]);
this.props.setLoading(false);
});
}
genUID = (vocab: IVocab): string => {
@@ -57,16 +67,16 @@ export default class LevelPage extends React.Component<IProps, IState> {
renderVocabListItem = (vocab: IVocab): any => {
// Check if the vocab was already looked at
const lookedAt = this.state.lookedAt.find((el) => el === vocab.id) || vocab.id === 0;
const lookedAt = this.props.lookedAt.find((el) => el === vocab.id) || vocab.id === 0;
return <ListItem button key={this.genUID(vocab)} onClick={() => {
// Prevent the user from using too much memory by always clicking on the elements
// Show the clicked at vocab word
this.setState({
currentVocab: vocab,
lookedAt: lookedAt ? this.state.lookedAt : this.state.lookedAt.concat(vocab.id),
});
this.props.setCurrentVocab(vocab);
this.props.setLookedAt(lookedAt ? (
this.props.lookedAt
) : this.props.lookedAt.concat(vocab.id));
}}>
<ListItemText>
{`${vocab.latin.grundform} ${lookedAt ? "✔" : ""}`}
@@ -75,23 +85,52 @@ export default class LevelPage extends React.Component<IProps, IState> {
}
toReview = () => {
const { levelVocab, id } = this.props;
const { vocab, lookedAt } = this.props;
// Only go to the review if all vocabulary item have been looked at
if (levelVocab(id).length === this.state.lookedAt.length) {
this.setState({
toReview: true,
});
if (vocab.length === lookedAt.length) {
this.props.setReview(true);
}
}
render() {
const { currentVocab } = this.state;
if (this.props.loading) {
return <div>
{/*
* This would be the case when the user presses the "to
* review" button. That is because we need the state of loading
* to be true, when this page gets called
* TODO:?
*/}
{
this.props.toReview ? (
<Redirect to={`/review/level/${this.props.id}`} />
) : undefined
}
<Grid
container
spacing={0}
direction="column"
alignItems="center"
justify="center"
style={{ minHeight: '100vh' }}>
<Grid item xs={12}>
<Paper className="paper">
<Grid container direction="column" spacing={8}>
<CircularProgress />
</Grid>
</Paper>
</Grid>
</Grid>
</div>;
}
const { currentVocab } = this.props;
return <div>
<Grid container direction="row">
<Grid item xs={3}>
<List>
{this.props.levelVocab(this.props.id)
{this.props.vocab
.map(this.renderVocabListItem)}
{/* TODO*/}
<ListItem button onClick={this.toReview}>
@@ -102,7 +141,7 @@ export default class LevelPage extends React.Component<IProps, IState> {
</List>
</Grid>
{
this.state.toReview ? (
this.props.toReview ? (
<Redirect to={`/review/level/${this.props.id}`} />
) : undefined
}