Module 13 Summary

This lesson is a summary of the work we've done in Module 13.0.

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two course and can be unlocked immediately with a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two with a single-time purchase.

Thumbnail for the \newline course TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two
  • [00:00 - 00:14] In this module, we've created the capability for a user to actually create a booking on another user's listing. In our GraphQL type definitions within our server project, we've introduced another root-level mutation called Create Booking.

    [00:15 - 00:38] And this Create Booking mutation receives an input object of type Create Book ing Input. And this Create Booking Input essentially contains the information necessary that we'll need to actually conduct the mutation, which is the payment source, which will be provided by the Stripe React element on the client, the ID of the listing that's being booked, as well as the check-in and checkout dates of the booking.

    [00:39 - 00:54] And when this mutation is to be resolved, it will return the actual created booking object as the returned item. In our booking resolvers map, we've established the Create Booking mutation res olver function.

    [00:55 - 01:05] This mutation is probably the biggest mutation function we have in our server and does quite a few different things. In the very beginning, we destruct the properties we need from the input argument.

    [01:06 - 01:16] We check to see if the viewer who's logged into our application is actually making this request, and we run the authorized function available to do this. And if this viewer doesn't exist, we throw an error.

    [01:17 - 01:27] We then look to find the listing document within the listings collection that matched the ID of the input provided. And if this listing document can't be found, we'll throw an error as well.

    [01:28 - 01:41] We also attempt to check to see if the viewer is trying to book their own listing, and we do this by comparing the host field within a listing document, which is an ID, with the ID field of the viewer document. And if they're the same, we throw an error.

    [01:42 - 01:50] We then construct date objects from the check-in and checkout values provided on the client. And when it's sent to the server, these check-in and checkout values are strings.

    [01:51 - 02:03] So we construct date objects to do some simple comparison between them. And we see if the checkout date object is less than the check-in date object, which basically means is the checkout date selected before the check-in date.

    [02:04 - 02:13] If that happens, we throw an error as well. If no errors are thrown just yet, we then attempt to create a new Bookings Index object for the listing.

    [02:14 - 02:28] Bookings index is essentially the field within a listing document that determine which Bookings have been made already on this listing. We have a function called resolve bookings index function that simply retrieves the existing Bookings Index, and the check-in and checkout dates the user is selected.

    [02:29 - 02:55] And we simply go through the existing Bookings Index, and for any dates the user has selected, it hasn't been selected before, we simply add the true value to specify that this date has already been booked. If we come across a date that the user is already booked or somebody else is already booked, and we determine this while we loop through the Bookings Index, we throw an error to determine the fact that the dates that have been selected have already overlapped dates that might have already been booked.

    [02:56 - 03:17] Once this new Bookings Index object is resolved, we then determine the total price that the user is attempting to actually pay by booking this listing. And though we can pass this value from the client, what we do is we simply compare the check-in and checkout dates on the server and multiply it with the price within the listing document, which is the price per day.

    [03:18 - 03:38] And this gives us the total price with determined by the number of days that have been booked. We then determine to find the host document or the user document of the person who owns the listing, and we find this by simply checking for the ID within the user's collection for a document in which it matches the host field within the listing document.

    [03:39 - 03:59] If this host doesn't exist, or if the wallet ID value within this host doesn't exist, this basically means the host can't be found or is not connected with Stripe, and in both cases we'll throw an error. Finally, in this context, when this host does exist, we call a charge function that we've created within our Stripe object.

    [04:00 - 04:19] And this charge function receives the total amount that the person who's making the booking is going to pay, the source of the payment, which is determined from the React Stripe element, and the actual Stripe account. And this Stripe account is the Stripe User ID of the host, which we've kept as the wallet ID of the host document.

    [04:20 - 04:39] And here is where we simply use the charges create function within the existing Stripe client to conduct a charge. We pass in the amount, the currency in which the charge is going to be made, the payment source, and the application fee amount, which is the amount we tiny house make to simply have this application be used.

    [04:40 - 04:48] And in the second options object, we determine the Stripe account in which this payment is going to be paid out to. And here's where we provide the value of the Stripe account argument.

    [04:49 - 05:09] Now keep in mind that this application fee, as well as any Stripe fees, once again, is under the context of being paid out from the connected Stripe account . The person making the payment doesn't pay these additional fees, however, we'll take this small fee amount from the total amount from the person who's about to receive the total payment, which is the host of the listing.

    [05:10 - 05:20] At this moment, things should have worked out the way we wanted. We found the host, we've created the Stripe charge, so now we simply have to update all the documents that we want within all the different collections.

    [05:21 - 05:38] At the very beginning, we're going to actually insert into the Bookings collection a new Bookings document, and this is to basically specify the new booking that has been made. And then we're going to update the host user document, and then basically increment their income with the total amount they've just made.

    [05:39 - 05:55] We'll then update the person who's making the booking, the tenant, and essentially introduce a new ID value within the Bookings array field that exists within the user document. And lastly, we're going to update the listing document or the listing that's being booked within the listings collection.

    [05:56 - 06:14] To essentially do two things, we're going to update the Bookings index of this particular listing, and we're going to introduce a new ID of the booking that's been made into the Bookings field of the newly updated listing. And lastly, we'll have this mutation function simply return the inserted booking documents.

    [06:15 - 06:34] And if we take a look at our client application, the most of the UI work we've made has been within the context of a single listing component section. And in this parent listing component, we now have a child component called List ing Create Booking Model that we actually render within the template.

    [06:35 - 07:03] And this model is only shown under the pretense that the user has selected the relevant dates, and have actually clicked the button within the Listing Create Booking elements to actually pay out and make the booking. And when we take a look at this Listing Create Booking Model component, we'll see that it's a wrapped component, or in other words, a higher order component where we use the inject stripe higher order function from the react stripe elements library.

    [07:04 - 07:19] And this inject stripe higher order function essentially allows us to provide a stripe prop object that contains information about the payment that the user is about to make. We also use a card element component from the react stripe elements library.

    [07:20 - 07:36] And this card element component is essentially the actual UI element where the user can provide their debit or credit card information. When the user provides their payment information and clicks the book button, we trigger a component function called Handle Create Booking.

    [07:37 - 07:51] And this is where we essentially would determine or retrieve the stripe token from the stripe prop object available by running the Create Token function. And with this stripe token, we're able to determine the source of the payment made with stripe token.id.

    [07:52 - 08:11] And this is where we actually conduct the Create Booking mutation. We pass in the ID of the Listing, the source of the payment, Stripe Token ID, as well as the check in and check out dates. Within our client application, we've been using Moment to keep track of our date objects. However, when we pass it to the server, we want to pass it as a string and we format it in this particular format.

    [08:12 - 08:25] Year, year, year, month, month, day, day. And another thing to note in our root level parent app component, we've also imported a few things from react stripe elements. And that is the Stripe provider component as well as the elements components.

    [08:26 - 08:44] We use the Stripe provider components and essentially wrap our entire application to make Stripe available everywhere. And we use the elements components to wrap the component in our application in which the Stripe elements we're going to use are going to be rendered. And that 's only within the Listing component.

    [08:45 - 08:58] And at this moment in time, we've practically concluded the main pieces within our application by conducting this large piece of allowing a user to actually pay another user for simply booking a listing of theirs.