‫So next up,
‫let's add the ability to also sort the cabin table.
‫So basically, besides this filter here
‫we want to have a dropdown menu where we can select
‫which of these fields here we want to sort the data by.
‫So let's create a sort by component
‫and I will do it again here
‫in the UI folder because we will want to reuse it later.
‫So for other tables.
‫Okay, so for now, let's just return sort here.
‫And this component, just like the filter component
‫will receive a list of options.
‫So here we have the filter
‫and actually we forgot to do something here
‫so let's just duplicate this line here
‫and also add the disabled prop.
‫So basically when we have this background here
‫which means that this is the currently applied filter
‫then we also want this button here to not be clickable.
‫All right, but anyway,
‫now let's actually also include the sort by component here.
‫And so as I was saying,
‫let's then specify immediately here the list of options.
‫And again, there will be a value and a label.
‫So let's start with sort by name
‫from A to Z
‫and then we will also have one to sort in the other way.
‫So basically we will have both the ascending
‫and the descending way.
‫And so let's then specify that right here in the value.
‫So name.asc for ascending
‫and then name-descending.
‫So basically right here in this value
‫we are encoding two types of information.
‫First, we have the field by which we want to sort
‫and then we also have the direction.
‫Now there would be other ways of doing this
‫so we could specify the direction here in a separate field
‫but I believe that it's best to keep it simple like this.
‫So next, let's sort by the price.
‫And here I will actually now use the name of the fields
‫as they are in the database, and so as we also receive them
‫here in our application from the API.
‫So I want to sort also by the price.
‫So when that's called,
‫on our API regular price
‫and then ascending,
‫and then here sort by price.
‫And then let's here say, low first
‫and then here,
‫high first.
‫Alright, duplicating this one here again.
‫So let's finally also add the ability to sort
‫by the max capacity
‫which is basically this column right here
‫which again in our database is called max capacity.
‫So sort by capacity low first
‫and then
‫the descending one and high first.
‫Now okay, and so now in our sort by component
‫we will want to have one select element
‫with one option for each of these elements of the array.
‫All right.
‫Now, since we will want a select element
‫many times in this application,
‫let's actually build ourselves a reusable one.
‫And I already have the styles for that here.
‫And so all we have to do is to write
‫a little bit of code here.
‫So this needs to receive,
‫of course, first the list of options
‫and the currently active value.
‫And the other things that we're gonna need
‫we will add them later.
‫So as the need arises.
‫So here we then use the styled select element
‫which is indeed just a select HTML element.
‫And so then we give it the currently active value
‫just like we do on all controlled components.
‫So this is in the end, just gonna be a controlled component
‫like we have always been using.
‫And then in here,
‫we just loop over the options that we receive.
‫And then for each of them,
‫indeed we create one option HTML element.
‫So here that will then contain,
‫well, first of all,
‫we need to actually have a callback
‫and then here we will have the option.label and
‫the value will be the current option.value.
‫And of course we then also need a key,
‫so option.value once again.
‫And now let's actually use that here.
‫So here all we want to return
‫is actually a select element with these options.
‫And the currently selected one,
‫we will pass it in later
‫because for now, we don't have it yet.
‫Okay, now here we need a bit more space to actually see.
‫And so here are all our options.
‫Now in terms of styling, there are actually different types
‫of select elements that I created.
‫So basically if we pass in the type prop set to white
‫then the styling here will be slightly different.
‫And so let's do that now.
‫So here we pass in type white
‫and then let's receive that here.
‫But this time I actually want to show you a nice trick.
‫So we can just like in any other destructuring,
‫also receive all the remaining props
‫using the rest operator like this.
‫So if you check this out, then in this case,
‫this will simply be
‫the type set to white
‫but if we passed in some other props
‫then all of them would now be contained here.
‫So that would then be probably an array.
‫Let's test this.
‫And so let's set test to Jonas and ah, yeah
‫then we get this object here with these multiple properties.
‫And so then what we can do here
‫is if we had this situation
‫where we received multiple properties
‫that all we want to do with them is to pass them right here
‫then we can use basically the same trick
‫that is also used in React Hook Form,
‫which is to enter JavaScript mode
‫and then spread those props here.
‫And so then the select component here
‫will get all of those props.
‫So we haven't ever used this trick before
‫and so I really want to show you what's happening,
‫now but here we have the sort by,
‫the selected and then also the style.select.
‫And so then indeed it is getting all the props
‫that I have spread now into that element.
‫So both test and type.
‫And so if you have multiple props
‫that you just want to receive here
‫and then pass them down into another element
‫or another component, then you can use this trick.
‫So you receive all the props here
‫and then you simply spread them
‫into that other component that should receive all of them.
‫so then you don't have to manually specify them here.
‫Or actually, I want this.
‫What I do not want is this test prop.
‫But anyway, now what we also need here of course
‫is a way of handling that an element has been clicked.
‫So here we will now create our function for that.
‫So let's call it handle change.
‫And then here,
‫the select component should of course
‫be able to receive that.
‫So let's come here.
‫And then on change
‫is on change.
‫Okay, and I think with this
‫we really made this component here 100% reusable
‫and can now use it in many different places
‫in the app and in many other apps as well.
‫So let's close this and then here,
‫we need to of course write this function.
‫So here we receive the event and then we need
‫to set that value that we received there
‫to the state again, so to the state in the URL.
‫So again, searchParams
‫and setSearchParams.
‫And then just like before
‫we then do searchParams.set,
‫and here let's call the field sortBy.
‫And so notice how here this field will always
‫be called sort by.
‫So we don't have the dynamic field name
‫like we had with the filter.
‫And then here the value is just gonna be e.target.value.
‫So just like always.
‫And then here it's time to call setSearchParams
‫and pass that in.
‫Now here we could also abstract all this logic
‫into a nice custom hook that might be called
‫something like use URL.
‫But here I will not do that
‫because that would be making it a bit too opinionated.
‫But of course you could totally do that.
‫So you could create a use URL hook,
‫and for example, that hook could then return a read URL
‫and a update URL function.
‫So then you could simplify this whole thing here
‫a little bit more.
‫But in any case, let's now check if this actually works.
‫And yeah, for that, all we have to do
‫is to click here and see if that is added to the URL then
‫and indeed, there it is.
‫So we already had the discount part here.
‫And so then React Router is smart enough to simply add that
‫to the search or to the query string by adding the end.
‫And then here we get or sort by field
‫with the value of regular price, great.
‫And of course if we start it with an empty string
‫then whatever value we now select a tier
‫would then get added like this.
‫Nice, and now just to finish this part here
‫let's also get the currently selected value
‫so that we can then now basically make that here,
‫the selected one.
‫So if we reload the page, for example with this URL,
‫then of course this value
‫in the select field should be selected by default.
‫So that is basically exactly what we did
‫with the filter before.
‫So searchParams.get,
‫and as a default value,
‫here we can just use an empty string
‫because that will then just select the first element.
‫And so finally, here we then pass in
‫the value prop that we specified earlier
‫and set it to sort by.
‫So let's just test that.
‫So here, let's select sort by price high first.
‫And now as we select this
‫then here it immediately goes back to that value.
‫Great, so this part is done, this part is also done.
‫And so all we have to do is now read
‫that value here in the table and then do the sorting.
‫So let's maybe first here,
‫say that this is for filter,
‫and then second, let's do
‫the sort.
‫So sortBy should be, once again,
‫searchParams.get,
‫sortBy or then by default
‫and here we cannot use the empty string
‫but instead the actual value.
‫So startDate.ascending,
‫and then remember how we actually encoded these two values
‫into the string.
‫So both the fields and the direction.
‫And so now we need to get both of them from there.
‫So what we're gonna do is sortBy.split
‫this string by the dash.
‫So this will then return an array to us.
‫And so let's then destructure that.
‫So the first value is gonna be called the field
‫and then the direction.
‫Okay, and then let's create sorted cabins
‫which will be based on the previous step.
‫So the filtered cabins.
‫So this is basically like a sequence where first
‫we take all the cabins, then we filter them
‫and then we use those filtered ones and sort them.
‫And so for that we can use JavaScript's sort method.
‫And so this will always take in these two values
‫and then we just need to subtract them from one another.
‫And we already did this before,
‫and I already explained it in depth
‫in the JavaScript review section.
‫So here we now need then the value of course,
‫for example a.price
‫minus b.price.
‫But here in this situation,
‫of course we cannot hard code the value here.
‫And instead, we need to pass in this field name
‫that we actually want to sort by.
‫And so we use these brackets.
‫And then here again.
‫All right and so this is the first step
‫and next we also need to take care of the direction.
‫So the way we're gonna do that is that
‫right now, this way of sorting,
‫basically sorts it in an as sending way.
‫But if we want to sort it in a descending way
‫we need to convert the positive number
‫that this here is gonna create to a negative number.
‫Or if this is a negative number
‫then we need to convert it to a positive number.
‫Again, that's just how the sort method here works.
‫And so one nice trick
‫that we can use here is to create a modifier.
‫So basically a value that we will then multiply.
‫And so here, if the direction is ascending
‫which is the default of the sort method
‫then the modifier will just become one.
‫And so then nothing will change
‫but otherwise it will be minus one.
‫And so then here we just multiply this with our modifier.
‫Okay, and now here we no longer use the filtered cabins
‫but actually these sorted cabins.
‫And here apparently we have some problem.
‫Alright, so let's see what's going on.
‫Maybe we can start by logging here
‫the field and direction to the console.
‫Now but here, everything looks correct to me.
‫Let's also check the modifier and the sorted cabins.
‫And now here we actually do get not a number,
‫so ah, of course we cannot multiply the entire array here
‫by the modifier but just the result
‫of this operation right here.
‫So let's wrap that into parenthesis
‫to give it priority and then multiply that.
‫And beautiful.
‫So now that seems to work.
‫So let's now sort by the price.
‫And that seems to be working.
‫So we start with the low, and if we click on high
‫then indeed it gets sorted the other way around
‫and the capacity is exactly the same and also the name.
‫Beautiful, so now we created two very nice
‫and flexible and reusable components here with this filter
‫and this sort that you will be able to reuse
‫in your own projects in the future if you'd like.
‫But before that, we will actually also reuse it
‫here in this project in the bookings table.
‫And so let's move on now
‫and first implement this bookings table.
‫And then we will also sort and filter that data as well.