diff --git a/src/components/SummaryTable.tsx b/src/components/SummaryTable.tsx new file mode 100644 index 0000000..c31d3b0 --- /dev/null +++ b/src/components/SummaryTable.tsx @@ -0,0 +1,40 @@ +import * as React from "react"; + +import Table from "@material-ui/core/Table"; +import TableHead from "@material-ui/core/TableHead"; +import TableBody from "@material-ui/core/TableBody"; +import TableRow from "@material-ui/core/TableRow"; +import TableCell from "@material-ui/core/TableCell"; + +import { IReviewMetadata } from "../models/review"; + +interface IProps { + reviewMeta: IReviewMetadata; +} + +export default class SummaryTable extends React.Component { + render() { + return + + + Antworten + Anzahl + + + + + Korrekt + {this.props.reviewMeta.correct} + + + Fast richtig + {this.props.reviewMeta.nearly} + + + Falsch + {this.props.reviewMeta.wrong} + + +
; + } +} diff --git a/src/components/app.tsx b/src/components/app.tsx index 1962f3a..0024059 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -25,9 +25,11 @@ import LoginPage from "../pages/login"; import LevelListPage from "../pages/levelList"; import LevelPage from "../pages/level"; import ReviewPage from "../pages/review"; +import SummaryPage from "../pages/summary"; import { ILevel } from "../models/level"; -import { IVocab } from "../models/vocab"; +import { IVocab, VocabType } from "../models/vocab"; +import { IReviewMetadata } from "../models/review"; interface IState { loggedIn: boolean; @@ -71,6 +73,15 @@ export default class Application extends React.Component<{}, IState> { return levels; } + getLastReview(): IReviewMetadata { + // TODO: Actually fetch this + return { + correct: 5, + nearly: 5, + wrong: 5, + }; + } + getLearners(): ILearner[] { return [{ username: "Polynomdivision", @@ -104,23 +115,27 @@ export default class Application extends React.Component<{}, IState> { latin: "Vinum", german: "Wein", hint: "Worte auf '-um' sind meistens NeutrUM" + type: VocabType.NOMEN, id: 0 }, { latin: "Vinum (Genitiv)", - german: "", + german: "Vini", + type: VocabType.NOMEN, id: 1 - }, { - latin: "Vici", - german: "", - hint: "Wird \"Viki\" und nicht \"Vichi\" ausgesprochen", - mnemonic: "Merk dir das Wort mit Caesars berühmten Worten: \"Veni Vidi Vici\"; Er kam, sah und siegte", - id: 2 - }, { - latin: "fuga", - german: "Flucht", - hint: "Worte auf \"-a\" sind FeminA", - id: 3 - }] as IVocab[]; + }/* , { + * latin: "Vici", + * german: "", + * hint: "Wird \"Viki\" und nicht \"Vichi\" ausgesprochen", + * mnemonic: "Merk dir das Wort mit Caesars berühmten Worten: \"Veni Vidi Vici\"; Er kam, sah und siegte", + * type: VocabType.NOMEN, + * id: 2 + }, { + * latin: "fuga", + * german: "Flucht", + * hint: "Worte auf \"-a\" sind FeminA", + * type: VocabType.NOMEN, + * id: 3 + } */] as IVocab[]; } login(username: string, password: string): Promise { @@ -233,7 +248,12 @@ export default class Application extends React.Component<{}, IState> { } /> + component={() => { + return + }} /> { return ; } }} /> + { + return + }} /> ; diff --git a/src/models/review.ts b/src/models/review.ts new file mode 100644 index 0000000..e69a58a --- /dev/null +++ b/src/models/review.ts @@ -0,0 +1,8 @@ +export interface IReviewMetadata { + // Number of correct answers + correct: number; + // Number of wrong answers + wrong: number; + // Number of nearly correct answers + nearly: number; +}; diff --git a/src/models/vocab.ts b/src/models/vocab.ts index ed7343a..e172ff4 100644 --- a/src/models/vocab.ts +++ b/src/models/vocab.ts @@ -3,12 +3,28 @@ export enum ReviewMode { LAT_TO_GER, } +export enum VocabType { + NOMEN, + VERB, + ADJEKTIV, + ADVERB +} + export interface IVocab { german: string; latin: string; hint?: string; mnemonic?: string; + type: VocabType; + // This number is lesson specific id: number; }; + +export const typeToPoints = (VocabType type) => { + switch (type) { + // Nomen: 2P + 1 (Wenn richtig) + // + } +} diff --git a/src/pages/dashboard.tsx b/src/pages/dashboard.tsx index 34de5fe..9ebbf2a 100644 --- a/src/pages/dashboard.tsx +++ b/src/pages/dashboard.tsx @@ -8,12 +8,15 @@ import Button from "@material-ui/core/Button"; import Paper from "@material-ui/core/Paper"; import Scoreboard from "../components/scoreboard"; +import SummaryTable from "../components/SummaryTable"; import { ILevel } from "../models/level"; import { ILearner } from "../models/learner"; +import { IReviewMetadata } from "../models/review"; interface IProps { nextLevel: () => ILevel; + lastReview: () => IReviewMetadata; learners: ILearner[]; } @@ -72,8 +75,11 @@ export default class Dashboard extends React.Component { - Some stuff - + + Letzte Wiederholung + + + ; diff --git a/src/pages/level.tsx b/src/pages/level.tsx index ae405c4..0366ac3 100644 --- a/src/pages/level.tsx +++ b/src/pages/level.tsx @@ -60,6 +60,15 @@ export default class LevelPage extends React.Component { ; } + toReview = () => { + // Only go to the review if all vocabulary item have been looked at + if (this.props.levelVocab().length === this.state.lookedAt.length) { + this.setState({ + toReview: true, + }); + } + } + render() { const { currentVocab } = this.state; @@ -69,9 +78,7 @@ export default class LevelPage extends React.Component { {this.props.levelVocab(this.props.id).map(this.renderVocabListItem)} {/* TODO*/} - this.setState({ - toReview: true, - })}> + Zur Übung diff --git a/src/pages/review.tsx b/src/pages/review.tsx index 7a4bf96..82afbe0 100644 --- a/src/pages/review.tsx +++ b/src/pages/review.tsx @@ -1,12 +1,17 @@ import * as React from "react"; import Card from "@material-ui/core/Card"; +import CardContent from "@material-ui/core/CardContent"; import TextField from "@material-ui/core/TextField"; import Grid from "@material-ui/core/Grid"; import Button from "@material-ui/core/Button"; -import Typography from "@material-ui/core/Button"; +import Typography from "@material-ui/core/Typography"; +import Popover from "@material-ui/core/Popover"; +import Paper from "@material-ui/core/Paper"; -import { IVocab, ReviewMode } from "../models/vocab"; +import { Redirect } from "react-router-dom"; + +import { IVocab, ReviewMode, VocabType } from "../models/vocab"; interface IProps { levelId: number; @@ -16,25 +21,38 @@ interface IProps { interface IState { input: string; current: number; + + toSummary: boolean; + + popoverOpen: boolean; + popoverText: string; + popoverColor: string; } -export default class ReviewPage extends React.Component { +export default class ReviewPage extends React.Component { private vocab: IVocab[] = []; + // Used for positioning the popover + private buttonRef: HTMLButtonElement; + constructor(props: any) { super(props); this.state = { input: "", current: 0, + + toSummary: false, + + popoverOpen: false, + popoverText: "", + popoverColor: "red", }; const { vocabByLevel, levelId } = this.props; this.vocab = vocabByLevel(levelId); - - this.currentVocab = this.currentVocab.bind(this); } - currentVocab() { + currentVocab = () => { return this.vocab[this.state.current]; } @@ -43,45 +61,91 @@ export default class ReviewPage extends React.Component { // Check if the user's answer was correct // TODO: Levensthein-Distance? - if (this.state.input === current.german) { + if (this.state.input.toLowerCase() === current.german.toLowerCase()) { // TODO: Show it's correct - console.log("Hell yeah"); - // Show the next vocab word if (this.state.current + 1 >= this.vocab.length) { - // TODO: Go to a summary screen + // TODO: Set some data that the summary screen will show + this.setState({ + toSummary: true, + }); } else { // Increase the vocab this.setState({ current: this.state.current + 1, + input: "", }); } } else { - // TODO: Show it's wrong - console.log("Hell no"); + this.setState({ + popoverOpen: true, + popoverText: "Das war nicht richtig", + popoverColor: "red", + // TODO: Or maybe don't reset the text + input: "", + }); } - // TODO: Show a snackbar for showing the updated score + // TODO(?): Show a snackbar for showing the updated score } render() { - return
+ return
+ { + this.state.toSummary ? ( + + ) : undefined + } - -

- {this.vocab[this.state.current].latin} -

- this.setState({ - input: ev.target.value, - })} /> - -
+
+
diff --git a/src/pages/summary.tsx b/src/pages/summary.tsx new file mode 100644 index 0000000..411a453 --- /dev/null +++ b/src/pages/summary.tsx @@ -0,0 +1,60 @@ +import * as React from "react"; + +import Typography from "@material-ui/core/Typography"; +import Paper from "@material-ui/core/Paper"; +import Grid from "@material-ui/core/Grid"; +import Button from "@material-ui/core/Button"; +import SummaryTable from "../components/SummaryTable"; + +import { Redirect } from "react-router-dom"; + +import { IReviewMetadata } from "../models/review"; + +interface IProps { + reviewMeta: () => IReviewMetadata; +} + +interface IState { + toDashboard: boolean; +} + +export default class SummaryPage extends React.Component { + constructor(props: any) { + super(props); + + this.state = { + toDashboard: false, + }; + } + + render() { + return
+ { + this.state.toDashboard ? ( + + ) : undefined + } + + + + Zusammenfassung + + + + + + + +
; + } +}