fix: Implement more APIs

This commit is contained in:
Alexander Polynomdivision 2018-09-24 13:36:42 +02:00
parent 11bbdc627f
commit 8b6bfb681b
9 changed files with 117 additions and 46 deletions

View File

@ -49,7 +49,10 @@ userRouter.get("/lastReview", async (req, res) => {
// TODO: Stub // TODO: Stub
res.send({ res.send({
error: "0", error: "0",
data: {}, data: {
correct: 6,
wrong: 2,
},
}); });
}); });
userRouter.post("/lastReview", async (req, res) => { userRouter.post("/lastReview", async (req, res) => {

View File

@ -44,6 +44,26 @@ app.use((req, res, next) => {
app.use("/api/level", LevelRouter); app.use("/api/level", LevelRouter);
app.use("/api/class", ClassRouter); app.use("/api/class", ClassRouter);
app.use("/api/user", UserRouter); app.use("/api/user", UserRouter);
app.get("/api/levels", async (req, res) => {
const levels = [{
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,
}];
res.send({
error: "0",
data: {
levels,
},
});
});
app.get("/api/health", (req, res) => { app.get("/api/health", (req, res) => {
res.send({ res.send({
error: "0", error: "0",

View File

@ -184,3 +184,11 @@ export function setDidLogin(state: boolean) {
state, state,
}; };
}; };
export const DASHBOARD_SET_LR_LOADING = "DASHBOARD_SET_LR_LOADING";
export function setDashboardLRLoading(state: boolean) {
return {
type: DASHBOARD_SET_LR_LOADING,
state,
};
};

View File

@ -9,12 +9,12 @@ 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(); const { reviewMeta } = this.props;
return <Table> return <Table>
<TableHead> <TableHead>
@ -26,11 +26,11 @@ export default class SummaryTable extends React.Component<IProps> {
<TableBody> <TableBody>
<TableRow> <TableRow>
<TableCell>Korrekt</TableCell> <TableCell>Korrekt</TableCell>
<TableCell numeric>{meta.correct}</TableCell> <TableCell numeric>{reviewMeta.correct}</TableCell>
</TableRow> </TableRow>
<TableRow> <TableRow>
<TableCell>Falsch</TableCell> <TableCell>Falsch</TableCell>
<TableCell numeric>{meta.wrong}</TableCell> <TableCell numeric>{reviewMeta.wrong}</TableCell>
</TableRow> </TableRow>
</TableBody> </TableBody>
</Table>; </Table>;

View File

@ -45,45 +45,49 @@ export default class Application extends React.Component<IProps> {
} }
} }
getLevels(): Promise<ILevel[]> { getLevels = (): Promise<ILevel[]> => {
console.log("STUB: Application::getLevels");
return new Promise((res, rej) => { return new Promise((res, rej) => {
// TODO: Actually fetch them from somewhere fetch(`${BACKEND_URL}/api/levels`, {
setTimeout(() => { headers: new Headers({
const levels = [{ "Content-Type": "application/json",
name: "Der Bauer auf dem Feld", "Token": this.props.user.sessionToken,
desc: "So fängt alles an: Du bist ein einfacher Bauer und musst dich die Karriereleiter mit deinen freshen Latein-Skills hinaufarbeiten", }),
level: 1, }).then(resp => resp.json(), err => rej(err))
done: true, .then(data => {
}, { if (data.error === "0") {
name: "???", res(data.data.levels);
desc: "Warum schreibe ich überhaupt was?dsd dddddddddddddddddddddd", } else {
level: 2, rej(data);
done: false, }
}]; });
res(levels);
}, 2000);
}); });
} }
getLastReview = (): IReviewMetadata => { getLastReview = (): Promise<IReviewMetadata> => {
console.log("STUB: Application::getLastReview"); return new Promise((res, rej) => {
fetch(`${BACKEND_URL}/api/user/lastReview`, {
// TODO: Actually fetch this headers: new Headers({
// TODO: Stub "Content-Type": "application/json",
return {} as IReviewMetadata; "Token": this.props.user.sessionToken,
}),
}).then(resp => resp.json(), err => rej(err))
.then(data => {
if (data.error === "0") {
res(data.data);
} else {
rej(data);
}
});
});
} }
setLastReview = (meta: IReviewMetadata) => { setLastReview = (meta: IReviewMetadata) => {
console.log("STUB: Application::setLastReview"); console.log("STUB: Application::setLastReview");
// TODO: Send this to the server // TODO: Send this to the server
this.setState({ /* this.setState({
lastReview: meta, * lastReview: meta,
}); * }); */
} }
getReviewQueue = (): Promise<IVocab[]> => { getReviewQueue = (): Promise<IVocab[]> => {

View File

@ -1,8 +1,13 @@
import { connect } from "react-redux"; import { connect } from "react-redux";
import { setNextLevel, setDashboardNLLoading, setTopTen, setDashboardTTLoading } from "../actions"; import {
setNextLevel, setDashboardNLLoading, setTopTen, setDashboardTTLoading,
setDashboardLRLoading, setLastReview,
} from "../actions";
import { ILevel } from "../models/level"; import { ILevel } from "../models/level";
import { ILearner } from "../models/learner";
import { IReviewMetadata } from "../models/review";
import DashboardPage from "../pages/dashboard"; import DashboardPage from "../pages/dashboard";
@ -12,6 +17,8 @@ const mapStateToProps = state => {
loadingNextLevel: state.dashboard.loadingNL, loadingNextLevel: state.dashboard.loadingNL,
loadingTopTen: state.dashboard.loadingTT, loadingTopTen: state.dashboard.loadingTT,
topTen: state.topTen, topTen: state.topTen,
loadingLastReview: state.dashboard.loadingLR,
lastReview: state.lastReview,
}; };
}; };
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
@ -20,6 +27,8 @@ const mapDispatchToProps = dispatch => {
setNextLevel: (level: ILevel) => dispatch(setNextLevel(level)), setNextLevel: (level: ILevel) => dispatch(setNextLevel(level)),
setTopTen: (topTen: ILearner[]) => dispatch(setTopTen(topTen)), setTopTen: (topTen: ILearner[]) => dispatch(setTopTen(topTen)),
setLoadingTT: (state: boolean) => dispatch(setDashboardTTLoading(state)), setLoadingTT: (state: boolean) => dispatch(setDashboardTTLoading(state)),
setLastReview: (review: IReviewMetadata) => dispatch(setLastReview(review)),
setLoadingLR: (state: boolean) => dispatch(setDashboardLRLoading(state)),
} }
}; };

View File

@ -17,7 +17,7 @@ import { IReviewMetadata } from "../models/review";
interface IProps { interface IProps {
getNextLevel: () => Promise<ILevel>; getNextLevel: () => Promise<ILevel>;
getLastReview: () => IReviewMetadata; getLastReview: () => Promise<IReviewMetadata>;
getTopTen: () => Promise<ILearner[]>; getTopTen: () => Promise<ILearner[]>;
nextLevel: ILevel; nextLevel: ILevel;
@ -28,6 +28,10 @@ interface IProps {
loadingTopTen: boolean; loadingTopTen: boolean;
setLoadingTT: (state: boolean) => void; setLoadingTT: (state: boolean) => void;
setTopTen: (topten: TopTen[]) => void; setTopTen: (topten: TopTen[]) => void;
lastReview: IReviewMetadata;
loadingLastReview: boolean;
setLoadingLR: (state: boolean) => void;
setLastReview: (review: IReviewMetadata) => void;
} }
export default class Dashboard extends React.Component<IProps> { export default class Dashboard extends React.Component<IProps> {
@ -47,6 +51,13 @@ export default class Dashboard extends React.Component<IProps> {
}, err => { }, err => {
console.log("Failed to fetch Top Ten"); console.log("Failed to fetch Top Ten");
}); });
this.props.getLastReview().then(res => {
this.props.setLoadingLR(false);
this.props.setLastReview(res);
}, err => {
console.log("Failed to fetch Last Review");
});
} }
render() { render() {
@ -97,16 +108,24 @@ export default class Dashboard extends React.Component<IProps> {
</Grid> </Grid>
<Grid item lg={4}> <Grid item lg={4}>
<Paper className="paper"> <Paper className="paper">
<Typography variant="title"> {
Letzte Wiederholung this.props.loadingLastReview ? (
</Typography> <CircularProgress />
<SummaryTable reviewMeta={this.props.getLastReview} /> ) : (
<div>
<Typography variant="title">
Letzte Wiederholung
</Typography>
<SummaryTable reviewMeta={this.props.lastReview} />
<Button <Button
component={Link} component={Link}
to="/review/queue"> to="/review/queue">
Vokabeln üben Vokabeln üben
</Button> </Button>
</div>
)
}
</Paper> </Paper>
</Grid> </Grid>
</Grid> </Grid>

View File

@ -41,7 +41,7 @@ const SummaryPageWithRouter = withRouter(
<Paper className="paper"> <Paper className="paper">
<Typography variant="title">Zusammenfassung</Typography> <Typography variant="title">Zusammenfassung</Typography>
<Grid container direction="column"> <Grid container direction="column">
<SummaryTable reviewMeta={() => this.props.reviewMeta} /> <SummaryTable reviewMeta={this.props.reviewMeta} />
<Button onClick={this.toDashboard}> <Button onClick={this.toDashboard}>
Zum Dashboard Zum Dashboard
</Button> </Button>

View File

@ -39,6 +39,7 @@ interface IState {
dashboard: { dashboard: {
loadingNL: boolean; loadingNL: boolean;
loadingTT: boolean; loadingTT: boolean;
loadingLR: boolean;
}; };
review: { review: {
@ -97,6 +98,7 @@ const initialState: IState = {
dashboard: { dashboard: {
loadingNL: true, loadingNL: true,
loadingTT: true, loadingTT: true,
loadingLR: true,
}, },
review: { review: {
@ -243,6 +245,12 @@ export function LateinicusApp(state: IState = initialState, action: any) {
return Object.assign({}, state, { return Object.assign({}, state, {
didLogin: state, didLogin: state,
}); });
case Actions.DASHBOARD_SET_LR_LOADING:
return Object.assign({}, state, {
dashboard: Object.assign({}, state.dashboard, {
loadingLR: action.state,
}),
});
default: default:
// Ignore the initialization call to the reducer. By that we can // Ignore the initialization call to the reducer. By that we can
// catch all actions that are not implemented // catch all actions that are not implemented