· Nikolaos Gkionis  Â· 4 min read

A difficult technical problem to solve

A difficult technical problem to solve, multiple divergent paths with a ton of dependencies. This is how we solved it.

A difficult technical problem to solve, multiple divergent paths with a ton of dependencies. This is how we solved it.

A difficult technical problem to solve

The Problem

The NCTS5 team consisted of 2 interaction designers, they were struggling with a highly complicated prototype. They wanted to achieve multi divergent paths and their dependencies.

The Solution

In an ‘pair programming’ session between myself and the 2 interaction designers, we managed to achieve this with nesting if/else statements and creating an array to store the information as described below. We also recorded the session and hosted it on our community slack channel and used this as a stepping stone for more ‘pair programming’ sessions.

Screenshots

A screenshot

The radio buttons lead to divergent paths in the rest of the user journey, this can be achieved in the routes.js file.

router.post('/guarantee-type', function (req, res) {
  const selectedGuarantee = req.session.data.guaranteeType;

  const guaranteeRadio = [
    '(0) Guarantee waiver',
    '(1) Comprehensive guarantee',
    '(2) Individual guarantee',
    '(4) Flat-rate voucher redirect(guarantee-reference)',
    '(5) Guarantee waiver',
    '(9) Individual guarantee with multiple usage',
    '(J) Guarantee not required for the journey',
  ];

  if (guaranteeRadio.includes(selectedGuarantee)) {
    res.redirect('guarantee-reference');
  } else if (selectedGuarantee == '(8) Guarantee not required for certain public bodies') {
    res.redirect('other-reference');
  } else if (selectedGuarantee == '(3) Individual guarantee in cash or other means of payment') {
    res.redirect('other-reference-cash-deposit');
  } else {
    res.redirect('check-answers');
  }
});

router.post('/guarantee-type-xi', function (req, res) {
  const selectedGuarantee = req.session.data.guaranteeType;

  const guaranteeRadio = [
    '(0) Guarantee waiver',
    '(1) Comprehensive guarantee',
    '(2) Individual guarantee',
    '(4) Flat-rate voucher redirect(guarantee-reference)',
    '(5) Guarantee waiver',
    '(J) Guarantee not required for the journey',
  ];

  if (guaranteeRadio.includes(selectedGuarantee)) {
    res.redirect('guarantee-reference');
  } else {
    let guaranteeType = req.session.data.guaranteeType;

    if (guaranteeType == '(8) Guarantee not required for certain public bodies') {
      res.redirect('other-reference');
    } else if (guaranteeType == '(3) Individual guarantee in cash or other means of payment') {
      res.redirect('other-reference-cash-deposit');
    } else res.redirect('check-answers');
  }
});

router.post('/guarantee-reference', function (req, res) {
  const selectedGuarantee2 = req.session.data.guaranteeType;

  const guaranteeRadio2 = [
    '(0) Guarantee waiver',
    '(1) Comprehensive guarantee',
    '(2) Individual guarantee',
    '(4) Flat-rate voucher redirect(guarantee-reference)',
    '(9) Individual guarantee with multiple usage (for CTC only)',
  ];

  if (guaranteeRadio2.includes(selectedGuarantee2)) {
    res.redirect('access-code');
  } else {
    res.redirect('check-answers');
  }
});

A screenshot

A screenshot

A screenshot

A screenshot

A screenshot

The add another feature

At the end of the journey the user is presented with an option to add another guarantee to their declaration, this can go up to 9 different guarantees and then the user needs to remove one before adding another.

A screenshot

A D.R.Y (A Do not Repeat Yourself)

The code required to add and remove guarantees from the declaration. This code builds an array and indexes the guarantee, every time the user adds another guarantee, the maximum is set to nine. This code will be made part of every other add another pattern required through the prototype in the Routes, Transport, House Consignments and so on.

router.get('/:index/remove-guarantee', function (req, res) {
  res.render(path.resolve(__dirname, 'remove-guarantee'));
});

router.post('/:index/remove-guarantee', function (req, res) {
  let removeGuarantee = req.session.data.removeGuarantee;
  const guarantees = req.session.data.guaranteeArray || [];

  if (removeGuarantee == 'Yes' && guarantees.length) {
    const deleteIndex = req.params.index - 1;
    const maxIndex = guarantees.length || 0;

    if (deleteIndex <= maxIndex) {
      guarantees.splice(deleteIndex, 1);

      req.session.data.guaranteeArray = guarantees;
      req.session.data.guaranteeCount = guarantees.length;
    }
  }

  res.redirect('../add-another-guarantee');
});

router.get('/:index/check-answers', function (req, res) {
  const data = req.session.data;
  const index = parseInt(req.params.index);
  const guarantees = data.guaranteeArray || [];

  if (!guarantees.length) {
    return res.redirect('../add-another-guarantee');
  }

  const guarantee = guarantees[req.params.index - 1] || {};

  req.session.data = {
    ...data,
    ...guarantee,
    editGuarantee: index,
  };

  res.redirect('../check-answers');
});

router.post('/check-answers', function (req, res) {
  const data = req.session.data;
  const guarantees = data.guaranteeArray || [];

  const guarantee = {
    guaranteeType: data.guaranteeType,
    guaranteeReference: data.guaranteeReference,
    liabilityAmount: data.liabilityAmount,
    accessCode: '****',
  };

  if (data.editGuarantee) {
    guarantees[data.editGuarantee - 1] = guarantee;
  } else {
    guarantees.push(guarantee);
    data.guaranteeArray = guarantees;
    data.guaranteeCount = guarantees.length;
  }

  delete data.editGuarantee;

  res.redirect('add-another-guarantee');
});

router.post('/add-another-guarantee-route', function (req, res) {
  var sessionData = req.session.data;
  var guaranteeArray = sessionData.guaranteeArray || [];
  var guarantee = {
    id: guaranteeArray.length + 1,
    guarantee: sessionData.guaranteeType,
  };
  guaranteeArray.push(guarantee);
  sessionData.guaranteeArray = guaranteeArray;
  sessionData.guaranteeCount = guaranteeArray.length;
  res.redirect('add-another-guarantee');
});

router.post('/guarantee-added-tir', function (req, res) {
  res.redirect('../task-list-3');
});

router.post('/add-another-guarantee', function (req, res) {
  delete req.session.data.editGuarantee;

  if (req.session.data.addAnotherGuarantee == 'Yes') {
    res.redirect('guarantee-type');
  } else {
    res.redirect('../task-list');
  }
});

router.post('/add-another-guarantee', function (req, res) {
  delete req.session.data.editGuarantee;

  if (req.session.data.guaranteeCount == '9') {
    res.redirect('../task-list');
  } else {
    res.redirect('guarantee-type');
  }
});

The declaration summary

At the end of the journey the user is then taken back to the declaration summary where they can see that they have completed this section.

A screenshot

    Share:
    Back to Blog

    Related Posts

    View All Posts »
    Macro interactions

    Macro interactions

    A series of different approaches to a single user problem. Iterations based on User Research. Achieving a 100% success task completion rate.

    Disclosure

    Disclosure

    When one thing per page does not work, and progressive disclosure does not fit the context. A brief Design History.

    Validation

    Validation

    Should prototypes have validation? Yes, they should. At a minimum empty field validation needs to be implemented to ensure branching is accurately rendered.

    Postcode search

    Postcode search

    Improving the user experience for the majority of the users. Adding a postcode search that is returns AAA accessible results.