| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- import { h, render, Component } from 'preact'; // eslint-disable-line no-unused-vars
- // content and config:
- import content from '../content/module.json';
- import config from '../config';
- // services and helper:
- import api from '../utilities/api';
- import { fixedDigits } from '../utilities/formatter';
- // screens and items:
- import TitleScreen from './TitleScreen.jsx';
- import FinalScreen from './FinalScreen.jsx';
- import QuestionScreen from './QuestionScreen.jsx';
- /**
- * titlescreen, questionscreen (repeat), finalscreen
- */
- export default class App extends Component {
- // construct and initialize functions
- constructor (props) {
- super(props);
- // for example: (1400 - 200) / 3 -> 400 points per section
- const diff = (config.numberOfPoints.first - config.numberOfPoints.last) / 3;
- // for example: 1400, 1000, 600, 200
- this.numberOfPoints = [
- parseInt(config.numberOfPoints.first, 10),
- parseInt(config.numberOfPoints.first - diff, 10),
- parseInt(config.numberOfPoints.last + diff, 10),
- parseInt(config.numberOfPoints.last, 10)
- ];
- this.state = {
- route: 'titlescreen', // current screen
- isFetching: false, // currently performing XHR?
- userId: null, // current user id for posting
- token: null, // current access token
- mode: 'intro', // current mode: init || intro || question || score
- currentQuestion: 0, // current question number
- currentAnswerIndex: null, // index in question pair of the currently set answer
- currentAnswerCorrect: false, // is the currently set question the correct one?
- currentNumberOfPoints: this.numberOfPoints[0], // current number of points
- nextNumberOfPoints: this.numberOfPoints[1], // next number of points
- currentAmount: config.highlightedAmount, // curent amount of points to be highlighted
- voteRatios: null // get votes from other users
- };
- if (window.location.hash) this.state.route = window.location.hash.replace('#', '');
- // context binding
- this.navigate = this.navigate.bind(this);
- this.toNextQuestion = this.toNextQuestion.bind(this);
- this.setAnswer = this.setAnswer.bind(this);
- this.getUserVotes = this.getUserVotes.bind(this);
- this.reset = this.reset.bind(this);
- this.setup = this.setup.bind(this);
- this.endUserSession = this.endUserSession.bind(this);
- }
- // to next question
- toNextQuestion () {
- // intro screen, introduce bubbles :P
- if (this.state.mode === 'intro') {
- this.setState({
- // currentQuestion: null,
- mode: 'init',
- route: 'question'
- });
- } else if (this.state.currentQuestion === 0 && this.state.mode === 'init') {
- // is first question?
- this.setState({
- currentAmount: 0,
- mode: 'question',
- route: 'question'
- });
- } else if (this.state.currentQuestion === 3 && this.state.mode === 'score') {
- // is last question? go to final screen
- this.setState({
- route: 'finalscreen',
- mode: 'intro',
- currentNumberOfPoints: this.numberOfPoints[0],
- currentAmount: config.highlightedAmount,
- currentQuestion: 0,
- currentAnswerIndex: null,
- currentAnswerCorrect: false,
- nextNumberOfPoints: this.numberOfPoints[1],
- voteRatios: null
- });
- } else if (this.state.voteRatios && this.state.mode === 'question') {
- // go to score screen
- this.setState({
- route: 'question',
- mode: 'score'
- });
- } else {
- // go to next question
- this.setState({
- route: 'question',
- mode: 'question',
- currentQuestion: this.state.currentQuestion + 1,
- currentAnswerIndex: null,
- currentNumberOfPoints: this.numberOfPoints[this.state.currentQuestion + 1],
- nextNumberOfPoints: this.numberOfPoints[this.state.currentQuestion + 2],
- currentAmount: 0,
- voteRatios: null
- });
- }
- }
- // set and check answer
- setAnswer (index, isCorrect) {
- if (this.state.currentAnswerIndex === null) {
- // check answer
- this.setState({
- currentAnswerIndex: index,
- currentAnswerCorrect: isCorrect,
- mode: 'question'
- });
- // submit answer
- if (!this.props.isOffline) {
- // only send answer for current question
- const payload = { userId: this.state.userId };
- payload[`answerQ${this.state.currentQuestion + 1}`] = this.state.currentAnswerIndex + 1;
- api.post(config.api.create, payload, this.state.token).then(() => this.getUserVotes());
- } else {
- this.getUserVotes();
- }
- }
- }
- // get user votes from api
- getUserVotes () {
- if (!this.props.isOffline) {
- api.get(config.api.proportions, { question: this.state.currentQuestion + 1 }).then(
- json => this.setState({ voteRatios: [ json.anteile.richtig, json.anteile.falsch ] })
- );
- } else {
- this.setState({ voteRatios: [] });
- }
- }
- // initial setup
- setup () {
- if (!this.props.isOffline) {
- this.setState({ isFetching: true });
- api.getToken().then(accessToken => {
- this.setState({ token: accessToken });
- // create user
- api.createUser(accessToken)
- .then(user => {
- this.setState({ userId: user.userId, isFetching: false });
- this.jumpTo();
- });
- });
- }
- }
- // shortcut: jump to specific screen using `#{something}`
- jumpTo () {
- if (window.location.hash) {
- const hashInfo = window.location.hash.replace('#', '').split('_');
- this.setState({
- route: 'question',
- mode: hashInfo[0],
- currentAmount: 0,
- currentAnswerCorrect: null,
- currentAnswerIndex: null,
- currentNumberOfPoints: 1000,
- currentQuestion: parseInt(hashInfo[1], 10),
- nextNumberOfPoints: 200,
- voteRatios: null
- });
- }
- }
- // set navigation state
- navigate (route) {
- this.setState({ route });
- }
- // finish user session
- endUserSession () {
- api.endSession(this.state.userId, this.state.token);
- }
- // reset everything to restart the module
- reset () {
- this.setState({ route: 'titlescreen' });
- this.setup();
- }
- // LIFECYLCE
- componentWillMount () {
- this.setup();
- }
- // RENDER
- render () {
- let outputContent;
- // get header content
- const total = fixedDigits(config.numberQuestions, 2);
- const index = this.state.currentQuestion + 1; // 0-indexed
- const headerState = `${fixedDigits(index, 2)}/${total}`;
- switch (this.state.route) {
- case 'question':
- outputContent = <QuestionScreen
- {...content}
- isOffline={this.props.isOffline}
- route={this.state.route}
- mode={this.state.mode}
- headerState={headerState}
- currentQuestion={this.state.currentQuestion}
- currentAnswerIndex={this.state.currentAnswerIndex}
- currentAnswerCorrect={this.state.currentAnswerCorrect}
- currentNumberOfPoints={this.state.currentNumberOfPoints}
- currentAmount={this.state.currentAmount}
- nextNumberOfPoints={this.state.nextNumberOfPoints}
- toNextQuestion={this.toNextQuestion}
- voteRatios={this.state.voteRatios}
- setAnswer={this.setAnswer} />;
- break;
- case 'finalscreen':
- outputContent = <FinalScreen
- {...content}
- navigate={this.navigate}
- isFetching={this.state.isFetching} />;
- break;
- case 'titlescreen':
- default:
- outputContent = <TitleScreen
- {...content}
- navigate={this.navigate}
- navigateTo='question'
- isFetching={this.state.isFetching} />;
- break;
- }
- return outputContent;
- }
- }
|