This episode is for members only

Sign up to access "Build an Appointment Booking System With Livewire" right now.

Get started
Already a member? Sign in to continue
Playing
26. Locking unavailable dates

Episodes

0%
Your progress
  • Total: 3h 4m
  • Played: 0m
  • Remaining: 3h 4m
Join or sign in to track your progress

Transcript

00:00
So now we want to take the availability that we have here. That includes the entire availability period we're looking in for this user to browse. We want to take that, put it into our calendar,
00:11
and we want to show the unavailable date. So we basically want to say, what is missing from here? Well, I want to gray these out. Now luckily for us, as we've already seen,
00:20
easePick contains a plug-in which allows us to lock specific dates. That will also lock dates in the past as well. So we don't want to click through and choose
00:29
a date that's in the past. That doesn't make sense. OK, let's take a look at how this plug-in works first of all. Then we will take our availability data,
00:37
transform it into JSON, and then we will pass this through to our plug-in. OK, so first things first, let's go ahead and get this plug-in actually installed.
00:45
So let's go over to our picker. And we already have the ability to pull this in because we're just importing the entire bundle. So there's the lock plug-in.
00:54
Inside of here, we can define which plug-ins we want to use. So we're going to say that we want to pull in that lock plug-in and use it as a plug-in. And then to define out the options for this,
01:04
we just use lock plug-in like this. And we can just pass any options we need directly through to this. So the first thing I'm going to do is set a minimum date.
01:13
So that is just going to be a new date. We're working in JavaScript. We'll just say new date. That's from today.
01:18
So now the difference is going to be when we look at our calendar, sure enough, you can see all of these dates are now unselectable. This is today.
01:26
And of course, we can only now go into the future. So that's the first one that we've done. The second thing that we want to do is do a custom filter on this.
01:35
And the date here will be returned to us for every single date in the calendar. And we just want to return something in here. So let's just return true and see
01:43
what happens to our calendar. So let's open this up. And yeah, every single date now, because we've returned true to filter that out as a locked date,
01:52
is now unavailable. But what we want to do is in here, use our actual availability to lock out dates where there is no availability.
02:00
There's no point in a customer clicking on them. And it's going to be good for them to not have to do that and cycle through every single day to find an available appointment.
02:09
Now, in order to do this, we need to get options through to this directive. So we need to be able to pass data into this directive. Let's take a look at how to do that.
02:18
Then we'll build up our custom structure of availability in JSON so we can easily pass it through. And then we'll get going. OK, so we're going to go ahead and open up the checkout again.
02:29
And under XPickup, we can pass through an object to this. So we can pass through any options we want. In fact, the first thing that we should probably do here is set this to the current or next available date.
02:40
So we could pass a date in here, for example. And let's just sort this out a little bit. So I'm going to pull this down just so we've got a little bit of room to work.
02:49
And we should be good. OK, so I'm also going to add x data here so we know that that is an Alpine component. And in here, let's say XPicker, pull this down.
02:59
The date that we're going to pass through to here is going to be the next available date. And that's just going to be the form date, because remember, we set that in our mount method.
03:08
So let's just look at how we pick this date up first of all, set this as the current date in the calendar. And then we'll go ahead and pass through an availability array of data.
03:20
OK, so back over to our Picker. Let's see how we do this. As the second argument to this, we're going to get in an expression, which
03:27
is going to be what we just passed through to there. And as the third argument, we have some helpers, like evaluate. So let's pull that in.
03:34
Let's just console log on the expression and see what we get. And then we'll see why we need to use evaluate here. OK, let's go over and just pull up our console. And yeah, sure enough, we get this object through.
03:48
But it's just a string. We can't say in here expression.date, because we can't access date on a property. It's going to be completely undefined.
03:57
So with this, what we do is we take evaluate, and we invoke that passing in the expression. And that's going to convert that to an object for us, which we can now read data from.
04:06
Super helpful. So now what we can do is we can assign this up here. So let's just call this options, because that kind of makes sense.
04:14
And then we can say in here date. So let's set the default date first of all. And that's going to be options.date. Now remember, originally on our calendar,
04:23
we had the 26th set to the current date. And of course, we now want it to be the 27th. OK, so we've got an error here. Let's just check this out.
04:31
And yeah, let's just make sure that we get rid of that empty bracket. So now this is set to the 27th. And it's already, well, we can't see it at the moment,
04:39
because we've locked out the dates. But this has now been set as a default to the 27th. And we now know how to pass our options through, which is great.
04:47
OK, I'm also going to go over to the checkout. And I'm just going to get rid of where we are dumping out that form date, because we don't need that anymore.
04:55
OK, so now we need to pass through an array of availability. Now we want this to be in a very specific structure so we can very easily read it.
05:07
Now unfortunately, because we're just working with Livewire, we don't have the concept of an API resource. In the inertia version of this, we could create an API resource and we could structure this data how we want.
05:18
So that's not really a problem. What we're going to do is if we head over to the checkout just here, we're going to create another computed property in here called availability.json.
05:30
And that's going to return to us a transformed version of this. So let's go ahead and make this computed as well. We don't necessarily need to persist this, because the underlying one is already persisted.
05:41
So let's just make that computed. And in here, we're going to return a transformed version of the availability. Let's just try this out first of all
05:49
by just returning availability. And then we'll wrap this and see why this isn't going to work. So let's go over to our checkout.blade.php file. And let's just try and dump the availability somewhere.
06:01
So let's say this availability.json. And let's just see what we get. So let's open this up. And here we go.
06:08
So for each of these dates, we now have slots. And we have the employees inside of here. But the structure of this isn't quite right. We want to transform this into be something a lot lighter.
06:18
We don't need all of this information. We don't need every single piece of information about the employee. We really just need that ID.
06:26
So in order to do this, what we're going to do over in our checkout here is wrap this in a transformer. Let's go ahead and create that transformer.
06:35
So I'm just going to put that back into the booking directory. Let's call this AvailabilityTransformer. So AvailabilityTransformer. And this is going to be a super simple class which
06:47
just takes in our date collection and then returns it to us in a structure that we want. So let's go and say DateCollection. And we'll call this Availability, of course.
06:58
And we don't need anything else. So now in here, what we can do is we can use a magic two-string method. So when this is accessed as JSON or just echoed out somewhere,
07:10
what we can do is return a structure that we want. So let's just test this out by returning an array with 123. And then we'll go ahead and wrap this. So over in our checkout here, we're
07:21
going to go and say New AvailabilityTransformer. Pass that in. And because we're returning this and we're going to eventually dump it out to our blade template,
07:31
this will use that two-string method over here. And it will convert it to the structure that we want. So over to the browser, if we just give this a refresh here. And oh, yeah, of course, we returned an array.
07:41
So let's say JSONEncode and JSONEncode that. OK, give that a refresh. And yeah, there we go. So we've got our own structure to this data now.
07:53
But what we want to do is take the date collection here and sort of filter this down and make it into the structure that we want. So let's return.
08:01
And we'll say this Availability. And we're going to just start mapping through the overall dates, the underlying slots, and all that kind of stuff, including the employees, and just return the data
08:13
that we need. So think of it just like a standard API resource in Laravel, but we're doing this on our own because it doesn't make sense to use an API
08:22
resource within Livewire. So for mapping through all of our dates, of course, we're going to get a date object into here, our custom date object.
08:31
And from here, we want to return an array. And we want the date to be in here. And we want it to be in the format that we want. So we don't want to carve an object within a blade template.
08:40
There's no point. So let's say to date string. And then under here, let's grab out our slots. So again, we're going to do a map on all of the slots
08:48
inside of this date. So let's say map on them slots. And of course, that is going to contain a slot like this. And then within here, yep, sure enough,
09:01
we're going to return another array to structure this. And we're going to grab the time out that we want to see. So we'll say slot time to time string. And with this, it's really cool.
09:11
You can just pass a minute. If you don't want this to look like this with the seconds, this will just return something like this. OK, let's leave it like this.
09:20
And then we'll go ahead and add in the employee stuff in just a second. So let's give that a refresh. And there we go.
09:26
So we now have a date, a really clear array with just objects inside with the date that we want to represent on the calendar and the amount of slots. Same with this one as well, all of the slots.
09:37
And it all looks good. So let's add the employees. And then we'll go ahead and structure this again. And we'll get to putting this into our calendar.
09:47
So let's say employees map. Again, exactly the same thing. We're going to have an employee inside of here. And this is where it gets good because we
09:57
don't want to show all of the information about the employees. We really just want the employee slug. So we can set that inside of our checkout component. Now, super important here, if we just have a look at this,
10:09
this looks fine. But we've still got this because we're sort of going through everything. We just want to grab the values out.
10:15
So what we want to do is on our overall return, we just want to grab the values out here. And we'll do the same for each of these as well. So let's say values.
10:30
And we'll do the same for our slots here as well. So let's say values. OK, there we go. So now we have a nice structure to this.
10:42
We don't have any keys that we don't need. We've just got all of the slots inside of a date, all of the employees with inside of a slot. And everything is looking good.
10:53
OK, so just looking at this list, you can see that just Alex is inside of here. And that is, of course, because we have chosen Alex. So he's only going to be the one that's passed into that slot.
11:03
If we go back and choose one of these, I've got a feeling, yeah, it's going to break. So we get must not be accessed before initialization. Remember, we did this ternary here, where if the employee exists,
11:14
we just collect all that single employee. Otherwise, we do all of the employees. Now, the reason that this doesn't work, if we just head back over, is inside of our checkout, we didn't assign a null value.
11:27
So good thing that we caught this. We want to make sure that this is null before it's initialized. So there, now we're on hair with any employee. You can see that Mabel is within each of these slots
11:39
that she can do, depending on the days that she works. OK, let's go back to just Alex and hair for now. And we have all of our availability. Let's now pass this directly into our availability here.
11:53
And we don't need to wrap this in anything, because it's already JSONed. This is going to work with JavaScript nicely. And there we go.
12:00
So we've got that availability now within that calendar. And we can use it now to lock out these dates. So let's go over to our picker. And let's take the availability and use this within this filter.
12:14
So let's take the options and check if we can't find one within this availability. So let's say options, availability. We're going to find one.
12:23
Let's just call this A for availability. And we're going to match up the date to the date that we are currently iterating through within this filter. So this will go through every single date in the calendar.
12:35
And we will get that in here. So we're going to say date format. So this is the JavaScript date. This is the date that we formatted
12:41
within our transformer. And we're going to format this to the way that we have output it within PHP. So it will be year, year, month, month, day, day.
12:51
So if it's not found, it's going to return true and false. And either way, it will just lock out the dates that we need. So this, if we just have a look, looks like it is not working. Now, let's think back to what we did over in our service slot
13:08
availability when we went ahead and removed empty slots just here. So let's have a look at this. Well, I returned true, which means
13:17
that all of the dates that don't have slots are still going to be available. So what we want to do, rather than return true for dates that just don't have any slots in at all,
13:28
we want to go ahead and take the date. We want to access the slots and check if they're empty. So as long as we have slots within a date, they will remain.
13:37
Otherwise, they'll be just completely removed from the list. So just something we forgot to update earlier. OK, let's go over and just give this another refresh
13:45
and check this out. OK, so this is looking better. Today is available. 27th, I work on a Saturday.
13:52
So it's showing us the next available date. No one works on Sunday. Everyone works on Monday and Tuesday. But if we click to the next one, you
14:00
can see here that Saturday is available because I work on Saturdays. And Friday and Sunday, I have time off. Now, if we go over and switch this over to Mabel,
14:10
so we could either go back to Mabel and click on one of these, this is going to look a little bit different because Mabel doesn't work on Sundays. She does work on Saturday.
14:20
And if we go here, you can see that this looks more or less the same. So let's actually get rid of Mabel's availability for Saturdays and give that another refresh.
14:29
So now, the next available date switched to the 29th because Mabel doesn't work on Saturdays or Sundays. And you can see that this has been reflected as well. So if we go back again to Alex, I'm sure you get the idea.
14:41
Yep, I can do today because I work, but I don't work on Sunday or Friday. So there we go. A little bit complicated because we've
14:49
had to create a transformer to get this data into the correct JSON format so we can put it in the calendar. But the good news is that from here, now that we've done that, the rest of this is going to be pretty straightforward.
36 episodes3 hrs 4 mins

Overview

Building an availability calendar and booking system is a notoriously difficult problem to solve. That’s exactly what we’re going to cover in this course.

Step by step, we’ll build an appointment slot generator that calculates availability based on employee schedules, employee’s booked time off, the length of service chosen, existing appointments, and cancelled appointments.

For maximum flexibility, we’ll also allow multi-employee availability checks, so we’ll be able to see every employee who can perform a service (and their available slots).

To finish up, we’ll create an entire booking flow with Livewire, including a beautiful booking calendar that shows detailed availability across multiple dates, the ability to choose a time slot — and finally the ability to book an appointment.

Phew. We’ve got a lot to learn — let’s build a booking system with Livewire!

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!