AirNYT: Firebase Favoriting & Final UI Tweaks

This is the last tutorial in a series called AirNYT, which shows how to the clone the Airbnb search interface to explore NYT travel recommendations. This section of the series will cover:

  • Installing Firebase to allow for user authentication and saving favorites
  • Creating a sign up / login page using Firebase-ui
  • Adding favorite buttons and styling them appropriately according to sign in state
  • Adding a user photo dropdown menu
  • Adding a help-area right-side pop-out Drawer like Airbnb has
  • Setting up toggling of the list vs. map on mobile
  • Creating clickable popup cards on the Map Markers

Repo: https://github.com/kpennell/airnytwithfavorting

Demo: airnytwithfavorting.surge.sh

Installing Firebase to allow for user authentication and saving favorites

As users scroll through these NYT travel recs, I’m hoping some will want an easy to save where they want to go some will want a way to save their favorites. This requires a backend with user authentication. Firebase is a really easy way to do this in React applications. I’m going to show the basic setup for how to let users login and save/retrieve their favorites.

First, install firebase and react-firebaseui using Yarn. Next, setup a basic Firebase project within Firebase (here’s a great tutorial on how to do this).

Next, you’ll need to put the basic config items (given to you by firebase) into your index.js:

Something like this:

Firebase folds fairly easily into React components. The most common way to get and incorporate firebase data into React components is via the lifestyle hook componentDidMount. Here’s an example of this in action:

Above is a very common pattern for working with firebase data in React. The parent container gets the data from the firebase ref (a specific part of the JSON tree), saves it in state and passes it to the child components to use. And that’s what we’ll do here for building out this favoriting functionality. Below are the steps I took to build out the Airbnb-esque favorites for this app.

Building a favoriting component (with buttons that style according to whether they are in favorites).

The favoriting component needs empty heart icons and full heart icons, depending on whether the item has been favorited. This component also needs to either add or remove the favorite, depending on whether it is in there or not. The end goal is something like this:

Below is what my FavoritingButton component looks like. Note that this component receives the favorites array and user object (from firebase) as a prop. I’ll comment in the code below to explain what’s going on:

I absolute positioned the favoriting heart icons within the LocationCard(s) and styled them a bit.

Built a signup/login modal using firebase-ui

Next, we need a way to login and signup users so they can use these favorite buttons. In keeping with the imitating Airbnb streak, I created a signup/login modal. Like most popup modals, this one will pop open above all the other content and close by clicking outside of it.

The core code for this modal is simple enough:

This uses the material-ui Grid to create a simple form page. StyledFirebaseAuth /> is an amazingly simple component given to us by the react-firebaseui library. It creates a nice login component with as many ways to login as we setup (e.g. Github, Facebook). It’s config settings also need to be configured in the index.js like so:

But with very little work, I can get some nice login buttons:

I put this modal component as a child in my App.js. Whether it is open or closed will be toggled with a simple function that changes a state value:

Hide or Show Menu Items According to Login State

Within Airbnb (and many major sites), the menu will show the user’s face with a dropdown menu if the user is logged in. If the user is logged out, it will show Button/Menu Items like sign up and login.

Let’s set this up now within the AirNYT app.

First, we need to pass some new props to our Header component within App.js:

Now, within Header, we need to add a menu and hide/show this menu according to whether user exists. So around login and signup, I wrap the inline conditional test like so:

But what if there is a user? What should I show then? Maybe something like this:

We get a basic little dropdown menu with a logout button. Notice how easy it is to pull in user.photoURL? This is the beauty of firebase auth-ing. Average/intermediate developers can very quickly put a professional touch on their app (like importing a user’s facebook or google photo into a new app). I put a grey border around the Avatar to make it a look a bit more airbnb-ish.

Obviously I skipped a lot of things here like styling and how all the parents and children get wired up, but the gist is all here. Firebase makes it incredibly simple to add a backend and user authing to an app like this.

Adding a help right-side pop-out Drawer like Airbnb has

Airbnb has a popout right-side help drawer on their desktop web app. It features access to common questions:

My guess would be this allows easy access to common questions while also not breaking users out of the buying flow (like if they immediately redirected to the help center). But who knows 🤷‍♂️? Either way, I wanted to show how easy it was to recreate this within material-ui. Here is my simple HelpDrawer component:

Within App.js, my drawer works much like the LoginSignupModal. It sits there and can be toggled open/close with a simple function:

And with that, we end up with a nice start for right-side Drawer. I need to cut this tutorial short, but this would an excellent place to show a list of user favorites.

Mobile: toggle map vs. list

Our desktop map vs. list toggling experience matches that of Airbnb and works fine. On a desktop sized screen, the map and list of cards can share the screen. Obviously, this won’t cut it on mobile. And so Airbnb (and many others) allow users to toggle between the map and list like so:

With a bit zIndex trickery and some responsive breakpoints in our CSS, this is actually fairly easily to emulate.

The action will happen within my LocationsGrid.js (where the List and Map live). First, I’ll show you what I accomplished:

To accomplish this, I need a state value and a toggling function

Now I need a floating action button:

Now I need to show and hide the map vs. the list. This is done easily with zIndex:

div className={classes.mapDiv} style={ this.state.mobileMapShowing ? {zIndex:4} : {zIndex:1} }>

So, in English, this toggles the zIndex from 1 to 4, depending on whether the value mobileMapShowing is true or false. Within my styles, the list has a higher initial zIndex vs. the map.

And just like that, we have a nice map vs. list toggling functionality on mobile. One button serves to toggle the zIndex of the map, thus hiding/showing it.

Map: Popup Cards on Markers

Airbnb’s map interface features clickable markers that show more info. This can be enormously helpful for exploring geographic data and keeping users from having to hop back and forth between the list and the map. The airbnb cards look something like this:

Here’s how I implement this card within my MapMarker. Within MapAndMarkers, I need to add some props onto the map marker:

I’m adding the user and favorites props so that the FavortingButton will work on the card. handleMarkerClick={this.openMarkerPopup} and closeAllMarkers={this.closeAllMarkers} refer to the following functions:

Now, within MapMarker.js, there’s a bit of logic going on. It’s actually fairly straightforward: There’s 1 condition for the default marker, 1 condition for the hovered card (which changes the background color on the marker), and 1 condition for the clicked marker (which pop ups a card like interface).

And just like that, we get a fairly intuitive popup card on the map.

Final Thoughts

Thanks for following along with this tutorial. Hopefully it showed you one way of piecing together some components to make an interactive Airbnb-esque map interface. Feel free to submit suggestions and pull requests to the Github repo for this project.

https://github.com/kpennell/airnytwithfavorting

This is the last tutorial in a series called AirNYT, which shows how to the clone the Airbnb search interface to explore NYT travel recommendations. This section of the series will cover:

  • Installing Firebase to allow for user authentication and saving favorites
  • Creating a sign up / login page using Firebase-ui
  • Adding favorite buttons and styling them appropriately according to sign in state
  • Adding a user photo dropdown menu
  • Adding a help-area right-side pop-out Drawer like Airbnb has
  • Setting up toggling of the list vs. map on mobile
  • Creating clickable popup cards on the Map Markers

Repo: https://github.com/kpennell/airnytwithfavorting

Demo: airnytwithfavorting.surge.sh

Installing Firebase to allow for user authentication and saving favorites

As users scroll through these NYT travel recs, I’m hoping some will want an easy to save where they want to go some will want a way to save their favorites. This requires a backend with user authentication. Firebase is a really easy way to do this in React applications. I’m going to show the basic setup for how to let users login and save/retrieve their favorites.

First, install firebase and react-firebaseui using Yarn. Next, setup a basic Firebase project within Firebase (here’s a great tutorial on how to do this).

Next, you’ll need to put the basic config items (given to you by firebase) into your index.js:

Something like this:

Firebase folds fairly easily into React components. The most common way to get and incorporate firebase data into React components is via the lifestyle hook componentDidMount. Here’s an example of this in action:

Above is a very common pattern for working with firebase data in React. The parent container gets the data from the firebase ref (a specific part of the JSON tree), saves it in state and passes it to the child components to use. And that’s what we’ll do here for building out this favoriting functionality. Below are the steps I took to build out the Airbnb-esque favorites for this app.

Building a favoriting component (with buttons that style according to whether they are in favorites).

The favoriting component needs empty heart icons and full heart icons, depending on whether the item has been favorited. This component also needs to either add or remove the favorite, depending on whether it is in there or not. The end goal is something like this:

Below is what my FavoritingButton component looks like. Note that this component receives the favorites array and user object (from firebase) as a prop. I’ll comment in the code below to explain what’s going on:

I absolute positioned the favoriting heart icons within the LocationCard(s) and styled them a bit.

Built a signup/login modal using firebase-ui

Next, we need a way to login and signup users so they can use these favorite buttons. In keeping with the imitating Airbnb streak, I created a signup/login modal. Like most popup modals, this one will pop open above all the other content and close by clicking outside of it.

The core code for this modal is simple enough:

This uses the material-ui Grid to create a simple form page. StyledFirebaseAuth /> is an amazingly simple component given to us by the react-firebaseui library. It creates a nice login component with as many ways to login as we setup (e.g. Github, Facebook). It’s config settings also need to be configured in the index.js like so:

But with very little work, I can get some nice login buttons:

I put this modal component as a child in my App.js. Whether it is open or closed will be toggled with a simple function that changes a state value:

Hide or Show Menu Items According to Login State

Within Airbnb (and many major sites), the menu will show the user’s face with a dropdown menu if the user is logged in. If the user is logged out, it will show Button/Menu Items like sign up and login.

Let’s set this up now within the AirNYT app.

First, we need to pass some new props to our Header component within App.js:

Now, within Header, we need to add a menu and hide/show this menu according to whether user exists. So around login and signup, I wrap the inline conditional test like so:

But what if there is a user? What should I show then? Maybe something like this:

We get a basic little dropdown menu with a logout button. Notice how easy it is to pull in user.photoURL? This is the beauty of firebase auth-ing. Average/intermediate developers can very quickly put a professional touch on their app (like importing a user’s facebook or google photo into a new app). I put a grey border around the Avatar to make it a look a bit more airbnb-ish.

Obviously I skipped a lot of things here like styling and how all the parents and children get wired up, but the gist is all here. Firebase makes it incredibly simple to add a backend and user authing to an app like this.

Adding a help right-side pop-out Drawer like Airbnb has

Airbnb has a popout right-side help drawer on their desktop web app. It features access to common questions:

My guess would be this allows easy access to common questions while also not breaking users out of the buying flow (like if they immediately redirected to the help center). But who knows 🤷‍♂️? Either way, I wanted to show how easy it was to recreate this within material-ui. Here is my simple HelpDrawer component:

Within App.js, my drawer works much like the LoginSignupModal. It sits there and can be toggled open/close with a simple function:

And with that, we end up with a nice start for right-side Drawer. I need to cut this tutorial short, but this would an excellent place to show a list of user favorites.

Mobile: toggle map vs. list

Our desktop map vs. list toggling experience matches that of Airbnb and works fine. On a desktop sized screen, the map and list of cards can share the screen. Obviously, this won’t cut it on mobile. And so Airbnb (and many others) allow users to toggle between the map and list like so:

With a bit zIndex trickery and some responsive breakpoints in our CSS, this is actually fairly easily to emulate.

The action will happen within my LocationsGrid.js (where the List and Map live). First, I’ll show you what I accomplished:

To accomplish this, I need a state value and a toggling function

Now I need a floating action button:

Now I need to show and hide the map vs. the list. This is done easily with zIndex:

So, in English, this toggles the zIndex from 1 to 4, depending on whether the value mobileMapShowing is true or false. Within my styles, the list has a higher initial zIndex vs. the map.

And just like that, we have a nice map vs. list toggling functionality on mobile. One button serves to toggle the zIndex of the map, thus hiding/showing it.

Map: Popup Cards on Markers

Airbnb’s map interface features clickable markers that show more info. This can be enormously helpful for exploring geographic data and keeping users from having to hop back and forth between the list and the map. The airbnb cards look something like this:

Here’s how I implement this card within my MapMarker. Within MapAndMarkers, I need to add some props onto the map marker:

I’m adding the user and favorites props so that the FavortingButton will work on the card. handleMarkerClick={this.openMarkerPopup} and closeAllMarkers={this.closeAllMarkers} refer to the following functions:

Now, within MapMarker.js, there’s a bit of logic going on. It’s actually fairly straightforward: There’s 1 condition for the default marker, 1 condition for the hovered card (which changes the background color on the marker), and 1 condition for the clicked marker (which pop ups a card like interface).

And just like that, we get a fairly intuitive popup card on the map.

Final Thoughts

Thanks for following along with this tutorial. Hopefully it showed you one way of piecing together some components to make an interactive Airbnb-esque map interface. Feel free to submit suggestions and pull requests to the Github repo for this project.

https://github.com/kpennell/airnytwithfavorting

Kyle Pennell
Kyle Pennell is a marketer and writer with a variety of technical chops (JavaScript, Google Sheets/Excel, WordPress, SEO). He loves clear and helpful copy and likes automating things and making web apps (mostly maps). Found at kyleapennall.com and many other digital spaces