This repository has been archived on 2022-03-12. You can view files and clone it, but cannot push or open issues or pull requests.
Lateinicus/frontend/src/pages/level.tsx

237 lines
9.9 KiB
TypeScript
Raw Normal View History

2018-09-06 18:05:21 +00:00
import * as React from "react";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import Typography from "@material-ui/core/Typography";
2018-09-18 18:20:26 +00:00
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
2018-09-06 18:05:21 +00:00
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
2018-09-18 18:20:26 +00:00
import CircularProgress from "@material-ui/core/CircularProgress";
2018-09-06 18:05:21 +00:00
2018-09-19 18:30:42 +00:00
import { withRouter } from "react-router-dom";
2018-10-02 11:10:33 +00:00
import { IVocab, VocabType, INomenData, IVerbData, IAdjektivData } from "../models/vocab";
2018-09-06 18:05:21 +00:00
interface IProps {
id: string;
2018-09-18 18:20:26 +00:00
levelVocab: (id: string) => Promise<IVocab[]>;
updateDoneLevels: (id: string) => void;
2018-09-18 18:20:26 +00:00
2018-09-19 18:30:42 +00:00
history: any;
2018-09-18 18:20:26 +00:00
loading: boolean;
setLoading: (state: boolean) => void;
vocab: IVocab[];
setVocab: (vocab: IVocab[]) => void;
setLookedAt: (ids: number[]) => void;
setCurrentVocab: (vocab: IVocab) => void;
drawerButtonState: (state: boolean) => void;
2018-09-06 18:05:21 +00:00
currentVocab: IVocab;
lookedAt: number[];
};
2018-09-19 18:30:42 +00:00
const LevelPageWithRouter = withRouter(
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 } = {};
2018-09-06 18:05:21 +00:00
2018-09-19 18:30:42 +00:00
componentDidMount() {
// Hide the drawer
this.props.drawerButtonState(false);
2018-09-19 18:30:42 +00:00
// Fetch the vocabulary
this.props.setLoading(true);
2018-09-18 18:20:26 +00:00
2018-09-19 18:30:42 +00:00
// TODO: Error handling
this.props.levelVocab(this.props.id).then(vocab => {
this.props.setVocab(vocab);
this.props.setCurrentVocab(vocab[0]);
this.props.setLookedAt([vocab[0].id]);
2018-09-19 18:30:42 +00:00
this.props.setLoading(false);
});
2018-09-18 18:20:26 +00:00
2018-09-19 18:30:42 +00:00
}
2018-09-06 18:05:21 +00:00
2018-09-19 18:30:42 +00:00
genUID = (vocab: IVocab): string => {
const { grundform } = vocab.latin;
if (grundform in this.uids) {
return this.uids[grundform];
} else {
this.uids[grundform] = "LEVELPAGE" + this.uid++;
return this.uids[grundform];
}
2018-09-14 14:13:42 +00:00
}
2018-09-06 18:05:21 +00:00
2018-09-19 18:30:42 +00:00
renderVocabListItem = (vocab: IVocab): any => {
// Check if the vocab was already looked at
const lookedAt = this.props.lookedAt.find((el) => el === vocab.id);
2018-09-19 18:30:42 +00:00
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.props.setCurrentVocab(vocab);
this.props.setLookedAt(lookedAt ? (
this.props.lookedAt
) : this.props.lookedAt.concat(vocab.id));
}}>
<ListItemText>
{`${vocab.latin.grundform} ${lookedAt ? "✔" : ""}`}
</ListItemText>
</ListItem>;
}
2018-09-06 18:05:21 +00:00
2018-09-19 18:30:42 +00:00
toReview = () => {
const { vocab, lookedAt, id } = this.props;
2018-09-19 18:30:42 +00:00
// Only go to the review if all vocabulary item have been looked at
if (vocab.length === lookedAt.length) {
this.props.updateDoneLevels(id);
2018-09-19 18:30:42 +00:00
this.props.setLoading(true);
this.props.history.push(`/review/level/${id}`);
}
2018-09-12 17:23:00 +00:00
}
2018-10-02 11:10:33 +00:00
vocabSpecificInformation(vocab: IVocab) {
switch (vocab.type) {
case VocabType.NOMEN:
const nData = vocab.latin as INomenData;
return <div>
<Typography variant="subheading" component="p">
<b>Genitiv:</b> {nData.genitiv}
</Typography>
<Typography variant="subheading" component="p">
<b>Genus:</b> {nData.genus}
</Typography>
</div>;
case VocabType.VERB:
const vData = vocab.latin as IVerbData;
return <div>
<Typography variant="subheading" component="p">
<b>1. Person Präsens:</b> {vData.praesens}
</Typography>
<Typography variant="subheading" component="p">
<b>1. Person Perfekt:</b> {vData.perfekt}
</Typography>
</div>;
case VocabType.ADJEKTIV:
const aData = vocab.latin as IAdjektivData;
return <div>
<Typography variant="subheading" component="p">
<b>Endung feminin:</b> {aData.endung_f}
</Typography>
<Typography variant="subheading" component="p">
<b>Endung neutrum:</b> {aData.endung_n}
</Typography>
</div>;
default:
return <div />;
}
}
2018-09-19 18:30:42 +00:00
render() {
if (this.props.loading) {
return <div>
<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>
2018-09-18 18:20:26 +00:00
</Grid>
2018-09-19 18:30:42 +00:00
</div>;
}
2018-09-06 18:05:21 +00:00
2018-10-02 11:10:33 +00:00
const vocabTypeToStr = {
[VocabType.NOMEN]: "Nomen",
[VocabType.VERB]: "Verb",
[VocabType.ADJEKTIV]: "Adjektiv",
[VocabType.ADVERB]: "Adverb",
};
2018-09-19 18:30:42 +00:00
const { currentVocab } = this.props;
return <div>
<Grid container direction="row">
<Grid item xs={3}>
<List>
{this.props.vocab
.map(this.renderVocabListItem)}
<ListItem button onClick={this.toReview}>
<ListItemText>
Zur Übung
2018-09-06 18:05:21 +00:00
</ListItemText>
2018-09-19 18:30:42 +00:00
</ListItem>
</List>
</Grid>
<Grid item lg={7} xs={9}>
<Grid container direction="column">
<Grid item style={{ margin: 12 }}>
<Card>
<CardContent>
<Typography gutterBottom variant="headline" component="h2">
2018-10-02 11:10:33 +00:00
{`${currentVocab.latin.grundform} (${vocabTypeToStr[currentVocab.type]})`}
2018-09-19 18:30:42 +00:00
</Typography>
<Typography gutterBottom variant="headline" component="h3">
{currentVocab.german.join(", ")}
</Typography>
2018-10-02 11:10:33 +00:00
{this.vocabSpecificInformation(currentVocab)}
2018-09-19 18:30:42 +00:00
{
currentVocab.hint ? (
<div style={{
border: "dashed",
borderColor: "red",
padding: 12,
}}>
<Typography variant="subheading" component="p">
<b>Tipp:</b>
</Typography>
<Typography variant="body2">
{currentVocab.hint}
</Typography>
</div>
) : undefined
}
{
currentVocab.mnemonic ? (
<div style={{
border: "dashed",
borderColor: "#f1c40f",
marginTop: 12,
padding: 12,
}}>
<Typography variant="subheading" component="p">
<b>Eselsbrücke:</b>
</Typography>
<Typography variant="body2">
{currentVocab.mnemonic}
</Typography>
</div>
) : undefined
}
</CardContent>
{/*TODO: Maybe "next" and "prev" buttons?*/}
</Card>
</Grid>
2018-09-06 18:05:21 +00:00
</Grid>
</Grid>
</Grid>
2018-09-19 18:30:42 +00:00
</div>;
}
2018-09-06 18:05:21 +00:00
}
2018-09-19 18:30:42 +00:00
);
export default LevelPageWithRouter;