From 8b6bfb681b3487858bb48efbdf83822949b1e1e0 Mon Sep 17 00:00:00 2001 From: Alexander Polynomdivision Date: Mon, 24 Sep 2018 13:36:42 +0200 Subject: [PATCH] fix: Implement more APIs --- backend/src/api/user.ts | 5 +- backend/src/main.ts | 20 ++++++++ frontend/src/actions/index.ts | 8 +++ frontend/src/components/SummaryTable.tsx | 8 +-- frontend/src/components/app.tsx | 62 +++++++++++++----------- frontend/src/containers/Dashboard.ts | 11 ++++- frontend/src/pages/dashboard.tsx | 39 +++++++++++---- frontend/src/pages/summary.tsx | 2 +- frontend/src/reducers/index.ts | 8 +++ 9 files changed, 117 insertions(+), 46 deletions(-) diff --git a/backend/src/api/user.ts b/backend/src/api/user.ts index 7db1c77..47723f7 100644 --- a/backend/src/api/user.ts +++ b/backend/src/api/user.ts @@ -49,7 +49,10 @@ userRouter.get("/lastReview", async (req, res) => { // TODO: Stub res.send({ error: "0", - data: {}, + data: { + correct: 6, + wrong: 2, + }, }); }); userRouter.post("/lastReview", async (req, res) => { diff --git a/backend/src/main.ts b/backend/src/main.ts index 76dd1f9..332cdd8 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -44,6 +44,26 @@ app.use((req, res, next) => { app.use("/api/level", LevelRouter); app.use("/api/class", ClassRouter); 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) => { res.send({ error: "0", diff --git a/frontend/src/actions/index.ts b/frontend/src/actions/index.ts index b8a6309..ae1cfb7 100644 --- a/frontend/src/actions/index.ts +++ b/frontend/src/actions/index.ts @@ -184,3 +184,11 @@ export function setDidLogin(state: boolean) { state, }; }; + +export const DASHBOARD_SET_LR_LOADING = "DASHBOARD_SET_LR_LOADING"; +export function setDashboardLRLoading(state: boolean) { + return { + type: DASHBOARD_SET_LR_LOADING, + state, + }; +}; diff --git a/frontend/src/components/SummaryTable.tsx b/frontend/src/components/SummaryTable.tsx index ccf6f76..268690b 100644 --- a/frontend/src/components/SummaryTable.tsx +++ b/frontend/src/components/SummaryTable.tsx @@ -9,12 +9,12 @@ import TableCell from "@material-ui/core/TableCell"; import { IReviewMetadata } from "../models/review"; interface IProps { - reviewMeta: () => IReviewMetadata; + reviewMeta: IReviewMetadata; } export default class SummaryTable extends React.Component { render() { - const meta = this.props.reviewMeta(); + const { reviewMeta } = this.props; return @@ -26,11 +26,11 @@ export default class SummaryTable extends React.Component { Korrekt - {meta.correct} + {reviewMeta.correct} Falsch - {meta.wrong} + {reviewMeta.wrong}
; diff --git a/frontend/src/components/app.tsx b/frontend/src/components/app.tsx index a74f739..53937c4 100644 --- a/frontend/src/components/app.tsx +++ b/frontend/src/components/app.tsx @@ -45,45 +45,49 @@ export default class Application extends React.Component { } } - getLevels(): Promise { - console.log("STUB: Application::getLevels"); - + getLevels = (): Promise => { return new Promise((res, rej) => { - // TODO: Actually fetch them from somewhere - setTimeout(() => { - 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(levels); - - }, 2000); + fetch(`${BACKEND_URL}/api/levels`, { + headers: new Headers({ + "Content-Type": "application/json", + "Token": this.props.user.sessionToken, + }), + }).then(resp => resp.json(), err => rej(err)) + .then(data => { + if (data.error === "0") { + res(data.data.levels); + } else { + rej(data); + } + }); }); } - getLastReview = (): IReviewMetadata => { - console.log("STUB: Application::getLastReview"); - - // TODO: Actually fetch this - // TODO: Stub - return {} as IReviewMetadata; + getLastReview = (): Promise => { + return new Promise((res, rej) => { + fetch(`${BACKEND_URL}/api/user/lastReview`, { + headers: new Headers({ + "Content-Type": "application/json", + "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) => { console.log("STUB: Application::setLastReview"); // TODO: Send this to the server - this.setState({ - lastReview: meta, - }); + /* this.setState({ + * lastReview: meta, + * }); */ } getReviewQueue = (): Promise => { diff --git a/frontend/src/containers/Dashboard.ts b/frontend/src/containers/Dashboard.ts index 68d7d52..ab61f78 100644 --- a/frontend/src/containers/Dashboard.ts +++ b/frontend/src/containers/Dashboard.ts @@ -1,8 +1,13 @@ 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 { ILearner } from "../models/learner"; +import { IReviewMetadata } from "../models/review"; import DashboardPage from "../pages/dashboard"; @@ -12,6 +17,8 @@ const mapStateToProps = state => { loadingNextLevel: state.dashboard.loadingNL, loadingTopTen: state.dashboard.loadingTT, topTen: state.topTen, + loadingLastReview: state.dashboard.loadingLR, + lastReview: state.lastReview, }; }; const mapDispatchToProps = dispatch => { @@ -20,6 +27,8 @@ const mapDispatchToProps = dispatch => { setNextLevel: (level: ILevel) => dispatch(setNextLevel(level)), setTopTen: (topTen: ILearner[]) => dispatch(setTopTen(topTen)), setLoadingTT: (state: boolean) => dispatch(setDashboardTTLoading(state)), + setLastReview: (review: IReviewMetadata) => dispatch(setLastReview(review)), + setLoadingLR: (state: boolean) => dispatch(setDashboardLRLoading(state)), } }; diff --git a/frontend/src/pages/dashboard.tsx b/frontend/src/pages/dashboard.tsx index d0315d9..90c0f04 100644 --- a/frontend/src/pages/dashboard.tsx +++ b/frontend/src/pages/dashboard.tsx @@ -17,7 +17,7 @@ import { IReviewMetadata } from "../models/review"; interface IProps { getNextLevel: () => Promise; - getLastReview: () => IReviewMetadata; + getLastReview: () => Promise; getTopTen: () => Promise; nextLevel: ILevel; @@ -28,6 +28,10 @@ interface IProps { loadingTopTen: boolean; setLoadingTT: (state: boolean) => void; setTopTen: (topten: TopTen[]) => void; + lastReview: IReviewMetadata; + loadingLastReview: boolean; + setLoadingLR: (state: boolean) => void; + setLastReview: (review: IReviewMetadata) => void; } export default class Dashboard extends React.Component { @@ -47,6 +51,13 @@ export default class Dashboard extends React.Component { }, err => { 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() { @@ -97,16 +108,24 @@ export default class Dashboard extends React.Component { - - Letzte Wiederholung - - + { + this.props.loadingLastReview ? ( + + ) : ( +
+ + Letzte Wiederholung + + - + +
+ ) + }
diff --git a/frontend/src/pages/summary.tsx b/frontend/src/pages/summary.tsx index 3d6d1cc..b1d834c 100644 --- a/frontend/src/pages/summary.tsx +++ b/frontend/src/pages/summary.tsx @@ -41,7 +41,7 @@ const SummaryPageWithRouter = withRouter( Zusammenfassung - this.props.reviewMeta} /> + diff --git a/frontend/src/reducers/index.ts b/frontend/src/reducers/index.ts index 74cdd0c..4be3c03 100644 --- a/frontend/src/reducers/index.ts +++ b/frontend/src/reducers/index.ts @@ -39,6 +39,7 @@ interface IState { dashboard: { loadingNL: boolean; loadingTT: boolean; + loadingLR: boolean; }; review: { @@ -97,6 +98,7 @@ const initialState: IState = { dashboard: { loadingNL: true, loadingTT: true, + loadingLR: true, }, review: { @@ -243,6 +245,12 @@ export function LateinicusApp(state: IState = initialState, action: any) { return Object.assign({}, state, { didLogin: state, }); + case Actions.DASHBOARD_SET_LR_LOADING: + return Object.assign({}, state, { + dashboard: Object.assign({}, state.dashboard, { + loadingLR: action.state, + }), + }); default: // Ignore the initialization call to the reducer. By that we can // catch all actions that are not implemented