feat: Implement setting the last review

This commit is contained in:
Alexander Polynomdivision 2018-09-15 17:32:20 +02:00
parent 18c13c06cd
commit 2c41347cea
5 changed files with 66 additions and 27 deletions

View File

@ -9,11 +9,13 @@ import TableCell from "@material-ui/core/TableCell";
import { IReviewMetadata } from "../models/review"; import { IReviewMetadata } from "../models/review";
interface IProps { interface IProps {
reviewMeta: IReviewMetadata; reviewMeta: () => IReviewMetadata;
} }
export default class SummaryTable extends React.Component<IProps> { export default class SummaryTable extends React.Component<IProps> {
render() { render() {
const meta = this.props.reviewMeta();
return <Table> return <Table>
<TableHead> <TableHead>
<TableRow> <TableRow>
@ -24,15 +26,11 @@ export default class SummaryTable extends React.Component<IProps> {
<TableBody> <TableBody>
<TableRow> <TableRow>
<TableCell>Korrekt</TableCell> <TableCell>Korrekt</TableCell>
<TableCell numeric>{this.props.reviewMeta.correct}</TableCell> <TableCell numeric>{meta.correct}</TableCell>
</TableRow>
<TableRow>
<TableCell>Fast richtig</TableCell>
<TableCell numeric>{this.props.reviewMeta.nearly}</TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell>Falsch</TableCell> <TableCell>Falsch</TableCell>
<TableCell numeric>{this.props.reviewMeta.wrong}</TableCell> <TableCell numeric>{meta.wrong}</TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>
</Table>; </Table>;

View File

@ -39,6 +39,8 @@ import { IReviewMetadata, ReviewType } from "../models/review";
interface IState { interface IState {
loggedIn: boolean; loggedIn: boolean;
lastReview: IReviewMetadata;
drawerOpen: boolean; drawerOpen: boolean;
showDrawerButton: boolean; showDrawerButton: boolean;
} }
@ -54,8 +56,15 @@ export default class Application extends React.Component<{}, IState> {
// TODO // TODO
const loggedIn = authKey !== null; const loggedIn = authKey !== null;
// TODO: Fetch the last review
this.state = { this.state = {
loggedIn, loggedIn,
lastReview: {
correct: 0,
wrong: 0,
},
drawerOpen: false, drawerOpen: false,
showDrawerButton: true, showDrawerButton: true,
}; };
@ -82,15 +91,18 @@ export default class Application extends React.Component<{}, IState> {
return levels; return levels;
} }
getLastReview(): IReviewMetadata { getLastReview = (): IReviewMetadata => {
console.log("STUB: Application::getLastReview"); console.log("STUB: Application::getLastReview");
// TODO: Actually fetch this // TODO: Actually fetch this
return { return this.state.lastReview;
correct: 5, }
nearly: 5,
wrong: 5, setLastReview = (meta: IReviewMetadata) => {
}; // TODO: Send this to the server
this.setState({
lastReview: meta,
});
} }
getReviewQueue = (): IVocab[] => { getReviewQueue = (): IVocab[] => {
@ -360,7 +372,7 @@ export default class Application extends React.Component<{}, IState> {
component={() => { component={() => {
return <Dashboard return <Dashboard
nextLevel={this.getNextLevel} nextLevel={this.getNextLevel}
lastReview={this.getLastReview} getLastReview={this.getLastReview}
getTopTen={this.getTopTenLearners} /> getTopTen={this.getTopTenLearners} />
}} /> }} />
<AuthRoute <AuthRoute
@ -382,7 +394,8 @@ export default class Application extends React.Component<{}, IState> {
return <LevelPage return <LevelPage
id={match.params.id} id={match.params.id}
levelVocab={this.getLevelVocab} levelVocab={this.getLevelVocab}
drawerButtonState={this.drawerButtonState} />; drawerButtonState={this.drawerButtonState}
setLastReview={this.setLastReview} />;
} else { } else {
return <Redirect to="/login" />; return <Redirect to="/login" />;
} }
@ -395,7 +408,8 @@ export default class Application extends React.Component<{}, IState> {
reviewType={ReviewType.LEVEL} reviewType={ReviewType.LEVEL}
levelId={match.params.id} levelId={match.params.id}
vocabByLevel={this.getLevelVocab} vocabByLevel={this.getLevelVocab}
drawerButtonState={this.drawerButtonState} />; drawerButtonState={this.drawerButtonState}
setLastReview={this.setLastReview} />;
} else { } else {
return <Redirect to="/login" />; return <Redirect to="/login" />;
} }
@ -407,7 +421,8 @@ export default class Application extends React.Component<{}, IState> {
return <ReviewPage return <ReviewPage
reviewType={ReviewType.QUEUE} reviewType={ReviewType.QUEUE}
vocabByQueue={this.getReviewQueue} vocabByQueue={this.getReviewQueue}
drawerButtonState={this.drawerButtonState} />; drawerButtonState={this.drawerButtonState}
setLastReview={this.setLastReview} />;
}} /> }} />
<AuthRoute <AuthRoute
isAuth={this.isAuthenticated} isAuth={this.isAuthenticated}

View File

@ -3,8 +3,6 @@ export interface IReviewMetadata {
correct: number; correct: number;
// Number of wrong answers // Number of wrong answers
wrong: number; wrong: number;
// Number of nearly correct answers
nearly: number;
}; };
export enum ReviewType { export enum ReviewType {

View File

@ -16,7 +16,7 @@ import { IReviewMetadata } from "../models/review";
interface IProps { interface IProps {
nextLevel: () => ILevel; nextLevel: () => ILevel;
lastReview: () => IReviewMetadata; getLastReview: () => IReviewMetadata;
getTopTen: () => ILearner[]; getTopTen: () => ILearner[];
} }
@ -59,7 +59,7 @@ export default class Dashboard extends React.Component<IProps> {
<Typography variant="title"> <Typography variant="title">
Letzte Wiederholung Letzte Wiederholung
</Typography> </Typography>
<SummaryTable reviewMeta={this.props.lastReview()} /> <SummaryTable reviewMeta={this.props.getLastReview} />
</Paper> </Paper>
</Grid> </Grid>
</Grid> </Grid>

View File

@ -11,7 +11,7 @@ import Popover from "@material-ui/core/Popover";
import { Redirect } from "react-router-dom"; import { Redirect } from "react-router-dom";
import { IVocab, IReviewCard, vocabToReviewCard, reviewQTypeToStr } from "../models/vocab"; import { IVocab, IReviewCard, vocabToReviewCard, reviewQTypeToStr } from "../models/vocab";
import { ReviewType } from "../models/review"; import { ReviewType, IReviewMetadata } from "../models/review";
import { levW } from "../algorithms/levenshtein"; import { levW } from "../algorithms/levenshtein";
import { LEVENSHTEIN_MAX_DISTANCE } from "../config"; import { LEVENSHTEIN_MAX_DISTANCE } from "../config";
@ -23,6 +23,8 @@ interface IProps {
vocabByLevel?: (level: number) => IVocab[]; vocabByLevel?: (level: number) => IVocab[];
vocabByQueue?: () => IVocab[]; vocabByQueue?: () => IVocab[];
setLastReview: (meta: IReviewMetadata) => void;
reviewType: ReviewType; reviewType: ReviewType;
drawerButtonState: (state: boolean) => void; drawerButtonState: (state: boolean) => void;
@ -32,6 +34,8 @@ interface IState {
input: string; input: string;
current: IReviewCard; current: IReviewCard;
metadata: IReviewMetadata;
toSummary: boolean; toSummary: boolean;
popoverOpen: boolean; popoverOpen: boolean;
@ -41,7 +45,7 @@ interface IState {
export default class ReviewPage extends React.Component<IProps, IState> { export default class ReviewPage extends React.Component<IProps, IState> {
private vocab: IVocab[] = []; private vocab: IVocab[] = [];
private reviewQueue: Queue<IReviewCard> = new Queue(); private reviewQueue: Queue<IReviewCard> = undefined;
// Used for positioning the popover // Used for positioning the popover
private buttonRef: HTMLButtonElement; private buttonRef: HTMLButtonElement;
@ -73,13 +77,20 @@ export default class ReviewPage extends React.Component<IProps, IState> {
} }
// Turn the vocabulary into IReviewCards and queue them // Turn the vocabulary into IReviewCards and queue them
if (!this.reviewQueue) {
this.reviewQueue = new Queue();
this.vocab.forEach((vocab) => { this.vocab.forEach((vocab) => {
vocabToReviewCard(vocab).forEach(this.reviewQueue.enqueue); vocabToReviewCard(vocab).forEach(this.reviewQueue.enqueue);
}); });
}
this.state = { this.state = {
input: "", input: "",
current: this.reviewQueue.dequeue(), current: this.reviewQueue.dequeue(),
metadata: {
correct: 0,
wrong: 0,
},
toSummary: false, toSummary: false,
@ -89,6 +100,15 @@ export default class ReviewPage extends React.Component<IProps, IState> {
}; };
} }
increaseMeta = (correct: number, wrong: number): IReviewMetadata => {
const { metadata } = this.state;
return {
wrong: metadata.wrong + wrong,
correct: metadata.correct + correct,
};
}
vocabFromId = (id: number) => { vocabFromId = (id: number) => {
return this.vocab.find((el) => el.id === this.state.current.id); return this.vocab.find((el) => el.id === this.state.current.id);
} }
@ -104,20 +124,27 @@ export default class ReviewPage extends React.Component<IProps, IState> {
// Find the lowest distance // Find the lowest distance
const minDist = Math.min(...dists); const minDist = Math.min(...dists);
console.log(this.reviewQueue.size());
// Check if the user's answer was correct // Check if the user's answer was correct
if (minDist === 0) { if (minDist === 0) {
// TODO: Show it's correct? // TODO: Show it's correct?
// Show the next vocab word // Show the next vocab word
if (this.reviewQueue.size() === 0) { if (this.reviewQueue.size() === 0) {
// TODO: Set some data that the summary screen will show // Go to the summary screen
this.setState({ this.setState({
toSummary: true, toSummary: true,
}, () => {
// Update the "Last Review" data
this.props.setLastReview(this.state.metadata);
}); });
} else { } else {
// Increase the vocab // Increase the vocab
this.setState({ this.setState({
current: this.reviewQueue.dequeue(), current: this.reviewQueue.dequeue(),
input: "", input: "",
// Add one correct answer
metadata: this.increaseMeta(1, 0),
}); });
} }
} else if (minDist <= LEVENSHTEIN_MAX_DISTANCE) { } else if (minDist <= LEVENSHTEIN_MAX_DISTANCE) {
@ -140,6 +167,7 @@ export default class ReviewPage extends React.Component<IProps, IState> {
popoverColor: "red", popoverColor: "red",
// TODO: Or maybe don't reset the text // TODO: Or maybe don't reset the text
input: "", input: "",
metadata: this.increaseMeta(0, 1),
}); });
} }