Hikes loading next hike

This commit is contained in:
Berkeley Martinez
2016-02-05 16:40:02 -08:00
parent c4ba7ac46a
commit 1e9c9baedd
4 changed files with 156 additions and 117 deletions

View File

@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
import { spring, Motion } from 'react-motion'; import { spring, Motion } from 'react-motion';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Button, Col, Row } from 'react-bootstrap'; import { Button, Col, Row } from 'react-bootstrap';
import { CompositeDisposable } from 'rx';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { import {
@ -53,6 +54,11 @@ const mapStateToProps = createSelector(
); );
class Question extends React.Component { class Question extends React.Component {
constructor(...args) {
super(...args);
this._subscriptions = new CompositeDisposable();
}
static displayName = 'Questions'; static displayName = 'Questions';
static propTypes = { static propTypes = {
@ -72,6 +78,10 @@ class Question extends React.Component {
shouldShakeQuestion: PropTypes.bool shouldShakeQuestion: PropTypes.bool
}; };
componentWillUnmount() {
this._subscriptions.dispose();
}
handleMouseUp(e, answer, info) { handleMouseUp(e, answer, info) {
e.stopPropagation(); e.stopPropagation();
if (!this.props.isPressed) { if (!this.props.isPressed) {
@ -84,12 +94,15 @@ class Question extends React.Component {
} = this.props; } = this.props;
releaseQuestion(); releaseQuestion();
answerQuestion({ const subscription = answerQuestion({
e, e,
answer, answer,
info, info,
threshold: answerThreshold threshold: answerThreshold
}); })
.subscribe();
this._subscriptions.add(subscription);
} }
handleMouseMove(isPressed, { delta, moveQuestion }) { handleMouseMove(isPressed, { delta, moveQuestion }) {
@ -101,17 +114,21 @@ class Question extends React.Component {
onAnswer(answer, userAnswer, info) { onAnswer(answer, userAnswer, info) {
const { isSignedIn, answerQuestion } = this.props; const { isSignedIn, answerQuestion } = this.props;
const subscriptions = this._subscriptions;
return e => { return e => {
if (e && e.preventDefault) { if (e && e.preventDefault) {
e.preventDefault(); e.preventDefault();
} }
return answerQuestion({ const subscription = answerQuestion({
answer, answer,
userAnswer, userAnswer,
info, info,
isSignedIn isSignedIn
}); })
.subscribe();
subscriptions.add(subscription);
}; };
} }

View File

@ -1,5 +1,5 @@
import { Observable } from 'rx'; import { Observable } from 'rx';
// import { routeActions } from 'react-simple-router'; import { push } from 'react-router-redux';
import types from './types'; import types from './types';
import { getMouse } from './utils'; import { getMouse } from './utils';
@ -7,13 +7,9 @@ import { getMouse } from './utils';
import { makeToast, updatePoints } from '../../../redux/actions'; import { makeToast, updatePoints } from '../../../redux/actions';
import { hikeCompleted, goToNextHike } from './actions'; import { hikeCompleted, goToNextHike } from './actions';
import { postJSON$ } from '../../../../utils/ajax-stream'; import { postJSON$ } from '../../../../utils/ajax-stream';
import { getCurrentHike } from './selectors';
export default () => ({ getState, dispatch }) => next => { function handleAnswer(getState, dispatch, next, action) {
return function answerSaga(action) {
if (types.answerQuestion !== action.type) {
return next(action);
}
const { const {
e, e,
answer, answer,
@ -22,15 +18,15 @@ export default () => ({ getState, dispatch }) => next => {
threshold threshold
} = action.payload; } = action.payload;
const state = getState();
const { id, name, challengeType, tests } = getCurrentHike(state);
const { const {
app: { isSignedIn }, app: { isSignedIn },
hikesApp: { hikesApp: {
currentQuestion, currentQuestion,
currentHike: { id, name, challengeType },
tests = [],
delta = [ 0, 0 ] delta = [ 0, 0 ]
} }
} = getState(); } = state;
let finalAnswer; let finalAnswer;
// drag answer, compute response // drag answer, compute response
@ -64,7 +60,7 @@ export default () => ({ getState, dispatch }) => next => {
} }
return Observable return Observable
.just({ type: types.removeShake }) .just({ type: types.endShake })
.delay(500) .delay(500)
.startWith({ type: types.startShake }) .startWith({ type: types.startShake })
.doOnNext(dispatch); .doOnNext(dispatch);
@ -74,7 +70,8 @@ export default () => ({ getState, dispatch }) => next => {
return Observable return Observable
.just({ type: types.goToNextQuestion }) .just({ type: types.goToNextQuestion })
.delay(300) .delay(300)
.startWith({ type: types.primeNextQuestion }); .startWith({ type: types.primeNextQuestion })
.doOnNext(dispatch);
} }
let updateUser$; let updateUser$;
@ -120,6 +117,28 @@ export default () => ({ getState, dispatch }) => next => {
.catch(error => Observable.just({ .catch(error => Observable.just({
type: 'error', type: 'error',
error error
})); }))
.doOnNext(dispatch);
}
export default () => ({ getState, dispatch }) => next => {
return function answerSaga(action) {
if (action.type === types.answerQuestion) {
return handleAnswer(getState, dispatch, next, action);
}
// let goToNextQuestion hit reducers first
const result = next(action);
if (action.type === types.goToNextHike) {
const { hikesApp: { currentHike } } = getState();
// if no next hike currentHike will equal '' which is falsy
if (currentHike) {
dispatch(push(`/videos/${currentHike}`));
} else {
dispatch(push('/map'));
}
}
return result;
}; };
}; };

View File

@ -1,6 +1,6 @@
import { handleActions } from 'redux-actions'; import { handleActions } from 'redux-actions';
import types from './types'; import types from './types';
import { findNextHike } from './utils'; import { findNextHikeName } from './utils';
const initialState = { const initialState = {
hikes: { hikes: {
@ -79,7 +79,7 @@ export default handleActions(
[types.goToNextHike]: state => ({ [types.goToNextHike]: state => ({
...state, ...state,
currentHike: findNextHike(state.hikes, state.currentHike), currentHike: findNextHikeName(state.hikes, state.currentHike),
showQuestions: false, showQuestions: false,
currentQuestion: 1, currentQuestion: 1,
mouse: [ 0, 0 ] mouse: [ 0, 0 ]

View File

@ -42,21 +42,24 @@ export function getCurrentHike(hikes = {}, dashedName) {
return hikes.entities[dashedName]; return hikes.entities[dashedName];
} }
export function findNextHike({ entities, results }, dashedName) { // findNextHikeName(
// hikes: { results: String[] },
// dashedName: String
// ) => String
export function findNextHikeName({ results }, dashedName) {
if (!dashedName) { if (!dashedName) {
log('find next hike no id provided'); log('find next hike no id provided');
return entities[results[0]]; return results[0];
} }
const currentIndex = _.findIndex( const currentIndex = _.findIndex(
results, results,
({ dashedName: _dashedName }) => _dashedName === dashedName _dashedName => _dashedName === dashedName
); );
if (currentIndex >= results.length) { if (currentIndex >= results.length) {
return ''; return '';
} }
return results[currentIndex + 1];
return entities[results[currentIndex + 1]];
} }