241 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import _ from 'lodash';
 | |
| import { Observable } from 'rx';
 | |
| import debugFactory from 'debug';
 | |
| import dedent from 'dedent';
 | |
| 
 | |
| 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(
 | |
|   '/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('/:lang', 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
 | |
|       );
 | |
|   }
 | |
| }
 |