diff --git a/.gitignore b/.gitignore
index 6db3c9a5bc..1e471b9f24 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,9 +7,24 @@
# Ignore bundler config.
/.bundle
+# Ignore the default SQLite database.
+/db/*.sqlite3
+/db/*.sqlite3-journal
+
# Ignore all logfiles and tempfiles.
/log/*
+/tmp/*
!/log/.keep
-/tmp
+!/tmp/.keep
+
+# Ignore Byebug command history file.
+.byebug_history
+# Ignore .env
+.env
+
+# Ignore .DS_Store
.DS_Store
+
+# Ignore .DS_Store
+/coverage
diff --git a/.ruby-gemset b/.ruby-gemset
deleted file mode 100644
index d5c660823f..0000000000
--- a/.ruby-gemset
+++ /dev/null
@@ -1 +0,0 @@
-betsy
diff --git a/.ruby-version b/.ruby-version
deleted file mode 100644
index 2bf1c1ccf3..0000000000
--- a/.ruby-version
+++ /dev/null
@@ -1 +0,0 @@
-2.3.1
diff --git a/Gemfile b/Gemfile
index c69f4ddde9..2e320832cb 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,46 +1,73 @@
source 'https://rubygems.org'
-ruby '2.3.1'
+gem 'rack-cache', require: 'rack/cache', group: :production
+gem 'dragonfly'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
-gem 'rails', '4.2.6'
-# Use postgresql as the database for Active Record
-# gem 'pg', '~> 0.15'
+gem 'rails', '4.2.7'
+# Use sqlite3 as the database for Active Record
+# Use Puma as the app server
+gem 'puma', '~> 3.0'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
-gem 'coffee-rails', '~> 4.1.0'
+gem 'coffee-rails', '~> 4.2'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
# Use jquery as the JavaScript library
gem 'jquery-rails'
-# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
-gem 'turbolinks'
+# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
+gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
-gem 'jbuilder', '~> 2.0'
-# bundle exec rake doc:rails generates the API under doc/api.
-gem 'sdoc', '~> 0.4.0', group: :doc
-
+gem 'jbuilder', '~> 2.5'
+# Use Redis adapter to run Action Cable in production
+# gem 'redis', '~> 3.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
-
-# Use Unicorn as the app server
-# gem 'unicorn'
-
+gem "omniauth"
+gem "omniauth-github"
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
- gem 'byebug'
+ gem 'byebug', platform: :mri
+ gem 'dotenv-rails'
+ gem 'sqlite3'
end
-group :development do
- # Access an IRB console on exception pages or by using <%= console %> in views
- gem 'web-console', '~> 2.0'
+group :test do
+ gem 'minitest-reporters'
+ gem "pry-rails"
+end
+gem 'simplecov', :require => false, :group => :test
+
+group :development do
+ # for bug bashing in the browser
+ gem "better_errors"
+ gem "binding_of_caller"
+ gem "pry-rails"
+ # for seeing our ERD for the visiual peeps
+ gem 'rails-erd'
+ # Access an IRB console on exception pages or by using <%= console %> anywhere in the code.
+ gem 'web-console'
+ gem 'listen', '~> 3.0.5'
# 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'
+end
+
+# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
+gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
+# Foundation Rails Gem
+gem 'foundation-rails'
+# Required due to an incompatibility between TurboLinks and Foundation.
+gem 'jquery-turbolinks'
+
+group :production do
+ gem 'pg'
+ gem 'rails_12factor'
end
diff --git a/Gemfile.lock b/Gemfile.lock
index 20975578b8..441ae0a00b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,93 +1,162 @@
GEM
remote: https://rubygems.org/
specs:
- actionmailer (4.2.6)
- actionpack (= 4.2.6)
- actionview (= 4.2.6)
- activejob (= 4.2.6)
+ actionmailer (4.2.7)
+ actionpack (= 4.2.7)
+ actionview (= 4.2.7)
+ activejob (= 4.2.7)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
- actionpack (4.2.6)
- actionview (= 4.2.6)
- activesupport (= 4.2.6)
+ actionpack (4.2.7)
+ actionview (= 4.2.7)
+ activesupport (= 4.2.7)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (4.2.6)
- activesupport (= 4.2.6)
+ actionview (4.2.7)
+ activesupport (= 4.2.7)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- activejob (4.2.6)
- activesupport (= 4.2.6)
+ activejob (4.2.7)
+ activesupport (= 4.2.7)
globalid (>= 0.3.0)
- activemodel (4.2.6)
- activesupport (= 4.2.6)
+ activemodel (4.2.7)
+ activesupport (= 4.2.7)
builder (~> 3.1)
- activerecord (4.2.6)
- activemodel (= 4.2.6)
- activesupport (= 4.2.6)
+ activerecord (4.2.7)
+ activemodel (= 4.2.7)
+ activesupport (= 4.2.7)
arel (~> 6.0)
- activesupport (4.2.6)
+ activesupport (4.2.7)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
+ addressable (2.4.0)
+ ansi (1.5.0)
arel (6.0.3)
+ babel-source (5.8.35)
+ babel-transpiler (0.7.0)
+ babel-source (>= 4.0, < 6)
+ execjs (~> 2.0)
+ better_errors (2.1.1)
+ coderay (>= 1.0.0)
+ erubis (>= 2.6.6)
+ rack (>= 0.9.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
builder (3.2.2)
- byebug (8.2.5)
- coffee-rails (4.1.1)
+ byebug (9.0.6)
+ choice (0.2.0)
+ coderay (1.1.1)
+ coffee-rails (4.2.1)
coffee-script (>= 2.2.0)
- railties (>= 4.0.0, < 5.1.x)
+ railties (>= 4.0.0, < 5.2.x)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.10.0)
- concurrent-ruby (1.0.1)
+ concurrent-ruby (1.0.2)
debug_inspector (0.0.2)
+ docile (1.1.5)
+ dotenv (2.1.1)
+ dotenv-rails (2.1.1)
+ dotenv (= 2.1.1)
+ railties (>= 4.0, < 5.1)
+ dragonfly (1.1.0)
+ addressable (~> 2.3)
+ multi_json (~> 1.0)
+ rack (>= 1.3)
erubis (2.7.0)
- execjs (2.6.0)
- globalid (0.3.6)
+ execjs (2.7.0)
+ faraday (0.9.2)
+ multipart-post (>= 1.2, < 3)
+ ffi (1.9.14)
+ foundation-rails (6.2.4.0)
+ railties (>= 3.1.0)
+ sass (>= 3.3.0, < 3.5)
+ sprockets-es6 (>= 0.9.0)
+ globalid (0.3.7)
activesupport (>= 4.1.0)
+ hashie (3.4.6)
i18n (0.7.0)
- jbuilder (2.4.1)
+ jbuilder (2.6.0)
activesupport (>= 3.0.0, < 5.1)
multi_json (~> 1.2)
- jquery-rails (4.1.1)
+ jquery-rails (4.2.1)
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 (1.8.3)
+ jwt (1.5.6)
+ listen (3.0.8)
+ rb-fsevent (~> 0.9, >= 0.9.4)
+ rb-inotify (~> 0.9, >= 0.9.7)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
mime-types (>= 1.16, < 4)
- mime-types (3.0)
+ method_source (0.8.2)
+ mime-types (3.1)
mime-types-data (~> 3.2015)
- mime-types-data (3.2016.0221)
- mini_portile2 (2.0.0)
- minitest (5.8.4)
- multi_json (1.11.3)
- nokogiri (1.6.7.2)
- mini_portile2 (~> 2.0.0.rc2)
+ mime-types-data (3.2016.0521)
+ mini_portile2 (2.1.0)
+ minitest (5.9.1)
+ minitest-reporters (1.1.11)
+ ansi
+ builder
+ minitest (>= 5.0)
+ ruby-progressbar
+ multi_json (1.12.1)
+ multi_xml (0.5.5)
+ multipart-post (2.0.0)
+ nokogiri (1.6.8.1)
+ mini_portile2 (~> 2.1.0)
+ oauth2 (1.2.0)
+ faraday (>= 0.8, < 0.10)
+ jwt (~> 1.0)
+ multi_json (~> 1.3)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 3)
+ omniauth (1.3.1)
+ hashie (>= 1.2, < 4)
+ rack (>= 1.0, < 3)
+ omniauth-github (1.1.2)
+ omniauth (~> 1.0)
+ omniauth-oauth2 (~> 1.1)
+ omniauth-oauth2 (1.4.0)
+ oauth2 (~> 1.0)
+ omniauth (~> 1.2)
+ pg (0.19.0)
+ pry (0.10.4)
+ coderay (~> 1.1.0)
+ method_source (~> 0.8.1)
+ slop (~> 3.4)
+ pry-rails (0.3.4)
+ pry (>= 0.9.10)
+ puma (3.6.0)
rack (1.6.4)
+ rack-cache (1.6.1)
+ rack (>= 0.4)
rack-test (0.6.3)
rack (>= 1.0)
- rails (4.2.6)
- actionmailer (= 4.2.6)
- actionpack (= 4.2.6)
- actionview (= 4.2.6)
- activejob (= 4.2.6)
- activemodel (= 4.2.6)
- activerecord (= 4.2.6)
- activesupport (= 4.2.6)
+ rails (4.2.7)
+ actionmailer (= 4.2.7)
+ actionpack (= 4.2.7)
+ actionview (= 4.2.7)
+ activejob (= 4.2.7)
+ activemodel (= 4.2.7)
+ activerecord (= 4.2.7)
+ activesupport (= 4.2.7)
bundler (>= 1.3.0, < 2.0)
- railties (= 4.2.6)
+ railties (= 4.2.7)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
@@ -95,67 +164,108 @@ GEM
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
+ rails-erd (1.5.0)
+ activerecord (>= 3.2)
+ activesupport (>= 3.2)
+ choice (~> 0.2.0)
+ ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
- railties (4.2.6)
- actionpack (= 4.2.6)
- activesupport (= 4.2.6)
+ rails_12factor (0.0.3)
+ rails_serve_static_assets
+ rails_stdout_logging
+ rails_serve_static_assets (0.0.5)
+ rails_stdout_logging (0.0.5)
+ railties (4.2.7)
+ actionpack (= 4.2.7)
+ activesupport (= 4.2.7)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
- rake (11.1.2)
- rdoc (4.2.2)
- json (~> 1.4)
+ rake (11.3.0)
+ rb-fsevent (0.9.7)
+ rb-inotify (0.9.7)
+ ffi (>= 0.5.0)
+ ruby-graphviz (1.2.2)
+ ruby-progressbar (1.8.1)
sass (3.4.22)
- sass-rails (5.0.4)
- railties (>= 4.0.0, < 5.0)
+ sass-rails (5.0.6)
+ railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
- sdoc (0.4.1)
- json (~> 1.7, >= 1.7.7)
- rdoc (~> 4.0)
- spring (1.7.1)
- sprockets (3.6.0)
+ simplecov (0.12.0)
+ docile (~> 1.1.0)
+ json (>= 1.8, < 3)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.0)
+ slop (3.6.0)
+ spring (2.0.0)
+ activesupport (>= 4.2)
+ spring-watcher-listen (2.0.1)
+ listen (>= 2.7, < 4.0)
+ spring (>= 1.2, < 3.0)
+ sprockets (3.7.0)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
- sprockets-rails (3.0.4)
+ sprockets-es6 (0.9.2)
+ babel-source (>= 5.8.11)
+ babel-transpiler
+ sprockets (>= 3.0.0)
+ sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
+ sqlite3 (1.3.12)
thor (0.19.1)
thread_safe (0.3.5)
- tilt (2.0.2)
- turbolinks (2.5.3)
- coffee-rails
+ tilt (2.0.5)
+ turbolinks (5.0.1)
+ turbolinks-source (~> 5)
+ turbolinks-source (5.0.0)
tzinfo (1.2.2)
thread_safe (~> 0.1)
- uglifier (3.0.0)
+ uglifier (3.0.2)
execjs (>= 0.3.0, < 3)
- web-console (2.3.0)
- activemodel (>= 4.0)
- binding_of_caller (>= 0.7.2)
- railties (>= 4.0)
- sprockets-rails (>= 2.0, < 4.0)
+ web-console (3.3.0)
+ activemodel (>= 4.2)
+ debug_inspector
+ railties (>= 4.2)
PLATFORMS
ruby
DEPENDENCIES
+ better_errors
+ binding_of_caller
byebug
- coffee-rails (~> 4.1.0)
- jbuilder (~> 2.0)
+ coffee-rails (~> 4.2)
+ dotenv-rails
+ dragonfly
+ foundation-rails
+ jbuilder (~> 2.5)
jquery-rails
- rails (= 4.2.6)
+ jquery-turbolinks
+ listen (~> 3.0.5)
+ minitest-reporters
+ omniauth
+ omniauth-github
+ pg
+ pry-rails
+ puma (~> 3.0)
+ rack-cache
+ rails (= 4.2.7)
+ rails-erd
+ rails_12factor
sass-rails (~> 5.0)
- sdoc (~> 0.4.0)
+ simplecov
spring
- turbolinks
+ spring-watcher-listen (~> 2.0.0)
+ sqlite3
+ turbolinks (~> 5)
+ tzinfo-data
uglifier (>= 1.3.0)
- web-console (~> 2.0)
-
-RUBY VERSION
- ruby 2.3.1p112
+ web-console
BUNDLED WITH
- 1.13.5
+ 1.13.6
diff --git a/Rakefile b/Rakefile
index ba6b733dd2..e85f913914 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,6 +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 File.expand_path('../config/application', __FILE__)
+require_relative 'config/application'
Rails.application.load_tasks
diff --git a/app/assets/images/1.jpg b/app/assets/images/1.jpg
new file mode 100644
index 0000000000..d24ffa1687
Binary files /dev/null and b/app/assets/images/1.jpg differ
diff --git a/app/assets/images/babay-cloth_2.jpg b/app/assets/images/babay-cloth_2.jpg
new file mode 100644
index 0000000000..8472fe400a
Binary files /dev/null and b/app/assets/images/babay-cloth_2.jpg differ
diff --git a/app/assets/images/baby-cloth.jpg b/app/assets/images/baby-cloth.jpg
new file mode 100644
index 0000000000..a6c133579f
Binary files /dev/null and b/app/assets/images/baby-cloth.jpg differ
diff --git a/app/assets/images/baby_robot .jpg b/app/assets/images/baby_robot .jpg
new file mode 100644
index 0000000000..3bec6647ac
Binary files /dev/null and b/app/assets/images/baby_robot .jpg differ
diff --git a/app/assets/images/bag-flappy-disk.jpg b/app/assets/images/bag-flappy-disk.jpg
new file mode 100644
index 0000000000..3947671aa1
Binary files /dev/null and b/app/assets/images/bag-flappy-disk.jpg differ
diff --git a/app/assets/images/bag.png b/app/assets/images/bag.png
new file mode 100644
index 0000000000..eea56813f9
Binary files /dev/null and b/app/assets/images/bag.png differ
diff --git a/app/assets/images/coffe_mug_3.jpg b/app/assets/images/coffe_mug_3.jpg
new file mode 100644
index 0000000000..c9f5b1227f
Binary files /dev/null and b/app/assets/images/coffe_mug_3.jpg differ
diff --git a/app/assets/images/coffe_mug_4.jpg b/app/assets/images/coffe_mug_4.jpg
new file mode 100644
index 0000000000..4cc76c0b21
Binary files /dev/null and b/app/assets/images/coffe_mug_4.jpg differ
diff --git a/app/assets/images/coffe_mug_7.jpg b/app/assets/images/coffe_mug_7.jpg
new file mode 100644
index 0000000000..dd86ac8398
Binary files /dev/null and b/app/assets/images/coffe_mug_7.jpg differ
diff --git a/app/assets/images/coffee_mug.jpg b/app/assets/images/coffee_mug.jpg
new file mode 100644
index 0000000000..89952df5c0
Binary files /dev/null and b/app/assets/images/coffee_mug.jpg differ
diff --git a/app/assets/images/coffee_mug_2.jpg b/app/assets/images/coffee_mug_2.jpg
new file mode 100644
index 0000000000..92b3466957
Binary files /dev/null and b/app/assets/images/coffee_mug_2.jpg differ
diff --git a/app/assets/images/computer-bag.jpg b/app/assets/images/computer-bag.jpg
new file mode 100644
index 0000000000..389d754262
Binary files /dev/null and b/app/assets/images/computer-bag.jpg differ
diff --git a/app/assets/images/computer_bag.jpg b/app/assets/images/computer_bag.jpg
new file mode 100644
index 0000000000..fee9ca28c1
Binary files /dev/null and b/app/assets/images/computer_bag.jpg differ
diff --git a/app/assets/images/computer_pad.jpg b/app/assets/images/computer_pad.jpg
new file mode 100644
index 0000000000..bd0ca3a9a4
Binary files /dev/null and b/app/assets/images/computer_pad.jpg differ
diff --git a/app/assets/images/computer_tote_bag.jpg b/app/assets/images/computer_tote_bag.jpg
new file mode 100644
index 0000000000..2512eb3cad
Binary files /dev/null and b/app/assets/images/computer_tote_bag.jpg differ
diff --git a/app/assets/images/cute_robots.jpg b/app/assets/images/cute_robots.jpg
new file mode 100644
index 0000000000..9829738c30
Binary files /dev/null and b/app/assets/images/cute_robots.jpg differ
diff --git a/app/assets/images/geek_coffee_5.jpg b/app/assets/images/geek_coffee_5.jpg
new file mode 100644
index 0000000000..61e98c351b
Binary files /dev/null and b/app/assets/images/geek_coffee_5.jpg differ
diff --git a/app/assets/images/no_image.png b/app/assets/images/no_image.png
new file mode 100644
index 0000000000..6cf924b33f
Binary files /dev/null and b/app/assets/images/no_image.png differ
diff --git a/app/assets/images/pen_holders.jpg b/app/assets/images/pen_holders.jpg
new file mode 100644
index 0000000000..74e6c62680
Binary files /dev/null and b/app/assets/images/pen_holders.jpg differ
diff --git a/app/assets/images/ran-robot.png b/app/assets/images/ran-robot.png
new file mode 100644
index 0000000000..1e1fbb093e
Binary files /dev/null and b/app/assets/images/ran-robot.png differ
diff --git a/app/assets/images/ran_rob.png b/app/assets/images/ran_rob.png
new file mode 100644
index 0000000000..073233122b
Binary files /dev/null and b/app/assets/images/ran_rob.png differ
diff --git a/app/assets/images/ran_robot_2.png b/app/assets/images/ran_robot_2.png
new file mode 100644
index 0000000000..1480d39058
Binary files /dev/null and b/app/assets/images/ran_robot_2.png differ
diff --git a/app/assets/images/robits_logo.jpg b/app/assets/images/robits_logo.jpg
new file mode 100644
index 0000000000..7ebf5ed28f
Binary files /dev/null and b/app/assets/images/robits_logo.jpg differ
diff --git a/app/assets/images/robot.png b/app/assets/images/robot.png
new file mode 100644
index 0000000000..4470fcd223
Binary files /dev/null and b/app/assets/images/robot.png differ
diff --git a/app/assets/images/t-shirt4.jpg b/app/assets/images/t-shirt4.jpg
new file mode 100644
index 0000000000..0208dd372b
Binary files /dev/null and b/app/assets/images/t-shirt4.jpg differ
diff --git a/app/assets/images/t-shirt_9.jpg b/app/assets/images/t-shirt_9.jpg
new file mode 100644
index 0000000000..71f64e8b07
Binary files /dev/null and b/app/assets/images/t-shirt_9.jpg differ
diff --git a/app/assets/images/t_shirt.jpg b/app/assets/images/t_shirt.jpg
new file mode 100644
index 0000000000..42eba31aaa
Binary files /dev/null and b/app/assets/images/t_shirt.jpg differ
diff --git a/app/assets/images/t_shirt_10.jpg b/app/assets/images/t_shirt_10.jpg
new file mode 100644
index 0000000000..09ef5cdc7b
Binary files /dev/null and b/app/assets/images/t_shirt_10.jpg differ
diff --git a/app/assets/images/tie.jpg b/app/assets/images/tie.jpg
new file mode 100644
index 0000000000..74f5aed741
Binary files /dev/null and b/app/assets/images/tie.jpg differ
diff --git a/app/assets/images/tishirt.jpg b/app/assets/images/tishirt.jpg
new file mode 100644
index 0000000000..55c8bc61ed
Binary files /dev/null and b/app/assets/images/tishirt.jpg differ
diff --git a/app/assets/images/tot_bag_2.jpg b/app/assets/images/tot_bag_2.jpg
new file mode 100644
index 0000000000..92ec193e37
Binary files /dev/null and b/app/assets/images/tot_bag_2.jpg differ
diff --git a/app/assets/images/tot_bags.jpg b/app/assets/images/tot_bags.jpg
new file mode 100644
index 0000000000..3ad8702ffc
Binary files /dev/null and b/app/assets/images/tot_bags.jpg differ
diff --git a/app/assets/images/travel_mug .jpg b/app/assets/images/travel_mug .jpg
new file mode 100644
index 0000000000..c01bd61292
Binary files /dev/null and b/app/assets/images/travel_mug .jpg differ
diff --git a/app/assets/images/wedding-cap.webp b/app/assets/images/wedding-cap.webp
new file mode 100644
index 0000000000..83a0b36764
Binary files /dev/null and b/app/assets/images/wedding-cap.webp differ
diff --git a/app/assets/images/wedding_shirt.webp b/app/assets/images/wedding_shirt.webp
new file mode 100644
index 0000000000..5ff9ac164c
Binary files /dev/null and b/app/assets/images/wedding_shirt.webp differ
diff --git a/app/assets/images/women-shirt.jpg b/app/assets/images/women-shirt.jpg
new file mode 100644
index 0000000000..f1fa2f3b28
Binary files /dev/null and b/app/assets/images/women-shirt.jpg differ
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index e07c5a830f..038d8d7ecc 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -12,5 +12,15 @@
//
//= require jquery
//= require jquery_ujs
+//= require foundation
//= require turbolinks
//= require_tree .
+
+$(function(){ $(document).foundation(); });
+
+//= require foundation
+$(document).foundation();
+
+$(document).on('turbolinks:load', function() {
+ $(function(){ $(document).foundation(); });
+});
diff --git a/app/assets/javascripts/welcome.coffee b/app/assets/javascripts/welcome.coffee
new file mode 100644
index 0000000000..24f83d18bb
--- /dev/null
+++ b/app/assets/javascripts/welcome.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss
new file mode 100644
index 0000000000..703053eb9d
--- /dev/null
+++ b/app/assets/stylesheets/_settings.scss
@@ -0,0 +1,574 @@
+// 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. Close Button
+// 15. Drilldown
+// 16. Dropdown
+// 17. Dropdown Menu
+// 18. Flex Video
+// 19. Forms
+// 20. Label
+// 21. Media Object
+// 22. Menu
+// 23. Meter
+// 24. Off-canvas
+// 25. Orbit
+// 26. Pagination
+// 27. Progress Bar
+// 28. Reveal
+// 29. Slider
+// 30. Switch
+// 31. Table
+// 32. Tabs
+// 33. Thumbnail
+// 34. Title Bar
+// 35. Tooltip
+// 36. Top Bar
+
+@import 'util/util';
+
+// 1. Global
+// ---------
+
+$global-font-size: 100%;
+$global-width: rem-calc(1200);
+$global-lineheight: 1.5;
+$foundation-palette: (
+ primary: #2199e8,
+ secondary: #777,
+ success: #3adb76,
+ warning: #ffae00,
+ alert: #ec5840,
+);
+$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-weight-normal: normal;
+$global-weight-bold: bold;
+$global-radius: 0;
+$global-text-direction: ltr;
+$global-flexbox: false;
+$print-transparent-backgrounds: true;
+
+@include add-foundation-colors;
+
+// 2. Breakpoints
+// --------------
+
+$breakpoints: (
+ small: 0,
+ medium: 640px,
+ large: 1024px,
+ xlarge: 1200px,
+ xxlarge: 1440px,
+);
+$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;
+$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-sizes: (
+ small: (
+ 'h1': 24,
+ 'h2': 20,
+ 'h3': 19,
+ 'h4': 18,
+ 'h5': 17,
+ 'h6': 16,
+ ),
+ medium: (
+ 'h1': 48,
+ 'h2': 40,
+ 'h3': 31,
+ 'h4': 25,
+ 'h5': 20,
+ 'h6': 16,
+ ),
+);
+$header-color: inherit;
+$header-lineheight: 1.4;
+$header-margin-bottom: 0.5rem;
+$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;
+$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: map-get($foundation-palette, alert);
+$form-label-color-invalid: map-get($foundation-palette, alert);
+$input-error-color: map-get($foundation-palette, alert);
+$input-error-font-size: rem-calc(12);
+$input-error-font-weight: $global-weight-bold;
+
+// 7. Accordion
+// ------------
+
+$accordion-background: $white;
+$accordion-plusminus: true;
+$accordion-item-color: foreground($accordion-background, $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: foreground($accordion-content-background, $body-font-color);
+$accordion-content-padding: 1rem;
+
+// 8. Accordion Menu
+// -----------------
+
+$accordionmenu-arrows: true;
+$accordionmenu-arrow-color: $primary-color;
+
+// 9. Badge
+// --------
+
+$badge-background: $primary-color;
+$badge-color: foreground($badge-background);
+$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-slash: true;
+
+// 11. Button
+// ----------
+
+$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-sizes: (
+ tiny: 0.6rem,
+ small: 0.75rem,
+ default: 0.9rem,
+ large: 1.25rem,
+);
+$button-opacity-disabled: 0.25;
+$button-background-hover-lightness: -20%;
+$button-hollow-hover-lightness: -50%;
+
+// 12. Button Group
+// ----------------
+
+$buttongroup-margin: 1rem;
+$buttongroup-spacing: 1px;
+$buttongroup-child-selector: '.button';
+$buttongroup-expand-max: 6;
+
+// 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. Close Button
+// ----------------
+
+$closebutton-position: right top;
+$closebutton-offset-horizontal: 1rem;
+$closebutton-offset-vertical: 0.5rem;
+$closebutton-size: 2em;
+$closebutton-lineheight: 1;
+$closebutton-color: $dark-gray;
+$closebutton-color-hover: $black;
+
+// 15. Drilldown
+// -------------
+
+$drilldown-transition: transform 0.15s linear;
+$drilldown-arrows: true;
+$drilldown-arrow-color: $primary-color;
+$drilldown-background: $white;
+
+// 16. Dropdown
+// ------------
+
+$dropdown-padding: 1rem;
+$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,
+);
+
+// 17. Dropdown Menu
+// -----------------
+
+$dropdownmenu-arrows: true;
+$dropdownmenu-arrow-color: $anchor-color;
+$dropdownmenu-min-width: 200px;
+$dropdownmenu-background: $white;
+$dropdownmenu-border: 1px solid $medium-gray;
+
+// 18. Flex Video
+// --------------
+
+$flexvideo-margin-bottom: rem-calc(16);
+$flexvideo-ratio: 4 by 3;
+$flexvideo-ratio-widescreen: 16 by 9;
+
+// 19. 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-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-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;
+$button-radius: $global-radius;
+
+// 20. Label
+// ---------
+
+$label-background: $primary-color;
+$label-color: foreground($label-background);
+$label-font-size: 0.8rem;
+$label-padding: 0.33333rem 0.5rem;
+$label-radius: $global-radius;
+
+// 21. Media Object
+// ----------------
+
+$mediaobject-margin-bottom: $global-margin;
+$mediaobject-section-padding: $global-padding;
+$mediaobject-image-width-stacked: 100%;
+
+// 22. Menu
+// --------
+
+$menu-margin: 0;
+$menu-margin-nested: 1rem;
+$menu-item-padding: 0.7rem 1rem;
+$menu-item-color-active: $white;
+$menu-item-background-active: map-get($foundation-palette, primary);
+$menu-icon-spacing: 0.25rem;
+
+// 23. 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;
+
+// 24. Off-canvas
+// --------------
+
+$offcanvas-size: 250px;
+$offcanvas-background: $light-gray;
+$offcanvas-zindex: -1;
+$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';
+$maincontent-shadow: 0 0 10px rgba($black, 0.5);
+
+// 25. 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;
+
+// 26. 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: foreground($pagination-item-background-current);
+$pagination-item-color-disabled: $medium-gray;
+$pagination-ellipsis-color: $black;
+$pagination-mobile-items: false;
+$pagination-mobile-current-item: false;
+$pagination-arrows: true;
+
+// 27. Progress Bar
+// ----------------
+
+$progress-height: 1rem;
+$progress-background: $medium-gray;
+$progress-margin-bottom: $global-margin;
+$progress-meter-background: $primary-color;
+$progress-radius: $global-radius;
+
+// 28. 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);
+
+// 29. 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;
+
+// 30. 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;
+
+// 31. 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-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;
+
+// 32. Tabs
+// --------
+
+$tab-margin: 0;
+$tab-background: $white;
+$tab-background-active: $light-gray;
+$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: foreground($tab-background, $primary-color);
+$tab-content-padding: 1rem;
+
+// 33. 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;
+
+// 34. 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;
+
+// 35. Tooltip
+// -----------
+
+$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-font-size: $small-font-size;
+$tooltip-pip-width: 0.75rem;
+$tooltip-pip-height: $tooltip-pip-width * 0.866;
+$tooltip-radius: $global-radius;
+
+// 36. Top Bar
+// -----------
+
+$topbar-padding: 0.5rem;
+$topbar-background: $light-gray;
+$topbar-submenu-background: $topbar-background;
+$topbar-title-spacing: 1rem;
+$topbar-input-width: 200px;
+$topbar-unstack-breakpoint: medium;
+
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
deleted file mode 100644
index f9cd5b3483..0000000000
--- a/app/assets/stylesheets/application.css
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * 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, vendor/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 styles
- * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
- * file per style scope.
- *
- *= require_tree .
- *= require_self
- */
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
new file mode 100644
index 0000000000..c69875f321
--- /dev/null
+++ b/app/assets/stylesheets/application.scss
@@ -0,0 +1,121 @@
+/*
+ * 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, vendor/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 styles
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
+ * file per style scope.
+ *
+ *= require_tree .
+ *= require_self
+ *= require foundation_and_overrides
+
+ */
+
+.container {
+ margin: 20px;
+}
+
+body {
+ background-color: rgba(245,242,225, 0.5);
+ font-family: 'Rubik', sans-serif;
+}
+
+h1, .title-area, .name {
+ margin: 0 0;
+ width: 100rem;
+ background-color: rgb(245,242,225);
+}
+
+.name {
+ list-style: none;
+}
+
+a {
+ color: #e6e6e6;
+}
+
+a:hover {
+ color: #cacaca;
+}
+
+.row.top-bar {
+ max-width: 100rem;
+ margin-left: none;
+ margin-right: none;
+}
+
+.top-bar {
+ box-shadow:0px 1px 1px rgb(136,149,194);
+}
+
+.top-bar, .top-bar ul {
+ background-color: rgb(136,149,194);
+ padding: 0;
+}
+
+.dropdown.menu.medium-horizontal > li.is-dropdown-submenu-parent > a::after {
+ border-top-color: #e6e6e6;
+}
+
+.logo-name {
+ position: absolute;
+ left: 8.5rem;
+ top: 2rem;
+ color: rgb(136, 149, 194);
+ text-shadow: 2px 2px 3px rgb(82, 82, 142);
+ font-family: 'Chelsea Market', cursive;
+
+}
+
+li.column, li.field {
+ list-style: none;
+}
+
+.small-up-4 > li, .small-up-3 > li {
+ margin-bottom: 2.25rem;
+ margin-top: 2rem;
+}
+
+
+h2 {
+ color: rgb(136, 149, 194);
+ text-shadow: 2px 2px 3px rgb(82, 82, 142);
+ font-family: 'Chelsea Market', cursive;
+}
+
+h3 {
+ font-family: 'Chelsea Market', cursive;
+ margin-top: 2rem;
+
+}
+
+.product-info {
+ color: rgb(82, 82, 142);
+ font-family: 'Rubik', sans-serif;
+}
+
+.notice {
+ font-weight: bold;
+ font-size: 1rem;
+}
+
+.body-text a {
+ color: #8895c2;
+}
+
+.body-text a:hover {
+ color: rgba(255, 0, 0, 0.66);
+}
+
+.button {
+ background-color: #8895c2;
+}
+
+#white-link{
+ color: white;
+}
diff --git a/app/assets/stylesheets/categories.scss b/app/assets/stylesheets/categories.scss
new file mode 100644
index 0000000000..42976cbc11
--- /dev/null
+++ b/app/assets/stylesheets/categories.scss
@@ -0,0 +1,3 @@
+// 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/
diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss
new file mode 100644
index 0000000000..458eb4fafb
--- /dev/null
+++ b/app/assets/stylesheets/foundation_and_overrides.scss
@@ -0,0 +1,52 @@
+@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-grid;
+@include foundation-typography;
+@include foundation-button;
+@include foundation-forms;
+@include foundation-visibility-classes;
+@include foundation-float-classes;
+@include foundation-accordion;
+@include foundation-accordion-menu;
+@include foundation-badge;
+@include foundation-breadcrumbs;
+@include foundation-button-group;
+@include foundation-callout;
+@include foundation-close-button;
+@include foundation-drilldown-menu;
+@include foundation-dropdown;
+@include foundation-dropdown-menu;
+@include foundation-flex-video;
+@include foundation-label;
+@include foundation-media-object;
+@include foundation-menu;
+@include foundation-menu-icon;
+@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;
+
+// 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;
diff --git a/app/assets/stylesheets/merchants.scss b/app/assets/stylesheets/merchants.scss
new file mode 100644
index 0000000000..f4c164d600
--- /dev/null
+++ b/app/assets/stylesheets/merchants.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Merchants 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/order_items.scss b/app/assets/stylesheets/order_items.scss
new file mode 100644
index 0000000000..1fddf19e2a
--- /dev/null
+++ b/app/assets/stylesheets/order_items.scss
@@ -0,0 +1,33 @@
+// Place all the styles related to the Order Items controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+.button {
+ background-color: rgba(245,242,225, 1);
+ border-radius: .25rem;
+ border: 1px solid #cacaca;
+}
+
+.button:hover {
+ background-color: rgba(245,242,225, 0.3);
+}
+
+.all-items, label {
+ color: rgb(136, 149, 194);
+}
+
+.items-output {
+ padding-left: 5rem;
+}
+
+.small-up-1 {
+ margin-top: 1rem;
+}
+
+.item-input {
+ padding-left: 5rem;
+ padding-right: 5rem;
+}
+
+.all-items, li {
+ list-style: none;
+}
diff --git a/app/assets/stylesheets/orders.scss b/app/assets/stylesheets/orders.scss
new file mode 100644
index 0000000000..05b36bb539
--- /dev/null
+++ b/app/assets/stylesheets/orders.scss
@@ -0,0 +1,26 @@
+// 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/
+
+main{
+ color: #52528e;
+}
+
+.totals {
+ font-weight: bold;
+ border-bottom: 2px solid;
+ border-radius: .1rem;
+}
+
+.row li {
+ list-style: none;
+}
+
+.small-8 {
+ padding-right: 20rem;
+}
+
+ul.purchases-list {
+ border-bottom: 2px solid;
+ border-bottom-right-radius: .5rem;
+}
diff --git a/app/assets/stylesheets/payment_details.scss b/app/assets/stylesheets/payment_details.scss
new file mode 100644
index 0000000000..9b1354edf8
--- /dev/null
+++ b/app/assets/stylesheets/payment_details.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the Payment Details 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/products.scss b/app/assets/stylesheets/products.scss
new file mode 100644
index 0000000000..5885f6597a
--- /dev/null
+++ b/app/assets/stylesheets/products.scss
@@ -0,0 +1,54 @@
+// 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/
+
+.small-up-1 {
+ margin-top: 1rem;
+}
+
+.notice > a {
+ color: rgb(82, 82, 142);
+ font-size: 2rem;
+}
+
+.reviews-output {
+ padding-left: 5rem;
+}
+
+.reviews-input {
+ padding-left: 5rem;
+ padding-right: 5rem;
+}
+
+.reviews-input, .reviews-output {
+ color: rgb(136, 149, 194);
+ font-family: 'Rubik', sans-serif;
+}
+
+.reviews-input > h4, .fix-me {
+ font-family: 'Rubik', sans-serif;
+ font-size: 2rem;
+}
+
+#review_rating, #review_description, .button {
+ background-color: rgba(245,242,225, 0.7);
+ border-radius: .25rem;
+}
+
+.button {
+ background-color: rgba(245,242,225, 1);
+ border-radius: .25rem;
+ border: 1px solid #cacaca;
+}
+
+.button:hover {
+ background-color: #5877B3;
+}
+
+.all-reviews, label {
+ color: rgb(136, 149, 194);
+}
+
+.link, a {
+ color: rgb(82, 82, 142);
+}
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..fd70ac12fc
--- /dev/null
+++ b/app/assets/stylesheets/sessions.scss
@@ -0,0 +1,20 @@
+// 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/
+
+.welcome-message {
+ margin-top: 2rem;
+}
+
+.welcome-message > h2, .welcome-message > h3 {
+ font-family: 'Chelsea Market', cursive;
+ text-shadow: 2px 2px 3px rgb(136, 149, 194);
+}
+
+.welcome-message > h2 {
+ color: rgb(82, 82, 142);
+}
+
+.welcome-message > h3 {
+ color: rgb(136, 149, 194);
+}
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index d83690e1b9..5928fffd80 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,5 +1,25 @@
class ApplicationController < ActionController::Base
- # Prevent CSRF attacks by raising an exception.
- # For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
+
+ before_action :require_login
+ helper_method :category, :merchant, :current_merchant
+
+ def current_merchant
+ @current_merchant ||= Merchant.find(session[:merchant_id]) if session[:merchant_id]
+ end
+
+ def require_login
+ if current_merchant.nil?
+ flash[:error] = "You have been logged out. Please continue to browse our website as a Guest User."
+ redirect_to root_path
+ end
+ end
+
+ def category
+ Category.all
+ end
+
+ def merchant
+ Merchant.all
+ end
end
diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb
new file mode 100644
index 0000000000..1438b71aa9
--- /dev/null
+++ b/app/controllers/categories_controller.rb
@@ -0,0 +1,44 @@
+class CategoriesController < ApplicationController
+ before_action :get_category, only: [:show]
+
+ #only logged in Merchant user can create a new Category
+ skip_before_action :require_login, except: [:new, :create]
+
+ # categories GET /categories
+ def index
+ @categories = Category.all
+ end
+
+ # new_category GET /categories/new
+ def show
+ @products = @category.products.where(active: true)
+ end
+
+ # GET /categories/new
+ def new
+ @category = Category.new
+ end
+
+ # categories POST /categories
+ def create
+ @category = Category.new(category_params)
+
+ if @category.save
+ redirect_to categories_path
+ else
+ render :new
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def get_category
+ @category = Category.find(params[:id])
+ end
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+ # I don't think we should be able to edit catergories, only add so I don't think we need this
+ def category_params
+ params.require(:category).permit(:name)
+ end
+end
diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb
new file mode 100644
index 0000000000..50d8d0e2f6
--- /dev/null
+++ b/app/controllers/merchants_controller.rb
@@ -0,0 +1,25 @@
+class MerchantsController < ApplicationController
+ before_action :get_merchant, only: [:show]
+
+ skip_before_action :require_login
+
+ # merchants GET /merchants
+ def index
+ @merchants = Merchant.all
+ end
+
+ # merchant GET /merchants/:id
+ def show
+ @products = @merchant.products.where(active: true)
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def get_merchant
+ @merchant = Merchant.find(params[:id])
+ end
+
+ def merchant_params
+ params.require(:merchant).permit(:email, :user_name, :uid, :provider)
+ end
+end
diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb
new file mode 100644
index 0000000000..3c6f06cecc
--- /dev/null
+++ b/app/controllers/order_items_controller.rb
@@ -0,0 +1,51 @@
+class OrderItemsController < ApplicationController
+ before_action :get_order_item, only: [:update, :destroy, :show, :ship]
+ skip_before_action :require_login
+
+ def index
+ @order = Order.find(session[:order_id])
+ @order_items = @order.order_items
+ end
+
+ def show
+ @payment_detail = @order_item.order.payment_detail
+ end
+
+ def update
+ product = @order_item.product
+ if product.update_quantity(order_item_params["quantity"])
+ @order_item.update(order_item_params)
+ else
+ flash[:error] = "Could not increase item quantity"
+ end
+ redirect_to order_order_items_path(@order_item.order)
+ end
+
+ def ship
+ # mark order_item as shipped
+ # check the order that the product belongs to to see if it can be marked as completed (called in complete order method)
+ @order_item.shipped = true
+ @order_item.save
+
+ order = @order_item.order
+ order.complete_order
+
+ redirect_to order_order_items_path(@order_item.order)
+ end
+
+
+ def destroy
+ order = @order_item.order
+ @order_item.destroy
+ redirect_to order_order_items_path(order)
+ end
+
+ private
+ def get_order_item
+ @order_item = OrderItem.find(params[:id])
+ end
+
+ def order_item_params
+ params.require(:order_item).permit(:quantity, :shipped)
+ end
+end
diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb
new file mode 100644
index 0000000000..2fe8658fe5
--- /dev/null
+++ b/app/controllers/orders_controller.rb
@@ -0,0 +1,115 @@
+class OrdersController < ApplicationController
+ before_action :get_order, only: [:show, :update, :destroy]
+ before_action :get_merchant, except: [:create, :cancel, :update, :destroy]
+ skip_before_action :require_login, except: [:index]
+
+
+ def index
+ get_all_merchant_orders
+ get_all_merchant_orders_by_status
+ filter_displayed_merchant_orders
+ end
+
+ def create
+ if in_stock?
+ require_order
+ save_order
+ save_order_item
+ redirect_to order_order_items_path(@order)
+ else
+ flash[:error] = "Product is out of stock"
+ redirect_to product_path(@product)
+ end
+ end
+
+ # see below - two ways to cancel an order
+ def cancel; end
+
+ def update
+ # canceling the order after the order has been purchased
+ # updates status to canceled
+ # adds stock back
+ payment_details = @order.payment_detail
+ if @order.update(order_status: "cancelled")
+ @order.increase_products_stock
+ redirect_to cancelled_order_path
+ else
+ flash[:error] = "This order could not be cancelled"
+ redirect_to order_order_items_path(@order.id)
+ end
+ end
+
+ def destroy
+ # canceling an order before it has been purchased destroys the order
+ @order.destroy
+ reset_session_values
+
+ redirect_to cancelled_order_path
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def get_order
+ @order = Order.find(params[:id])
+ end
+
+ def get_merchant
+ @merchant = Merchant.find(session[:merchant_id])
+ end
+
+ def get_all_merchant_orders
+ # "Order" to merchant is the order_items they must fulfill
+ @order_items = @merchant.get_merchant_orders
+ end
+
+ def get_all_merchant_orders_by_status
+ # "Order" to merchant is the order_items they must fulfill
+ @completed_orders = @merchant.get_merchant_orders("completed")
+ @paid_orders = @merchant.get_merchant_orders("paid")
+ @pending_orders = @merchant.get_merchant_orders("pending")
+ @cancelled_orders = @merchant.get_merchant_orders("cancelled")
+ end
+
+ def filter_displayed_merchant_orders
+ # "Order" to merchant is the order_items they must fulfill
+ if params['commit'].nil?
+ @filtered_orders = @merchant.get_merchant_orders
+ else
+ @filtered_orders = @merchant.get_merchant_orders(params["commit"].downcase)
+ end
+ end
+
+ # Before create action, check if there is a cart. If there is, it is assined in "current_order." If not, we make a new order.
+ def current_order
+ @order ||= Order.find(session[:order_id]) if session[:order_id]
+ end
+
+ def require_order
+ @order = Order.build_order if current_order.nil?
+ end
+
+ def in_stock?
+ @product = Product.find(session[:product_id])
+ # check_availability returns true or false
+ @product.check_availability(1)
+ end
+
+ def save_order
+ if @order.save
+ session[:order_id] = @order.id
+ else
+ flash[:error] = "Something went really wrong!"
+ end
+ end
+
+ def save_order_item
+ order_item = OrderItem.add_order_item_to_order(@order.id, session[:product_id])
+ (flash[:error] = "Couldn't add product to cart") unless order_item.save
+ end
+
+ def reset_session_values
+ session[:order_id] = nil
+ session[:product_id] = nil
+ end
+
+end
diff --git a/app/controllers/payment_details_controller.rb b/app/controllers/payment_details_controller.rb
new file mode 100644
index 0000000000..b617515206
--- /dev/null
+++ b/app/controllers/payment_details_controller.rb
@@ -0,0 +1,55 @@
+class PaymentDetailsController < ApplicationController
+ before_action :get_payment_details, only: [:show]
+ before_action :get_order, only: [:create]
+ skip_before_action :require_login
+
+ def show
+ @order = @payment_details.order
+ @order_items = @order.order_items
+ @total_order_price = OrderItem.sum_total_prices(@order_items)
+ end
+
+ def new
+ @payment_details = PaymentDetail.new
+ end
+
+ def create
+ @payment_details = PaymentDetail.new(payment_details_params)
+ @payment_details.set_order_id(session[:order_id])
+ @payment_details.record_time_placed
+ if @payment_details.save
+ reset_session_values
+ update_order_status
+ @order.decrease_products_stock
+ redirect_to @payment_details
+ else
+ render :new
+ end
+ end
+
+ private
+ def get_payment_details
+ @payment_details = PaymentDetail.find(params[:id])
+ end
+
+ def get_order
+ @order = Order.find(session[:order_id])
+ end
+
+ def payment_details_params
+ params.require(:payment_details).permit(:buyer_name, :email, :cc_expiration_date, :cc_four_digits, :city, :email, :state, :street, :zip)
+ end
+
+ def reset_session_values
+ session[:order_id] = nil
+ session[:product_id] = nil
+ end
+
+ def update_order_status
+ order = Order.find(params[:order_id])
+ order.mark_order_paid
+ unless order.save
+ flash[:error] = "Could not mark order paid"
+ end
+ end
+end
diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb
new file mode 100644
index 0000000000..db3d2625d4
--- /dev/null
+++ b/app/controllers/products_controller.rb
@@ -0,0 +1,74 @@
+class ProductsController < ApplicationController
+ before_action :get_product, only: [:show, :edit, :update]
+
+ before_action :require_login, only: [:new, :create, :edit, :create]
+
+ # products_path GET /products
+ # merchant_products_path GET /merchants/:merchant_id/products
+ def index
+ if params[:category_id] != nil
+ category = Category.find(params[:category_id])
+ @products = category.products.where(active: true)
+ elsif params[:merchant_id] != nil
+ @merchant = Merchant.find(params[:merchant_id])
+ @products = @merchant.products.where(active: true)
+ else
+ @products = Product.where(active: true)
+ end
+ end
+
+ # product_path GET /products/:id
+ # merchant_product_path GET /merchants/:merchant_id/products/:id
+ def show
+ session[:product_id] = @product.id
+ @review = Review.new
+ @reviews = Review.where product_id: @product.id
+ end
+
+ # new_merchant_product_path GET /merchants/:merchant_id/products/new
+ def new
+ @product = @current_merchant.products.new
+ end
+
+ # merchant_products_path POST /merchants/:merchant_id/products
+ def create
+ @product = @current_merchant.products.new(product_params)
+ if @product.save
+ redirect_to products_path
+ else
+ #TODO Put flash notice here maybe.
+ render :new, status: 400
+ end
+ end
+
+ # edit_merchant_product_path GET /merchants/:merchant_id/products/:id/edit
+ def edit
+ if @product.merchant_id != session[:merchant_id]
+ render :no_show, status: 400
+ end
+ end
+
+ # merchant_product_path PATCH/PUT /merchants/:merchant_id/products/:id
+ def update
+ if @product.merchant_id != session[:merchant_id]
+ render :no_show, status: 400
+ end
+
+ if @product.update(product_params)
+ redirect_to product_path(@product.id)
+ else
+ render :edit, status: 400
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def get_product
+ @product = Product.find(params[:id])
+ end
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+ def product_params
+ params.require(:product).permit(:name, :price, :quantity, :image, :description, :active, category_ids: [])
+ end
+end
diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb
new file mode 100644
index 0000000000..abc4e03a79
--- /dev/null
+++ b/app/controllers/reviews_controller.rb
@@ -0,0 +1,32 @@
+class ReviewsController < ApplicationController
+
+ skip_before_action :require_login
+
+ # new_product_review_path GET /products/:product_id/reviews/new
+ def new
+ product = Product.find(params[:product_id])
+ if product.merchant_id == session[:merchant_id]
+ render :no_show
+ else
+ @product_review = product.reviews.build
+ end
+ end
+
+ # product_review_path POST /products/:product_id/reviews(.:format)
+ def create
+ product = Product.find(params[:product_id])
+ if product.merchant_id == session[:merchant_id]
+ render :no_show
+ else
+ @review_product = product.reviews.create(review_params)
+ redirect_to product_path(product.id)
+ end
+ end
+
+ private
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+ def review_params
+ params.require(:review).permit(:rating, :description)
+ end
+end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
new file mode 100644
index 0000000000..df4af06f29
--- /dev/null
+++ b/app/controllers/sessions_controller.rb
@@ -0,0 +1,38 @@
+class SessionsController < ApplicationController
+ skip_before_action :require_login, only: [:index_log_out, :login, :create]
+
+ def index_log_out
+ render 'sessions/index'
+ end
+
+ def index_log_in
+ render 'sessions/index'
+ end
+
+ def create
+ auth_hash = request.env['omniauth.auth']
+ redirect_to login_failure_path unless auth_hash['uid']
+ @merchant = Merchant.find_by(uid: auth_hash[:uid], provider: 'github')
+ if @merchant.nil?
+ @merchant = Merchant.build_from_github(auth_hash)
+ render :creation_failure unless @merchant.save
+ end
+
+ # Save the user ID in the session
+ session[:merchant_id] = @merchant.id
+ redirect_to sessions_log_in_path
+ end
+
+ def login_failure; end
+
+ def login; end
+
+ def destroy
+ session.delete(:merchant_id)
+ redirect_to sessions_log_out_path
+ end
+
+ def merchant_login
+ # @merchant = Merchant.find(session[:merchant_id])
+ end
+end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index de6be7945c..8f1afa282b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,2 +1,75 @@
module ApplicationHelper
+ def user_name
+ begin
+ user = Merchant.find(session[:merchant_id])
+ if user.user_name
+ return user.user_name
+ elsif user.email
+ return user.email
+ else
+ return "#{user.provider} user #{user.uid}"
+ end
+ rescue ActiveRecord::RecordNotFound
+ return "ERROR: user not in database"
+ end
+ end
+
+ def login_status
+ if session[:merchant_id].nil?
+ sign_up_button
+ else
+ # if a Merchant is logged in they can see their dashboard
+ link_to "#{user_name.upcase}'S Dashboard", sessions_merchant_login_path, method: :get
+ end
+ end
+
+ def login_button(**kwargs)
+ if session[:merchant_id].nil?
+ text = "Log In"
+ path = "/auth/github"
+ method = :get
+ else
+ text = "Log Out"
+ path = sessions_path
+ method = :delete
+ end
+ link_to text, path, method: method, **kwargs
+ end
+
+ def sign_up_button(**kwargs)
+ if session[:merchant_id].nil?
+ text = "Sign Up with Github"
+ path = "https://github.com/join?source=header-home"
+ method = :get
+ end
+ link_to text, path, method: method, **kwargs
+ end
+
+ def cart_button(**kwargs)
+ order = session[:order_id]
+ if !order.nil?
+ text = "Cart"
+ path = order_order_items_path(order)
+ method = :get
+ link_to text, path, method: method, **kwargs
+ end
+ end
+
+ def product_image(product, pic_size, **kwargs)
+ if product.image.nil?
+ path = ["robot.png", "baby_robot .jpg", "ran_rob.png", "ran_robot_2.png", "ran-robot.png"].sample
+ dimensions = pic_size
+ text = "Robits"
+ else
+ path = (product.image_stored? ? product.image.thumb(pic_size).url : "")
+ dimensions = pic_size
+ text = "Buy Me"
+ end
+ image_tag path, size: dimensions, alt: text
+ end
+
+ def render_date(date)
+ ("" + date.strftime("%A, %b %d %Y") + "").html_safe
+ end
+
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/order_items_helper.rb b/app/helpers/order_items_helper.rb
new file mode 100644
index 0000000000..e197528ae1
--- /dev/null
+++ b/app/helpers/order_items_helper.rb
@@ -0,0 +1,2 @@
+module OrderItemsHelper
+end
diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb
new file mode 100644
index 0000000000..6cbe7fcc40
--- /dev/null
+++ b/app/helpers/orders_helper.rb
@@ -0,0 +1,26 @@
+module OrdersHelper
+
+ def ship_order(item, **kwargs)
+ if item.shipped != true
+ text = "Ship Order"
+ path = ship_order_item_path(item)
+ method = :patch
+ else
+ return "Order shipped"
+ end
+ link_to text, path, method: method, **kwargs
+ end
+
+ def order_time_placed(item)
+ order = item.order
+ if order.order_status == "pending"
+ "Order has not been placed"
+ else
+ payment_detail = order.payment_detail
+ return "Order has no payment details" if payment_detail.nil?
+ render_date(payment_detail.time_placed)
+ end
+
+ end
+
+end
diff --git a/app/helpers/payment_details_helper.rb b/app/helpers/payment_details_helper.rb
new file mode 100644
index 0000000000..e7a39a0857
--- /dev/null
+++ b/app/helpers/payment_details_helper.rb
@@ -0,0 +1,2 @@
+module PaymentDetailsHelper
+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..682b7b1abc
--- /dev/null
+++ b/app/helpers/reviews_helper.rb
@@ -0,0 +1,2 @@
+module ReviewsHelper
+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/categories_product.rb b/app/models/categories_product.rb
new file mode 100644
index 0000000000..2543e8a734
--- /dev/null
+++ b/app/models/categories_product.rb
@@ -0,0 +1,4 @@
+class CategoriesProduct < ApplicationRecord
+ belongs_to :product
+ belongs_to :category
+end
diff --git a/app/models/category.rb b/app/models/category.rb
new file mode 100644
index 0000000000..30bdd7bb09
--- /dev/null
+++ b/app/models/category.rb
@@ -0,0 +1,6 @@
+class Category < ApplicationRecord
+ has_many :products, through: :categories_products
+ has_many :categories_products
+
+ validates :name, presence: true, uniqueness: true
+end
diff --git a/app/models/merchant.rb b/app/models/merchant.rb
new file mode 100644
index 0000000000..5db48f00ae
--- /dev/null
+++ b/app/models/merchant.rb
@@ -0,0 +1,32 @@
+class Merchant < ApplicationRecord
+ has_many :products
+ validates :email, :uid, :provider, presence: true
+
+ def self.build_from_github(auth_hash)
+ merchant = Merchant.new
+ merchant.uid = auth_hash[:uid]
+ merchant.provider = 'github'
+ merchant.user_name = auth_hash['info']['nickname']
+ merchant.email = auth_hash['info']['email']
+
+ return merchant
+ end
+
+ def get_merchant_orders(status = nil)
+ # "Order" to merchant is the order_items they must fulfill
+ order_items = OrderItem.joins(:order, :product)
+.where('products.merchant_id = ?', self.id)
+
+ # narrow the seach to specific status if status is provided
+ if !status.nil? && status != "completed"
+ order_items = order_items.where('orders.order_status = ?', status).where('order_items.shipped = ?', false)
+ elsif status == "completed"
+ # a merchant considers an order complete when they have shipped the item, regarless of buyer's order_status
+ order_items = order_items.where('order_items.shipped = ?', true)
+ end
+
+ return order_items
+
+ end
+
+end
diff --git a/app/models/order.rb b/app/models/order.rb
new file mode 100644
index 0000000000..9b68eaefc3
--- /dev/null
+++ b/app/models/order.rb
@@ -0,0 +1,61 @@
+class Order < ApplicationRecord
+ has_many :order_items
+ has_many :products, through: :order_items
+ has_one :payment_detail
+
+ validates :order_status, presence: true
+ # TODO: only allow certain pre-defined statuses
+
+ def self.build_order
+ return self.new(order_status: "pending")
+ end
+
+ def mark_order_paid
+ self.order_status = "paid"
+ return self
+ end
+
+ def cancel_order
+ self.order_status = "cancelled"
+ return self
+ end
+
+ def complete_order
+ if self.all_items_shipped?
+ self.order_status = "completed"
+ self.save
+ end
+ return self
+ end
+
+ def all_items_shipped?
+ # when a merchant ships an order item, check if the order can be marked as complete
+ self.order_items.each do |item|
+ if item.shipped != true
+ return false
+ end
+ end
+
+ return true
+ end
+
+ def decrease_products_stock
+ self.products.each do |product|
+ order_item = product.order_items.where(order_id: self.id).first
+ # pass update_quantity a negative number for purchases
+ stock_change = order_item.quantity
+ product.update_quantity(-stock_change)
+ end
+ end
+
+ def increase_products_stock
+ self.products.each do |product|
+ order_item = product.order_items.where(order_id: self.id).first
+ stock_change = order_item.quantity
+ product.update_quantity(stock_change)
+ end
+ end
+
+
+
+end
diff --git a/app/models/order_item.rb b/app/models/order_item.rb
new file mode 100644
index 0000000000..b9abf9284e
--- /dev/null
+++ b/app/models/order_item.rb
@@ -0,0 +1,27 @@
+class OrderItem < ApplicationRecord
+ belongs_to :product
+ belongs_to :order
+
+ validates :quantity, numericality: {greater_than: 0}
+
+ def self.add_order_item_to_order(this_order_id, this_product_id)
+ order_item = self.new(quantity: 1)
+ order_item.order_id = this_order_id
+ order_item.product_id = this_product_id
+ return order_item
+ end
+
+ def self.sum_total_prices(order_items_collection)
+ return 0 if order_items_collection.nil?
+
+ sum = 0
+ order_items_collection.each do |item|
+ product = item.product
+ quantity = item.quantity
+ price = product.price
+ sum += quantity * price
+ end
+ return sum
+ end
+
+end
diff --git a/app/models/payment_detail.rb b/app/models/payment_detail.rb
new file mode 100644
index 0000000000..66e6309239
--- /dev/null
+++ b/app/models/payment_detail.rb
@@ -0,0 +1,100 @@
+class PaymentDetail < ActiveRecord::Base
+ belongs_to :order
+
+ #TODO: create tests related to credit card number.
+
+ before_validation(on: :create) do
+ cc_long_enough?
+ if valid_cc_number?
+ set_cc_four_digits
+ end
+ end
+
+ validates :buyer_name, presence: true
+ validates :email, presence: true
+ # REGEX to validate format of email is ---@---.---
+ validates_format_of :email,:with => /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
+
+ validates :street, presence: true
+ validates :city, presence: true
+ validates :state, presence: true
+ # US Zip for MA is min: 1001, AK is max: 99950
+ validates :zip, presence: true, numericality: { greater_than: 1000, less_than: 99951, only_integer: true }
+
+ validates :cc_four_digits, presence: true, length: { is: 4 }
+ validates :cc_expiration_date, presence: true
+ validate :expiration_date_cannot_be_in_the_past
+
+ validates :time_placed, presence: true
+
+ # validates :CVV, presence: true, length: {is: 3}
+
+ def record_time_placed
+ self.time_placed = Time.now
+ end
+
+ def set_order_id(this_order_id)
+ self.order_id = this_order_id
+ end
+
+ private
+
+ #### EXPIRATION DATE ####
+
+ def expiration_date_cannot_be_in_the_past
+ if self.cc_expiration_date == nil
+ errors.add(:cc_expiration_date, "can't be nil")
+ elsif self.cc_expiration_date <= Time.now
+ errors.add(:cc_expiration_date, "can't be in the past")
+ end
+ end
+
+
+ #### FOR CREDIT CARD NUMBER ####
+
+ # Visa, MasterCard, Amex have 13-16 digits
+ def cc_long_enough?
+ digits = self.cc_four_digits.to_s.length
+ errors.add(:cc_four_digits, 'Sorry, the card number must be between 13 and 16 digits') unless digits.between?(13,16)
+ end
+
+ # Luhn from: http://en.wikipedia.org/wiki/Luhn_algorithm
+ # 1. From the rightmost digit, which is the check digit, moving left, double the value of every second digit; if product of this doubling operation is greater than 9 (e.g., 7 * 2 = 14).
+ # 2. Sum the digits of the products (e.g., 10: 1 + 0 = 1, 14: 1 + 4 = 5) together with the undoubled digits from the original number.
+ # 3. If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the Luhn formula; else it is not valid.
+
+ # Returns true or false
+ def valid_cc_number?
+ #remove non-digits and read from right to left
+ number = self.cc_four_digits.to_s.gsub(/\D/, '').reverse
+
+ sum, i = 0, 0
+
+ number.each_char do |ch|
+ n = ch.to_i
+
+ # Step 1
+ n *= 2 if i.odd?
+
+ # Step 2
+ n = 1 + (n - 10) if n >= 10
+
+ sum += n
+ i += 1
+ end
+
+ if (sum % 10).zero? # Step 3
+ return true
+ else
+ errors.add(:cc_four_digits, 'Sorry, an invalid cardNumber Entered')
+ return false
+ end
+
+ end
+
+ def set_cc_four_digits
+ self.cc_four_digits = cc_four_digits.to_s.last(4).to_i
+ end
+
+ #### END CREDIT CARD NUMBER ####
+end
diff --git a/app/models/product.rb b/app/models/product.rb
new file mode 100644
index 0000000000..f904621b98
--- /dev/null
+++ b/app/models/product.rb
@@ -0,0 +1,40 @@
+class Product < ApplicationRecord
+ dragonfly_accessor :image
+ # validates_property :mime_type, of: :image, in: %w(image)
+ has_many :order_items
+ has_many :reviews
+
+ belongs_to :merchant
+
+ has_many :categories, through: :categories_products
+ has_many :categories_products
+ accepts_nested_attributes_for :categories, reject_if: :all_blank
+
+ validates :name, presence: :true, uniqueness: :true
+ validates :price, presence: :true, numericality: {greater_than: 0}
+ validates :merchant_id, presence: :true
+
+ # when purchasing, pass a negative number
+ def update_quantity(number)
+ number = number.to_i
+ if number > 0 || check_availability(-number)
+ self.quantity += number
+ # save this to the database
+ self.save
+ return self.quantity
+ end
+ end
+
+ def check_availability(number)
+ self.quantity >= number
+ end
+
+ def retire_product
+ self.active = false
+ end
+
+ def unretire_product
+ self.active = true
+ end
+
+end
diff --git a/app/models/review.rb b/app/models/review.rb
new file mode 100644
index 0000000000..cc2beee797
--- /dev/null
+++ b/app/models/review.rb
@@ -0,0 +1,6 @@
+class Review < ApplicationRecord
+ belongs_to :product
+
+ validates :rating, numericality: {greater_than: 0, less_than_or_equal_to: 5}, presence: true
+ validates :product_id, presence: true
+end
diff --git a/app/views/application/_index.html.erb b/app/views/application/_index.html.erb
new file mode 100644
index 0000000000..6ce89819a8
--- /dev/null
+++ b/app/views/application/_index.html.erb
@@ -0,0 +1,5 @@
+
+ <% collection.each do |item| %>
+ <%= link_to (item[field]), polymorphic_url(item) %>
+ <% end %>
+
diff --git a/app/views/application/_order_details.html.erb b/app/views/application/_order_details.html.erb
new file mode 100644
index 0000000000..57da850cd1
--- /dev/null
+++ b/app/views/application/_order_details.html.erb
@@ -0,0 +1,17 @@
+
+ <% order_items.each do |item| %>
+ <% product = item.product %>
+ -
+ <%= link_to product.name, product_path(product) %>
+
+ -
+ Price: <%= price = product.price %>
+
+ -
+ Quantity: <%= quantity = item.quantity %>
+
+ -
+ Subtotal: <%= subtotal = price * quantity %>
+
+ <% end %>
+
diff --git a/app/views/application/_products_index.html.erb b/app/views/application/_products_index.html.erb
new file mode 100644
index 0000000000..46d7e945ea
--- /dev/null
+++ b/app/views/application/_products_index.html.erb
@@ -0,0 +1,16 @@
+
+ <% @products.each do |product| %>
+ -
+ <%= link_to product_image(product, "80x60"), product_path(product.id) %>
+
+ <%= link_to product.name, product_path(product.id) %>
+ - $ <%= product.price %>0
+ <% if !product.quantity%>
+ - PRODUCT OUT OF STOCK
+ <% else %>
+ - Only <%= product.quantity %> left!
+ <% end %>
+
+
+ <% end %>
+
diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb
new file mode 100644
index 0000000000..75dd542d5a
--- /dev/null
+++ b/app/views/categories/_form.html.erb
@@ -0,0 +1,24 @@
+
+ <%= form_for(category) do |f| %>
+ <% if category.errors.any? %>
+
+
<%= pluralize(category.errors.count, "error") %> prohibited this category from being saved:
+
+
+ <% category.errors.full_messages.each do |message| %>
+ - <%= message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form_for @category do |f| %>
+ <%= f.label :"Category Name"%>
+ <%= f.text_field :name, class: "form-control" %>
+ <% end %>
+ <%= f.submit %>
+
+
+ <% end %>
+
diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb
new file mode 100644
index 0000000000..1095bf3ca6
--- /dev/null
+++ b/app/views/categories/index.html.erb
@@ -0,0 +1,13 @@
+<%= notice %>
+
+Categories
+
+
+
+ <% @categories.each do |item| %>
+ <%= link_to (item.name), category_path(item) %>
+ <% end %>
+
+
+<%#render partial: '/application/index', locals: {collection: @categories, field:'name'}%>
+
diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb
new file mode 100644
index 0000000000..12c0523436
--- /dev/null
+++ b/app/views/categories/new.html.erb
@@ -0,0 +1,7 @@
+Create New Category
+
+
+<%= render 'form', category: @category %>
+
+<%= link_to 'Back', categories_path, class: "button", id: "white-link" %>
+
diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb
new file mode 100644
index 0000000000..74a49b9047
--- /dev/null
+++ b/app/views/categories/show.html.erb
@@ -0,0 +1,8 @@
+<%= notice %>
+<%= @category.name %>
+
+
+<%= render partial: '/application/products_index' %>
+
+<%= link_to 'Back', categories_path, class: "button", id: "white-link" %>
+
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 9b70e01c2e..9f20a0bb32 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -1,14 +1,83 @@
-
+
- Betsy
- <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
- <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
+
+
+
+ <%= content_for?(:title) ? yield(:title) : "Untitled" %>
+
+ <%= stylesheet_link_tag "application" %>
+ <%= javascript_include_tag "application", 'data-turbolinks-track' => true %>
+
+
+
<%= csrf_meta_tags %>
+
+
+
+
+
+
-
-
+
+ <%= yield %>
+
+
+