feat: Implement a vocabulary view

This commit is contained in:
Alexander Polynomdivision 2018-10-11 14:37:21 +02:00
parent 528c291b70
commit a902d9e8f7
7 changed files with 178 additions and 1 deletions

View File

@ -249,3 +249,20 @@ export function setRegisterLoading(state: boolean) {
state, state,
}; };
}; };
export const VOCAB_SET_LOADING = "VOCAB_SET_LOADING";
export function setVocabLoading(state: boolean) {
return {
type: VOCAB_SET_LOADING,
state,
};
};
export const VOCAB_SET_VOCAB = "VOCAB_SET_VOCAB";
export function setVocabVocab(vocab: IVocab[]) {
return {
type: VOCAB_SET_VOCAB,
vocab,
};
};

View File

@ -172,6 +172,16 @@ export default class Drawer extends React.Component<IProps> {
Vokabeln üben Vokabeln üben
</ListItemText> </ListItemText>
</ListItem> </ListItem>
<ListItem
component={Link}
to="/vocab"
onClick={this.closeDrawer}
button>
{/* <ListItemIcon>
<HomeIcon />
</ListItemIcon> */}
<ListItemText primary="Vokabelliste" />
</ListItem>
<ListItem <ListItem
component={Link} component={Link}
to="/levelList" to="/levelList"

View File

@ -13,6 +13,7 @@ import ReviewPage from "../containers/Review";
import SummaryPage from "../containers/SummaryPage"; import SummaryPage from "../containers/SummaryPage";
import WelcomePage from "../pages/intro"; import WelcomePage from "../pages/intro";
import RegisterPage from "../containers/Register"; import RegisterPage from "../containers/Register";
import VocabPage from "../containers/VocabPage";
import Drawer from "../containers/Drawer"; import Drawer from "../containers/Drawer";
@ -83,6 +84,24 @@ export default class Application extends React.Component<IProps> {
}); });
} }
getVocab = (): Promise<IVocab[]> => {
return new Promise((res, rej) => {
fetch(`${BACKEND_URL}/api/user/vocab`, {
headers: new Headers({
"Content-Type": "application/json",
"Token": this.props.user.sessionToken,
}),
}).then(resp => resp.json(), err => rej(err))
.then(data => {
if (data.error === "200") {
res(data.data);
} else {
rej(data);
}
});
});
}
getLevels = (): Promise<ILevel[]> => { getLevels = (): Promise<ILevel[]> => {
return new Promise((res, rej) => { return new Promise((res, rej) => {
fetch(`${BACKEND_URL}/api/levels`, { fetch(`${BACKEND_URL}/api/levels`, {
@ -431,6 +450,13 @@ export default class Application extends React.Component<IProps> {
component={() => { component={() => {
return <SummaryPage /> return <SummaryPage />
}} /> }} />
<AuthRoute
isAuth={this.isAuthenticated}
path="/vocab"
component={() => {
return <VocabPage
getVocab={this.getVocab} />;
}} />
</div> </div>
</div > </div >
</BrowserRouter >; </BrowserRouter >;

View File

@ -0,0 +1,24 @@
import { connect } from "react-redux";
import { setVocabLoading, setVocabVocab } from "../actions";
import { IVocab } from "../models/vocab";
import VocabPage from "../pages/vocab";
const mapStateToProps = state => {
return {
loading: state.vocab.loading,
vocab: state.vocab.vocab,
};
};
const mapDispatchToProps = dispatch => {
return {
setLoading: (state: boolean) => dispatch(setVocabLoading(state)),
setVocab: (vocab: IVocab[]) => dispatch(setVocabVocab(vocab)),
};
};
const VocabPageContainer = connect(mapStateToProps,
mapDispatchToProps)(VocabPage);
export default VocabPageContainer;

View File

@ -8,7 +8,6 @@ import CardActions from '@material-ui/core/CardActions';
import CardContent from '@material-ui/core/CardContent'; import CardContent from '@material-ui/core/CardContent';
import Paper from "@material-ui/core/Paper"; import Paper from "@material-ui/core/Paper";
import Snackbar from "@material-ui/core/Snackbar"; import Snackbar from "@material-ui/core/Snackbar";
import CircularProgress from "@material-ui/core/CircularProgress"; import CircularProgress from "@material-ui/core/CircularProgress";
import { withRouter } from "react-router-dom"; import { withRouter } from "react-router-dom";

View File

@ -0,0 +1,79 @@
import * as React from "react";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import CircularProgress from "@material-ui/core/CircularProgress";
import { IVocab, VocabType } from "../models/vocab";
import VocabularyData from "../components/VocabularyData";
interface IProps {
getVocab: () => Promise<IVocab[]>;
loading: boolean;
vocab: IVocab[];
setLoading: (state: boolean) => void;
setVocab: (vocab: IVocab[]) => void;
}
export default class VocabPage extends React.Component<IProps> {
private uid = 0;
genUID = () => {
return `VOCABPAGE-${this.uid++}`;
}
componentDidMount() {
this.props.setLoading(true);
// TODO: Errorhandling
this.props.getVocab().then(vocab => {
this.props.setVocab(vocab);
this.props.setLoading(false);
});
}
vocabToCard = (voc: IVocab) => {
const vocabTypeToStr = {
[VocabType.NOMEN]: "Nomen",
[VocabType.VERB]: "Verb",
[VocabType.ADJEKTIV]: "Adjektiv",
[VocabType.ADVERB]: "Adverb",
};
return <Paper key={this.genUID()} style={{ marginBottom: 12, padding: 12 }}>
<Typography gutterBottom variant="headline" component="h2">
{`${voc.latin.grundform} (${vocabTypeToStr[voc.type]})`}
</Typography>
<VocabularyData vocab={voc} />
</Paper>;
}
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>
</Grid>
</div>;
}
const { vocab } = this.props;
return <div className="content">
{vocab.map(this.vocabToCard)}
</div>;
}
};

View File

@ -58,6 +58,11 @@ interface IState {
showHelp: boolean; showHelp: boolean;
}; };
vocab: {
loading: boolean;
vocab: IVocab[];
};
register: { register: {
loading: boolean; loading: boolean;
snackMsg: string; snackMsg: string;
@ -126,6 +131,11 @@ const initialState: IState = {
showHelp: false, showHelp: false,
}, },
vocab: {
loading: true,
vocab: [],
},
register: { register: {
loading: false, loading: false,
snackOpen: false, snackOpen: false,
@ -313,6 +323,18 @@ export function LateinicusApp(state: IState = initialState, action: any) {
leaveDialog: action.state, leaveDialog: action.state,
}), }),
}); });
case Actions.VOCAB_SET_LOADING:
return Object.assign({}, state, {
vocab: Object.assign({}, state.vocab, {
loading: action.state,
}),
});
case Actions.VOCAB_SET_VOCAB:
return Object.assign({}, state, {
vocab: Object.assign({}, state.vocab, {
vocab: action.vocab,
}),
});
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