Module 9 Summary
This lesson is a summary of the work we've done in Module 9.0.
📝 This module's quiz can be found - here.
🗒️ Solutions for this module's quiz can be found - here.
In this module, we'll set up the functionality that will allow users to search for a collection of listings based on location.
Server Project#
src/graphql/typeDefs.ts
#
We've updated the root-level listings
query field to accept an optional location
argument. When the location
argument is provided, the listings
field is to return the collection of listings that pertain to the specific location
that is being searched for.
type Query {
authUrl: String!
user(id: ID!): User!
listing(id: ID!): Listing!
listings(
location: String
filter: ListingsFilter!
limit: Int!
page: Int!
): Listings!
}
src/graphql/resolvers/Listing/index.ts
#
In the listings()
resolver function within the listingResolvers
map, we check to see if the location
argument has been provided. If location
exists, we determine the country
, admin
, and city
of the location being searched for by using Google's Geocoding API. When the geocoded information of the location is determined, we query for the listings in the "listings"
collection that have the country
, admin
, and/or city
of the location being searched for.
listings: async (
_root: undefined,
{ location, filter, limit, page }: ListingsArgs,
{ db }: { db: Database }
): Promise<ListingsData> => {
try {
const query: ListingsQuery = {};
const data: ListingsData = {
region: null,
total: 0,
result: []
};
if (location) {
const { country, admin, city } = await Google.geocode(location);
if (city) query.city = city;
if (admin) query.admin = admin;
if (country) {
query.country = country;
} else {
throw new Error("no country found");
}
const cityText = city ? `${city}, ` : "";
const adminText = admin ? `${admin}, ` : "";
data.region = `${cityText}${adminText}${country}`;
}
let cursor = await db.listings.find(query);
if (filter && filter === ListingsFilter.PRICE_LOW_TO_HIGH) {
cursor = cursor.sort({ price: 1 });
}
if (filter && filter === ListingsFilter.PRICE_HIGH_TO_LOW) {
cursor = cursor.sort({ price: -1 });
}
cursor = cursor.skip(page > 0 ? (page - 1) * limit : 0);
cursor = cursor.limit(limit);
data.total = await cursor.count();
data.result = await cursor.toArray();
return data;
} catch (error) {
throw new Error(`Failed to query listings: ${error}`);
}
}
},
src/lib/api/Google.ts
#
In the Google
object instance within the src/lib/api/Google.ts
file, we've introduced a geocode()
function that runs the Geocoding API from Google Maps services.
export const Google = { geocode: async (address: string) => {
const res = await maps.geocode({ address }).asPromise();
This page is a preview of TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two