- Overview
- Getting Started
- Project Structure
- User Interface
- Distribution Build
- Code Documentation
- Integration Tests
- To Do
- License
This is my submission for the Room Key Front End Development Challenge. I ended up working closer to 32 hours than the suggested 8, but I really got into the project. I hope you will forgive the enthusiasm.
Here are the key things I wanted to show:
- Robust, functional interface
- Expanded hotel searching by distance rather than having hotels bound to a location
- Responsive design that's easy to use on any size device
- Localization and language switching
I am always looking to improve, so please don't hesitate to comment on any part of this project. Feedback is welcome and will be put to good use.
-
Install NodeJS if you haven't already.
-
Clone this repository to your local machine, and navigate to it's root directory in your command line interface.
-
Install all required dependencies by running the following command:
npm install
-
Start the server by running the following command:
npm start
-
Navigate to http://localhost:9696/ in your browser.
I chose to use a single page JavaScript application design rather than having users navigate between separate pages. There may be more initial loading, but the overall user experience should be smoother and more dynamic, with less drag on the back end system.
The user interface leverages Backbone.js to manage a modular design pattern. Views render data to templates, and automatically update as data is modified. Dependencies are managed using npm and browserify.
Here is the directory structure for this project:
+---data
| +---hotels
+---public
| +---images
| +---img
| +---src
| +---collections
| +---models
| +---styles
| +---templates
| +---views
+---routes
+---scripts
The back end provided for this coding challenge was written by Room Key staff in NodeJS with existing API methods that returned data from flat JSON files. I would use a full, relational database for a live version of this application to be able to perform more flexible
queries and take advantage of indexing. I imported US ZipCode data and created a new data/zipcodes.json
file to serve up more locations than the
original 3 provided in the coding challenge.
I implement latitude/longitude based distance calculation in the back end based on this formula to be able to find all hotels within a dynamic distance of any given point. Doing so on data from a flat JSON is not optimal, and would not scale well to searching a very large set of hotels. This would likely require a database scheme that supports indexing, caching, or other optimization tricks like first mapping hotels to regions encompassing several adjacent cities and searching distance only on those hotels within a given region.
The back end server provides real-time bundling of all source files. Accessing \index.js
in the browser causes the back end to run browserify to serve a bundled file containing all of the scripts. Accessing \index.css
in the browser causes the back end to run less to generate and serve up a bundled file containing all of the stylesheets.
The user interface code is held within public
. The public/src
directory contains the various collections, models, styles, templates, and views required to render the user interface.
When loaded in a browser, public/index.html
asks the back end for \index.js
and \index.css
, which will automatically be generated containing bundles of all necessary scripts and styles from public/src
.
Many of the interactive input elements are generated using jQuery UI to create a rich experience with less coding time and good cross-browser support.
I am more of a coder than a graphic designer, so I focused on functionality over aesthetics. I personally prefer the "Google aesthetic", featuring flat, simple UI elements that put content and usability first. I chose to emulate much of the existing Room Key color scheme and layout in order to see how it could be adapted to a responsive design.
The massive increase in use of phones, tablets, and other mobile devices means that users are viewing sites on a wide variety of screen sizes. The user interface for this project is designed to adapt to any size screen in order to provide an optimal user experience. This is an area in which I hope to be able to contribute.
Chrome provides an excellent device preview mode, allowing you to easily re-render the interface as it would be displayed on a variety of mobile devices.
The search interface is the primary point of interaction within the application. Users are prompted to enter a city or zipcode for their destination, as well as check-in/check-out dates and a maximum distance within which to find hotels.
The interface will make a location search request to the back end API after a short delay from the most recent key-press. A small loading indicator in the right portion of the search input lets users know that data is being loading. Matching locations are displayed in a drop-down, and the desired location can then be selected by clicking/tapping or using the arrow keys on the keyboard and pressing enter. An error message is displayed if the user attempts to perform a search without first selecting a valid location.
The check-in and check-out fields are pre-populated with the current and following days for convenience. These can be changed by clicking/tapping on either date and selecting a new date from the pop-up calendars. The interface prevents users from selecting a check-out date before their check-in date, and vice-versa. The number of nights the user will stay is displayed next to the check-out field.
Filters are available to further limit and refine search results. Hotel preview cards are rendered in a Pinterest like, stacking layout using the Masonry library. The hotel preview cards are automatically updated as filters are applied.
The location search field is large, taking up the full width. The check-in, check-out, and maximum distance fields are displayed in three columns to save on vertical space. Filters are easily accessible on the left.
The interface automatically adjusts to fit the maximum number of hotel preview card columns. All user elements are touch responsive, and sliders can be moved with touch events thanks to the touchpunch library.
The check-in and check-out fields are displayed in two columns, while the maximum distance slider is displayed below, taking up the full width.
The filter box is moved from the left side of the screen to above the search results, and most of the fields are hidden to avoid taking up too much vertical space. Clicking on the "Filter Search Results" button will expand the search box so that all filters are accessible.
Similar to a vertical iPad, but the interface has resized to show two hotel preview card columns.
A small amount of scrolling down reveals two centered hotel preview card columns
The language selector in the top right is moved down so the site title does not wrap to multiple lines. The search and filter boxes automatically scale to fit.
A small amount of scrolling reveals centered hotel preview cards.
Clicking/tapping on a hotel preview card opens a modal dialog containing details about the selected hotel. This dialog animates up from the selected card to the center of the screen, creating a sense of physicality to the interaction. The dialog can be closed by clicking/tapping anywhere outside of the dialog box, by clicking/tapping on the "X" button in the top right, or by pressing the escape key on the keyboard.
There are four navigational tabs. The overview tab contains a horizontally scrolling preview of the photos available for the selected hotel. It can be moved right or left by clicking and dragging or through touch gestures thanks to the Sly library. Clicking/tapping on any photo will open a touch-enabled, full-screen view, allowing users to click or swipe to view the next photo thanks to the Swipebox library.
The photos tab contains a grid of thumbnails of all available photos for the hotel. Selecting any of these will open the full screen photo view. The map tab features a larger, Google-powered map of the hotel's location. The reviews tab contains a breakdown of the frequency of guest ratings as well as a list of guest reviews.
The hotel name, address, stars, rating, and booking information are displayed across the top of the dialog box for easy access. The hotel description, amenities, and a small preview map are displayed in 3 columns.
Guest rating frequencies are displayed to the left of guest reviews.
The dialog box is centered, taking up most of the screen, but similar in layout to the desktop experience.
The dialog box is resized to fit the screen, and the booking information is shown below ratings, address, and hotel name.
A small amount of scrolling reveals amenities and map preview.
-
Navigate to the root folder of the project in your command line and minify the scripts and styles by running:
npm run build
-
Modify
public/index.html
so that the script and style tags refer to the minified files as follows:... <link rel="stylesheet" type="text/css" href="index.bundle.css"> ... <script src="index.js"></script> ...
becomes
... <link rel="stylesheet" type="text/css" href="index.min.css"> ... <script src="index.min.js"></script> ...
Note: A better, automated build process is planned in the To Do section below.
Normally I would include full JSDoc style comments within all of my code to be able to generate documentation through something like YUIDoc. As much as I would have liked to fully document everything in this project, doing so was beyond the scope this challenge given everything else I wanted to get done. I included comments where appropriate to make it clear what the code is doing, as well as provide the groundwork for document generation in the future.
I've also started investigating the jsdoc-to-markdown module, which does a great job of turning JSDoc style comments into markdown (*.md
) files.
Integration tests are run using webdriver.io. To run them, first make sure the site is running on localhost:9696
by running npm start
as described above, then launch the tests in a separate terminal window with:
npm test
-
Write more tests and show example of browsermob proxy for monitoring network traffic
-
Create a gulp/grunt process to automate distribution build steps.
-
Handle jQuery-ui and Swipebox module image paths without having to manually copy images to
public
to support defaults in their respective CSS files -
Various bugs fixes and small features designated within the source code by TODO tags
-
Refactor styles in
public/src/styles
to take advantage of less. These styles were originally written in flat CSS and have not been optimized yet. -
Allow clicking on stars to set Hotel Stars and Guest Rating filters rather than forcing users to use the sliders
-
Implement a short list feature allowing users to add hotels by click on an icon while hovering over a hotel preview card
-
Fill initial empty space below search box with popular hotels or deals
To my knowledge, all code and libraries used in this project are distributed unter the MIT license. The modifications to the original coding challenge that resulted in this submission are licensed under Creative Commons Attribution 3.0. I just ask that you include a link back here in your code or documentation if you use any of my modifications in your own work.