Need2Speed.png

Lightning-Speed Development with ES6, AngularJS and NodeJS

Lightning-Speed Development with ES6, AngularJS and NodeJS

 

The client

I was approached by my friend at Nevada IT Solutions with request: could I build simple event registration application for a client of theirs on a very tight budget? If you're not from the consulting/freelance world, tight-budget means you can't spend a lot of time on this. This is always a difficult request to hear as a designer, because our natural inclination is to spend a lot of time exploring design solutions and careful planning, but since the request was pretty straight forward, I decided to take on the task.

The client was the owner of the probably very coveted domain Need2Speed.com, a go-kart company in Reno, Nevada. Need 2 Speed had a process problem. They often hosted go-kart events for big groups, and they currently had to manually register each individual racer on location at the front desk before the race could begin. They were struggling with big lines and an annoying process they thought could be easily automated and accessible in the web, and they were right.

I proposed designing a separate NodeJS application under a subdomain, events.need2speed.com to handle all this business. 

The design

We didn't have a whole lot of time to go over design decisions, so I made a set of simple wireframes to outline the general layout and figure out what fields, options and controls would be available in the app.

Scaffolding the project, fast!

Once the wireframes were approved, it was time to build the app and I had to do so quickly. Without a doubt, I reached for my trusty ol' friend Yeoman. Yeoman is a web scaffolding application that runs on the command line. You can select from a great selection of generators that will set up a started app using the technologies of your choice. For this project, I opted for the Angular-Fullstack generator, which gets you started with an app that uses AngularJS on the client side using ES6 through BabelJS. On the server side, Yeoman sets up NodeJS with ExpressJS. The scaffold also includes a great GulpJS file that helps you automate all sorts of tasks like code minification, linting and deploying. You can also easily manage dependencies using NPM and WebPack.

 

Sending the data and consuming a RESTful API

To create accounts and register users to races, we used the great go-kart API from ClubSpeed Timing. ClubSpeed Timing allowed us to simply send the user-submitted data to their RESTful API and have everything show up in the Need 2 Speed folk's system. All we had to do now is take data from our users (either by them manually logging in, signing up or doing either via Facebook's login API) and sending the data to the API with NodeJS.

Collecting the data using AngularJS in ES6

'use strict';
const angular = require('angular');
const uiRouter = require('angular-ui-router');
import routes from './event.routes';

export class EventComponent {
  /*@ngInject*/
  constructor($http, $stateParams, $state, Util, $timeout) {
    this.$http = $http;
    this.$stateParams = $stateParams;
    this.$state = $state;
    this.util = Util;
    this.$timeout = $timeout;
  }
  $onInit() {
    this._event = Object.create(this.util.newState);
    this._event.loading = true;
    this.loginForm = Object.create(this.util.newState);
    this.login = () => {
      this._event.loading = true;
      this.$http.post('/api/login', this.loginForm.data )
      .then((response) => {
        console.log('Login response:', response);
        this.register(response.data.customerId);
      }, (error) => {
        console.log('Login error', error);
        this._event.loading = false;
        this.loginForm.data = {};
        this.util.showErrorDialog('The username and password combination did not match an existing account. ');
      });
    };
    this.register = (customerId) => {
      let requestData = {
        eventId: this._event.data.eventId,
        customerId: customerId,
        added: new Date().toISOString()
      };
      this.$http.post('/api/register', requestData )
      .then((response) => {
        console.log('Registration response:', response);
        this._event.loading = false;
        this._event.success = true;
      }, (error) => {
        console.log('Registration error', error);
        this._event.loading = false;
        if ( error.data.search('Cannot insert duplicate key in object') ) {
          this.util.showErrorDialog('This username is already registered to this event.', false);
          this._event.success = true;
        } else {
          this.util.showErrorDialog('An error occured while trying to register your account to the event.');          
          this.resetState();
        }
      });
    };
  }
}

(Note: That's just the code for logging via the form but you can also sign up for a new account via a form or use the Facebook login button which is not included in this code snippet)

Communicating between the app's client side and the API with NodeJS

'use strict';

import request from 'request';
import base from '../../config/base.js';

var endpoint = 'customers/login/';

export function post (req, res) {
    var reqData = req.body;
    console.log('== Request data:');
    console.log(reqData);
    request.post(
    base.url + endpoint + '?key=' + base.authKey,
    { json: reqData },
    function (error, response, body) {
      if (!error && response.statusCode == 200) {
        console.log('== Login response:');
        console.log(body);
                res.json(body);
      }
      else {
        console.log('== Login POST Error');
        console.log(error);
                res.status('500').send('Invalid login. Error: ' + body.error.message);
      }
    }
    );
}

The final result

The Yeoman scaffold worked great. The client and server sides communicated seamlessly and data was channeled back and forth with the ClubSpeed API. Now users can register to races on their own devices after receiving an email invite, saving Need 2 Speed and their customers from spending valuable time filling out registrations on the front desk.

You can the full repository of the code on github.