Module 13 Summary
This lesson is a summary of the work we've done in Module 13.0.
π This module's quiz can be found - here.
ποΈ Solutions for this module's quiz can be found - here.
In this module, we've created the capability for users to book listings in our application.
Server Project#
src/graphql/typeDefs.ts
#
In the GraphQL API type definitions of our server project, we introduced a new root-level mutation field labeled createBooking
.
type Mutation {
logIn(input: LogInInput): Viewer!
logOut: Viewer!
connectStripe(input: ConnectStripeInput!): Viewer!
disconnectStripe: Viewer!
hostListing(input: HostListingInput!): Listing!
createBooking(input: CreateBookingInput!): Booking!
}
The createBooking
mutation accepts an input
that is to have an object type of CreateBookingInput
. The input
is to contain a series of field values that describe the booking that is to be created, such as the id
of the listing being booked, the payment source being made, and the check-in/check-out dates of the booking
input CreateBookingInput {
id: ID!
source: String!
checkIn: String!
checkOut: String!
}
src/graphql/resolvers/Booking/index.ts
#
We've constructed the resolver function for the createBooking
mutation in the bookingResolvers
map within the src/graphql/resolvers/Booking/index.ts
file. The createBooking()
resolver function does a few different things:
The utility
authorize()
function is first called to verify the viewer making the request.The listing document being booked is found from the
id
argument passed in as input to the mutation.A check is made to verify the viewer making the booking is not the host of the listing.
Another check is made to verify the check-out date is not before the check-in date of the booking.
The
bookingsIndex
object of the listing is updated to recognize the new dates that have been booked for the listing.The total price of the booking is determined based on the number of days the listing is being booked.
A check is made to verify the host is still connected with Stripe such that they will be able to receive payment.
A Stripe charge is conducted to pay the host from the person creating the booking.
The
"bookings"
collection is updated with a new booking document.The
income
of the user document of the host is updated with the new amount of income earned.The
bookings
field of the user document of the viewer is updated with theid
of the new booking that has been made.The listing document of the listing being booked is updated to have a new
bookingsIndex
object. Thebookings
field of the listing document is also updated with theid
of the new booking that has been made.
export const bookingResolvers: IResolvers = { Mutation: {
createBooking: async (
_root: undefined,
{ input }: CreateBookingArgs,
{ db, req }: { db: Database; req: Request }
): Promise<Booking> => {
try {
const { id, source, checkIn, checkOut } = input;
let viewer = await authorize(db, req);
if (!viewer) {
throw new Error("viewer cannot be found");
}
const listing = await db.listings.findOne({
_id: new ObjectId(id)
});
if (!listing) {
throw new Error("listing can't be found");
}
if (listing.host === viewer._id) {
throw new Error("viewer can't book own listing");
}
const checkInDate = new Date(checkIn);
const checkOutDate = new Date(checkOut);
if (checkOutDate < checkInDate) {
throw new Error("check out date can't be before check in date");
}
const bookingsIndex = resolveBookingsIndex(
listing.bookingsIndex,
checkIn,
checkOut
);
const totalPrice =
listing.price *
((checkOutDate.getTime() - checkInDate.getTime()) / 86400000 + 1);
const host = await db.users.findOne({
_id: listing.host
});
if (!host || !host.walletId) {
throw new Error(
"the host either can't be found or is not connected with Stripe"
);
}
This page is a preview of TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two