# 🗓️ Simple Booking App Tutorial (No Double Bookings)

**URL:** https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534
**Category:** Community Resources
**Tags:** tutorial
**Created:** [June 7, 2023, 7:42am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534 "2023-06-07T07:42:42Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 7:42am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/1 "2023-06-07T07:42:42Z")

</div>

[![](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/e/f/efd1bbb596ef595f5a3a9881dc2c6e2755721260.jpeg "🎓 Glide Tutorial - Simple Booking App") ](https://www.youtube.com/watch?v=lHeis2JR2e8)

**What’s going on Gliders!**

A member of Loqode School recently had a question about booking/scheduling functionality in Glide, so I thought I’d share here too.

For this particular use-case the time slots are exactly 30 minutes each and span from 8am to 4pm… But you can very easily tweak this solution to suit your needs _(e.g. variable length bookings)_.

Of course there are plenty of alternate ways to achieve the same functionality, but this appears to be a very simple option. It utilises what is known as a “Helper Table” (shoutout to @Darren_Murphy) to check for double-bookings on the fly and only allows users to select time slots that are free.

Enjoy! 🥂

---

<div class="post-metadata">

### Author: ![Structure\_Art\_DIGITA](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/structure_art_digita/32/59811_2.png) [@Structure\_Art\_DIGITA](https://community.glideapps.com/u/Structure_Art_DIGITA)
#### Post date: [June 7, 2023, 8:21am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/2 "2023-06-07T08:21:09Z")

</div>

I did a similar App…

 ![Schedule Appointment](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/f/e/fef1a9c1f5ca2cdb6407e49347bb5a0a50973bd8.jpeg)

I see we have the same interest in making Apps 😉

---

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 8:35am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/3 "2023-06-07T08:35:35Z")

</div>

Interesting! Did you use a similar method?

---

<div class="post-metadata">

### Author: ![Structure\_Art\_DIGITA](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/structure_art_digita/32/59811_2.png) [@Structure\_Art\_DIGITA](https://community.glideapps.com/u/Structure_Art_DIGITA)
#### Post date: [June 7, 2023, 8:38am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/4 "2023-06-07T08:38:22Z")

</div>

Kind of… same idea… but more advanced… I have to match my time zone and users… to rearrange inline lists for options and calendar view… and do a lot of HTML to make UI more friendly 😉

---

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 8:50am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/5 "2023-06-07T08:50:36Z")

</div>

Awesome 👍  
Just shows that with a bit of creativity you can build just about anything in Glide 🤓

---

<div class="post-metadata">

### Author: ![Darren\_Murphy](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/darren_murphy/32/47326_2.png) [@Darren\_Murphy](https://community.glideapps.com/u/Darren_Murphy)
#### Post date: [June 7, 2023, 9:45am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/6 "2023-06-07T09:45:52Z")

</div>

Very nice - love your tutorials, always clean and easy to follow.

A couple of comments/tips, because you know I can’t help myself 😉

- Those two template columns you have in the Helper table for the UserID and Name - it appears that you don’t actually use them anywhere? (or did I miss something?)
- When you open the form, you use a Show New Screen action. Whilst that is fine, it does limit you to only being able to create bookings whilst in the context of that screen. What I like to do is create a Single Value → First → Helper Table → Whole Row in the User Profile table, and then use a Show Details (not Show New) screen via that column. Doing it that way essentially gives you a reusable Custom Form that you can call from anywhere in the App.
- Clearing the User Specific columns in the Form. I like to do this as the form is opened, rather than when the form is submitted. Functionally it is the same, but it does eliminate the possibility of any race conditions where the columns might be cleared before the new row is created.
- Date Formatting: this is one to watch out for, especially when you are using Dates in relations. The thing is, every users device could format the dates in a slightly different way depending on their device/browser regional settings, and this can result in unexpected (and broken) behaviour. The best way to avoid that is to first convert the dates to an integer: `Year(Date) * 10000 + Month(Date) * 100 + Day(Date)`, which gives you something like `20230615`. And then use that in your template. So that would become `20230615 8:30 am`. Doing it that way will guarantee that your relations will always work for all users.

---

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 10:49am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/7 "2023-06-07T10:49:47Z")

</div>

Thanks Darren, glad you enjoy them 🍿

And I’d expect nothing less! Always appreciate your input.

- Your 100% correct in saying the UserID and Name columns _aren’t_ used… Forgot to remove them when simplifying the app, and while recording I went on full auto-pilot mode explaining everything column by column without the penny dropping that they were now redundant 🤣 You have a keen eye!
- Thats a great idea, thanks for explaining 👍
- Makes sense and it’s a very simple change to make.
- I’d normally use [Luxon](https://moment.github.io/luxon/?gspk=cm9iZXJ0cGV0aXR0bzU5NDE&gsxid=Q9CRCDFpkU2X#/formatting?id=table-of-tokens) (Other \> Date & Time \> Format Date) to standardise the dates but I kept it simple for the tutorial in order to get the point across, but you’re correct in pointing that out 🙏

---

<div class="post-metadata">

### Author: ![Darren\_Murphy](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/darren_murphy/32/47326_2.png) [@Darren\_Murphy](https://community.glideapps.com/u/Darren_Murphy)
#### Post date: [June 7, 2023, 11:07am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/8 "2023-06-07T11:07:01Z")

</div>

> [@Loqode](#):
>
> I’d normally use [Luxon](https://moment.github.io/luxon/?gspk=cm9iZXJ0cGV0aXR0bzU5NDE&gsxid=Q9CRCDFpkU2X#/formatting?id=table-of-tokens) (Other \> Date & Time \> Format Date) to standardise the dates but I kept it simple for the tutorial in order to get the point across, but you’re correct in pointing that out

I’ve even had inconsistent results with that one in the past. When it was first added to Glide it seemed to be particularly buggy so I got turned right off it. It might be better now, I’m not sure. I just avoid it because I find that I can almost always get what I need with a bit of Date math 🤷‍♂️

---

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 11:15am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/9 "2023-06-07T11:15:35Z")

</div>

> [@Darren\_Murphy](#):
>
> I’ve even had inconsistent results with that one in the past. When it was first added to Glide it seemed to be particularly buggy so I got turned right off it.

Interesting! I’ve used it sporadically for the past 5-6 months and haven’t come across any bugs yet 🤞 but I’ll definitely keep an eye out. I wonder if anyone else has dealt with issues/inconsistencies with it lately… 🤔

---

<div class="post-metadata">

### Author: ![Structure\_Art\_DIGITA](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/structure_art_digita/32/59811_2.png) [@Structure\_Art\_DIGITA](https://community.glideapps.com/u/Structure_Art_DIGITA)
#### Post date: [June 7, 2023, 11:20am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/10 "2023-06-07T11:20:05Z")

</div>

It is always an issue… I would rely on Java and transform to Glide… for the general uniform results

---

<div class="post-metadata">

### Author: ![Darren\_Murphy](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/darren_murphy/32/47326_2.png) [@Darren\_Murphy](https://community.glideapps.com/u/Darren_Murphy)
#### Post date: [June 7, 2023, 11:33am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/11 "2023-06-07T11:33:49Z")

</div>

I had a bit of a rant about it below:

> [@Time Format](https://community.glideapps.com/t/time-format/50074/8):
>
> The other thing you need to do is test it at different times of the year. Early on, when I was trying to use it, I found that it would sometimes get the day and month mixed up, but only under certain circumstances, and only if the date was ambiguous. For example, today is September 25th. In the US, they write that as 9/25/2022. In the real world, we write it as 25/9/2022. But either way, it’s obvious that it’s September 25. It can’t be anything else, because there is no 25th month. But, le…

---

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 11:52am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/12 "2023-06-07T11:52:34Z")

</div>

> [@Time Format](https://community.glideapps.com/t/time-format/50074/8):
>
> In the US, they write that as 9/25/2022. In the real world, we write it as 25/9/2022.

_In the real world 🤣_

Thank you for pointing it out though, good information to have on hand. I’ll watch for any oddities in the future… And if it’s relation-based and mission critical then something like your simple math solution may be the safest bet.

---

<div class="post-metadata">

### Author: ![Eric\_Penn](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/eric_penn/32/73888_2.png) [@Eric\_Penn](https://community.glideapps.com/u/Eric_Penn)
#### Post date: [June 7, 2023, 12:21pm UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/13 "2023-06-07T12:21:32Z")

</div>

Great tutorial @Loqode! Thanks for sharing 🙏

How would you approach this issue…

If two or more people are using the app at the same time and select the same booking slot… at the end of the flow I assume only one will win.

How would you temporarily disable a time slot while someone is filling out details and release it if they back out?

Maybe set a timestamp when they enter the slot and give ‘em 5 min?

---

<div class="post-metadata">

### Author: ![Structure\_Art\_DIGITA](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/structure_art_digita/32/59811_2.png) [@Structure\_Art\_DIGITA](https://community.glideapps.com/u/Structure_Art_DIGITA)
#### Post date: [June 7, 2023, 12:22pm UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/14 "2023-06-07T12:22:54Z")

</div>

the flush app… solution… lol (plus clever script to deal with it)

---

<div class="post-metadata">

### Author: ![gvalero](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/gvalero/32/1037_2.png) [@gvalero](https://community.glideapps.com/u/gvalero)
#### Post date: [June 7, 2023, 12:24pm UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/15 "2023-06-07T12:24:42Z")

</div>

I agree!

I have used both methods for a long time and they both work fine so far. In the beginning, when the Format Date plugin did not exist, the trick to convert the dates to an integer was something mandatory but I can bet that it works without problems currently.

![image](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/5/0/502165493e01b1f3609a2543aae9e0e3201f9dea.png)

Furthermore, I think that since the “Respect Time Zones” feature was released, any relation that uses 2 date columns will work just fine if **both have** the “Respect Time Zones” feature enabled so, there is no need to use the trick.

Technically, which method is faster to sort/lookup data if the key field is a number or a text? … a number!

When your dataset is small, you can’t see the difference in response time, but if you have more than 100k+ rows, the improvement is noticeable. In short and as advice: do not rule out the trick at all! 😉

Saludos a todos!

---

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 11:15pm UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/16 "2023-06-07T23:15:42Z")

</div>

Thanks Eric! Happy to share.

Here’s one way of doing it 🤔

I wouldn’t use timers to temporarily disable it etc, what I would probably do is add a simple if/else check in the action that’s triggered on Submit.

Here’s how I’d set that up:

- Add a Lookup column named **Validation/All Bookings** to the Booking Form table.
- Select **Bookings \> Date & Time \> Full** as the value.
- Add an **Array Contains Element** column named **Validation/Date Taken** next to it.
- Select **Validation/All Bookings** as the values and **Date & Time \> Full Selection** as the “To Find”.
- Run an if/else scenario in the action that is submitting the booking.
  - If “Date Taken = Not Checked” then proceed as usual.
  - Else show notification to select another time (_e.g. Someone has just taken this slot, please select another time_).

Hopefully that makes sense! Not sure how quickly the Lookup column would be updated with the newly added booking, but off the top of my head this is how I’d do it.

 ![Xnapper-2023-06-08-08.59.17](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/4/b/4bbbdfb8fcb0475d7d4c88c6766d4035c0cc587b.jpeg)

 ![Xnapper-2023-06-08-09.04.16](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/0/d/0dd84fa683a4a592550d7a89d07ca9a47db3642c.jpeg)

 ![Xnapper-2023-06-08-09.04.47](https://us1.discourse-cdn.com/flex002/uploads/glideapps/original/3X/8/3/839f72f2458fc55598fa6ee6606bd9a45edc78ca.jpeg)

---

<div class="post-metadata">

### Author: ![Loqode](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/loqode/32/50217_2.png) [@Loqode](https://community.glideapps.com/u/Loqode)
#### Post date: [June 7, 2023, 11:19pm UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/17 "2023-06-07T23:19:36Z")

</div>

Great to hear Gustavo! Thank you for sharing. And it definitely makes sense to consider any/all performance or reliability improvements when the datasets start getting substantial 👌

---

<div class="post-metadata">

### Author: ![Darren\_Murphy](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/darren_murphy/32/47326_2.png) [@Darren\_Murphy](https://community.glideapps.com/u/Darren_Murphy)
#### Post date: [June 8, 2023, 1:29am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/18 "2023-06-08T01:29:22Z")

</div>

> [@Eric\_Penn](#):
>
> If two or more people are using the app at the same time and select the same booking slot… at the end of the flow I assume only one will win.

In this case, no. You would actually wind up with duplicate bookings. Last man in only happens when you have two or more users trying to _update_ existing rows. In this case we are adding new rows - and there is nothing going on server side to detect/prevent duplicates - so that’s what we’ll get.

> [@Loqode](#):
>
> I wouldn’t use timers to temporarily disable it etc, what I would probably do is add a simple if/else check in the action that’s triggered on Submit.
> 
> Here’s how I’d set that up:
> 
> - Add a Lookup column named **Validation/All Bookings** to the Booking Form table.
> - Select **Bookings \> Date & Time \> Full** as the value.
> - Add an **Array Contains Element** column named **Validation/Date Taken** next to it.
> - Select **Validation/All Bookings** as the values and **Date & Time \> Full Selection** as the “To Find”.
> - Run an if/else scenario in the action that is submitting the booking.
> - If “Date Taken = Not Checked” then proceed as usual.
> - Else show notification to select another time (_e.g. Someone has just taken this slot, please select another time_).

I’m afraid that won’t work. The challenge is that all of those calculations happen independently on each users device, and potentially at the same time. So every user could perform that check, and because they all haven’t synced up yet, they all pass, and you still wind up with duplicate bookings.

The only way to reliably deal with this situation is to delegate the allocation of the bookings to a 3rd party, eg. Make. Then they can be queued and handled sequentially, with a Make scenario checking for duplicates before adding each new booking.

---

<div class="post-metadata">

### Author: ![Eric\_Penn](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/eric_penn/32/73888_2.png) [@Eric\_Penn](https://community.glideapps.com/u/Eric_Penn)
#### Post date: [June 8, 2023, 1:35am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/19 "2023-06-08T01:35:24Z")

</div>

Thank you for the detailed follow up but let me clarify. I think no two people should be looking at the same time slot in the first place.

If there is 1 seat left on the plane and I click it on it…I should be the only person who can book that ticket for either some amount of time or until I back out.

In Glide determining when someone backs out can be tricky because you can close overlays, click tabs, etc… without the ability to trigger an action.

---

<div class="post-metadata">

### Author: ![Eric\_Penn](https://sea2.discourse-cdn.com/flex002/user_avatar/community.glideapps.com/eric_penn/32/73888_2.png) [@Eric\_Penn](https://community.glideapps.com/u/Eric_Penn)
#### Post date: [June 8, 2023, 1:40am UTC](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534/20 "2023-06-08T01:40:02Z")

</div>

> [@Darren\_Murphy](#):
>
> Then they can be queued and handled sequentially, with a Make scenario checking for duplicates before adding each new booking.

What about making the slot unavailable because someone is simply looking at it…”reserved” if you will… same process? That could be a lot of rows?

Maybe use something like Make to set a helper table with timestamp + userID in booking slots and clear it after xx:xx time passes 🤷‍♂️

[Next page](https://community.glideapps.com/t/simple-booking-app-tutorial-no-double-bookings/62534.md?page=2)
