243 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			243 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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
 | 
						|
      );
 | 
						|
  }
 | 
						|
}
 |