import _ from 'lodash'; import { Observable } from 'rx'; import debugFactory from 'debug'; import dedent from 'dedent'; import { homeLocation } from '../../../config/env'; import nonprofits from '../utils/commit.json'; import { commitGoals, completeCommitment$ } from '../utils/commit'; import { unDasherize } from '../utils'; import { observeQuery, saveInstance } from '../utils/rx'; import { ifNoUserRedirectTo } from '../utils/middleware'; const sendNonUserToSignIn = ifNoUserRedirectTo( `${homeLocation}/signin`, 'You must be signed in to commit to a nonprofit.', 'info' ); const sendNonUserToCommit = ifNoUserRedirectTo( '/commit', 'You must be signed in to update commit', 'info' ); const debug = debugFactory('fcc:commit'); function findNonprofit(name) { let nonprofit; if (name) { nonprofit = _.find(nonprofits, (nonprofit) => { return name === nonprofit.name; }); } nonprofit = nonprofit || nonprofits[ _.random(0, nonprofits.length - 1) ]; return nonprofit; } export default function commit(app) { const router = app.loopback.Router(); const api = app.loopback.Router(); const { Pledge } = app.models; router.get( '/commit', commitToNonprofit ); router.get( '/commit/pledge', sendNonUserToSignIn, pledge ); router.get( '/commit/directory', renderDirectory ); api.post( '/commit/stop-commitment', sendNonUserToCommit, stopCommit ); api.post( '/commit/complete-goal', sendNonUserToCommit, completeCommitment ); app.use(api); app.use(router); function commitToNonprofit(req, res, next) { const { user } = req; let nonprofitName = unDasherize(req.query.nonprofit); debug('looking for nonprofit', nonprofitName); const nonprofit = findNonprofit(nonprofitName); Observable.just(user) .flatMap(user => { if (user) { debug('getting user pledge'); return observeQuery(user, 'pledge'); } return Observable.just(); }) .subscribe( pledge => { if (pledge) { debug('found previous pledge'); req.flash( 'info', dedent` Looks like you already have a pledge to ${pledge.displayName}. Clicking "Commit" here will replace your old commitment. If you do change your commitment, please remember to cancel your previous recurring donation directly with ${pledge.displayName}. ` ); } res.render( 'commit/', { title: 'Commit to a nonprofit. Commit to your goal.', pledge, ...commitGoals, ...nonprofit } ); }, next ); } function pledge(req, res, next) { const { user } = req; const { nonprofit: nonprofitName = 'girl develop it', amount = '5', goal = commitGoals.respWebDesignCert } = req.query; const nonprofit = findNonprofit(nonprofitName); observeQuery(user, 'pledge') .flatMap(oldPledge => { // create new pledge for user const pledge = Pledge( { amount, goal, userId: user.id, ...nonprofit } ); if (oldPledge) { debug('user already has pledge, creating a new one'); // we orphan last pledge since a user only has one pledge at a time oldPledge.userId = ''; oldPledge.formerUser = user.id; oldPledge.endDate = new Date(); oldPledge.isOrphaned = true; return saveInstance(oldPledge) .flatMap(() => { return saveInstance(pledge); }); } return saveInstance(pledge); }) .subscribe( ({ displayName, goal, amount }) => { req.flash( 'success', dedent` Congratulations, you have committed to giving ${displayName} $${amount} each month until you have completed your ${goal}. Please remember to cancel your pledge directly with ${displayName} once you finish. ` ); res.redirect('/' + user.username); }, next ); } function renderDirectory(req, res) { res.render('commit/directory', { title: 'Commit Directory', nonprofits }); } function completeCommitment(req, res, next) { const { user } = req; return completeCommitment$(user) .subscribe( msgOrPledge => { if (typeof msgOrPledge === 'string') { return res.send(msgOrPledge); } return res.send(true); }, next ); } function stopCommit(req, res, next) { const { user } = req; observeQuery(user, 'pledge') .flatMap(pledge => { if (!pledge) { return Observable.just(); } pledge.formerUserId = pledge.userId; pledge.userId = null; pledge.isOrphaned = true; pledge.dateEnded = new Date(); return saveInstance(pledge); }) .subscribe( pledge => { let msg = dedent` You have successfully stopped your pledge. Please remember to cancel your recurring donation directly with the nonprofit if you haven't already done so. `; if (!pledge) { msg = dedent` It doesn't look like you had an active pledge, so there's no pledge to stop. `; } req.flash('info', msg); return res.redirect(`/${user.username}`); }, next ); } }