diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000000..a82f419738
Binary files /dev/null and b/.DS_Store differ
diff --git a/.env b/.env
new file mode 100644
index 0000000000..68eb7dd8dd
--- /dev/null
+++ b/.env
@@ -0,0 +1,2 @@
+GITHUB_CLIENT_ID: 7de823906fd607e07f3d
+GITHUB_CLIENT_SECRET: a7fd0670681c55d342e8580b38c2a95b74286ba1
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..cf7ce543cd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,22 @@
+# See https://help.github.com/articles/ignoring-files for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile '~/.gitignore_global'
+
+# Ignore bundler config.
+/.bundle
+
+# Ignore all logfiles and tempfiles.
+/log/*
+/tmp/*
+!/log/.keep
+!/tmp/.keep
+
+/node_modules
+/yarn-error.log
+
+.byebug_history
+
+.env
+/coverage/*
diff --git a/Alibonbon_ERD.jpeg b/Alibonbon_ERD.jpeg
new file mode 100644
index 0000000000..6523bc003c
Binary files /dev/null and b/Alibonbon_ERD.jpeg differ
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000000..4b4fd46be0
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,81 @@
+source 'https://rubygems.org'
+
+ruby '2.5.0'
+
+git_source(:github) do |repo_name|
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
+ "https://github.com/#{repo_name}.git"
+end
+
+gem 'simplecov', require: true, group: :test
+# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
+gem 'rails', '~> 5.1.6'
+# Use postgresql as the database for Active Record
+gem 'pg', '>= 0.18', '< 2.0'
+# Use Puma as the app server
+gem 'puma', '~> 3.7'
+# Use SCSS for stylesheets
+gem 'sass-rails', '~> 5.0'
+# Use Uglifier as compressor for JavaScript assets
+gem 'uglifier', '>= 1.3.0'
+# See https://github.com/rails/execjs#readme for more supported runtimes
+# gem 'therubyracer', platforms: :ruby
+
+# Use CoffeeScript for .coffee assets and views
+# gem 'coffee-rails', '~> 4.2'
+# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
+gem 'jbuilder', '~> 2.5'
+# Use Redis adapter to run Action Cable in production
+# gem 'redis', '~> 4.0'
+# Use ActiveModel has_secure_password
+# gem 'bcrypt', '~> 3.1.7'
+
+# Use Capistrano for deployment
+# gem 'capistrano-rails', group: :development
+
+gem "omniauth"
+gem "omniauth-github"
+
+gem 'will_paginate'
+
+
+group :development, :test do
+ # Call 'byebug' anywhere in the code to stop execution and get a debugger console
+ gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
+ # Adds support for Capybara system testing and selenium driver
+ gem 'capybara', '~> 2.13'
+ gem 'selenium-webdriver'
+end
+
+group :development do
+ # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
+ gem 'web-console', '>= 3.3.0'
+ gem 'listen', '>= 3.0.5', '< 3.2'
+ # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
+ gem 'spring'
+ gem 'spring-watcher-listen', '~> 2.0.0'
+
+ gem 'dotenv-rails'
+end
+
+# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
+gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+
+gem 'jquery-turbolinks'
+gem 'jquery-rails'
+gem 'foundation-rails'
+gem 'autoprefixer-rails'
+gem 'normalize-rails'
+group :development, :test do
+ gem 'pry-rails'
+end
+
+group :development do
+ gem 'better_errors'
+ gem 'binding_of_caller'
+end
+
+group :test do
+ gem 'minitest-rails'
+ gem 'minitest-reporters'
+end
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000000..096b0251ee
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,279 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actioncable (5.1.6)
+ actionpack (= 5.1.6)
+ nio4r (~> 2.0)
+ websocket-driver (~> 0.6.1)
+ actionmailer (5.1.6)
+ actionpack (= 5.1.6)
+ actionview (= 5.1.6)
+ activejob (= 5.1.6)
+ mail (~> 2.5, >= 2.5.4)
+ rails-dom-testing (~> 2.0)
+ actionpack (5.1.6)
+ actionview (= 5.1.6)
+ activesupport (= 5.1.6)
+ rack (~> 2.0)
+ rack-test (>= 0.6.3)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
+ actionview (5.1.6)
+ activesupport (= 5.1.6)
+ builder (~> 3.1)
+ erubi (~> 1.4)
+ rails-dom-testing (~> 2.0)
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
+ activejob (5.1.6)
+ activesupport (= 5.1.6)
+ globalid (>= 0.3.6)
+ activemodel (5.1.6)
+ activesupport (= 5.1.6)
+ activerecord (5.1.6)
+ activemodel (= 5.1.6)
+ activesupport (= 5.1.6)
+ arel (~> 8.0)
+ activesupport (5.1.6)
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ i18n (>= 0.7, < 2)
+ minitest (~> 5.1)
+ tzinfo (~> 1.1)
+ addressable (2.5.2)
+ public_suffix (>= 2.0.2, < 4.0)
+ ansi (1.5.0)
+ arel (8.0.0)
+ autoprefixer-rails (8.2.0)
+ execjs
+ babel-source (5.8.35)
+ babel-transpiler (0.7.0)
+ babel-source (>= 4.0, < 6)
+ execjs (~> 2.0)
+ better_errors (2.4.0)
+ coderay (>= 1.0.0)
+ erubi (>= 1.0.0)
+ rack (>= 0.9.0)
+ bindex (0.5.0)
+ binding_of_caller (0.8.0)
+ debug_inspector (>= 0.0.1)
+ builder (3.2.3)
+ byebug (10.0.2)
+ capybara (2.18.0)
+ addressable
+ mini_mime (>= 0.1.3)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ xpath (>= 2.0, < 4.0)
+ childprocess (0.9.0)
+ ffi (~> 1.0, >= 1.0.11)
+ coderay (1.1.2)
+ concurrent-ruby (1.0.5)
+ crass (1.0.4)
+ debug_inspector (0.0.3)
+ docile (1.3.0)
+ dotenv (2.2.2)
+ dotenv-rails (2.2.2)
+ dotenv (= 2.2.2)
+ railties (>= 3.2, < 6.0)
+ erubi (1.7.1)
+ execjs (2.7.0)
+ faraday (0.12.2)
+ multipart-post (>= 1.2, < 3)
+ ffi (1.9.23)
+ foundation-rails (6.4.3.0)
+ railties (>= 3.1.0)
+ sass (>= 3.3.0, < 3.5)
+ sprockets-es6 (>= 0.9.0)
+ globalid (0.4.1)
+ activesupport (>= 4.2.0)
+ hashie (3.5.7)
+ i18n (1.0.1)
+ concurrent-ruby (~> 1.0)
+ jbuilder (2.7.0)
+ activesupport (>= 4.2.0)
+ multi_json (>= 1.2)
+ jquery-rails (4.3.3)
+ rails-dom-testing (>= 1, < 3)
+ railties (>= 4.2.0)
+ thor (>= 0.14, < 2.0)
+ jquery-turbolinks (2.1.0)
+ railties (>= 3.1.0)
+ turbolinks
+ json (2.1.0)
+ jwt (1.5.6)
+ listen (3.1.5)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
+ ruby_dep (~> 1.2)
+ loofah (2.2.2)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.5.9)
+ mail (2.7.0)
+ mini_mime (>= 0.1.1)
+ method_source (0.9.0)
+ mini_mime (1.0.0)
+ mini_portile2 (2.3.0)
+ minitest (5.11.3)
+ minitest-rails (3.0.0)
+ minitest (~> 5.8)
+ railties (~> 5.0)
+ minitest-reporters (1.2.0)
+ ansi
+ builder
+ minitest (>= 5.0)
+ ruby-progressbar
+ multi_json (1.13.1)
+ multi_xml (0.6.0)
+ multipart-post (2.0.0)
+ nio4r (2.3.0)
+ nokogiri (1.8.2)
+ mini_portile2 (~> 2.3.0)
+ normalize-rails (4.1.1)
+ oauth2 (1.4.0)
+ faraday (>= 0.8, < 0.13)
+ jwt (~> 1.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ omniauth (1.8.1)
+ hashie (>= 3.4.6, < 3.6.0)
+ rack (>= 1.6.2, < 3)
+ omniauth-github (1.3.0)
+ omniauth (~> 1.5)
+ omniauth-oauth2 (>= 1.4.0, < 2.0)
+ omniauth-oauth2 (1.5.0)
+ oauth2 (~> 1.1)
+ omniauth (~> 1.2)
+ pg (1.0.0)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry-rails (0.3.6)
+ pry (>= 0.10.4)
+ public_suffix (3.0.2)
+ puma (3.11.4)
+ rack (2.0.4)
+ rack-test (1.0.0)
+ rack (>= 1.0, < 3)
+ rails (5.1.6)
+ actioncable (= 5.1.6)
+ actionmailer (= 5.1.6)
+ actionpack (= 5.1.6)
+ actionview (= 5.1.6)
+ activejob (= 5.1.6)
+ activemodel (= 5.1.6)
+ activerecord (= 5.1.6)
+ activesupport (= 5.1.6)
+ bundler (>= 1.3.0)
+ railties (= 5.1.6)
+ sprockets-rails (>= 2.0.0)
+ rails-dom-testing (2.0.3)
+ activesupport (>= 4.2.0)
+ nokogiri (>= 1.6)
+ rails-html-sanitizer (1.0.4)
+ loofah (~> 2.2, >= 2.2.2)
+ railties (5.1.6)
+ actionpack (= 5.1.6)
+ activesupport (= 5.1.6)
+ method_source
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ rake (12.3.1)
+ rb-fsevent (0.10.3)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
+ ruby-progressbar (1.9.0)
+ ruby_dep (1.5.0)
+ rubyzip (1.2.1)
+ sass (3.4.25)
+ sass-rails (5.0.7)
+ railties (>= 4.0.0, < 6)
+ sass (~> 3.1)
+ sprockets (>= 2.8, < 4.0)
+ sprockets-rails (>= 2.0, < 4.0)
+ tilt (>= 1.1, < 3)
+ selenium-webdriver (3.11.0)
+ childprocess (~> 0.5)
+ rubyzip (~> 1.2)
+ simplecov (0.16.1)
+ docile (~> 1.1)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.2)
+ spring (2.0.2)
+ activesupport (>= 4.2)
+ spring-watcher-listen (2.0.1)
+ listen (>= 2.7, < 4.0)
+ spring (>= 1.2, < 3.0)
+ sprockets (3.7.1)
+ concurrent-ruby (~> 1.0)
+ rack (> 1, < 3)
+ sprockets-es6 (0.9.2)
+ babel-source (>= 5.8.11)
+ babel-transpiler
+ sprockets (>= 3.0.0)
+ sprockets-rails (3.2.1)
+ actionpack (>= 4.0)
+ activesupport (>= 4.0)
+ sprockets (>= 3.0.0)
+ thor (0.20.0)
+ thread_safe (0.3.6)
+ tilt (2.0.8)
+ turbolinks (5.1.1)
+ turbolinks-source (~> 5.1)
+ turbolinks-source (5.1.0)
+ tzinfo (1.2.5)
+ thread_safe (~> 0.1)
+ uglifier (4.1.9)
+ execjs (>= 0.3.0, < 3)
+ web-console (3.6.1)
+ actionview (>= 5.0)
+ activemodel (>= 5.0)
+ bindex (>= 0.4.0)
+ railties (>= 5.0)
+ websocket-driver (0.6.5)
+ websocket-extensions (>= 0.1.0)
+ websocket-extensions (0.1.3)
+ will_paginate (3.1.6)
+ xpath (3.0.0)
+ nokogiri (~> 1.8)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ autoprefixer-rails
+ better_errors
+ binding_of_caller
+ byebug
+ capybara (~> 2.13)
+ dotenv-rails
+ foundation-rails
+ jbuilder (~> 2.5)
+ jquery-rails
+ jquery-turbolinks
+ listen (>= 3.0.5, < 3.2)
+ minitest-rails
+ minitest-reporters
+ normalize-rails
+ omniauth
+ omniauth-github
+ pg (>= 0.18, < 2.0)
+ pry-rails
+ puma (~> 3.7)
+ rails (~> 5.1.6)
+ sass-rails (~> 5.0)
+ selenium-webdriver
+ simplecov
+ spring
+ spring-watcher-listen (~> 2.0.0)
+ tzinfo-data
+ uglifier (>= 1.3.0)
+ web-console (>= 3.3.0)
+ will_paginate
+
+RUBY VERSION
+ ruby 2.5.0p0
+
+BUNDLED WITH
+ 1.16.1
diff --git a/README.md b/README.md
index 2758975bf5..7db80e4ca1 100644
--- a/README.md
+++ b/README.md
@@ -1,205 +1,24 @@
-# bEtsy
-[Much like other e-commerce platforms](https://www.etsy.com/), your team will make an online store where a wide variety of products can be listed and sold by any user. This project focuses on reinforcing the major components of Rails, model validations, testing, and more complex logic such as user authentication.
+# README
-This is a [Stage 3](https://github.com/Ada-Developers-Academy/pedagogy/blob/master/rule-of-three.md) project requiring you to expand upon what you have learned in class.
+This README would normally document whatever steps are necessary to get the
+application up and running.
-## Project Learning Goals
-- Core comprehension of:
- - Routes
- - Controllers
- - Models
- - Views
-- User based application logic
-- User authentication
-- Testing on models and controllers
-- Agile practices
-- Feature branch management with Git
-- Group project ownership
+Things you may want to cover:
-## Guidelines
-- Groups of three or four will collaborate in pairs or individually and will report to their assigned Project Manager (one of the instructors)
-- Use a task manager like [Trello](http://trello.com) to track your team's efforts
-- Build a logical user-flow that moves across multiple controllers and models
-- Use HTML/CSS and Foundation to style your website
+* Ruby version
-## Getting Started
-1. As a group decide on an app name (this may help lead the aesthetic)
-1. As a group decide on a team name (this will amuse your instructors)
-1. Have one person on your team fork/clone the project master as per usual
- 1. Create a new rails app using `rails new .`
- 1. Add all other team members as collaborators
- 1. Each team member should clone the repo to their computer
-1. Figure out your workflow for the project, re: Git and Task management
- 1. Do you want to use git branches? Pull requests?
- 1. Determine who will be the Stand Up Leader and Task Leader for the first week
-1. Create a Trello board to use as a Kanban board and ensure that all team members and instructors have access
-1. Review the User Stories below and create Trello tasks to represent them
-1. Slack your team name, app name, and link to your Trello board to your Project Manager
+* System dependencies
-## Expectations
-Build an online system for listing, selling, reviewing, and buying a wide variety of products listed by multiple merchants.
+* Configuration
-### General Requirements
-- Unit tests and/or specs for
- - Models
- - Controllers
-- Test code coverage (using SimpleCov - remember me!)
- - 90% for all controller and model classes
+* Database creation
-### User Stories
-#### Guest User (Unauthenticated)
-As a guest to the website (not signed in) I **can**:
+* Database initialization
-- Browse all products
-- Browse products by category
-- Browse products by merchant (users)
-- View any individual product with additional details
-- Leave a review for a product providing:
- - A text review
- - A rating out of 5
-- Add in-stock products to my cart
-- Remove products from my cart
-- Change the quantity of an existing product in my cart
-- Purchase the items in my cart, providing:
- - Email Address
- - Mailing Address
- - Name on credit card
- - Credit card number
- - Credit cart expiration
- - Credit Card CVV (security code)
- - Billing zip code
-- Purchasing an order makes the following changes:
- - Reduces the number of inventory for each product
- - Changes the order state from "pending" to "paid"
- - Clears the current cart
-- After purchasing an order, I can view a confirmation screen including:
- - Each item in the order with a quantity and line-item subtotal
- - A link to the item description page
- - Order total price
- - Date/time the order was placed
- - The current status of the order
-- Sign up to be a merchant using OAuth
- - Every merchant must have a username
-- Sign in to my merchant account using OAuth
+* How to run the test suite
-As a guest I **cannot**:
+* Services (job queues, cache servers, search engines, etc.)
-- Add products to the cart that are out of stock
-- View any link or page to manage any products
-- View any of the account pages
+* Deployment instructions
-#### Authenticated Users
-As a signed-in user, I **can**:
-
-- Do everything a guest user can do except for sign up and sign in
-- Sign out
-- Create new categories (categories are shared between all merchants)
-- Create a new product providing:
- - name
- - description
- - price
- - photo URL
- - stock
-- Assign my products to any number of categories
-- Retire a product from being sold, which hides it from browsing
-- View an account page to edit/update my existing products
-- View an account page showing my order fulfillment
-- On the order fulfillment page:
- - Total Revenue
- - Total Revenue by status
- - Total number of orders by status
- - Filter orders displayed by status
- - Link to each individual order
- - A list of orders including at least one of my products:
- - Each order item sold by me with a quantity and line-item subtotal
- - A link to the item description page
- - DateTime the order was placed
- - Link to transition the order item to marked as shipped
- - The current status of the order ("pending", "paid", "complete", "cancelled")
-- View an individual order to see the user's:
- - Name
- - Email address
- - Mailing address
- - Last four digits of their credit card
- - Credit card expiration date
-
-As a signed-in user, I **cannot**:
-
-- Review my own products
-- View order items from a shared order that belong to another merchant
-- View another user's private data (i.e. order fulfillment or product management)
-
-### Validations
-Many of our models will have attributes that are required for our application to use and display data consistently. Each model will have attributes with requirements for a valid record. The requirements are summarized below:
-
-#### Merchant
-- Username must be present
-- Username must be unique
-- Email Address must be present
-- Email Address must be unique
-
-#### Product
-- Name must be present
-- Name must be unique
-- Price must be present
-- Price must be a number
-- Price must be greater than 0
-- Product must belong to a User
-
-#### Order
-- An Order must have one or more Order Items
-
-#### OrderItem
-- Must belong to a Product
-- Must belong to an Order
-- Quantity must be present
-- Quantity must be an integer
-- Quantity must be greater than 0
-
-#### Review
-- Rating must be present
-- Rating must be an integer
-- Rating must be between 1 and 5
-
-## Submission Guidelines
-Your final project must be deployed to [Heroku](http://heroku.com). Your team will open a single pull request for the entire project. There are comprehension questions to answer with your submission that you should complete together as a group. Remember, you can submit a PR and still make some final changes to your code, so don't wait until the last minute.
-
-## Team Leaders
-Each team will have team leaders who are responsible for keeping track of each team member's contributions. Rotate leader roles at the beginning of the second week; every team member should be in at least one leader role during the project.
-
-- **Stand Up Leader**
- - Notifies team members about meeting schedule and ensures that everyone is present and ready
- - Takes notes about each person's daily report in Stand Up
- - Keeps the meeting moving
-- **Task Leader**
- - Leads discussion on task assignment and prioritization
- - Decide if a task should be completed alone or in a pair
- - Assign tasks based on...
- - Individual comfort
- - Desire
- - Ability
- - Ensures the Kanban board stays up to date
-
-## Stand Up Meetings
-The Stand Up Leader should determine the daily time for your stand up meeting with the team. Once you come up with a time, confirm with your PM that this time will work for them.
-
-At the end of each day, your team's assigned Project Manager will review the Trello board to ensure it captures the updates that your team has made throughout the day.
-
-## Interim Demo
-In a real world work environment, a team's success is measured by their product as opposed to each individual's contribution.
-
-Each team will present their progress and respond to questions from their Project Manager on the first Friday. Every team member will participate in these demos; the PM will ask specific questions regarding
-1. The team's progress and plan for completing the project
-1. The technical decisions and implementation
-1. Every team member's understanding of the underlying technical structures
-
-## Final Presentation
-Each team will present their product in a final presentation to the group on the final Friday. Your presentation should be no more than 7 minutes. The presentation should include every team member and:
-- what you learned as individuals and as a group
-- a short story-driven demo of interesting features
-
-## Due Date
-This project is due EOD Apr 27 via PR against Ada-C9/betsy.
-
-## What Instructors Are Looking For
-Check out the [feedback template](feedback.md) which lists the items instructors will be looking for as they evaluate your project.
+* ...
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000000..e85f913914
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,6 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require_relative 'config/application'
+
+Rails.application.load_tasks
diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
new file mode 100644
index 0000000000..b16e53d6d5
--- /dev/null
+++ b/app/assets/config/manifest.js
@@ -0,0 +1,3 @@
+//= link_tree ../images
+//= link_directory ../javascripts .js
+//= link_directory ../stylesheets .css
diff --git a/app/assets/images/.keep b/app/assets/images/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/app/assets/images/cake.png b/app/assets/images/cake.png
new file mode 100644
index 0000000000..6bbfcb7578
Binary files /dev/null and b/app/assets/images/cake.png differ
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
new file mode 100644
index 0000000000..bbeccf9c77
--- /dev/null
+++ b/app/assets/javascripts/application.js
@@ -0,0 +1,19 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's
+// vendor/assets/javascripts directory can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// compiled file. JavaScript code in this file should be added after the last require_* statement.
+//
+// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
+// about supported directives.
+//= require jquery
+
+//
+//= require rails-ujs
+//= require foundation
+//= require_tree .
+
+$(function(){ $(document).foundation(); });
diff --git a/app/assets/javascripts/cable.js b/app/assets/javascripts/cable.js
new file mode 100644
index 0000000000..739aa5f022
--- /dev/null
+++ b/app/assets/javascripts/cable.js
@@ -0,0 +1,13 @@
+// Action Cable provides the framework to deal with WebSockets in Rails.
+// You can generate new channels where WebSocket features live using the `rails generate channel` command.
+//
+//= require action_cable
+//= require_self
+//= require_tree ./channels
+
+(function() {
+ this.App || (this.App = {});
+
+ App.cable = ActionCable.createConsumer();
+
+}).call(this);
diff --git a/app/assets/javascripts/cartitems.js b/app/assets/javascripts/cartitems.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/cartitems.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/carts.js b/app/assets/javascripts/carts.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/carts.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/categories.js b/app/assets/javascripts/categories.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/categories.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/channels/.keep b/app/assets/javascripts/channels/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/app/assets/javascripts/merchants.js b/app/assets/javascripts/merchants.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/merchants.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/orders.js b/app/assets/javascripts/orders.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/orders.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/products.js b/app/assets/javascripts/products.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/products.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/reviews.js b/app/assets/javascripts/reviews.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/reviews.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/javascripts/sessions.js b/app/assets/javascripts/sessions.js
new file mode 100644
index 0000000000..dee720facd
--- /dev/null
+++ b/app/assets/javascripts/sessions.js
@@ -0,0 +1,2 @@
+// Place all the behaviors and hooks related to the matching controller here.
+// All this logic will automatically be available in application.js.
diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss
new file mode 100644
index 0000000000..f22f7b05ec
--- /dev/null
+++ b/app/assets/stylesheets/_settings.scss
@@ -0,0 +1,868 @@
+// Foundation for Sites Settings
+// -----------------------------
+//
+// Table of Contents:
+//
+// 1. Global
+// 2. Breakpoints
+// 3. The Grid
+// 4. Base Typography
+// 5. Typography Helpers
+// 6. Abide
+// 7. Accordion
+// 8. Accordion Menu
+// 9. Badge
+// 10. Breadcrumbs
+// 11. Button
+// 12. Button Group
+// 13. Callout
+// 14. Card
+// 15. Close Button
+// 16. Drilldown
+// 17. Dropdown
+// 18. Dropdown Menu
+// 19. Flexbox Utilities
+// 20. Forms
+// 21. Label
+// 22. Media Object
+// 23. Menu
+// 24. Meter
+// 25. Off-canvas
+// 26. Orbit
+// 27. Pagination
+// 28. Progress Bar
+// 29. Prototype Arrow
+// 30. Prototype Border-Box
+// 31. Prototype Border-None
+// 32. Prototype Bordered
+// 33. Prototype Display
+// 34. Prototype Font-Styling
+// 35. Prototype List-Style-Type
+// 36. Prototype Overflow
+// 37. Prototype Position
+// 38. Prototype Rounded
+// 39. Prototype Separator
+// 40. Prototype Shadow
+// 41. Prototype Sizing
+// 42. Prototype Spacing
+// 43. Prototype Text-Decoration
+// 44. Prototype Text-Transformation
+// 45. Prototype Text-Utilities
+// 46. Responsive Embed
+// 47. Reveal
+// 48. Slider
+// 49. Switch
+// 50. Table
+// 51. Tabs
+// 52. Thumbnail
+// 53. Title Bar
+// 54. Tooltip
+// 55. Top Bar
+// 56. Xy Grid
+
+@import 'util/util';
+
+// 1. Global
+// ---------
+
+$global-font-size: 100%;
+$global-width: rem-calc(1200);
+$global-lineheight: 1.5;
+$foundation-palette: (
+ primary: #1779ba,
+ secondary: #767676,
+ success: #3adb76,
+ warning: #ffae00,
+ alert: #cc4b37,
+);
+$light-gray: #e6e6e6;
+$medium-gray: #cacaca;
+$dark-gray: #8a8a8a;
+$black: #0a0a0a;
+$white: #fefefe;
+$body-background: $white;
+$body-font-color: $black;
+$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;
+$body-antialiased: true;
+$global-margin: 1rem;
+$global-padding: 1rem;
+$global-position: 1rem;
+$global-weight-normal: normal;
+$global-weight-bold: bold;
+$global-radius: 0;
+$global-menu-padding: 0.7rem 1rem;
+$global-menu-nested-margin: 1rem;
+$global-text-direction: ltr;
+$global-flexbox: true;
+$global-prototype-breakpoints: false;
+$global-button-cursor: auto;
+$global-color-pick-contrast-tolerance: 0;
+$print-transparent-backgrounds: true;
+
+@include add-foundation-colors;
+
+// 2. Breakpoints
+// --------------
+
+$breakpoints: (
+ small: 0,
+ medium: 640px,
+ large: 1024px,
+ xlarge: 1200px,
+ xxlarge: 1440px,
+);
+$print-breakpoint: large;
+$breakpoint-classes: (small medium large);
+
+// 3. The Grid
+// -----------
+
+$grid-row-width: $global-width;
+$grid-column-count: 12;
+$grid-column-gutter: (
+ small: 20px,
+ medium: 30px,
+);
+$grid-column-align-edge: true;
+$grid-column-alias: 'columns';
+$block-grid-max: 8;
+
+// 4. Base Typography
+// ------------------
+
+$header-font-family: $body-font-family;
+$header-font-weight: $global-weight-normal;
+$header-font-style: normal;
+$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace;
+$header-color: inherit;
+$header-lineheight: 1.4;
+$header-margin-bottom: 0.5rem;
+$header-styles: (
+ small: (
+ 'h1': ('font-size': 24),
+ 'h2': ('font-size': 20),
+ 'h3': ('font-size': 19),
+ 'h4': ('font-size': 18),
+ 'h5': ('font-size': 17),
+ 'h6': ('font-size': 16),
+ ),
+ medium: (
+ 'h1': ('font-size': 48),
+ 'h2': ('font-size': 40),
+ 'h3': ('font-size': 31),
+ 'h4': ('font-size': 25),
+ 'h5': ('font-size': 20),
+ 'h6': ('font-size': 16),
+ ),
+);
+$header-text-rendering: optimizeLegibility;
+$small-font-size: 80%;
+$header-small-font-color: $medium-gray;
+$paragraph-lineheight: 1.6;
+$paragraph-margin-bottom: 1rem;
+$paragraph-text-rendering: optimizeLegibility;
+$code-color: $black;
+$code-font-family: $font-family-monospace;
+$code-font-weight: $global-weight-normal;
+$code-background: $light-gray;
+$code-border: 1px solid $medium-gray;
+$code-padding: rem-calc(2 5 1);
+$anchor-color: $primary-color;
+$anchor-color-hover: scale-color($anchor-color, $lightness: -14%);
+$anchor-text-decoration: none;
+$anchor-text-decoration-hover: none;
+$hr-width: $global-width;
+$hr-border: 1px solid $medium-gray;
+$hr-margin: rem-calc(20) auto;
+$list-lineheight: $paragraph-lineheight;
+$list-margin-bottom: $paragraph-margin-bottom;
+$list-style-type: disc;
+$list-style-position: outside;
+$list-side-margin: 1.25rem;
+$list-nested-side-margin: 1.25rem;
+$defnlist-margin-bottom: 1rem;
+$defnlist-term-weight: $global-weight-bold;
+$defnlist-term-margin-bottom: 0.3rem;
+$blockquote-color: $dark-gray;
+$blockquote-padding: rem-calc(9 20 0 19);
+$blockquote-border: 1px solid $medium-gray;
+$cite-font-size: rem-calc(13);
+$cite-color: $dark-gray;
+$cite-pseudo-content: '\2014 \0020';
+$keystroke-font: $font-family-monospace;
+$keystroke-color: $black;
+$keystroke-background: $light-gray;
+$keystroke-padding: rem-calc(2 4 0);
+$keystroke-radius: $global-radius;
+$abbr-underline: 1px dotted $black;
+
+// 5. Typography Helpers
+// ---------------------
+
+$lead-font-size: $global-font-size * 1.25;
+$lead-lineheight: 1.6;
+$subheader-lineheight: 1.4;
+$subheader-color: $dark-gray;
+$subheader-font-weight: $global-weight-normal;
+$subheader-margin-top: 0.2rem;
+$subheader-margin-bottom: 0.5rem;
+$stat-font-size: 2.5rem;
+
+// 6. Abide
+// --------
+
+$abide-inputs: true;
+$abide-labels: true;
+$input-background-invalid: get-color(alert);
+$form-label-color-invalid: get-color(alert);
+$input-error-color: get-color(alert);
+$input-error-font-size: rem-calc(12);
+$input-error-font-weight: $global-weight-bold;
+
+// 7. Accordion
+// ------------
+
+$accordion-background: $white;
+$accordion-plusminus: true;
+$accordion-title-font-size: rem-calc(12);
+$accordion-item-color: $primary-color;
+$accordion-item-background-hover: $light-gray;
+$accordion-item-padding: 1.25rem 1rem;
+$accordion-content-background: $white;
+$accordion-content-border: 1px solid $light-gray;
+$accordion-content-color: $body-font-color;
+$accordion-content-padding: 1rem;
+
+// 8. Accordion Menu
+// -----------------
+
+$accordionmenu-padding: $global-menu-padding;
+$accordionmenu-nested-margin: $global-menu-nested-margin;
+$accordionmenu-submenu-padding: $accordionmenu-padding;
+$accordionmenu-arrows: true;
+$accordionmenu-arrow-color: $primary-color;
+$accordionmenu-item-background: null;
+$accordionmenu-border: null;
+$accordionmenu-submenu-toggle-background: null;
+$accordion-submenu-toggle-border: $accordionmenu-border;
+$accordionmenu-submenu-toggle-width: 40px;
+$accordionmenu-submenu-toggle-height: $accordionmenu-submenu-toggle-width;
+$accordionmenu-arrow-size: 6px;
+
+// 9. Badge
+// --------
+
+$badge-background: $primary-color;
+$badge-color: $white;
+$badge-color-alt: $black;
+$badge-palette: $foundation-palette;
+$badge-padding: 0.3em;
+$badge-minwidth: 2.1em;
+$badge-font-size: 0.6rem;
+
+// 10. Breadcrumbs
+// ---------------
+
+$breadcrumbs-margin: 0 0 $global-margin 0;
+$breadcrumbs-item-font-size: rem-calc(11);
+$breadcrumbs-item-color: $primary-color;
+$breadcrumbs-item-color-current: $black;
+$breadcrumbs-item-color-disabled: $medium-gray;
+$breadcrumbs-item-margin: 0.75rem;
+$breadcrumbs-item-uppercase: true;
+$breadcrumbs-item-separator: true;
+$breadcrumbs-item-separator-item: '/';
+$breadcrumbs-item-separator-item-rtl: '\\';
+$breadcrumbs-item-separator-color: $medium-gray;
+
+// 11. Button
+// ----------
+
+$button-font-family: inherit;
+$button-padding: 0.85em 1em;
+$button-margin: 0 0 $global-margin 0;
+$button-fill: solid;
+$button-background: $primary-color;
+$button-background-hover: scale-color($button-background, $lightness: -15%);
+$button-color: $white;
+$button-color-alt: $black;
+$button-radius: $global-radius;
+$button-hollow-border-width: 1px;
+$button-sizes: (
+ tiny: 0.6rem,
+ small: 0.75rem,
+ default: 0.9rem,
+ large: 1.25rem,
+);
+$button-palette: $foundation-palette;
+$button-opacity-disabled: 0.25;
+$button-background-hover-lightness: -20%;
+$button-hollow-hover-lightness: -50%;
+$button-transition: background-color 0.25s ease-out, color 0.25s ease-out;
+
+// 12. Button Group
+// ----------------
+
+$buttongroup-margin: 1rem;
+$buttongroup-spacing: 1px;
+$buttongroup-child-selector: '.button';
+$buttongroup-expand-max: 6;
+$buttongroup-radius-on-each: true;
+
+// 13. Callout
+// -----------
+
+$callout-background: $white;
+$callout-background-fade: 85%;
+$callout-border: 1px solid rgba($black, 0.25);
+$callout-margin: 0 0 1rem 0;
+$callout-padding: 1rem;
+$callout-font-color: $body-font-color;
+$callout-font-color-alt: $body-background;
+$callout-radius: $global-radius;
+$callout-link-tint: 30%;
+
+// 14. Card
+// --------
+
+$card-background: $white;
+$card-font-color: $body-font-color;
+$card-divider-background: $light-gray;
+$card-border: 1px solid $light-gray;
+$card-shadow: none;
+$card-border-radius: $global-radius;
+$card-padding: $global-padding;
+$card-margin-bottom: $global-margin;
+
+// 15. Close Button
+// ----------------
+
+$closebutton-position: right top;
+$closebutton-offset-horizontal: (
+ small: 0.66rem,
+ medium: 1rem,
+);
+$closebutton-offset-vertical: (
+ small: 0.33em,
+ medium: 0.5rem,
+);
+$closebutton-size: (
+ small: 1.5em,
+ medium: 2em,
+);
+$closebutton-lineheight: 1;
+$closebutton-color: $dark-gray;
+$closebutton-color-hover: $black;
+
+// 16. Drilldown
+// -------------
+
+$drilldown-transition: transform 0.15s linear;
+$drilldown-arrows: true;
+$drilldown-padding: $global-menu-padding;
+$drilldown-nested-margin: 0;
+$drilldown-background: $white;
+$drilldown-submenu-padding: $drilldown-padding;
+$drilldown-submenu-background: $white;
+$drilldown-arrow-color: $primary-color;
+$drilldown-arrow-size: 6px;
+
+// 17. Dropdown
+// ------------
+
+$dropdown-padding: 1rem;
+$dropdown-background: $body-background;
+$dropdown-border: 1px solid $medium-gray;
+$dropdown-font-size: 1rem;
+$dropdown-width: 300px;
+$dropdown-radius: $global-radius;
+$dropdown-sizes: (
+ tiny: 100px,
+ small: 200px,
+ large: 400px,
+);
+
+// 18. Dropdown Menu
+// -----------------
+
+$dropdownmenu-arrows: true;
+$dropdownmenu-arrow-color: $anchor-color;
+$dropdownmenu-arrow-size: 6px;
+$dropdownmenu-arrow-padding: 1.5rem;
+$dropdownmenu-min-width: 200px;
+$dropdownmenu-background: $white;
+$dropdownmenu-submenu-background: $dropdownmenu-background;
+$dropdownmenu-padding: $global-menu-padding;
+$dropdownmenu-nested-margin: 0;
+$dropdownmenu-submenu-padding: $dropdownmenu-padding;
+$dropdownmenu-border: 1px solid $medium-gray;
+$dropdown-menu-item-color-active: get-color(primary);
+$dropdown-menu-item-background-active: transparent;
+
+// 19. Flexbox Utilities
+// ---------------------
+
+$flex-source-ordering-count: 6;
+$flexbox-responsive-breakpoints: true;
+
+// 20. Forms
+// ---------
+
+$fieldset-border: 1px solid $medium-gray;
+$fieldset-padding: rem-calc(20);
+$fieldset-margin: rem-calc(18 0);
+$legend-padding: rem-calc(0 3);
+$form-spacing: rem-calc(16);
+$helptext-color: $black;
+$helptext-font-size: rem-calc(13);
+$helptext-font-style: italic;
+$input-prefix-color: $black;
+$input-prefix-background: $light-gray;
+$input-prefix-border: 1px solid $medium-gray;
+$input-prefix-padding: 1rem;
+$form-label-color: $black;
+$form-label-font-size: rem-calc(14);
+$form-label-font-weight: $global-weight-normal;
+$form-label-line-height: 1.8;
+$select-background: $white;
+$select-triangle-color: $dark-gray;
+$select-radius: $global-radius;
+$input-color: $black;
+$input-placeholder-color: $medium-gray;
+$input-font-family: inherit;
+$input-font-size: rem-calc(16);
+$input-font-weight: $global-weight-normal;
+$input-line-height: $global-lineheight;
+$input-background: $white;
+$input-background-focus: $white;
+$input-background-disabled: $light-gray;
+$input-border: 1px solid $medium-gray;
+$input-border-focus: 1px solid $dark-gray;
+$input-padding: $form-spacing / 2;
+$input-shadow: inset 0 1px 2px rgba($black, 0.1);
+$input-shadow-focus: 0 0 5px $medium-gray;
+$input-cursor-disabled: not-allowed;
+$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out;
+$input-number-spinners: true;
+$input-radius: $global-radius;
+$form-button-radius: $global-radius;
+
+// 21. Label
+// ---------
+
+$label-background: $primary-color;
+$label-color: $white;
+$label-color-alt: $black;
+$label-palette: $foundation-palette;
+$label-font-size: 0.8rem;
+$label-padding: 0.33333rem 0.5rem;
+$label-radius: $global-radius;
+
+// 22. Media Object
+// ----------------
+
+$mediaobject-margin-bottom: $global-margin;
+$mediaobject-section-padding: $global-padding;
+$mediaobject-image-width-stacked: 100%;
+
+// 23. Menu
+// --------
+
+$menu-margin: 0;
+$menu-nested-margin: $global-menu-nested-margin;
+$menu-items-padding: $global-menu-padding;
+$menu-simple-margin: 1rem;
+$menu-item-color-active: $white;
+$menu-item-background-active: get-color(primary);
+$menu-icon-spacing: 0.25rem;
+$menu-item-background-hover: $light-gray;
+$menu-state-back-compat: true;
+$menu-centered-back-compat: true;
+$menu-icons-back-compat: true;
+
+// 24. Meter
+// ---------
+
+$meter-height: 1rem;
+$meter-radius: $global-radius;
+$meter-background: $medium-gray;
+$meter-fill-good: $success-color;
+$meter-fill-medium: $warning-color;
+$meter-fill-bad: $alert-color;
+
+// 25. Off-canvas
+// --------------
+
+$offcanvas-sizes: (
+ small: 250px,
+);
+$offcanvas-vertical-sizes: (
+ small: 250px,
+);
+$offcanvas-background: $light-gray;
+$offcanvas-shadow: 0 0 10px rgba($black, 0.7);
+$offcanvas-inner-shadow-size: 20px;
+$offcanvas-inner-shadow-color: rgba($black, 0.25);
+$offcanvas-overlay-zindex: 11;
+$offcanvas-push-zindex: 12;
+$offcanvas-overlap-zindex: 13;
+$offcanvas-reveal-zindex: 12;
+$offcanvas-transition-length: 0.5s;
+$offcanvas-transition-timing: ease;
+$offcanvas-fixed-reveal: true;
+$offcanvas-exit-background: rgba($white, 0.25);
+$maincontent-class: 'off-canvas-content';
+
+// 26. Orbit
+// ---------
+
+$orbit-bullet-background: $medium-gray;
+$orbit-bullet-background-active: $dark-gray;
+$orbit-bullet-diameter: 1.2rem;
+$orbit-bullet-margin: 0.1rem;
+$orbit-bullet-margin-top: 0.8rem;
+$orbit-bullet-margin-bottom: 0.8rem;
+$orbit-caption-background: rgba($black, 0.5);
+$orbit-caption-padding: 1rem;
+$orbit-control-background-hover: rgba($black, 0.5);
+$orbit-control-padding: 1rem;
+$orbit-control-zindex: 10;
+
+// 27. Pagination
+// --------------
+
+$pagination-font-size: rem-calc(14);
+$pagination-margin-bottom: $global-margin;
+$pagination-item-color: $black;
+$pagination-item-padding: rem-calc(3 10);
+$pagination-item-spacing: rem-calc(1);
+$pagination-radius: $global-radius;
+$pagination-item-background-hover: $light-gray;
+$pagination-item-background-current: $primary-color;
+$pagination-item-color-current: $white;
+$pagination-item-color-disabled: $medium-gray;
+$pagination-ellipsis-color: $black;
+$pagination-mobile-items: false;
+$pagination-mobile-current-item: false;
+$pagination-arrows: true;
+
+// 28. Progress Bar
+// ----------------
+
+$progress-height: 1rem;
+$progress-background: $medium-gray;
+$progress-margin-bottom: $global-margin;
+$progress-meter-background: $primary-color;
+$progress-radius: $global-radius;
+
+// 29. Prototype Arrow
+// -------------------
+
+$prototype-arrow-directions: (
+ down,
+ up,
+ right,
+ left
+);
+$prototype-arrow-size: 0.4375rem;
+$prototype-arrow-color: $black;
+
+// 30. Prototype Border-Box
+// ------------------------
+
+$prototype-border-box-breakpoints: $global-prototype-breakpoints;
+
+// 31. Prototype Border-None
+// -------------------------
+
+$prototype-border-none-breakpoints: $global-prototype-breakpoints;
+
+// 32. Prototype Bordered
+// ----------------------
+
+$prototype-bordered-breakpoints: $global-prototype-breakpoints;
+$prototype-border-width: rem-calc(1);
+$prototype-border-type: solid;
+$prototype-border-color: $medium-gray;
+
+// 33. Prototype Display
+// ---------------------
+
+$prototype-display-breakpoints: $global-prototype-breakpoints;
+$prototype-display: (
+ inline,
+ inline-block,
+ block,
+ table,
+ table-cell
+);
+
+// 34. Prototype Font-Styling
+// --------------------------
+
+$prototype-font-breakpoints: $global-prototype-breakpoints;
+$prototype-wide-letter-spacing: rem-calc(4);
+$prototype-font-normal: $global-weight-normal;
+$prototype-font-bold: $global-weight-bold;
+
+// 35. Prototype List-Style-Type
+// -----------------------------
+
+$prototype-list-breakpoints: $global-prototype-breakpoints;
+$prototype-style-type-unordered: (
+ disc,
+ circle,
+ square
+);
+$prototype-style-type-ordered: (
+ decimal,
+ lower-alpha,
+ lower-latin,
+ lower-roman,
+ upper-alpha,
+ upper-latin,
+ upper-roman
+);
+
+// 36. Prototype Overflow
+// ----------------------
+
+$prototype-overflow-breakpoints: $global-prototype-breakpoints;
+$prototype-overflow: (
+ visible,
+ hidden,
+ scroll
+);
+
+// 37. Prototype Position
+// ----------------------
+
+$prototype-position-breakpoints: $global-prototype-breakpoints;
+$prototype-position: (
+ static,
+ relative,
+ absolute,
+ fixed
+);
+$prototype-position-z-index: 975;
+
+// 38. Prototype Rounded
+// ---------------------
+
+$prototype-rounded-breakpoints: $global-prototype-breakpoints;
+$prototype-border-radius: rem-calc(3);
+
+// 39. Prototype Separator
+// -----------------------
+
+$prototype-separator-breakpoints: $global-prototype-breakpoints;
+$prototype-separator-align: center;
+$prototype-separator-height: rem-calc(2);
+$prototype-separator-width: 3rem;
+$prototype-separator-background: $primary-color;
+$prototype-separator-margin-top: $global-margin;
+
+// 40. Prototype Shadow
+// --------------------
+
+$prototype-shadow-breakpoints: $global-prototype-breakpoints;
+$prototype-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16),
+ 0 2px 10px 0 rgba(0,0,0,.12);
+
+// 41. Prototype Sizing
+// --------------------
+
+$prototype-sizing-breakpoints: $global-prototype-breakpoints;
+$prototype-sizing: (
+ width,
+ height
+);
+$prototype-sizes: (
+ 25: 25%,
+ 50: 50%,
+ 75: 75%,
+ 100: 100%
+);
+
+// 42. Prototype Spacing
+// ---------------------
+
+$prototype-spacing-breakpoints: $global-prototype-breakpoints;
+$prototype-spacers-count: 3;
+
+// 43. Prototype Text-Decoration
+// -----------------------------
+
+$prototype-decoration-breakpoints: $global-prototype-breakpoints;
+$prototype-text-decoration: (
+ overline,
+ underline,
+ line-through,
+);
+
+// 44. Prototype Text-Transformation
+// ---------------------------------
+
+$prototype-transformation-breakpoints: $global-prototype-breakpoints;
+$prototype-text-transformation: (
+ lowercase,
+ uppercase,
+ capitalize
+);
+
+// 45. Prototype Text-Utilities
+// ----------------------------
+
+$prototype-utilities-breakpoints: $global-prototype-breakpoints;
+$prototype-text-overflow: ellipsis;
+
+// 46. Responsive Embed
+// --------------------
+
+$responsive-embed-margin-bottom: rem-calc(16);
+$responsive-embed-ratios: (
+ default: 4 by 3,
+ widescreen: 16 by 9,
+);
+
+// 47. Reveal
+// ----------
+
+$reveal-background: $white;
+$reveal-width: 600px;
+$reveal-max-width: $global-width;
+$reveal-padding: $global-padding;
+$reveal-border: 1px solid $medium-gray;
+$reveal-radius: $global-radius;
+$reveal-zindex: 1005;
+$reveal-overlay-background: rgba($black, 0.45);
+
+// 48. Slider
+// ----------
+
+$slider-width-vertical: 0.5rem;
+$slider-transition: all 0.2s ease-in-out;
+$slider-height: 0.5rem;
+$slider-background: $light-gray;
+$slider-fill-background: $medium-gray;
+$slider-handle-height: 1.4rem;
+$slider-handle-width: 1.4rem;
+$slider-handle-background: $primary-color;
+$slider-opacity-disabled: 0.25;
+$slider-radius: $global-radius;
+
+// 49. Switch
+// ----------
+
+$switch-background: $medium-gray;
+$switch-background-active: $primary-color;
+$switch-height: 2rem;
+$switch-height-tiny: 1.5rem;
+$switch-height-small: 1.75rem;
+$switch-height-large: 2.5rem;
+$switch-radius: $global-radius;
+$switch-margin: $global-margin;
+$switch-paddle-background: $white;
+$switch-paddle-offset: 0.25rem;
+$switch-paddle-radius: $global-radius;
+$switch-paddle-transition: all 0.25s ease-out;
+
+// 50. Table
+// ---------
+
+$table-background: $white;
+$table-color-scale: 5%;
+$table-border: 1px solid smart-scale($table-background, $table-color-scale);
+$table-padding: rem-calc(8 10 10);
+$table-hover-scale: 2%;
+$table-row-hover: darken($table-background, $table-hover-scale);
+$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale);
+$table-is-striped: true;
+$table-striped-background: smart-scale($table-background, $table-color-scale);
+$table-stripe: even;
+$table-head-background: smart-scale($table-background, $table-color-scale / 2);
+$table-head-row-hover: darken($table-head-background, $table-hover-scale);
+$table-foot-background: smart-scale($table-background, $table-color-scale);
+$table-foot-row-hover: darken($table-foot-background, $table-hover-scale);
+$table-head-font-color: $body-font-color;
+$table-foot-font-color: $body-font-color;
+$show-header-for-stacked: false;
+$table-stack-breakpoint: medium;
+
+// 51. Tabs
+// --------
+
+$tab-margin: 0;
+$tab-background: $white;
+$tab-color: $primary-color;
+$tab-background-active: $light-gray;
+$tab-active-color: $primary-color;
+$tab-item-font-size: rem-calc(12);
+$tab-item-background-hover: $white;
+$tab-item-padding: 1.25rem 1.5rem;
+$tab-expand-max: 6;
+$tab-content-background: $white;
+$tab-content-border: $light-gray;
+$tab-content-color: $body-font-color;
+$tab-content-padding: 1rem;
+
+// 52. Thumbnail
+// -------------
+
+$thumbnail-border: solid 4px $white;
+$thumbnail-margin-bottom: $global-margin;
+$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2);
+$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5);
+$thumbnail-transition: box-shadow 200ms ease-out;
+$thumbnail-radius: $global-radius;
+
+// 53. Title Bar
+// -------------
+
+$titlebar-background: $black;
+$titlebar-color: $white;
+$titlebar-padding: 0.5rem;
+$titlebar-text-font-weight: bold;
+$titlebar-icon-color: $white;
+$titlebar-icon-color-hover: $medium-gray;
+$titlebar-icon-spacing: 0.25rem;
+
+// 54. Tooltip
+// -----------
+
+$has-tip-cursor: help;
+$has-tip-font-weight: $global-weight-bold;
+$has-tip-border-bottom: dotted 1px $dark-gray;
+$tooltip-background-color: $black;
+$tooltip-color: $white;
+$tooltip-padding: 0.75rem;
+$tooltip-max-width: 10rem;
+$tooltip-font-size: $small-font-size;
+$tooltip-pip-width: 0.75rem;
+$tooltip-pip-height: $tooltip-pip-width * 0.866;
+$tooltip-radius: $global-radius;
+
+// 55. Top Bar
+// -----------
+
+$topbar-padding: 0.5rem;
+$topbar-background: rgba(193, 84, 246, 0.78);
+$topbar-submenu-background: $topbar-background;
+$topbar-title-spacing: 0.5rem 1rem 0.5rem 0;
+$topbar-input-width: 200px;
+$topbar-unstack-breakpoint: medium;
+
+// 56. Xy Grid
+// -----------
+
+$xy-grid: true;
+$grid-container: $global-width;
+$grid-columns: 12;
+$grid-margin-gutters: (
+ small: 20px,
+ medium: 30px
+);
+$grid-padding-gutters: $grid-margin-gutters;
+$grid-container-padding: $grid-padding-gutters;
+$grid-container-max: $global-width;
+$xy-block-grid-max: 8;
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
new file mode 100644
index 0000000000..d59cb3f72b
--- /dev/null
+++ b/app/assets/stylesheets/application.css
@@ -0,0 +1,159 @@
+/*
+* This is a manifest file that'll be compiled into application.css, which will include all the files
+* listed below.
+*
+* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
+* vendor/assets/stylesheets directory can be referenced here using a relative path.
+*
+* You're free to add application-wide styles to this file and they'll appear at the bottom of the
+* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
+* files in this directory. Styles in this file should be added after the last require_* statement.
+* It is generally better to create a new file per style scope.
+*= require normalize-rails
+
+*
+*= require_tree .
+*= require_self
+*= require foundation_and_overrides
+
+*/
+html {
+ height: 100%;
+ width: 100%;
+ margin: auto;
+}
+a {
+ color: rgb(64, 34, 2);
+}
+body {
+ color: rgb(64, 34, 2);
+ height: 100%;
+
+ /* Full height */
+ height: 100%;
+ width: 100%;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+
+body {
+ font-family: 'Berkshire Swash';font-size: 22px;
+ font-weight: lighter;
+}
+.image-header a {
+ font-family: 'Berkshire Swash';font-size: 75px;
+ text-align: center;
+ background-color: rgb(192, 242, 205);
+}
+.image-header a {
+ color: rgb(64, 34, 2);
+}
+ul.menu.toggle {
+ background-color: rgb(192, 242, 205);
+}
+
+.button-group {
+ float: right;
+}
+header {
+ color: rgb(64, 34, 2);
+ background-color: #3adb765c;
+ border-top-style:double;
+ border-bottom-style:double;
+ padding-top:5px;
+ padding-bottom:5px;
+ border-top-color:inherit;
+ border-bottom-color:inherit;
+ border-top-width:20px;
+ border-bottom-width:20px;
+}
+
+a.float-right {
+ padding-left: 10px;
+ padding-right: 10px;
+}
+
+div.top-bar {
+ background-color: rgb(192, 242, 205);
+}
+
+#nav-list > .top-bar > .top-bar-left ul {
+ background-color: rgb(192, 242, 205);
+}
+body .button {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+ border: 2px solid rgb(64, 34, 2);
+}
+
+body .button:hover {
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+}
+
+main {
+ color: rgb(64, 34, 2);
+ border: 10px double rgb(64, 34, 2);
+ background-color: rgb(192, 242, 205);
+}
+
+img.orbit-image {
+ border: 10px solid rgb(64, 34, 2);
+ border-width: 5px;
+ margin-top: 30px;
+}
+
+footer {
+ margin-top: 2em;
+ height: 15%;
+ color: rgb(64, 34, 2);
+ border: 10px double rgb(64, 34, 2);
+ background-color: rgb(192, 242, 205);
+}
+
+.ownership ul {
+ margin: auto;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+}
+.ownership p {
+ padding-left: 10px;
+}
+.pagination .current {
+ background-color: rgb(64, 34, 2);
+}
+
+#nav-list .button {
+ margin: 20px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.1rem;
+}
+
+#nav-list .button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+#new-product-form .button {
+ margin: 20px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.1rem;
+}
+
+#new-product-form .button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+
+}
+
+#new-product-form {
+ margin: 30px;
+}
+
+#distance {
+ margin-right: 500px;
+}
diff --git a/app/assets/stylesheets/browserslist b/app/assets/stylesheets/browserslist
new file mode 100644
index 0000000000..6019618a9a
--- /dev/null
+++ b/app/assets/stylesheets/browserslist
@@ -0,0 +1,4 @@
+last 2 versions
+ie >= 9
+Android >= 2.3
+ios >= 7
diff --git a/app/assets/stylesheets/cartitems.scss b/app/assets/stylesheets/cartitems.scss
new file mode 100644
index 0000000000..5ae554e0c1
--- /dev/null
+++ b/app/assets/stylesheets/cartitems.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the cartitems controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/carts.scss b/app/assets/stylesheets/carts.scss
new file mode 100644
index 0000000000..4294fe7f67
--- /dev/null
+++ b/app/assets/stylesheets/carts.scss
@@ -0,0 +1,44 @@
+// Place all the styles related to the carts controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+
+.cart-page .double-button {
+ margin: 20px 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.2rem;
+}
+
+.cart-page .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.order-new .lowerbar .double-button {
+ margin: 20px 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.2rem;
+}
+
+.order-new .lowerbar .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+#form-order .double-button {
+ margin: 20px 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.2rem;
+}
+
+#form-order .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.edit-order, .order-new, .cart-page{
+ margin: 20px;
+}
diff --git a/app/assets/stylesheets/categories.scss b/app/assets/stylesheets/categories.scss
new file mode 100644
index 0000000000..cd0c304aed
--- /dev/null
+++ b/app/assets/stylesheets/categories.scss
@@ -0,0 +1,63 @@
+// Place all the styles related to the Categories controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+
+.cate-display {
+ list-style-type: none;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+.cate-display > li {
+ margin: 10px 40px;
+}
+
+.small-pro {
+ width: 250px;
+ height: 200px;
+ border-radius: 30%;
+ border: 1px solid rgb(64, 34, 2);
+}
+
+.small-pro:hover {
+ border-radius: 50%;
+}
+
+.all-categories h2 {
+ text-align: left;
+}
+
+.all-categories .pro-name {
+ width: 250px;
+ height: 120px;
+ text-align: center;
+}
+
+.show-category .grid-container {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ align-items: center;
+ grid-gap: 50px;
+ margin-bottom: 3em;
+}
+.product-cat-img {
+ display: grid;
+ align-items: center;
+ width: 400px;
+ height: 400px;
+ border: 10px double rgb(64, 34, 2);
+ border-radius: 50%;
+}
+h2 {
+ display: flex;
+ justify-content: center;
+}
+.category-name {
+ padding-top: 20px;
+ padding-bottom: 20px;
+}
+.product-stuff li {
+ font-size: 26px;
+ font-family: "Helvetica", sans-serif;
+}
diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss
new file mode 100644
index 0000000000..2595ef6d0c
--- /dev/null
+++ b/app/assets/stylesheets/foundation_and_overrides.scss
@@ -0,0 +1,82 @@
+@charset 'utf-8';
+
+@import 'settings';
+@import 'foundation';
+
+// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
+//
+// @import 'motion-ui/motion-ui';
+
+// We include everything by default. To slim your CSS, remove components you don't use.
+
+@include foundation-global-styles;
+@include foundation-xy-grid-classes;
+//@include foundation-grid;
+//@include foundation-flex-grid;
+@include foundation-flex-classes;
+@include foundation-typography;
+@include foundation-forms;
+@include foundation-button;
+@include foundation-accordion;
+@include foundation-accordion-menu;
+@include foundation-badge;
+@include foundation-breadcrumbs;
+@include foundation-button-group;
+@include foundation-callout;
+@include foundation-card;
+@include foundation-close-button;
+@include foundation-menu;
+@include foundation-menu-icon;
+@include foundation-drilldown-menu;
+@include foundation-dropdown;
+@include foundation-dropdown-menu;
+@include foundation-responsive-embed;
+@include foundation-label;
+@include foundation-media-object;
+@include foundation-off-canvas;
+@include foundation-orbit;
+@include foundation-pagination;
+@include foundation-progress-bar;
+@include foundation-slider;
+@include foundation-sticky;
+@include foundation-reveal;
+@include foundation-switch;
+@include foundation-table;
+@include foundation-tabs;
+@include foundation-thumbnail;
+@include foundation-title-bar;
+@include foundation-tooltip;
+@include foundation-top-bar;
+@include foundation-visibility-classes;
+@include foundation-float-classes;
+
+// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package.
+//
+// @include motion-ui-transitions;
+// @include motion-ui-animations;
+@import 'motion-ui/motion-ui';
+@include motion-ui-transitions;
+@include motion-ui-animations;
+
+
+.status {
+ border-radius: 5px;
+ background-color: $light-gray;
+ padding: 20px 25px;
+ margin-bottom: 20px;
+ color: $dark-gray;
+}
+
+
+.status.failure {
+ h3 {
+ color: #C70039;
+ }
+}
+
+.status.failure, .status.success {
+ h3 {
+ font-weight: normal;
+ font-size: 1em;
+ }
+}
diff --git a/app/assets/stylesheets/merchants.scss b/app/assets/stylesheets/merchants.scss
new file mode 100644
index 0000000000..831fccb4a4
--- /dev/null
+++ b/app/assets/stylesheets/merchants.scss
@@ -0,0 +1,50 @@
+.merchant-display {
+ list-style-type: none;
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.merchant-display > li {
+ margin: 10px 40px;
+}
+
+.middle-pro {
+ width: 250px;
+ height: 200px;
+}
+
+.middle-pro:hover {
+ border-radius: 50%;
+}
+
+.all-merchants h2 {
+ text-align: left;
+}
+
+.all-merchants .pro-name {
+ width: 250px;
+ height: 120px;
+ text-align: center;
+}
+
+.show-merchant > ul {
+ list-style-type: none;
+}
+
+.show-merchant {
+ padding: 20px 20px;
+}
+
+.edit-product, .display-products, .create-category {
+ padding: 30px 50px;
+}
+
+
+.show-merchant-products .grid-container {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ align-items: center;
+ grid-gap: 50px;
+ margin-bottom: 3em;
+}
diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss
new file mode 100644
index 0000000000..4c24b28dd5
--- /dev/null
+++ b/app/assets/stylesheets/orders.scss
@@ -0,0 +1,180 @@
+// Place all the styles related to the orders controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+.lowerbar {
+ display: flex;
+}
+.lowerbar a {
+ margin-left: 6px;
+ margin-right: 6px;
+}
+
+.display-my-order, .orders-display {
+ margin: 30px 150px;
+ padding-bottom: 60px;
+}
+
+.display-my-order > ul {
+ list-style-type: none;
+}
+.display-my-order .button {
+ margin-right: 60px;
+}
+
+.display-products h4 {
+ padding-left: 30px;
+ font-weight: bold;
+ margin: 20px auto;
+}
+
+.table-orders .table-head .small {
+ width: 200px;
+}
+
+.display-products .double-button {
+ margin-left: 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.5rem;
+}
+
+.display-products .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.show-merchant .button {
+ margin: auto 20px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.5rem;
+}
+
+.show-merchant .button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.orders-display .double-button {
+ margin-left: 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.5rem;
+
+}
+
+.orders-display .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.display-my-order .double-button {
+ margin-left: 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.5rem;
+}
+
+.display-my-order .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.new-product-form .double-button {
+ margin-left: 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.5rem;
+}
+
+.new-product-form .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.new-category-form .double-button {
+ margin:auto 30px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+ font-size: 1.2rem;
+}
+
+.new-category-form .double-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+.orders-display .orders-table .small {
+ width: 100px;
+ padding-left: 30px;
+}
+
+.orders-display .orders-table .middle {
+ width: 200px;
+}
+
+.orders-display .orders-table .large {
+ width: 400px;
+}
+
+.status-bar {
+ display: inline-block;
+ width: 100px;
+}
+
+#search-button {
+ margin: auto 20px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+}
+
+#search-button:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+#search-field {
+ display: inline;
+ width: 600px;
+}
+
+#search-bar {
+ justify-content: center;
+ text-align: center;
+}
+
+#example-tabs .tabs-title > a {
+ color: rgb(64, 34, 2);
+ font-size: 1.2rem;
+}
+
+#example-tabs .tabs-title > a:hover {
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+}
+
+.tabs-panel > p {
+ font-size: 2rem;
+}
+
+
+#search-button-2 {
+ margin: 20px;
+ background-color: rgb(64, 34, 2);
+ color: rgb(192, 242, 205);
+}
+
+#search-button-2:hover {
+ background-color: rgb(192, 242, 205);
+ color: rgb(64, 34, 2);
+}
+
+#search-field-2 {
+ display: inline;
+ width: 600px;
+}
+
+#search-bar-2 {
+ justify-content: center;
+ text-align: center;
+}
diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss
new file mode 100644
index 0000000000..98c397a8f6
--- /dev/null
+++ b/app/assets/stylesheets/products.scss
@@ -0,0 +1,172 @@
+// Place all the styles related to the Products controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+header {
+ max-width: 100%;
+ background: rgba(193, 84, 246, 0.78);
+ background-repeat: no-repeat;
+ border-bottom: 60px rgb(64, 34, 2);
+ margin-bottom: 60px;
+ margin-left: auto;
+ margin-right: auto;
+ color: rgb(64, 34, 2);
+}
+h2 {
+ font-family: 'Berkshire Swash';font-size: 45px;
+ font-weight: lighter;
+}
+
+// Image styling
+.orbit {
+ width: 50%;
+ height: 50%;
+ margin-left: auto;
+ margin-right: auto;
+}
+.bonbon-img {
+ width: 900px;
+ display: block;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ border: 10px double rgb(64, 34, 2);
+}
+.image-container {
+ display: flex;
+ margin: auto;
+ align-items: center;
+ justify-content: center;
+ width: 45%;
+ padding-bottom: 100px;
+ padding-top: 100px;
+ padding-left: 60px;
+}
+
+
+.pagination {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ font-size: 23px;
+}
+em.current {
+ border-radius: 5px;
+}
+.product_pic {
+ border: 1px solid rgb(64, 34, 2);
+ border-radius: 4px; /* Rounded border */
+ padding: 5px; /* Some padding */
+ width: 150px; /* Set a small width */
+}
+
+// Product Info and Details Stylings
+section.product-show-page {
+ display: flex;
+ flex-wrap: wrap;
+ align-content: space-around;
+ padding: 10px 10px 40px 10px;
+}
+div.product-info-container {
+ width: 600px;
+ margin: auto;
+ margin-bottom: 5em;
+ border: 10px double rgb(64, 34, 2);
+ border-radius: 8px;
+ text-align: center;
+ padding: 10px 10px 10px 10px;
+ float: left;
+}
+div.rating-form-container {
+ width: 100%;
+ height: 390px;
+ margin: auto;
+ margin-left: 2em;
+ margin-right: 2em;
+ border: 10px double rgb(64, 34, 2);
+ border-radius: 8px;
+ text-align: center;
+ padding: 10px 10px 10px 10px;
+}
+
+// Ratings and Reviews Info Styling
+section.all-ratings-box {
+ display: flex;
+ justify-content: center;
+ align-content: space-around;
+ padding: 20px 20px 20px 20px;
+}
+div.all-reviews-container {
+ display: grid;
+ width: 800px;
+ margin-bottom: auto;
+ margin-top: auto;
+ border: 10px double rgb(64, 34, 2);
+ border-radius: 8px;
+ text-align: center;
+ padding: 10px 10px 10px 10px;
+ float: left;
+}
+.all-reviews-container p {
+ display: flex;
+ flex-direction: row;
+}
+.review-deets {
+ border: 10px double rgb(64, 34, 2);
+ padding-top: 20px;
+ padding-bottom: 20px;
+ margin-bottom: 2em;
+}
+
+.plain-font {
+ font-family: sans-serif;
+}
+.average-rating-score {
+ border-top: 5px double rgb(64, 34, 2);
+ border-bottom: 5px double rgb(64, 34, 2);
+ margin-left: auto;
+ margin-right: auto;
+ padding-bottom: 20px;
+ padding-top: 20px;
+}
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+}
+td, th {
+ padding: 6px;
+ text-align: left;
+}
+@media
+only screen and (max-width: 760px),
+(min-device-width: 768px) and (max-device-width: 1024px) {
+ table, thead, tbody, th, td, tr {
+ display: block;
+ }
+}
+thead tr {
+ top: -9999px;
+ left: -9999px;
+}
+
+tr { border: 1px solid #ccc; }
+
+td {
+ /* Behave like a "row" */
+ border: none;
+ border-bottom: 1px solid #eee;
+ position: relative;
+ padding-left: 50%;
+}
+
+td:before {
+ /* Now like a table header */
+ position: absolute;
+ /* Top/left values mimic padding */
+ top: 6px;
+ left: 6px;
+ width: 45%;
+ padding-right: 10px;
+ white-space: nowrap;
+}
diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss
new file mode 100644
index 0000000000..11bbb12cd5
--- /dev/null
+++ b/app/assets/stylesheets/reviews.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Reviews controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss
new file mode 100644
index 0000000000..7bef9cf826
--- /dev/null
+++ b/app/assets/stylesheets/sessions.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the sessions controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/channels/application_cable/channel.rb b/app/channels/application_cable/channel.rb
new file mode 100644
index 0000000000..d672697283
--- /dev/null
+++ b/app/channels/application_cable/channel.rb
@@ -0,0 +1,4 @@
+module ApplicationCable
+ class Channel < ActionCable::Channel::Base
+ end
+end
diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb
new file mode 100644
index 0000000000..0ff5442f47
--- /dev/null
+++ b/app/channels/application_cable/connection.rb
@@ -0,0 +1,4 @@
+module ApplicationCable
+ class Connection < ActionCable::Connection::Base
+ end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
new file mode 100644
index 0000000000..b380c8c58d
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,12 @@
+class ApplicationController < ActionController::Base
+ protect_from_forgery with: :exception
+
+ private
+ def find_merchant
+ if session[:merchant_id]
+ @login_merchant = Merchant.find_by(id: session[:merchant_id])
+
+ end
+ end
+
+end
diff --git a/app/controllers/cartitems_controller.rb b/app/controllers/cartitems_controller.rb
new file mode 100644
index 0000000000..17a09989d0
--- /dev/null
+++ b/app/controllers/cartitems_controller.rb
@@ -0,0 +1,78 @@
+class CartitemsController < ApplicationController
+ before_action :find_cartitem, only: [:show, :update, :destroy]
+ before_action :cartitem_params, only: [:update, :create]
+
+ def create
+ if session[:cart_id]
+ @cart = Cart.find_by(id: session[:cart_id])
+ @cartitem = Cartitem.new(cartitem_params)
+ @cartitem.cart_id = session[:cart_id]
+ if @cartitem.save
+ flash[:status] = :success
+ flash[:result_text] = "Your item has been added to your shopping cart"
+ return redirect_to products_path
+ else
+ if @cart.cartitems.find_by(product_id: @cartitem.product_id)
+ flash[:messages] = @cartitem.errors.messages
+ return redirect_to cart_path(@cart)
+ end
+ flash[:result_text] = "It was not possible to add this product to the cart"
+ flash[:messages] = @cartitem.errors.messages
+ end
+ else
+ @cart = Cart.new
+ if @cart.save
+ session[:cart_id] = @cart.id
+ @cartitem = Cartitem.new(cartitem_params)
+ @cartitem.cart_id = session[:cart_id]
+ if @cartitem.save
+ flash[:status] = :success
+ flash[:result_text] = "This product has been added to your shopping cart"
+ return redirect_to products_path
+ else
+ flash[:result_text] = "It was not possible to add this product to the cart"
+ end
+ end
+ end
+ flash[:status] = :failure
+ redirect_back(fallback_location: products_path)
+ end
+
+
+ def update
+ @cartitem.assign_attributes(cartitem_params)
+ if @cartitem.product.available?(params[:cartitem][:quantity].to_i)
+ if @cartitem.save
+ flash[:status] = :success
+ flash[:result_text] = "Successfully updated your #{@cartitem.product.name} quantity"
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "Could not update your #{@cartitem.product.name} quantity"
+ flash[:messages] = @cartitem.errors.messages
+ end
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "There is not enough #{@cartitem.product.name} in stock"
+ end
+
+ redirect_to cart_path(@cartitem.cart_id)
+ end
+
+ def destroy
+ @cartitem.destroy
+ flash[:status] = :success
+ flash[:result_text] = "Successfully removed #{@cartitem.product.name} from cart"
+ redirect_to cart_path(@cartitem.cart_id)
+ end
+
+ private
+ def find_cartitem
+ @cartitem = Cartitem.find_by(id: params[:id])
+ head :not_found unless @cartitem
+ end
+
+ def cartitem_params
+ params.require(:cartitem).permit(:quantity, :product_id)
+ end
+
+end
diff --git a/app/controllers/carts_controller.rb b/app/controllers/carts_controller.rb
new file mode 100644
index 0000000000..c1127e213c
--- /dev/null
+++ b/app/controllers/carts_controller.rb
@@ -0,0 +1,28 @@
+class CartsController < ApplicationController
+
+ before_action :find_cart, only: [:show, :empty_cart]
+
+ def show; end
+
+ def empty_cart
+ if @cart.id == session[:cart_id]
+ @cart.cartitems.destroy_all
+
+ if @cart.total_items == 0
+ flash[:success]
+ flash[:result_text] = "Your cart has been emptied"
+ end
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "You can could not empty other people's cart"
+ flash[:messages] = @cart.errors.messages
+ end
+ redirect_back(fallback_location: cart_path(@cart))
+ end
+
+ private
+ def find_cart
+ @cart = Cart.find_by(id: params[:id])
+ head :not_found unless @cart
+ end
+end
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
new file mode 100644
index 0000000000..1dc9933fc8
--- /dev/null
+++ b/app/controllers/categories_controller.rb
@@ -0,0 +1,41 @@
+class CategoriesController < ApplicationController
+ before_action :find_category, only: [:show]
+ def index
+ @categories = Category.all.paginate(:page => params[:page], :per_page => 3)
+ end
+
+ def new
+ find_merchant
+ if params[:merchant_id]
+ @category = Category.new
+ end
+ end
+
+ def show; end
+
+ def create
+ @category = Category.new(category_params)
+
+ if @category.save
+ flash[:status] = :success
+ flash[:result_text] = "Category added successfully"
+ redirect_to new_merchant_product_path
+ else
+ flash.now[:status] = :failure
+ flash.now[:result_text] = "Failed to add new category"
+ flash.now[:messages] = @category.errors.messages
+ render :new, status: :bad_request
+ end
+ end
+
+ private
+ def category_params
+ return params.require(:category).permit(:name)
+ end
+
+ def find_category
+ @category = Category.find_by(id: params[:id])
+ head :not_found unless @category
+ end
+
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb
new file mode 100644
index 0000000000..9fff835166
--- /dev/null
+++ b/app/controllers/merchants_controller.rb
@@ -0,0 +1,38 @@
+class MerchantsController < ApplicationController
+ before_action :find_merchant, only: [:show, :show_products]
+
+ def index
+ @merchants = Merchant.all.paginate(:page => params[:page], :per_page => 3)
+ end
+
+ def show
+ if session[:merchant_id].to_s == params[:id]
+ @orders = @merchant.my_orders
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "You can not view other merchant's account page"
+ redirect_back fallback_location: root_path
+ end
+ end
+
+ def display
+ @merchant = Merchant.find_by(id: params[:merchant_id])
+ end
+
+ def show_products
+ @products = Product.where(merchant_id: params[:id])
+ end
+
+ def by_name
+ merchant_name = params[:username]
+ @merchants = Merchant.where("LOWER(username) like ?", "%#{merchant_name.downcase}%")
+
+ render :index
+ end
+
+ private
+ def find_merchant
+ @merchant = Merchant.find_by(id: params[:id])
+ head :not_found unless @merchant
+ end
+end
diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb
new file mode 100644
index 0000000000..2cfa87a739
--- /dev/null
+++ b/app/controllers/orders_controller.rb
@@ -0,0 +1,113 @@
+class OrdersController < ApplicationController
+
+ before_action :find_order, only: [:update, :edit, :show, :my_order, :change_status]
+
+ before_action :find_cart_by_session, only: [:new]
+ before_action :find_cart_by_order, only: [:update, :show]
+
+
+ def new
+ @order = Order.new
+ end
+
+ def create
+ @order = Order.new(order_params)
+ @order.cart_id = session[:cart_id]
+
+ if @order.save
+ flash[:status] = :success
+ redirect_to edit_order_path(@order)
+ else
+ flash.now[:status] = :failure
+ flash.now[:result_text] = "Could not place your order"
+ flash.now[:messages] = @order.errors.messages
+
+ render :new, status: :bad_request
+ end
+ end
+
+ def show; end
+
+ def edit; end
+
+ def update
+ @order.assign_attributes(order_params)
+
+ if @order.save
+ @cart.cartitems.each do |cartitem|
+ product = Product.find(cartitem.product_id)
+ product.stock = product.new_stock(cartitem.quantity)
+ product.visible = false if product.stock == 0
+ unless product.save
+ flash.now[:status] = :failure
+ flash.now[:result_text] = "Our #{product.name} is out of stock, please update your cart!"
+ redirect_to cart_path(@cart)
+ end
+ end
+
+ flash[:status] = :success
+ flash[:result_text] = "Your order has been placed !"
+ flash[:order_number] = "Order number: #{@order.id}"
+ session[:cart_id] = nil
+ redirect_to order_path(@order)
+ else
+
+ flash.now[:status] = :failure
+ flash.now[:result_text] = "Could not place your order"
+ flash.now[:messages] = @order.errors.messages
+
+ render :edit, status: :bad_request
+ end
+ end
+
+ def change_status
+ @order.assign_attributes(order_params)
+
+ if @order.save
+ flash[:status] = :success
+ flash[:result_text] = "Status updated !"
+ flash[:order_number] = "Current status: #{@order.status}"
+ redirect_back fallback_location: order_path(@order)
+ else
+ flash.now[:status] = :failure
+ flash.now[:result_text] = "Could not update status"
+ flash.now[:messages] = @order.errors.messages
+
+ render :edit, status: :bad_request
+ end
+ end
+
+ def my_orders
+ @orders = []
+ Order.all.each do |order|
+ order.cart.products.each do |product|
+ if product.merchant_id == session[:merchant_id]
+ @orders << order unless @orders.include?(order)
+ end
+ end
+ end
+ end
+
+ def my_order; end
+
+ private
+ def order_params
+ params.require(:order).permit(:name, :email, :creditcard, :name_on_card, :expiration_month, :expiration_year, :cvv, :mail_address, :billing_address, :zipcode, :status)
+ end
+
+ def find_order
+ @order = Order.find_by(id: params[:id])
+ head :not_found unless @order
+ end
+
+ def find_cart_by_order
+ order = Order.find_by(id: params[:id])
+ @cart = Cart.find_by(id: order.cart_id)
+ head :not_found unless @cart
+ end
+
+ def find_cart_by_session
+ @cart = Cart.find_by(id: session[:cart_id])
+ head :not_found unless @cart
+ end
+end
diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb
new file mode 100644
index 0000000000..412846ffc0
--- /dev/null
+++ b/app/controllers/products_controller.rb
@@ -0,0 +1,128 @@
+class ProductsController < ApplicationController
+ before_action :find_product, only: [:show, :edit, :update, :retire, :destroy]
+
+ def homepage;end
+
+ def index
+ @products = Product.where(visible: true).paginate(:page => params[:page], :per_page => 5)
+ end
+
+
+ def new
+ if session[:merchant_id]
+ @product = Product.new(merchant_id: params[:merchant_id])
+ else
+ flash[:message] = "You must log in to add a product"
+ redirect_back fallback_location: products_path
+ end
+ end
+
+ def create
+ if session[:merchant_id]
+ @product = Product.new(product_params)
+ if @product.save
+ flash[:status] = :success
+ flash[:result_text] = "Product added successfully"
+ redirect_to product_path(@product)
+ else
+ flash.now[:status] = :failure
+ flash.now[:result_text] = "Failed to add new product"
+ flash.now[:messages] = @product.errors.messages
+ render :new, status: :bad_request
+ end
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "You must be logged in to do that"
+ redirect_back fallback_location: products_path
+ end
+ end
+
+ def show
+ @cartitem = Cartitem.new
+ @review = Review.new
+ end
+
+ def edit
+ if session[:merchant_id]
+ @product = Product.find(params[:id])
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "You must be logged in to do that"
+ redirect_to products_path
+ return
+ end
+ end
+
+ def update
+ if session[:merchant_id]
+ @product.merchant_id = session[:merchant_id]
+ @product.assign_attributes(product_params)
+ if @product.save
+ redirect_to product_path(@product)
+ else
+ render :edit, status: :bad_request
+ end
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "You must be logged in to do that"
+ redirect_to products_path, status: :unauthorized
+ return
+ end
+ end
+
+
+ def retire
+ if session[:merchant_id]
+ # retires a product that still has stock
+ if @product.visible == true
+ @product.update(visible: false)
+ flash[:status] = :success
+ flash[:result_text] = "Successfully retire #{@product.name}"
+ elsif
+ # can unretire an item as long as the stock is NOT 0
+ @product.visible == false && @product.stock != 0
+ @product.update(visible: true)
+ flash[:status] = :success
+ flash[:result_text] = "Successfully unretire #{@product.name}"
+ elsif
+ # retires a product if the stock drops to 0
+ @product.visible == true && @product.stock == 0
+ @product.update(visible: false)
+ flash[:status] = :failure
+ flash[:result_text] = "All out of #{@product.name}."
+ else
+ # will not retire an already retired item
+ flash[:status] = :failure
+ flash[:result_text] = "#{@product.name} has already retired."
+ end
+ else
+ # fails to retire an item
+ flash[:status] = :failure
+ if @product.visible == true
+ flash[:result_text] = "Failed to retire #{@product.name}"
+ else
+ # fails to unretire an item
+ flash[:result_text] = "Failed to unretire #{@product.name}"
+ end
+ end
+ redirect_back fallback_location: root_path
+ end
+
+ def by_name
+ product_name = params[:name]
+ @products = Product.where(visible: true).where("LOWER(name) like ?", "%#{product_name.downcase}%").paginate(:page => params[:page], :per_page => 5)
+
+ render :index
+
+ end
+
+ private
+ def product_params
+ params.require(:product).permit(:name, :price, :merchant_id, :description, :image, :stock, :visible, category_ids: [])
+ end
+
+ def find_product
+ @product = Product.find_by(id: params[:id])
+ head :not_found unless @product
+ end
+end
diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb
new file mode 100644
index 0000000000..bc00fae6e5
--- /dev/null
+++ b/app/controllers/reviews_controller.rb
@@ -0,0 +1,38 @@
+class ReviewsController < ApplicationController
+ before_action :find_product, only: [:create]
+
+ def new
+ @review = Review.new
+ end
+
+ def create
+ @review = Review.new(review_params)
+
+ if @product.merchant_id == session[:merchant_id]
+ flash[:status] = :failure
+ flash[:result_text] = "You may not review your own product"
+ redirect_to product_path(@review.product_id), status: :forbidden
+ else
+ if @review.save
+ flash[:status] = :success
+ flash[:result_text] = "Successfully created a review"
+ redirect_to product_path(@review.product_id)
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "Could not create a review"
+ flash[:messages] = @review.errors.messages
+ redirect_back fallback_location: products_path, status: :bad_request
+ end
+ end
+ end
+
+ private
+ def review_params
+ return params.require(:review).permit(:rating, :comment, :product_id)
+ end
+
+ def find_product
+ @product = Product.find_by(id: params[:review][:product_id])
+ head :not_found unless @product
+ end
+end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
new file mode 100644
index 0000000000..1fb3a78ca9
--- /dev/null
+++ b/app/controllers/sessions_controller.rb
@@ -0,0 +1,45 @@
+class SessionsController < ApplicationController
+
+ def login
+ auth_hash = request.env["omniauth.auth"]
+ if auth_hash["uid"]
+ @merchant = Merchant.find_by(uid: auth_hash["uid"], provider: auth_hash["provider"])
+
+ if @merchant.nil?
+ @merchant = Merchant.build_from_github(auth_hash)
+ if @merchant.id
+ flash[:status] = :success
+ flash[:result_text] = "#{@merchant.username} successfully logged in as a new merchant"
+ else
+ flash[:status] = :failure
+ flash[:result_text] = @merchant.errors.messages
+ end
+ else
+ flash[:status] = :success
+ flash[:result_text] = "#{@merchant.username} successfully logged in as existing merchant"
+ end
+ session[:merchant_id] = @merchant.id
+
+ else
+ flash[:error] = "Could not log in"
+ end
+
+ redirect_to root_path
+ end
+
+ def logout
+ if session[:merchant_id]
+ @login_merchant = Merchant.find_by(id: session[:merchant_id])
+ if session[:merchant_id] == @login_merchant.id
+ session[:merchant_id] = nil
+ flash[:status] = :success
+ flash[:result_text] = "Successfully logged out"
+ end
+ else
+ flash[:status] = :failure
+ flash[:result_text] = "You must login in"
+ end
+ redirect_to root_path
+ end
+
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
new file mode 100644
index 0000000000..5ade132bf2
--- /dev/null
+++ b/app/helpers/application_helper.rb
@@ -0,0 +1,14 @@
+module ApplicationHelper
+ def display_dollars(cents)
+ dollars = cents / 100.0
+ return '%.2f' % dollars
+ end
+
+ def display_date(input)
+ return input.strftime("%B %d, %Y")
+ end
+
+ def display_date_time(input)
+ return input.strftime("%m/%d/%Y at %I:%M%p")
+ end
+end
diff --git a/app/helpers/cartitems_helper.rb b/app/helpers/cartitems_helper.rb
new file mode 100644
index 0000000000..ae03e13635
--- /dev/null
+++ b/app/helpers/cartitems_helper.rb
@@ -0,0 +1,2 @@
+module CartitemsHelper
+end
diff --git a/app/helpers/carts_helper.rb b/app/helpers/carts_helper.rb
new file mode 100644
index 0000000000..d99c380cb5
--- /dev/null
+++ b/app/helpers/carts_helper.rb
@@ -0,0 +1,2 @@
+module CartsHelper
+end
diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb
new file mode 100644
index 0000000000..e06f31554c
--- /dev/null
+++ b/app/helpers/categories_helper.rb
@@ -0,0 +1,2 @@
+module CategoriesHelper
+end
diff --git a/app/helpers/merchants_helper.rb b/app/helpers/merchants_helper.rb
new file mode 100644
index 0000000000..5337747b0f
--- /dev/null
+++ b/app/helpers/merchants_helper.rb
@@ -0,0 +1,2 @@
+module MerchantsHelper
+end
diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb
new file mode 100644
index 0000000000..443227fd48
--- /dev/null
+++ b/app/helpers/orders_helper.rb
@@ -0,0 +1,2 @@
+module OrdersHelper
+end
diff --git a/app/helpers/products_helper.rb b/app/helpers/products_helper.rb
new file mode 100644
index 0000000000..ab5c42b325
--- /dev/null
+++ b/app/helpers/products_helper.rb
@@ -0,0 +1,2 @@
+module ProductsHelper
+end
diff --git a/app/helpers/reviews_helper.rb b/app/helpers/reviews_helper.rb
new file mode 100644
index 0000000000..4c038f2d60
--- /dev/null
+++ b/app/helpers/reviews_helper.rb
@@ -0,0 +1,9 @@
+module ReviewsHelper
+ def stars (rating_num)
+ stars = " "
+ rating_num.to_i.times do
+ stars += "🍰"
+ end
+ return stars
+ end
+end
diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb
new file mode 100644
index 0000000000..309f8b2eb3
--- /dev/null
+++ b/app/helpers/sessions_helper.rb
@@ -0,0 +1,2 @@
+module SessionsHelper
+end
diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb
new file mode 100644
index 0000000000..a009ace51c
--- /dev/null
+++ b/app/jobs/application_job.rb
@@ -0,0 +1,2 @@
+class ApplicationJob < ActiveJob::Base
+end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
new file mode 100644
index 0000000000..286b2239d1
--- /dev/null
+++ b/app/mailers/application_mailer.rb
@@ -0,0 +1,4 @@
+class ApplicationMailer < ActionMailer::Base
+ default from: 'from@example.com'
+ layout 'mailer'
+end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 0000000000..10a4cba84d
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,3 @@
+class ApplicationRecord < ActiveRecord::Base
+ self.abstract_class = true
+end
diff --git a/app/models/cart.rb b/app/models/cart.rb
new file mode 100644
index 0000000000..1341f8aa78
--- /dev/null
+++ b/app/models/cart.rb
@@ -0,0 +1,34 @@
+class Cart < ApplicationRecord
+ has_many :cartitems
+ has_many :products, through: :cartitems
+ has_one :order
+
+ TAXRATE = 0.10
+
+ def subtotal
+ subtotal = 0
+ self.cartitems.each do |cartitem|
+ subtotal += cartitem.subtotal
+ end
+ # self.cartitems.inject {|total, cartitem.subtotal| total + subtotal}
+ return subtotal
+ end
+
+ def total_items
+ total_items = 0
+ self.cartitems.each do |item|
+ total_items += item.quantity
+ end
+ return total_items
+ end
+
+ def tax
+ tax = self.subtotal * TAXRATE
+ return tax
+ end
+
+ def total_cost
+ total_cost = self.subtotal + self.tax
+ return total_cost
+ end
+end
diff --git a/app/models/cartitem.rb b/app/models/cartitem.rb
new file mode 100644
index 0000000000..c7f591934d
--- /dev/null
+++ b/app/models/cartitem.rb
@@ -0,0 +1,14 @@
+class Cartitem < ApplicationRecord
+ belongs_to :product
+ belongs_to :cart
+
+ validates :quantity, presence: true, numericality: {only_integer: true, greater_than: 0}
+ validates :cart_id, uniqueness: { scope: :product_id, message: "This item is already in your cart, please update quantity in cart." }
+
+ def subtotal
+ unit_price = self.product.price
+ subtotal = unit_price * self.quantity
+ return subtotal
+ end
+
+end
diff --git a/app/models/category.rb b/app/models/category.rb
new file mode 100644
index 0000000000..7019ddecbf
--- /dev/null
+++ b/app/models/category.rb
@@ -0,0 +1,12 @@
+class Category < ApplicationRecord
+ has_and_belongs_to_many :products
+
+ validates :name, presence: true, uniqueness: true
+
+ def show_four
+ if self.products.count > 4
+ return self.products.first(4)
+ end
+ return self.products
+ end
+end
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/app/models/merchant.rb b/app/models/merchant.rb
new file mode 100644
index 0000000000..15e5e65427
--- /dev/null
+++ b/app/models/merchant.rb
@@ -0,0 +1,84 @@
+class Merchant < ApplicationRecord
+ has_many :products
+
+ validates :username, presence: true, uniqueness: true
+ validates :email, presence: true, uniqueness: true
+
+ def self.build_from_github(auth_hash)
+ merchant = Merchant.new(
+ username: auth_hash[:info][:nickname],
+ email: auth_hash[:info][:email],
+ uid: auth_hash[:uid],
+ provider: auth_hash[:provider]
+ )
+ merchant.save
+ return merchant
+ end
+
+ def show_four
+ if self.visible_products.count > 4
+ return self.visible_products.first(4)
+ end
+ return self.visible_products
+ end
+
+ def visible_products
+ return self.products.reject{ |pro| pro.visible == false }
+ end
+
+ def invisible_products
+ return self.products.reject{ |pro| pro.visible == true}
+ end
+
+ def my_cartitems
+ my_cartitems = []
+ Cartitem.all.each do |cartitem|
+ if self.products.include?(cartitem.product)
+ my_cartitems << cartitem
+ end
+ end
+ return my_cartitems
+ end
+
+ def my_orders
+ my_orders = []
+ Order.all.each do |order|
+ order.cart.cartitems.each do |cartitem|
+ if self.products.include?(cartitem.product)
+ my_orders << order
+ end
+ end
+ end
+ my_orders.uniq!
+ return my_orders
+ end
+
+ def my_total_revenue
+ return 0 if self.my_cartitems.empty?
+ total_revenue = 0
+ my_orders.each do |order|
+ order.cart.cartitems.each do |item|
+ if self.products.include?(item.product)
+ revenue = item.product.price * item.quantity
+ total_revenue += revenue
+ end
+ end
+ end
+ return total_revenue
+ end
+
+ def my_revenue_by_status(status)
+ return 0 if self.my_cartitems.empty?
+ total_revenue = 0
+ orders_by_status = my_orders.select { |order| order.status.downcase == status }
+ orders_by_status.each do |order|
+ order.cart.cartitems.each do |item|
+ if self.products.include?(item.product)
+ revenue = item.product.price * item.quantity
+ total_revenue += revenue
+ end
+ end
+ end
+ return total_revenue
+ end
+end
diff --git a/app/models/order.rb b/app/models/order.rb
new file mode 100644
index 0000000000..760f411dc5
--- /dev/null
+++ b/app/models/order.rb
@@ -0,0 +1,33 @@
+class Order < ApplicationRecord
+ belongs_to :cart
+
+ validates :name, presence: true, unless: :is_pending
+ validates :email, presence: true, unless: :is_pending
+ validates :creditcard, presence: true, length: {is: 16}, unless: :is_pending
+ validates :expiration_month, presence: true, unless: :is_pending
+ validates :expiration_year, presence: true, unless: :is_pending
+ validates :name_on_card, presence: true, unless: :is_pending
+ validates :cvv, presence: true, length: {minimum: 3, maximum: 4}, unless: :is_pending
+ validates :mail_address, presence: true, unless: :is_pending
+ validates :billing_address, presence: true, unless: :is_pending
+ validates :status, presence: true
+ validates :zipcode, presence: true, unless: :is_pending
+
+
+ def is_pending
+ return self.status == "pending"
+ end
+
+ TAXRATE = 0.10
+ def order_tax
+ cart = Cart.find(self.cart_id)
+ tax = cart.subtotal * TAXRATE
+ return tax
+ end
+#Sorry it is all double but need to dry it
+ def total
+ cart = Cart.find(self.cart_id)
+ total = (cart.subtotal * TAXRATE) + cart.subtotal
+ return total
+ end
+end
diff --git a/app/models/product.rb b/app/models/product.rb
new file mode 100644
index 0000000000..6788ecf417
--- /dev/null
+++ b/app/models/product.rb
@@ -0,0 +1,31 @@
+class Product < ApplicationRecord
+ has_and_belongs_to_many :categories
+ has_many :cartitems, dependent: :restrict_with_error
+ has_many :reviews, dependent: :destroy
+ # Included dependent destroy till we decide if we want these permanantly deleted -ALS
+ belongs_to :merchant
+
+ validates :name, presence: true
+ validates :price, presence: true, numericality: {only_integer: true, greater_than: 0}
+
+ def available?(new_quantity)
+ return self.stock >= new_quantity
+ end
+
+ def average_rating
+ return nil unless self.reviews.any?
+
+ total = 0
+ self.reviews.each do |review|
+ total += review.rating
+ end
+ average_rating = total / self.reviews.count
+ return average_rating
+ end
+
+ def new_stock(items_bought)
+ new_total = self.stock - items_bought
+ return new_total
+ end
+
+end
diff --git a/app/models/review.rb b/app/models/review.rb
new file mode 100644
index 0000000000..1c38def4fd
--- /dev/null
+++ b/app/models/review.rb
@@ -0,0 +1,5 @@
+class Review < ApplicationRecord
+ belongs_to :product
+
+ validates :rating, presence: true, numericality: {only_integer: true, greater_than: 0, less_than: 6}
+end
diff --git a/app/views/carts/show.html.erb b/app/views/carts/show.html.erb
new file mode 100644
index 0000000000..df4b6f9c49
--- /dev/null
+++ b/app/views/carts/show.html.erb
@@ -0,0 +1,47 @@
+ Your cart includes <%= @cart.total_items %> delicious items.My Cart
+
+
+
+
+
+<%= link_to "Continue Shopping", products_path, class: "button double-button" %>
+<%= link_to "Empty Cart", empty_cart_path(@cart), method: :patch, data: { confirm: "Are you sure you want to empty your entire cart?" }, class: "button double-button" %>
+<%= link_to "Proceed to Checkout", new_order_path, class: "button double-button" %>
+
+
+
+
+
+ <% @cart.cartitems.each do |item| %>
+ Delicious Baked Goodness
+ Quantity
+
+ Unit Price
+ Subtotal
+
+
+ <% end %>
+ <%= link_to "#{item.product.name}", product_path(item.product_id) %>
+
+ <%= form_for item do |f| %>
+ <%= f.number_field(:quantity, in: 1..item.product.stock) %>
+ <%= f.submit("Update Quantity") %>
+ <% end %>
+
+ <%= link_to("Remove this item", cartitem_path(item), method: :delete, data: { confirm: "Are you sure you want to delete #{item.product.name} from your cart?" }) %>
+ <%= display_dollars(item.product.price) %>
+ <%= display_dollars(item.subtotal) %>
+
+
+
+
+
+
+
+ Subtotal:
+ <%= display_dollars(@cart.subtotal) %>
+
+ <%= link_to cate.name, category_path(cate) %>
+
+
+ <% cate.show_four.each do |pro| %>
+
+ <% end %>
+<%= link_to pro.name, product_path(pro) %>
+ <%= link_to image_tag(pro.image, alt: "bonbon-image", class: "small-pro"), product_path(pro) %>
+
+ <%= @category.name %>
+
+
+
+
| Product ID | +Name | +Stock | +Status | +Edit | +|
|---|---|---|---|---|---|
| <%= d.id %> | +<%= link_to d.name, product_path(d) %> | +<%= d.stock %> | + <% if d.visible == true %> +<%= link_to "Retire", retire_path(d), method: :patch, class: "button" %> + | + + <% else %> +<%= link_to "Unretire", retire_path(d), method: :patch, class: "button" %> + | + <% end %> +<%= link_to "Edit", edit_product_path(d.id), class: "button" %> | + +
$ <%= display_dollars(@merchant.my_total_revenue) %>
+$ <%= display_dollars(@merchant.my_revenue_by_status("pending")) %>
+$ <%= display_dollars(@merchant.my_revenue_by_status("paid")) %>
+$ <%= display_dollars(@merchant.my_revenue_by_status("completed")) %>
+$ <%= display_dollars(@merchant.my_revenue_by_status("cancelled")) %>
+Delicious Baked Goodness |
+ Quantity |
+ + | Unit Price |
+ Subtotal |
+
|---|---|---|---|---|
| <%= link_to "#{item.product.name}", product_path(item.product_id) %> | +<%= item.quantity %> | ++ | <%= display_dollars(item.product.price) %> | +<%= display_dollars(item.subtotal) %> | +
| + ID + | ++ Date + | ++ My products + | ++ Revenue + | ++ Status + | +
|---|---|---|---|---|
| + <%= link_to order.id, my_order_path(order) %> + | ++ <%= display_date(order.created_at) %> + | +
+ <% revenue = []%>
+ <% order.cart.cartitems.joins(:product).where(products: { merchant_id: session[:merchant_id]}).each do |cartitem|%>
+ <% revenue << (Product.find(cartitem.product_id).price * cartitem.quantity)%>
+
|
+ $<%= display_dollars(revenue.sum)%> | ++ <%= form_for order, url: change_status_path(order) do |f| %> + <%= f.label :status %> + <%= f.select :status, options_for_select([["#{order.status}",""],"Pending", "Paid", "Completed", "Cancelled"],:disabled => ["Pending"],:prompt => ["#{order.status}"] )%> + <%= f.submit "Change status"%> + <%end%> + | +
| Subtotal: $<%= display_dollars(@cart.subtotal)%> | +
| Tax: $<%= display_dollars(@cart.tax)%> | +
Total: $<%= display_dollars(@cart.total_cost)%> |
+