Travel Planning with Mapbox, Google places, what3words and Google calendar

It’s my birthday!! well, not really but one year ago today I signed up for this forum so I thought it deserved a showcase but what? Not long after I signed up @THEDJW posted this:

Now for various reasons at the time I was unable to give a good solution and it has niggled at the back of my mind ever since so whilst this is no doubt too late for Dave here is my take on the solution for his Gig Management system, with some bonus automation and intergrations thrown in.

Short video

Gig Management System Overview

The system includes a Gigs App and a Venues App. Key features and functionalities are as follows:

Venue Management

  • Automatic Information Retrieval: When a venue is added with an address, the system automatically retrieves:

    • The average travel time from the band’s base to the venue.
    • The distance from the base to the venue.
    • Parking options in the surrounding area.
    • The what3words addresses for both the venue and the parking locations.
    • The travel cost to the venue.
  • Parking and Setup Difficulty: The Venue record includes simple button selections for indicating parking and setup difficulty. These selections influence time allowances, which are factored into the itinerary.

  • Centralised Venue Information: All gathered information is displayed on the Venue record, providing an easy-to-access overview.


Example what3words map:

Gig Management

  • Venue Information Integration: When creating a Gig record, it is linked to a Venue record, automatically pulling in all relevant venue details to assist with pricing and logistics.

  • Dynamic Travel Updates: Once a date and time are set for a gig, the system can update travel times based on the calculated arrival time, which considers the gig’s start time, and the setup and parking allowances.

  • Itinerary Building: The system compiles all relevant information into the Gig record, forming a detailed itinerary for the event.

Automation & Integration

  • Calendar Integration: When the band leader is ready, a single button press generates three calendar entries:

    1. Travel
    2. Setup
    3. Gig
  • Gig Web Page: The Gig record includes any additional information added and provides a link to a generated web page with all gig details.

Technology Stack

All automations are managed within Tape, with no need for external automation tools. The systems and tools utilised include:

  1. Tape - Obviously - Central automation and database management.
  2. Mapbox - For calculating distances and travel times.
  3. what3words - For precise location identification.
  4. Google Places API - To find nearby parking.
  5. Google Calendar - For creating calendar entries.

How is it done

Venue

There are 6 Automation flows in the venue app:

The first thing that happens is the 00 - Initial checks if an address is present and if there is then it triggers 2000 - Get Coordinates before we do anything else we need to convert the address to coordinates so we send the address to Mapbox and request coordinates.


As you can see it is a really simple call to get the coordinates, we then strip what we want from the response and update the record. Now we have the coordinates we can go and get some more information, we could do it all in one flow but I have split them up so we call another three flows, it doesn’t matter what order these three happen in they all use the new coordinates but are not dependent on each other. I will go through them in the order I built them.

2200 - Get distance from Base

We are going to use Mapbox again for this and the flow is:

  1. We need coordinates so we do a quick ‘sanity check’
  2. Grab the Mapbox API from our key store
  3. We need a base location so I have stored one in a Variables App
  4. Build the request, make the request, strip the data from the response and update the record.

2300 - Get Venue what3words

I love what3words so I thought why not build it into this system also there API is as easy as pie.

  1. Again sanity check the coordinates
  2. Get the what3words API Key
  3. Build the call, make the call, strip the data and update the record

Now I got stumped here for a while as whilst I have used Mapbox before I have never used it in conjunction with a different mapping service. For some reason, Mapbox uses a Longitude,Latitude system and both what3words and Google operate on a Latitude,Longitude system so the first part of building the call is to switch the Mapbox Coordinates around.
Once over that hurdle it is a simple call and split to get the information we want to add to the record. However, what3words along with their location words also provides a link to the location on a map and it seems a shame to waste that so we are going to construct an HTML link and save that to the record so we can use it later.

const w3wFull = `<a href="${map}" target="_blank">${words}</a>`;

  

const fieldResponse = await tape.Record.update(current_record_id, {fields: {venue_what3words:w3wFull});

Now we have our venue what3words sorted we can move on to our last of the three automation.

2400 - Parking

This one is a biggy it does a lot in its 6 blocks!


The first five blocks are relatively obvious they are just getting the API kets we need in the 6th as we are going to go to both google and what3words to collect some parking details and then we will build an HTML table of the relevant data giving us easy access to parking information around the venue.

Hopefully, those who want to can read my scribbles if you can’t and want to understand it then reach out and we can go through it. It is worth bearing in mind that I have built it the way I have however there are lots of options with this. It could be done without functions and it could be split into different blocks or even automations depending on what you find easiest, it doesn’t matter how you do it and obviously what I have done is push the ‘low-code’ boundaries to the limit but Tape does give you all the tools you need to achieve this in a ‘low-code’ way.

Gig

Five automation flow’s in this one:

6100 - Get Travel Time

We want the travel time based on the time we will be travelling rather than the default time we got before and this is were we get that:


The first three blocks collect the information we will need from other records before we move on to getting the travel duration from Mapbox.

I think my comments explain this one:

// #### Get the setup time number ####

const setupTime = parseFloat(collected_venue_field_setup_string_value) || 0;

console.info(`Setup: ${setupTime}`)

  

// #### Get the Parking Faff Time ####

const parkingTime = parseFloat(collected_venue_field_parking_time_string_value) || 0;

console.info(`Parking: ${parkingTime}`);

  

// #### Total Pre Gig Time ####

const t = setupTime + parkingTime;

  

// #### Make the latest arrival time ####

console.info(`gig Time: ${date_fns.format(date_fns.parseISO(gig_field_date_formatted),'HH:mm')}`);

let arriveTime = date_fns.subMinutes(date_fns.parseISO(gig_field_date_formatted), t);

console.info(`Arrive Time: ${date_fns.format(arriveTime,'HH:mm')}`);

const aTime = arriveTime; // this makes a variable for use much lower down

  
  

// #### Add the arrival time to the record ####

const timeZonedArrivalTime = date_fns_tz.zonedTimeToUtc(arriveTime, 'Europe/London');

console.log(`Date added to record: ${timeZonedArrivalTime}`);

await tape.Record.update(current_record_id, {fields: {arrival:timeZonedArrivalTime}));

console.log(`Additional time: ${t}`);

  

console.warn(`####-- Arrival time now added to record --####`);

  

// #### Format the latest arrival time for MapBox ###

arriveTime = date_fns.format(arriveTime, "yyyy-MM-dd'T'HH:mm"); //Mapbox will take timezone from country directions are in

console.info(`Arrive Time formated for MapBox: ${arriveTime}`);

  

// #### Setup the Mapbox request ####

const baseUrl = `https://api.mapbox.com/directions/v5/mapbox/driving`;

const accessToken = collected_api_key_field_apikey_value;

// Get and encode there various parts

const baseLocation = encodeURIComponent(collected_variable_field_coordinates_value);

// console.info('baseLocation', baseLocation);

const venueLocation = encodeURIComponent(collected_venue_field_coordinates_value);

// console.info('Venue Location', venueLocation);

arriveTime = encodeURIComponent(arriveTime); // arrive by date/time needs to be encoded to send to MapBox

//build the options

const options = `alternatives=true&exclude=unpaved%2Ccash_only_tolls&geometries=geojson&language=en&overview=simplified&arrive_by=${arriveTime}&`;

  

// Construct the full URL

const url = `${baseUrl}/${baseLocation};${venueLocation}?${options}access_token=${accessToken}`;

// #### make the call and get distances ####

const response = await http.get(url,);

console.log('response', JSON.stringify(response.data));

  

// Get the base distance and Time

// const distance = jsonata('data.routes[0].distance').evaluate(response);

const time = jsonata('data.routes[0].duration').evaluate(response);

// make the distance and time more useful

const hTime = (time/3600).toFixed(2);

const mTime = (time/60).toFixed(2);

//const km = (distance/1000).toFixed(2);

//console logs

console.info('hours', hTime);

console.info(`Minutes: ${mTime}`);

  

// #### Create the departure time

  

const dTime = date_fns.subMinutes(aTime, mTime); // aTime taken from the top

console.info(`The latest time of departure: ${dTime}`);

// Change the time zone

const timeZonedDeparture = date_fns_tz.zonedTimeToUtc(dTime, 'Europe/London');

console.info(`Timezoned Departure time added to record: ${timeZonedDeparture}`);

// Add travel time to the record

const fieldResponse = await tape.Record.update(current_record_id, {fields: {departure_time:timeZonedDeparture travel_time:hTime});

// console.log('field info', JSON.stringify(fieldResponse));

Most of that is messing around with the date and time as it builds the latest time of arrival based on the parking and setup allowance. We also mess around with timezones here and date time formats. Be careful with your formats as both Mapbox and Google (for calendar entries) I would suggest checking out this post: Date-fns Interactive Format Builder and using the tool to check your format otherwise you might end up as i did with all your events being at 8 minutes past the hour :wink:

6200 - Add the Gig to Google Calendar

The final important automation flow is to get the events we want into our Google calendar:


Again most of this one is messing around with dates and times so we send the correct start and finish time to Google for the three different events we are creating.

Full Video Walk Through

Thanks

If you have got all the way down to here then thank you and I hope that you got something from your read.

I have tried to cover as much as possible without going step by step so please do reach out if you have any questions I am always happy to help.

4 Likes

After writing this up I felt it was wrong for me to have built the whole of the Parking flow the way I had (especially as I normally try and avoid functions in Tape), so I re-built it making it as low-code as I practically could and the following is the automation I ended up with. It does everything the first one did apart from the duping which wasn’t as successful as I wanted anyway. The important thing that this shows is the amazing versatility of Tape

The first few blocks just set the API keys as before, then:

  1. We still have to sort the venue coordinates out so this is what we do here also as we are in a script block I initialise an array for use further down.

  2. We use the HTTP request block to make our call to Google for parking places

  3. This is my favourite part we construct a completely new JSON object from different parts of the massive Google response all in a calculation block (this pleases me way more than it should!)

  4. We now loop through each of our parking places

  5. In the first part of the loop we pull out the coordinates to send to what3words

  6. We again use the HTTP request block to get the what3words details for the coordinates.

  7. We now have two sets of data we want some of each so we put what we want to keep in that array we built at the top

  8. Once we have finished the loops we are left with an array of objects made up of the Name from Google, Words from what3words and a map URL from what3words - We make a two-column table from our array merging the words and map URL into a link in the second column

  9. We encode the HTML table and add it to the record

4 Likes

@Jason, you’re simply amazing! :100: :gift:

a massive thank you from the whole Tape team on your Tape community forum birthday! Your valuable showcases, contributions, and unwavering support for the entire Tape community over the past year have been incredible. We’re so grateful to have you with us, and it’s a joy to see your engagement in action!

Thank you also for this fantastic travel planing showcase, highlighting the complex use cases that are possible with Tape automations and system integrations. Even with your expert-level knowledge as a Tape pro, you always make everything so easy to understand and perfectly structured. It’s truly impressive!

Once again, a huge thank you from me and the entire Tape team for your extraordinary commitment and the amazing work you do, which means so much to us and the amazing Tape community :blue_heart:

Cheers
Leo

4 Likes

Happy birthday homie! :gift:

I feel like we’re friends at this point because of how often we interact on here.

4 Likes

Fantastic tutorial, Jason! Lots of practical stuff here.

3 Likes

This guy… :exploding_head: :partying_face:
Amazing every time you decide to contribute to community. Thanks for sharing a lot of your work.
Happy birthday!

4 Likes