No description, website, or topics provided.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
app Reseed database for presentation Sep 1, 2017
bin
config
db
docs
frontend
images Add demo gif Oct 4, 2017
lib
log
public
test
tmp
vendor/assets
.README.md.swp
.gitignore Create bnb schema and model with appropriate validations Aug 24, 2017
Gemfile
Gemfile.lock
README.md Update README.md Oct 4, 2017
README_BACKUP_7260.md
README_BASE_7260.md
README_LOCAL_7260.md
README_REMOTE_7260.md
Rakefile
config.ru
package.json
webpack.config.js

README.md

WhereBnb?

Live demo

WhereBnb? is a web application inspired by AirBnb that allows users to search for and book bed and breakfasts. It uses the Ruby on Rails framework on the back end. On the front end, it uses a combination of React.js and Redux. The database used is PostgreSQL.

Demo of bnb index page

Current Features

Google Map API Search

The most prominent feature on the application, the map search, appears on the search page. The Google Map interface allows users to search for their desired bed and breakfasts by location using the intuitive dragging and zoom features.

This feature works by means of an event listener that waits for idle events, which occur after any sort of change to the viewport, e.g., drags and zooms in and out. These events trigger a callback function that takes the latitude and longitude coordinates of the Northeastern and Southwestern most points of the map viewport and gives them as a bounds filter argument to an updateFilter method.

// frontend/components/map/bnb_map.jsx

this.map = new google.maps.Map(this.mapNode, mapOptions);

// ....

this.map.addListener('idle', () => {
  const latLngBounds = this.map.getBounds();
  const northEast = {
    lat: latLngBounds.getNorthEast().lat(),
    lng: latLngBounds.getNorthEast().lng(),
  };
  const southWest = {
    lat: latLngBounds.getSouthWest().lat(),
    lng: latLngBounds.getSouthWest().lng(),
  }
  const bounds = {
    northEast,
    southWest,
  };
  this.props.updateFilter('bounds', bounds);

The updateFilter method then makes a request to the Rails framework with the bounds filter (among others such as price and room type). The Rails controller then queries the database for Bed and Breakfasts that are within the viewport bounds.

# app/controllers/api/bnbs_controller.rb

class Api::BnbsController < ApplicationController
  def index
    bnbs = Bnb.in_bounds(params[:bounds])
    # ...
    # ...
  end

  # ...

end
# app/models/bnb.rb

class Bnb < ApplicationRecord

  # ...

  def self.in_bounds(bounds)
    self
      .where(["lat < ?", bounds[:northEast][:lat]])
      .where(["lat > ?", bounds[:southWest][:lat]])
      .where(["lng < ?", bounds[:northEast][:lng]])
      .where(["lng > ?", bounds[:southWest][:lng]])
  end

  # ...

end

Upon reception, it sends a response with the in-bounds bed and breakfasts to the request point in the front end. This results in an update to Redux store, which ultimately triggers a re-render in the bed and breakfast index component to the left of the map.

Bookings

Another pivotal feature of WhereBnb? is the ability to book bed and breakfasts directly on the show page. The inputs are formatted to facilitate the user's selection of check-in and check-out dates.

The most notable aspect of this feature are the backend validations that ensure that a user cannot add a booking to the database that clash with a pre-existing booking. This is done by making a query to the database for a pre-existing booking for the same Bed and Breakfast that clashes with the current booking. If this query yields any results, the current booking will not be persisted to the database and instead the user will receive an appropriate error message. The following code handles this logic.

class Booking < ApplicationRecord

  # ...

  validate :no_booking_overlap

  def no_booking_overlap
    unless overlapping_bookings.empty?
      errors[:base] << 'Booking conflicts with prior booking'
    end
  end

  def overlapping_bookings
    Booking
      .where.not(id: self.id)
      .where(bnb_id: bnb_id)
      .where.not('start_date > :end_date OR end_date < :start_date',
                 start_date: start_date, end_date: end_date)
  end
end

Future Features

User Profiles

Create a page for users to customize their settings and allow them to view their bookings and related personal information.

Messaging

Create an inbox page and messaging functionality so prospective and actual bookers can communicate with hosts to improve the bed and breakfast experience.