¶
Here at Fetch, we love dogs, and hope you do too! Your task is to build a website to help a dog-lover like yourself search through a database of shelter dogs, with the hope of finding a lucky dog a new home!
You first should have users enter their name and email on a login screen. Then, you should use this information to hit our login endpoint to authenticate with our service (see API Reference below).
Once a user is successfully authenticated, they should be brought to a search page where they can browse available dogs. This page must meet the following requirements:
Users should be able to select their favorite dogs from the search
results. When finished searching, they should be able to generate a
match based on dogs added to the favorites list. A single match will be
generated by sending all favorited dog IDs to the
/dogs/match
endpoint. You should display this match however
you see fit.
As for everything else, you have free rein, so get creative! We strongly encourage you to go beyond the minimum requirements to build something that showcases your strengths.
You may find it helpful to make use of a component library.
Please provide a link to your deployed site and your public code repository via Greenhouse.
An engineer will review the code you submit. You will be evaluated based on:
If at all possible, we prefer a public repository because we do not know which engineer will be evaluating your submission. If you are still uncomfortable providing a public repository, you can work with your recruiter to provide access to the reviewing engineer.
There is no time limit for the exercise. Out of respect for your time, we designed this exercise with the intent that it should take you a few hours. However, you may take as much time as you need to complete the work.
For any further questions or clarifications, please reach out to your recruiter.
We provide our own backend to facilitate searching/fetching dog info.
The base URL is
https://frontend-take-home-service.fetch.com
.
Here is the Typescript interface for the Dog objects returned by our API:
interface Dog {
: string
id: string
img: string
name: number
age: string
zip_code: string
breed }
We also provide endpoints for fetching location data, which should be useful if you’d like to implement filtering dogs by location. Here is the Typescript interface for the Location objects returned by our API:
interface Location {
: string
zip_code: number
latitude: number
longitude: string
city: string
state: string
county }
interface Coordinates {
: number;
lat: number;
lon }
You will need to hit the login endpoint in order to access other
endpoints. A successful request to the login endpoint will return an
auth cookie included in the set-cookie
response header.
It’s an HttpOnly
cookie, so you will not be able to access
this value from any Javascript code (nor should you need to). Your
browser will automatically send this cookie with all successive
credentialed requests to the API. Note that you will need to pass a
config option in order to send credentials (cookies) with each request.
Some documentation to help you with this:
fetch
(set
credentials: 'include'
in request config)axios
(set
withCredentials: true
in request config)Postman will do this for you automatically.
POST /auth/login
name
- the user’s nameemail
- the user’s emailExample
// API Request Function
...
: {
body: string,
name: string
email
}...
200 OK
An auth cookie, fetch-access-token
, will be included in
the response headers. This will expire in 1 hour.
POST /auth/logout
Hit this endpoint to end a user’s session. This will invalidate the auth cookie.
GET /dogs/breeds
Returns an array of all possible breed names.
GET /dogs/search
The following query parameters can be supplied to filter the search results. All are optional; if none are provided, the search will match all dogs.
breeds
- an array of breedszipCodes
- an array of zip codesageMin
- a minimum ageageMax
- a maximum ageAdditionally, the following query parameters can be used to configure the search:
size
- the number of results to return; defaults to 25
if omittedfrom
- a cursor to be used when paginating results
(optional)sort
- the field by which to sort results, and the
direction of the sort; in the format sort=field:[asc|desc]
.
breed
name
age
sort=breed:asc
Returns an object with the following properties:
resultIds
- an array of dog IDs matching your
querytotal
- the total number of results for the query (not
just the current page)next
- a query to request the next page of results (if
one exists)prev
- a query to request the previous page of results
(if one exists)The maximum total number of dogs that will be matched by a single query is 10,000.
POST /dogs
The body should be an array of no more than 100 dog IDs to fetch (no pun intended).
// API Request Function
...
: string[]
body...
Returns an array of dog objects
POST /dogs/match
The body of this request should be an array of dog IDs.
Example
// API Request Function
...
: string[]
body...
This endpoint will select a single ID from the provided list of dog IDs. This ID represents the dog the user has been matched with for adoption.
interface Match {
: string
match }
POST /locations
The body of this request should be an array of no more than 100 ZIP codes.
Example
// API Request Function
...
: string[]
body...
Returns an array of Location objects.
POST /locations/search
The following body parameters can be supplied to filter the search results. All are optional; if none are provided, the search will match all locations.
city
- the full or partial name of a citystates
- an array of two-letter
state/territory abbreviationsgeoBoundingBox
- an object defining a geographic
bounding box:
top
, left
, bottom
,
right
bottom_left
, top_right
bottom_right
, top_left
bottom_left
, top_right
,
bottom_right
, top_left
should have the
following data:
lat
- latitudelon
- longitudetop
, left
, bottom
,
right
should be numbers corresponding to higher latitude,
left-most longitude, lower latitude and right-most longitude
respectively.Additionally, the following body parameters can be used to configure the search:
size
- the number of results to return; defaults to 25
if omittedfrom
- a cursor to be used when paginating results
(optional)The maximum total number of ZIP codes that will be matched by a single query is 10,000.
Example
// API Request Function
...
: {
body?: string,
city?: string[],
states?: {
geoBoundingBox?: number,
top?: number,
left?: number,
bottom?: number,
right?: Coordinates,
bottom_left?: Coordinates
top_left,
}?: number,
size?: number
from
}...
Returns an object with the following properties:
results
- an array of Location objectstotal
- the total number of results for the query (not
just the current page)
{: Location[],
results: number
total }