diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000..44f98a42bc Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..0533f6352f --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# 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' + +.env +/coverage + +# Ignore bundler config. +/.bundle + + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +/node_modules +/yarn-error.log +/coverage + +/coverage + +.byebug_history + +.env + +public/assets/** diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..52f7545eb5 --- /dev/null +++ b/Gemfile @@ -0,0 +1,76 @@ +source 'https://rubygems.org' + +git_source(:github) do |repo_name| + repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/") + "https://github.com/#{repo_name}.git" +end + +gem 'awesome_print' +gem "omniauth" +gem "omniauth-github" +gem 'jquery-rails' + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.1.4' +# Use postgresql as the database for Active Record +gem 'pg', '~> 0.18' +# 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' +# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks +gem 'jquery-turbolinks' +gem 'turbolinks', '~> 5' +# 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', '~> 3.0' +# Use ActiveModel has_secure_password +# gem 'bcrypt', '~> 3.1.7' +gem 'foundation-rails', '6.4.1.2' + + +# 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', platforms: [:mri, :mingw, :x64_mingw] + # Adds support for Capybara system testing and selenium driver + gem 'capybara', '~> 2.13' + gem 'selenium-webdriver' + gem 'pry-rails' + gem 'dotenv-rails' + gem 'simplecov' +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' +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' +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..9b0d888b7f --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,275 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.1.4) + actionpack (= 5.1.4) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.1.4) + actionview (= 5.1.4) + activesupport (= 5.1.4) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.1.4) + activesupport (= 5.1.4) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.1.4) + activesupport (= 5.1.4) + globalid (>= 0.3.6) + activemodel (5.1.4) + activesupport (= 5.1.4) + activerecord (5.1.4) + activemodel (= 5.1.4) + activesupport (= 5.1.4) + arel (~> 8.0) + activesupport (5.1.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + 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) + awesome_print (1.8.0) + 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.7.2) + debug_inspector (>= 0.0.1) + builder (3.2.3) + byebug (9.1.0) + capybara (2.15.4) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (~> 2.0) + childprocess (0.8.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + concurrent-ruby (1.0.5) + crass (1.0.2) + debug_inspector (0.0.3) + docile (1.1.5) + dotenv (2.2.1) + dotenv-rails (2.2.1) + dotenv (= 2.2.1) + railties (>= 3.2, < 5.2) + erubi (1.7.0) + execjs (2.7.0) + faraday (0.12.2) + multipart-post (>= 1.2, < 3) + ffi (1.9.18) + foundation-rails (6.4.1.2) + railties (>= 3.1.0) + sass (>= 3.3.0, < 3.5) + sprockets-es6 (>= 0.9.0) + globalid (0.4.0) + activesupport (>= 4.2.0) + hashie (3.5.6) + i18n (0.9.0) + concurrent-ruby (~> 1.0) + jbuilder (2.7.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + jquery-rails (4.3.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 (2.0.2) + 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.1.1) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.6.6) + mime-types (>= 1.16, < 4) + method_source (0.9.0) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mini_mime (0.1.4) + mini_portile2 (2.3.0) + minitest (5.10.3) + minitest-rails (3.0.0) + minitest (~> 5.8) + railties (~> 5.0) + minitest-reporters (1.1.18) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + multi_json (1.12.2) + multi_xml (0.6.0) + multipart-post (2.0.0) + nio4r (2.1.0) + nokogiri (1.8.1) + mini_portile2 (~> 2.3.0) + 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.7.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.4.0) + oauth2 (~> 1.0) + omniauth (~> 1.2) + pg (0.21.0) + pry (0.11.2) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-rails (0.3.6) + pry (>= 0.10.4) + public_suffix (3.0.0) + puma (3.10.0) + rack (2.0.3) + rack-test (0.7.0) + rack (>= 1.0, < 3) + rails (5.1.4) + actioncable (= 5.1.4) + actionmailer (= 5.1.4) + actionpack (= 5.1.4) + actionview (= 5.1.4) + activejob (= 5.1.4) + activemodel (= 5.1.4) + activerecord (= 5.1.4) + activesupport (= 5.1.4) + bundler (>= 1.3.0) + railties (= 5.1.4) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (5.1.4) + actionpack (= 5.1.4) + activesupport (= 5.1.4) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (12.1.0) + rb-fsevent (0.10.2) + 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.6) + 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.6.0) + childprocess (~> 0.5) + rubyzip (~> 1.0) + simplecov (0.15.1) + docile (~> 1.1.0) + 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.0.1) + turbolinks-source (~> 5) + turbolinks-source (5.0.3) + tzinfo (1.2.3) + thread_safe (~> 0.1) + uglifier (3.2.0) + execjs (>= 0.3.0, < 3) + web-console (3.5.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.2) + xpath (2.1.0) + nokogiri (~> 1.3) + +PLATFORMS + ruby + +DEPENDENCIES + awesome_print + better_errors + binding_of_caller + byebug + capybara (~> 2.13) + dotenv-rails + foundation-rails (= 6.4.1.2) + jbuilder (~> 2.5) + jquery-rails + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + omniauth + omniauth-github + pg (~> 0.18) + pry-rails + puma (~> 3.7) + rails (~> 5.1.4) + sass-rails (~> 5.0) + selenium-webdriver + simplecov + spring + spring-watcher-listen (~> 2.0.0) + turbolinks (~> 5) + tzinfo-data + uglifier (>= 1.3.0) + web-console (>= 3.3.0) + +BUNDLED WITH + 1.16.0.pre.3 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/PNW-logo3.png b/app/assets/images/PNW-logo3.png new file mode 100644 index 0000000000..34ace2b988 Binary files /dev/null and b/app/assets/images/PNW-logo3.png differ diff --git a/app/assets/images/PNWdefaultphoto.jpg b/app/assets/images/PNWdefaultphoto.jpg new file mode 100644 index 0000000000..77172b89f3 Binary files /dev/null and b/app/assets/images/PNWdefaultphoto.jpg differ diff --git a/app/assets/images/PNWhummingbirdpillow.jpg b/app/assets/images/PNWhummingbirdpillow.jpg new file mode 100644 index 0000000000..22f2c55127 Binary files /dev/null and b/app/assets/images/PNWhummingbirdpillow.jpg differ diff --git a/app/assets/images/PNWpintglasses.jpg b/app/assets/images/PNWpintglasses.jpg new file mode 100644 index 0000000000..74c68e9a81 Binary files /dev/null and b/app/assets/images/PNWpintglasses.jpg differ diff --git a/app/assets/images/Triad B.png b/app/assets/images/Triad B.png new file mode 100644 index 0000000000..766dbbe8ee Binary files /dev/null and b/app/assets/images/Triad B.png differ diff --git a/app/assets/images/background.jpg b/app/assets/images/background.jpg new file mode 100644 index 0000000000..61a020b54e Binary files /dev/null and b/app/assets/images/background.jpg differ diff --git a/app/assets/images/banner-Rainier1.jpg b/app/assets/images/banner-Rainier1.jpg new file mode 100644 index 0000000000..d2aa597384 Binary files /dev/null and b/app/assets/images/banner-Rainier1.jpg differ diff --git a/app/assets/images/banner-Rainier2.jpg b/app/assets/images/banner-Rainier2.jpg new file mode 100644 index 0000000000..339a856cc1 Binary files /dev/null and b/app/assets/images/banner-Rainier2.jpg differ diff --git a/app/assets/images/campfire-on-beach.jpg b/app/assets/images/campfire-on-beach.jpg new file mode 100644 index 0000000000..758344cb31 Binary files /dev/null and b/app/assets/images/campfire-on-beach.jpg differ diff --git a/app/assets/images/clothing_placeholder.png b/app/assets/images/clothing_placeholder.png new file mode 100644 index 0000000000..6798cb2344 Binary files /dev/null and b/app/assets/images/clothing_placeholder.png differ diff --git a/app/assets/images/hoh_boundary_waters.jpg b/app/assets/images/hoh_boundary_waters.jpg new file mode 100644 index 0000000000..1c26f012d6 Binary files /dev/null and b/app/assets/images/hoh_boundary_waters.jpg differ diff --git a/app/assets/images/lake.jpg b/app/assets/images/lake.jpg new file mode 100644 index 0000000000..7ac2caa655 Binary files /dev/null and b/app/assets/images/lake.jpg differ diff --git a/app/assets/images/mountain.jpeg b/app/assets/images/mountain.jpeg new file mode 100644 index 0000000000..9725bb1297 Binary files /dev/null and b/app/assets/images/mountain.jpeg differ diff --git a/app/assets/images/pendleton-1.jpg b/app/assets/images/pendleton-1.jpg new file mode 100644 index 0000000000..8dfe324d65 Binary files /dev/null and b/app/assets/images/pendleton-1.jpg differ diff --git a/app/assets/images/purple.jpg b/app/assets/images/purple.jpg new file mode 100644 index 0000000000..790fe6e6b2 Binary files /dev/null and b/app/assets/images/purple.jpg differ diff --git a/app/assets/images/shopping-cart (1).png b/app/assets/images/shopping-cart (1).png new file mode 100644 index 0000000000..70424fdd49 Binary files /dev/null and b/app/assets/images/shopping-cart (1).png differ diff --git a/app/assets/images/shopping-cart.png b/app/assets/images/shopping-cart.png new file mode 100644 index 0000000000..97048101c4 Binary files /dev/null and b/app/assets/images/shopping-cart.png differ diff --git a/app/assets/images/three.jpg b/app/assets/images/three.jpg new file mode 100644 index 0000000000..41f7e186cf Binary files /dev/null and b/app/assets/images/three.jpg differ diff --git a/app/assets/images/two.jpg b/app/assets/images/two.jpg new file mode 100644 index 0000000000..24f6457f6f Binary files /dev/null and b/app/assets/images/two.jpg differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000000..f0a4f1a839 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,20 @@ +// 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 jquery_ujs +//= require foundation +//= require turbolinks +//= require_tree . + + +$(function(){ $(document).foundation(); }); diff --git a/app/assets/javascripts/billing_data.js b/app/assets/javascripts/billing_data.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/billing_data.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/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/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/items.js b/app/assets/javascripts/items.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/items.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/main_page.js b/app/assets/javascripts/main_page.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/main_page.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/orders_products.js b/app/assets/javascripts/orders_products.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/orders_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/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/javascripts/users.js b/app/assets/javascripts/users.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/users.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..b67ff00cdc --- /dev/null +++ b/app/assets/stylesheets/_settings.scss @@ -0,0 +1,863 @@ +// 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-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; + +// 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-size: 250px; +$offcanvas-vertical-size: 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: $light-gray; +$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; +$block-grid-max: 8; + diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss new file mode 100644 index 0000000000..4304a2deab --- /dev/null +++ b/app/assets/stylesheets/application.scss @@ -0,0 +1,206 @@ +/* + * 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_tree . + *= require_self +//= require foundation_and_overrides + + *= require foundation_and_overrides + + */ + +body, h1, h2, h3, h4, h5, footer { + // font-family: 'Slabo 27px', serif; + font-family: 'Muli', sans-serif; + +} + +body { + width: 100%; + height: calc(100vh - 200px); + background-repeat: no-repeat; + // opacity: 0.2; + + } + + +//Nav-------------------------------------- +nav { + background: #3f6172; + text-transform: uppercase; + width: auto; + height: 200px; + font-size: 1em; + letter-spacing: 0.1em; + +} + +nav ul, +nav li { + list-style-type: none; + margin: 0; + padding: 0; +} + +nav li { + display: inline-block; + float: left; +} + +nav li a { + display: block; + min-width: 140px; + height: 40px; + text-align: center; + line-height: 40px; + text-decoration: none; + color:black; +} + +/*Dropdown*/ +.menu_item a:hover{ + background: #8c4511; +} + +nav li:hover ul a { + height: 40px; + line-height: 40px; +} + +nav li ul li { + display: block; + float: none; + background: none; +} + +/*Display on hover*/ +nav ul li a:hover + .hidden, +.hidden:hover { + display: block; +} + +/*Hides the drop down links*/ +nav li ul { + display: none; +} + + + +//NAV-----ADDED--------------------------------- + +.right { + margin-top: 5px; + float: right; +} + + +.right ul li a:hover { + background-color: transparent; + color: black; + border: solid 1px; + border-radius: 15px; +} + +.left { + font-size: 3em; + height: 200px; +} + + +.left:hover +{ + -webkit-transform: scale(1.03); + -ms-transform: scale(1.03); + transform: scale(1.03); +} + + +.left a{ + // width: 40%; + font-size: 4em; + text-align: center; + margin-left: 2%; + line-height: 1; + color:white; +} + +.button { + color: black; + background: none; +} + +.button:hover { + color: black; +} + +// CHECKBOXES-------------------------------------------- + + +input[type="checkbox"] { + // display: none; +} + +input[type="checkbox"]:checked ~ #menu { + display: block; +} + + +// PROFILE & CART------------------------------ + +.background { + width: 100%; + height: calc(100vh - 200px); + background-image: image-url('purple.jpg'); + background-repeat: no-repeat; +} + + +.top-links { + margin-left: 5%; + margin-bottom: 2%; +} + +.profile-section { + display: inline-block; + margin-left: 5%; + margin-right: 5%; +} + +.button:hover { + color: black; + background: none; + background-color: transparent; + border: solid 1px; + border-radius: 15px; +} + +tbody:nth-child(even) { + background-color: white; + } + +tbody:nth-child(odd) { + background-color: #ebebeb; +} + +.table th, +.table td { + text-align: center; +} + +.order-title { + // margin-left: 5%; +} + +.totals { + float: right; + // margin-right: 5%; +} diff --git a/app/assets/stylesheets/billing_data.scss b/app/assets/stylesheets/billing_data.scss new file mode 100644 index 0000000000..4060296673 --- /dev/null +++ b/app/assets/stylesheets/billing_data.scss @@ -0,0 +1,7 @@ +// Place all the styles related to the BillingData controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ + +.billing-ul li{ + // display: inline; +} 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..ebc38966d9 --- /dev/null +++ b/app/assets/stylesheets/foundation_and_overrides.scss @@ -0,0 +1,57 @@ +@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'; +// +// @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-card; +@include foundation-close-button; +@include foundation-drilldown-menu; +@include foundation-dropdown; +@include foundation-dropdown-menu; +@include foundation-responsive-embed; +@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; + +// @include motion-ui-transitions; +// @include motion-ui-animations; diff --git a/app/assets/stylesheets/items.scss b/app/assets/stylesheets/items.scss new file mode 100644 index 0000000000..a3a147ad0b --- /dev/null +++ b/app/assets/stylesheets/items.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Items 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/main_page.scss b/app/assets/stylesheets/main_page.scss new file mode 100644 index 0000000000..bf3e21ace6 --- /dev/null +++ b/app/assets/stylesheets/main_page.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the MainPage 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_products.scss b/app/assets/stylesheets/order_products.scss new file mode 100644 index 0000000000..4e38cdae9b --- /dev/null +++ b/app/assets/stylesheets/order_products.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the OrderProducts 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/orders.scss b/app/assets/stylesheets/orders.scss new file mode 100644 index 0000000000..741506954d --- /dev/null +++ b/app/assets/stylesheets/orders.scss @@ -0,0 +1,3 @@ +// 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/ diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss new file mode 100644 index 0000000000..9029b874df --- /dev/null +++ b/app/assets/stylesheets/products.scss @@ -0,0 +1,47 @@ +// 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/ + +// INDEX------------------------------------------ +section { + width: 95%; + margin-left: 2%; + margin-right: 2%; +} + +article { + display: inline-block; + border: solid 1px; + border-radius: 25px; + width: 20%; + min-width: auto; + height: 300px; + text-align: center; + margin: 2% 2% 2% %2%; +} + +article img { + margin-top: 5%; + height: 100px; + width: 100px; +} + +// SHOW------------------------------------------------ + +.product-details { + // border: solid 1px; + display: block; + width: 45%; + min-width: 40%; + margin-top: 3%; +} + + +.text { + width: 100 px; +} + + +.reviews{ + margin-top: 3%; +} diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss new file mode 100644 index 0000000000..d1257bf340 --- /dev/null +++ b/app/assets/stylesheets/reviews.scss @@ -0,0 +1,17 @@ +// 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/ + +.checkbox { + display: inline; + +} + +.review-form { + margin-top: 3%; + width: 50%; +} + +.categories li { + margin-top: 3%; +} diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000000..ccb1ed25b2 --- /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/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss new file mode 100644 index 0000000000..88e6b3f05a --- /dev/null +++ b/app/assets/stylesheets/users.scss @@ -0,0 +1,32 @@ +// Place all the styles related to the users controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ + +// .storename { +// padding-top: 15px; +// padding-bottom: 15px; +// } +// +// .productinfo-container { +// display: flex; +// } +// +// .productinfo { +// display: inline-flex; +// } +// +// div h3, div ul { +// // display: flex; +// } + +li { + list-style-type: none; +} + + +// =============================== + +.table-head { + background-color: #3f6172; + color: white; +} 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..1c21447d96 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,76 @@ +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + before_action :find_user + before_action :find_cart + before_action :set_session_to_cart + + + # + # def render_404 + # raise ActionController::RoutingError.new('Not Found') + # end + + + + private + def find_user + if session[:user_id] + @user = User.find_by(id: session[:user_id]) + end + end + + + + def find_cart + if @user #find auth_user cart + @pending_order = @user.find_pending_order + session[:pending_order_id] = @pending_order.id if @pending_order + if !(@pending_order) #make them one if they don't have + # @pending_order = Order.find_by(session_id: session[:session_id]) + @pending_order = Order.new(session_id: session[:session_id]) + @pending_order.user_id = @user.id + @pending_order.save + session[:pending_order_id] = @pending_order.id + end + else + if session[:pending_order_id] #find guest's current cart + @pending_order = Order.find(session[:pending_order_id]) + else #make them one if they don't have + # @pending_order = new_pending_order(session[:session_id], nil) + @pending_order = Order.new + @pending_order.session_id = "guest_user" + # binding.pry + @pending_order.save + session[:pending_order_id] = @pending_order.id + end + end + + end + def set_session_to_cart + @pending_order.session_id = session[:session_id] + @pending_order.save + end + + # def not_found + # raise ActionController::RoutingError.new('Not Found') + # redirect_to root_path + # end + # this one is harder to test + # def render_404 + # # DPR: supposedly this will actually render a 404 page in production + # raise ActionController::RoutingError.new('Not Found') + # end + # this one just gives 404 status, easier to test + def render_404 + render file: "/public/404.html", status: 404 + end + + + def new_pending_order(input_session_id, input_user_id) + new_order = Order.new + new_order.session_id = input_session_id + new_order.user_id = input_user_id + return new_order + end + +end diff --git a/app/controllers/billing_data_controller.rb b/app/controllers/billing_data_controller.rb new file mode 100644 index 0000000000..7756f0460b --- /dev/null +++ b/app/controllers/billing_data_controller.rb @@ -0,0 +1,79 @@ +class BillingDataController < ApplicationController + before_action :find_billing, only: [:permission, :edit, :update, :show] + before_action :permission, only: [:edit, :update, :show] + + + def index + render render_404 + end + + def show + unless @billing_data + flash[:error] = "Billing data not found" + redirect_to root_path + end + end + + def edit + unless @billing_data + redirect_to root_path + end + end + + def update + if @billing_data.update_attributes billing_data_params + redirect_to billing_datum_path(@billing_data.id) + @billing_data.user = @user + else + flash[:result_text] = "Didn't save. Make sure your fields are complete!" + render :edit + end + end + + def new + @user = session[:user_id] + @billing_data = BillingDatum.new + + end + + def create + @billing_data = BillingDatum.new billing_data_params + @billing_data.user = @user + if @billing_data.save + flash[:result_text] = "Does this look right?" + redirect_to billing_datum_path(@billing_data.id) + save_billing(@billing_data.id) + else + flash.now[:error] = "Could not create Billing Data" + render :new + end + end + + private + def find_billing + @billing_data = BillingDatum.find_by(id: params[:id].to_i) + end + + def save_billing(id) + @user = session[:user_id] + if @user + user = User.find_by(id: @user) + user.billing_datum_id = id + user.save + end + + @pending_order.billing_datum_id = id + @pending_order.save + end + + def billing_data_params + return params.require(:billing_datum).permit(:email, :mailing_address, :credit_card_name, :credit_card_number, :credit_card_cvv, :billing_zip_code, :expiration_date) + end + + def permission + unless session[:user_id] == @billing_data.user_id || @pending_order.billing_datum_id == @billing_data.id + render render_404 + end + end + +end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..37ae73d07b --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,73 @@ +class CategoriesController < ApplicationController + + def index + @categories = Category.order(:id) + @user = session[:user_id] + end + + #show all products in a specific category + def show + @category = Category.find_by(id: params[:id]) + unless @category + flash[:error] = "Category does not exist" + redirect_to root_path + end + end + + #makes changes to a category that's already created + def edit + @category = Category.find_by(id: params[:id]) + unless @category + redirect_to categories_path + end + end + + def update + @category = Category.find_by(id: params[:id]) + redirect_to categories_path unless @category + + if @category.update_attributes category_params + flash[:success] = "Category edited successfully" + redirect_to categories_path + else + flash.now[:error] = "Category not edited successfully" + render :edit + end + + end + + #sign-in user can create a new category + def new + @category = Category.new + end + + def create + @category = Category.new category_params + if @category.save + puts "SUCCESS" + flash[:success] = "Category created!" + + redirect_to categories_path + + else + puts "FAIL" + flash.now[:error] = "Could not create category" + render :new + end + end + + #signed-in user can delete a category + def destroy + @category = Category.find_by(id: params[:id]) + @category.destroy + flash[:status] = :success + flash[:result_text] = "Successfully destroyed category" + redirect_to categories_path + end + + private + + def category_params + return params.require(:category).permit(:name) + 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/items_controller.rb b/app/controllers/items_controller.rb new file mode 100644 index 0000000000..6e5ed150f9 --- /dev/null +++ b/app/controllers/items_controller.rb @@ -0,0 +1,64 @@ +class ItemsController < ApplicationController + def index + @item = Item.order(:id) + end + + + def show + @item = Item.find_by(id: params[:id]) + puts params[:id] + + # render_404 unless @item + + unless @item + flash[:error] = "Item not found" + redirect_to root_path + end + end + + def new + @item = Item.new + end + + def create + # if !(Product.find_by(id: params[:id])) + # render_404 + # return + # end + @item = Item.new(product_id: params[:id]) + # binding.pry + + if @item.save + # puts "success" + flash[:success] = "#{Product.find(params[:id]).name} item added successfully" + redirect_back(fallback_location: root_path) + else + # puts "fail" + # puts @item.errors.messages + flash.now[:error] = "Item not added to Product # #{params[:id]}" + redirect_to profile_path, status: 400 + end + end + + def destroy + + if Item.where(product_id: params[:id]).length > 0 + @item = Item.where(product_id: params[:id]) + @item.last.destroy + redirect_back(fallback_location: root_path) + + flash[:result_text] = "1 #{Product.find(params[:id]).name} removed from inventory!" + + else + flash[:result_text] = "There are no more items to remove" + redirect_to profile_path, status: 400 + end + end + + private + # GM: This never gets called in this controller + # def item_params + # return params.require(:items).permit(:shipping_status, :purchase_status, :product_id, :order_id) + # end + +end diff --git a/app/controllers/main_page_controller.rb b/app/controllers/main_page_controller.rb new file mode 100644 index 0000000000..617b243dd8 --- /dev/null +++ b/app/controllers/main_page_controller.rb @@ -0,0 +1,4 @@ +class MainPageController < ApplicationController + def index + end +end diff --git a/app/controllers/order_products_controller.rb b/app/controllers/order_products_controller.rb new file mode 100644 index 0000000000..d3777f4af6 --- /dev/null +++ b/app/controllers/order_products_controller.rb @@ -0,0 +1,105 @@ +class OrderProductsController < ApplicationController + def ship + find_entry + if !(@entry) + render_404 + return + end + if @entry.items_shipped? + render_404 + return + end + ship_items + + end + + # def create + # @cart_entry = OrderProduct.new(product_id: params[:id], order_id: @pending_order) + # + # if @cart_entry.save + # flash[:status] = :success + # flash[:result_text] = "Successfully added this to your cart!" + # redirect_to order_path(@pending_order) + # # redirect_to product_path(params[:id]) + # end + # end + + def update + sent_params = params + find_entry + if !@entry + render_404 + return + end + old_quantity = @entry.quantity + sent_quantity = params[:order_product][:quantity].to_i + if sent_quantity == 0 + flash[:result_text] = "Could not update #{@entry.product.name}. Make sure you are entering a number greater than 0. If you wanted to delete it, click delete from cart." + flash[:status] = :error + redirect_to cart_path, status: 400 + return + end + @entry.quantity = sent_quantity + new_quantity = @entry.quantity + if @entry.save + flash[:status] = :success + flash[:result_text] = "Successfully updated #{@entry.product.name} from #{old_quantity} to #{new_quantity}! The params were #{sent_params} " + # redirect_to order_path(@pending_order) + redirect_to cart_path + else + flash[:result_text] = "Could not update #{@entry.product.name}. Please check errors." + flash[:messages] = @entry.errors + redirect_to cart_path + end + end + + def destroy + find_entry + if !@entry + render_404 + return + end + deleted_entry = "#{@entry.product.name}" + if @entry.destroy + flash[:success] = "Successfully deleted #{deleted_entry}." + redirect_to cart_path + else + + end + end + + + private + def cart_entry_params + # params.require(:product).permit(:id, :name, :description, :price, :user) + end + + def find_entry + @entry = OrderProduct.find_by(id: params[:id]) + end + + def ship_items + order = @entry.order + product = @entry.product + entry_items = [] + order.items.each do |item| + entry_items << item if item.product_id == product.id + end + if entry_items.length > 0 + entry_items.each do |item| + item.shipping_status = true + item.save + end + flash[:status] = :success + + flash[:result_text] = "Successfully shipped entry #{@entry.id}!" + redirect_to order_fulfillment_path + + else + flash[:result_text] = "There was an error with updating entry #{@entry.id}. There are no items associated with this order. Sorry." + flash[:status] = :error + redirect_to order_fulfillment_path + + end + end +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 0000000000..66ca83f626 --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,117 @@ +class OrdersController < ApplicationController + before_action :permission, except: [:show, :checkout] + before_action :view_order_permission, only: [:view] + + def view + find_order + end + + + def show + @cart = @pending_order + end + + + def checkout + if mark_items_as_purchased + @cart = @pending_order + flash[:status] = :success + @pending_order.order_status = "paid" + @pending_order.save + session[:pending_order_id] = nil + find_cart + else + flash[:status] = :error + flash[:result_text] = "There was an error; you could not be checked out at this time" + redirect_back(fallback_location: cart_path) + end + end + + + # def add_product + # @cart_entry = OrderProduct.new(product_id: params[:id].to_i, order_id: @pending_order.id) + # if @cart_entry.save + # flash[:status] = :success + # flash[:result_text] = "Successfully added to your cart!" + # redirect_to order_path(@pending_order) + # redirect_to product_path(params[:id]) + # else + # flash[:result_text] = "Could not add that product to your cart" + # flash[:messages] = @cart_entry.errors + # redirect_to root_path + # end + # end + + + + private + def cart_entry_params + # params.require(:product).permit(:id, :name, :description, :price, :user) + end + + def mark_items_as_purchased + entries = @pending_order.order_products + order_id = @pending_order.id + @items_for_purchase = [] + + entries.each do |entry| + if !(entry.valid?) + flash[:status] = :error + flash[:result_text] = "Check your cart, inventory has changed" + flash[:messages] = entry.errors + return false + end + quantity = entry.quantity + available_items = entry.product.available_items + + quantity.times do + @items_for_purchase << available_items.pop + end + end + + @items_for_purchase.each {|item| item.purchase(order_id)} + + + @items_for_purchase.each do |item| + + if item.save + flash[:result_text] = "Items were saved." + else + # flash[:status] = :error + flash[:result_text] << "Items were not saved. Please contact web administrator. " + flash[:messages] = "There were errors" + # item.errors + # redirect_to cart_path + return + end + + end + end + + def find_order + # binding.pry + @order_for_view = Order.find(params[:id].to_i) + # binding.pry + end + + + def permission + unless @user + render_404 + end + end + + def view_order_permission + @order_for_view = Order.find(params[:id].to_i) + if @order_for_view + products = @order_for_view.order_products.map {|entry| entry.product} + # binding.pry + owners_of_products = [] + products.each {|product| owners_of_products << product.user_id} + if !(owners_of_products.include? @user.id) + render_404 + # return + end + end + end +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..5dc9c6a425 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,137 @@ +class ProductsController < ApplicationController + before_action :find_product, except: [:index, :new, :create] + before_action :permission, except: [:show, :index, :add_to_order] + before_action :owns, only: [:edit, :update] + + def index + @products = Product.show_available + end + + def show + unless @product + render_404 + end + @current_user_is_not_product_owner = session[:user_id] != @product.user_id + + @user = @product.user + end + + def edit + if @product.id.nil? + render render_404 + end + end + + def update + unless @product + render render_404 + end + + @product.update_attributes product_params + if @product.save + flash[:status] = :success + flash[:result_text] = "Successfully updated #{@product.name}" + redirect_to profile_path(@user) + else + flash[:status] = :failure + flash[:result_text] = "Could not update #{@product.name}" + flash.now[:messages] = @product.errors.message + render :edit, status: :not_found + end + end + + def new + @product = Product.new + end + + def create + # as long as this exists: session[:user_id] + # product_params.user_id = session[:user_id] + + @product = Product.new(product_params) + if @product.save + flash[:status] = :success + flash[:result_text] = "Successfully created product #{@product.id} #{@product.name}" + redirect_to profile_path(@user) + else + flash[:status] = :failure + flash[:result_text] = "Unable to create a product" + flash[:messages] = @product.errors.messages + render :new, status: :bad_request + end + end + + def add_to_order + # binding.pry + @cart_entry = @pending_order.check_for_duplicates(@product.id) + if @cart_entry + @cart_entry.quantity += params[:quantity].to_i + else + @cart_entry = create_entry(params[:quantity]) + end + + if @cart_entry.save + flash[:status] = :success + flash[:result_text] = "Successfully added to your cart!" + # redirect_to order_path(@pending_order) + redirect_to product_path(@product.id) + else + flash[:result_text] = "Could not add that product to your cart" + flash[:messages] = @cart_entry.errors + redirect_to product_path(@product.id) + end + end + + def change_visibility + if @product.visibility == false + @product.visibility = true + @product.save + flash[:result_text] = "Your product is now visible in browsing" + redirect_back(fallback_location: products_path) + + else + # binding.pry + @product.visibility = false + @product.save + flash[:result_text] = "Your product is no longer visibile in browsing" + redirect_back(fallback_location: products_path) + end + end + + private + def product_params + params.require(:product).permit(:name, :description, :product_photo, :user_id, :price, category_ids:[]) + end + + def entry_params + # params.require(:entry).permit(:quantity) + # return + end + + def find_product + @product = Product.find_by(id: params[:id].to_i) + end + + + def permission + unless @user + render render_404 + end + end + + def owns + unless @product && @user.id == @product.user_id + render render_404 + end + end + + + def create_entry(input_quantity) + entry = OrderProduct.new + entry.product_id = @product.id + entry.order_id = @pending_order.id + entry.quantity = input_quantity.to_i + return entry + end + +end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..839aa9726c --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,77 @@ +class ReviewsController < ApplicationController + # def index + # @reviews = Review.order(:id) + # end + + # def show + # @review = Review.find_by(id: params[:id].to_i) + # + # unless @review + # flash[:error] = "Review not found" + # redirect_to root_path + # end + # end + + + + # def edit + # @review = Review.find_by(id: params[:id].to_i) + # unless @review + # redirect_to root_path + # end + # end + + + + # def update + # @review = Review.find_by(id: params[:id].to_i) + # + # if @review.update_attributes review_params + # redirect_to root_path + # else + # render :edit + # end + # end + + + + def new + @review = Review.new + @product = Product.find_by(id: params[:product_id].to_i) + end + + + + def create + @review = Review.new(review_params) + # puts "*********" + # puts "review = #{@review}" + # puts "review valid? = #{@review.valid?}" + # + # puts "*********" + + if @review.save + redirect_to product_path(review_params[:product_id]) + else + flash.now[:error] = "Could not create Review" + render :new + end + end + + + + # def destroy + # @review = Review.find_by(id: params[:id].to_i) + # @review.destroy + # redirect_to root_path + # end + + + + private + + def review_params + return params.require(:review).permit(:user_id, :product_id, :text, :rating) + end + +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000000..e74bf6dfa6 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,62 @@ +class SessionsController < ApplicationController + + + def login_form + end + + def not_logged_in + end + + def login + username = params[:username] + if username && user = User.find_by(user: username) + session[:user_id] = user.id + flash[:status] = :success + flash[:result_text] = "Successfully logged in as #{@user.username}" + redirect_to root_path + else + user = User.new(username: username) + if user.save + session[:user_id] = @user.id + flash[:success] = "Successfully created user: #{@user.username}" + redirect_to root_path + else + flash.now[:status] = :failure + flash.now[:result_text] = "Could not log in" + flash.now[:messages] = users.errors.messages + render "login_form", status: bad_request + end + end + end + + def create + @auth_hash = request.env['omniauth.auth'] + # ap @auth_hash + + @user = User.find_by(uid: @auth_hash['uid'], provider: @auth_hash['provider']) + + if @user + session[:user_id] = @user.id + flash[:result_text] = "#{@user.username} has been logged in!" + + else + @user = User.new(uid: @auth_hash['uid'], provider: @auth_hash['provider'], email: @auth_hash['info']['email'], username: @auth_hash['info']['nickname']) + @user.save + if @user.save + session[:user_id] = @user.id + flash[:result_text] = "#{@user.username} has been logged in!" + else + flash[:result_text] = "Unable to save user!" + end + end + redirect_to root_path + end + + def logout + session[:user_id] = nil + flash[:result_text] = "Successfully logged out!" + session[:pending_order_id] = nil + + redirect_to root_path + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000000..94417b4021 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,105 @@ +class UsersController < ApplicationController + before_action :permission, except: [:index, :show] + + # def new + # @user = User.new + # end + + def index + @users = [] + User.all.each do |user| + if user.products.length > 0 + @users.push(user) + end + end + return @users + end + + def show + @user = User.find_by(id: params[:id].to_i) + # render_404 unless @user + + unless @user + flash[:error] = "User not found" + redirect_to root_path + end + end + + # def create + # @user = User.new user_params + # + # if @user.save + # flash[:success] = "User added successfully" + # redirect_to root_path + # else + # flash.now[:error] = "User not added" + # render :new + # end + # end + + + # def login + # end + + # def update + # @user = User.find_by(id: params[:id].to_i) + # redirect_to root_path + # + # unless @user + # redirect_to users_path + # end + # end + + def profile + @user = @user + end + + def order_fulfillment + @entries = @user.merchant_entries + organize_entries if @entries + + end + + + # TODO if the user is to be deleted, me must then delete all of there products. + # def destroy + # @user = User.find_by(id: params[:id]) + # @user.destroy + # + # redirect_to root_path + # end + +# --------------------------------------- + # def edit + # end +# --------------------------------------- + + + + private + + # def user_params + # return params.require(:users).permit(:username, :email) + # end + + def permission + if !(@user) + render_404 + end + end + + def render_404 + render file: "/public/404.html", status: 404 + end + + def organize_entries + @paid_entries = @user.paid_entries + @shipped_entries = @user.shipped_entries + @canceled_entries = @user.canceled_entries + # @entries.each do |entry| + # @paid_entries << entry if entry.paid? + # @shipped_entries << entry if entry.shipped? + # @canceled_entries << entry if entry.canceled? + # end + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000000..a83dad11bf --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,25 @@ +module ApplicationHelper + def readable_date(date) + ("" + date.strftime("%b %d %Y") + "").html_safe + end + + def readable_money(money) + #10 => $10.00 + #10.0 => $10.00 + #10.00 => $10.00 + #10.3333 => $10.33 + if !money + return "$0.00" + end + money = money.to_s + if money[-3] == "." + return "$#{money}" + elsif money[-2..-1] == ".0" + return "$#{money}0" + elsif + money[-3..-1] == ".00" + return "$#{money}" + else + end + end +end diff --git a/app/helpers/billing_data_helper.rb b/app/helpers/billing_data_helper.rb new file mode 100644 index 0000000000..2fbe44319c --- /dev/null +++ b/app/helpers/billing_data_helper.rb @@ -0,0 +1,2 @@ +module BillingDataHelper +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/items_helper.rb b/app/helpers/items_helper.rb new file mode 100644 index 0000000000..cff0c9fe21 --- /dev/null +++ b/app/helpers/items_helper.rb @@ -0,0 +1,2 @@ +module ItemsHelper +end diff --git a/app/helpers/main_page_helper.rb b/app/helpers/main_page_helper.rb new file mode 100644 index 0000000000..4810c2f081 --- /dev/null +++ b/app/helpers/main_page_helper.rb @@ -0,0 +1,2 @@ +module MainPageHelper +end diff --git a/app/helpers/order_products_helper.rb b/app/helpers/order_products_helper.rb new file mode 100644 index 0000000000..fb2828b523 --- /dev/null +++ b/app/helpers/order_products_helper.rb @@ -0,0 +1,2 @@ +module OrderProductsHelper +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..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/helpers/users_helper.rb b/app/helpers/users_helper.rb new file mode 100644 index 0000000000..2310a240d7 --- /dev/null +++ b/app/helpers/users_helper.rb @@ -0,0 +1,2 @@ +module UsersHelper +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/billing_datum.rb b/app/models/billing_datum.rb new file mode 100644 index 0000000000..41d7344a22 --- /dev/null +++ b/app/models/billing_datum.rb @@ -0,0 +1,14 @@ +class BillingDatum < ApplicationRecord + has_many :orders + belongs_to :user, optional: true + + validates :email, presence: true + validates :mailing_address, presence: true + validates :credit_card_name, presence: true + validates :credit_card_number, presence: true + validates :credit_card_cvv, presence: true + validates :billing_zip_code, presence: true + # validates :expiration_date, presence: true + + +end diff --git a/app/models/category.rb b/app/models/category.rb new file mode 100644 index 0000000000..a64dfca32e --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,21 @@ +class Category < ApplicationRecord + # add through: to associate join table + has_and_belongs_to_many :products, through: :categories_products + validates :name, presence: true + validates :name, uniqueness: true + + # before_validation :fix_category + + + # private + # def fix_category + # if self.category + # self.category = self.category.downcase.singularize + # end + # end + + #TODO Julia removed the below method because it is a duplicate of a method in the product class (where it belongs) + # def show_available + # Product.where(visibility: true) + # 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/item.rb b/app/models/item.rb new file mode 100644 index 0000000000..d11bc8d0c7 --- /dev/null +++ b/app/models/item.rb @@ -0,0 +1,30 @@ +class Item < ApplicationRecord + belongs_to :product + belongs_to :order, optional: true + validates :shipping_status, inclusion: {in: [true,false]} + validates :purchase_status, inclusion: {in: [true,false]} + + def purchase(input_order_id) + if self.purchase_status != false + self.errors[:order_id] << "does not match item. This items is tied to order #{self.order_id}, you were trying to ship it for #{input_order_id}." + return false + else + self.order_id = input_order_id + self.purchase_status = true + return true + end + end + + def ship(input_order_id) + if self.purchase_status != true + self.errors[:purchase_status] << "Cannot ship an unpurchased item. Please make sure item is purchased before shipping." + return false + elsif input_order_id != self.order_id + self.errors[:order_id] << "does not match item. This items is tied to order #{self.order_id}, you were trying to ship it for #{input_order_id}." + return false + else + self.purchase_status = true + return true + end + end +end diff --git a/app/models/order.rb b/app/models/order.rb new file mode 100644 index 0000000000..3ff3f6c427 --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,97 @@ +class Order < ApplicationRecord + belongs_to :billing_datum, optional: true + has_many :order_products + has_many :items + belongs_to :user, optional: true + validates :session_id, presence: true + validates :order_status, presence: true + validate :has_billing_datum? + validate :has_valid_order_status? + # validate :has_valid_order_products? + + + def sub_total + entries = self.order_products + sub_total = 0 + entries.each do |entry| + unit_price = entry.product.price + entry_cost = unit_price * entry.quantity + sub_total += entry_cost + end + return sub_total + end + + def tax_amount + sub_total = self.sub_total + tax = sub_total * 0.0887 + return tax + end + + def taxed_total + tax = self.tax_amount + sub_total = self.sub_total + return sub_total + tax + end + + def has_billing_datum? + if self.order_status != "pending" + self.errors[:billing_datum_id] << "is missing. Please entire valid billing information." if !(self.billing_datum_id) + end + end + + def has_valid_order_status? + valid_statuses = ["pending", "paid", "shipped", "canceled"] + if !(valid_statuses.include? self.order_status) + self.errors[:order_status] << "is invalid." + end + end + + def has_invalid_entries? + invalid_entries = [] + order_products = self.order_products + order_products.each do |entry| + invalid_entries << entry if !(entry.valid?) + end + if invalid_entries.first != nil + self.errors[:entries] << "are invalid." + #TODO: Julia took out below line. Does not seem needed. Also, sytnax is incorrect- does not use variable entry in ternary. + + invalid_entries.each {|entry| self.errors[:entries] << entry.errors} + + return true #is NOT a valid order + else + return false #is a valid order + end + end + + def entries_by_product + entries_by_product = self.order_products.group_by {|entry| entry.product_id} + return entries_by_product + end + + #used in the controller method add_to_order. + #If there is already a productorder in the cart that has the same product_id, this method will return the product_order object. If there is no duplicate, it will return false. + def check_for_duplicates(input_product_id) + entries = self.entries_by_product + if entries[input_product_id] + return entries[input_product_id][0] + else + return false + end + end + + #gets called if check_for_duplicates returns true + #TODO: Julia removed below method. Does not appear to be applied in any part of the project. + # def combine_entries(entry_id) + # entries = self.entries_by_product + # product = entry.product + # end + + #TODO: Julia removed below method. Does not appear to be applied in any part of the project. Also repeats the logic of the above has_invalid_entries? method above + # def has_valid_order_products + # entries = self.order_products + # entries.each { |entry| return false if !(entry.valid?)} + # return true + # end + +end diff --git a/app/models/order_product.rb b/app/models/order_product.rb new file mode 100644 index 0000000000..32441a0f66 --- /dev/null +++ b/app/models/order_product.rb @@ -0,0 +1,78 @@ +class OrderProduct < ApplicationRecord + belongs_to :order + belongs_to :product + validates :quantity, presence: true + validates :quantity, numericality: { only_integer: true } + validates :quantity, numericality: { greater_than: 0 } + validate :items_available? + + def items_available? + product = self.product + quantity = self.quantity + return false if !(product.num_available) + if product.num_available >= quantity + return true + else + self.errors[:quantity] << "is invalid. There are currently only #{product.num_available} of #{product.name}. Please update your order." + end + return false + end + + def pending? + order = self.order + # binding.pry + if order.order_status == "pending" + return true + else + return false + end + end + + def paid? + order = self.order + if order.order_status == "paid" + return true + else + return false + end + end + + def canceled? + order = self.order + if order.order_status == "canceled" + return true + else + return false + end + end + + def shipped? + order = self.order + if order.order_status == "shipped" + return true + else + return false + end + end + + def subtotal + return (self.quantity) * (self.product.price) + end + + def items_shipped? + order = self.order + entry_items = [] + if order + order.items.each do |item| + entry_items << item if item.product_id == product.id + end + if entry_items + entry_items.each do |item| + return true if item.shipping_status #if item has been shipped, return true + end + end + return false + end + end + +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000000..41cc83b2f9 --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,37 @@ +class Product < ApplicationRecord + has_many :reviews + has_many :items + belongs_to :user + # add through: to associate join table + has_and_belongs_to_many :categories, through: :categories_products + validates :user_id, presence: true + validates :name, uniqueness: true + validates :name, presence: true + validates :price, presence: true + # validates :category_id, presence: true + validates :price, numericality: {greater_than: 0} + validates :visibility, inclusion: {in: [true,false]} + + def num_available + available = available_items + if available + return available.length + else + return 0 + end + end + + def available_items + available = [] + self.items.each do |item| + available << item if !(item.shipping_status) && !(item.purchase_status) + end + return available if available.first != nil + return false + end + + def self.show_available + Product.where(visibility: true) + end + +end diff --git a/app/models/review.rb b/app/models/review.rb new file mode 100644 index 0000000000..1b2004b3df --- /dev/null +++ b/app/models/review.rb @@ -0,0 +1,8 @@ +class Review < ApplicationRecord + belongs_to :user, optional: true + belongs_to :product + validates :rating, numericality: { only_integer: true, greater_than: 0, less_than: 6 } + validates :rating, presence: true + + +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000000..253cefc9ec --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,145 @@ +class User < ApplicationRecord + has_many :products + has_many :orders + has_many :reviews + + belongs_to :billing_datum, optional: true + + validates :username, presence: true + validates :username, uniqueness: true + validates :email, presence: true, uniqueness: true + + def merchant_entries + products = self.products + merchant_entries = [] + products.each do |product| + entries = OrderProduct.where(product_id: product.id) + entries.each { |entry| merchant_entries << entry if !(entry.pending?)} + end + return merchant_entries if merchant_entries.first != nil + return false + end + + def paid_entries + entries = self.merchant_entries + paid_entries = [] + return false if !(entries) + entries.each do |entry| + paid_entries << entry if entry.paid? + end + return paid_entries if paid_entries.first != nil + return false + end + + + def shipped_entries + entries = self.merchant_entries + shipped_entries = [] + return false if !(entries) + entries.each do |entry| + shipped_entries << entry if entry.shipped? + end + return shipped_entries if shipped_entries.first != nil + return false + end + + def canceled_entries + entries = self.merchant_entries + canceled_entries = [] + return false if !(entries) + entries.each do |entry| + canceled_entries << entry if entry.canceled? + end + return canceled_entries if canceled_entries.first != nil + return false + end + + def canceled_revenue + entries = canceled_entries + subtotal = 0 + if entries + entries.each do |entry| + subtotal += entry.subtotal + end + end + return subtotal + end + + def shipped_revenue + entries = shipped_entries + subtotal = 0 + if entries + entries.each do |entry| + subtotal += entry.subtotal + end + end + return subtotal + end + + + def paid_revenue + entries = paid_entries + subtotal = 0 + if entries + entries.each do |entry| + subtotal += entry.subtotal + end + end + return subtotal + end + + def total_revenue + subtotal = 0 + paid_amount = paid_revenue + shipped_amount = shipped_revenue + subtotal = paid_amount + shipped_amount + return subtotal + end + + def find_pending_order #synonymous to cart + pending_orders = [] + self.orders.each do |order| + if order.order_status == "pending" + pending_orders << order + end + end + + #TODO- Question from Julia- Why would a user have multiple pending orders? If they sign in as a user and add to cart, and then logout and add some to a new cart, then sign back in? + if pending_orders.length > 0 + return pending_orders.first + else + return false + end + end + + #TODO-Question from Julia- I think we can remove this method. It is not referenced anywhere in the project. + # def has_products + # has_products = [] + # User.all.each do |user| + # if user.products.length > 0 + # has_products.push(user) + # end + # end + # return has_products + # end + + #TODO- Question from Julia- This method is shown in two places: here and in the application model. I think we can remove it here. + def show_available + Product.where(visibility: true) + end + + def has_past_orders? + past_orders = [] + self.orders.each do |order| + if order.order_status == "paid" || order.order_status == "shipped" || order.order_status == "canceled" + past_orders << order + end + end + if past_orders.length >= 1 + return true + else + return false + end + end + +end diff --git a/app/views/billing_data/_form.html.erb b/app/views/billing_data/_form.html.erb new file mode 100644 index 0000000000..59b9c41f9f --- /dev/null +++ b/app/views/billing_data/_form.html.erb @@ -0,0 +1,33 @@ +
+ +

Enter your Billing Data

+ + <%= form_for @billing_data do |f| %> + + <% f.hidden_field :user_id, value: @user %> + + <%= f.label :email %> + <%= f.text_field :email%> + + <%= f.label :cred_card_name %> + <%= f.text_field :credit_card_name %> + + <%= f.label :mailing_address %> + <%= f.text_field :mailing_address%> + + <%= f.label :credit_card_number%> + <%= f.text_field :credit_card_number%> + + <%= f.label :credit_card_cvv%> + <%= f.text_field :credit_card_cvv%> + + <%= f.label :billing_zip_code%> + <%= f.text_field :billing_zip_code%> + + <%= f.label :expiration_date %> + <%= f.text_field :expiration_date %> + + <%= f.submit "Submit Payment Information" %> + <%end%> + +
diff --git a/app/views/billing_data/create.html.erb b/app/views/billing_data/create.html.erb new file mode 100644 index 0000000000..110190f472 --- /dev/null +++ b/app/views/billing_data/create.html.erb @@ -0,0 +1,2 @@ +

BillingData#create

+

Find me in app/views/billing_data/create.html.erb

diff --git a/app/views/billing_data/destroy.html.erb b/app/views/billing_data/destroy.html.erb new file mode 100644 index 0000000000..421c69f891 --- /dev/null +++ b/app/views/billing_data/destroy.html.erb @@ -0,0 +1,2 @@ +

BillingData#destroy

+

Find me in app/views/billing_data/destroy.html.erb

diff --git a/app/views/billing_data/edit.html.erb b/app/views/billing_data/edit.html.erb new file mode 100644 index 0000000000..f1e16d3aac --- /dev/null +++ b/app/views/billing_data/edit.html.erb @@ -0,0 +1,2 @@ + +<%= render partial: "form", local: {button_name: "Update Billing Information"} %> diff --git a/app/views/billing_data/index.html.erb b/app/views/billing_data/index.html.erb new file mode 100644 index 0000000000..092796e6f6 --- /dev/null +++ b/app/views/billing_data/index.html.erb @@ -0,0 +1,2 @@ +

BillingData#index

+

Find me in app/views/billing_data/index.html.erb

diff --git a/app/views/billing_data/new.html.erb b/app/views/billing_data/new.html.erb new file mode 100644 index 0000000000..04a5c820a8 --- /dev/null +++ b/app/views/billing_data/new.html.erb @@ -0,0 +1 @@ +<%= render partial: "form", local: {button_name: "Add Billing Information"} %> diff --git a/app/views/billing_data/show.html.erb b/app/views/billing_data/show.html.erb new file mode 100644 index 0000000000..36510ee56c --- /dev/null +++ b/app/views/billing_data/show.html.erb @@ -0,0 +1,45 @@ +<%= link_to "Edit Billing Information", edit_billing_datum_path(@billing_data.id), class:"button" %> +<%= link_to "Confirm Order", checkout_path, class:"button"%> + + +
+ +

Your Billing Information

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RequiredYour Info
Email Address<%= @billing_data.email %>
Name on Card<%= @billing_data.credit_card_name %>
Mailing Address<%= @billing_data.mailing_address %>
Credit Card Number<%= @billing_data.credit_card_number %>
CVV<%= @billing_data.credit_card_cvv %>
Billing Zipcode<%= @billing_data.billing_zip_code %>
+
diff --git a/app/views/billing_data/update.html.erb b/app/views/billing_data/update.html.erb new file mode 100644 index 0000000000..71d5458e7d --- /dev/null +++ b/app/views/billing_data/update.html.erb @@ -0,0 +1,2 @@ +

BillingData#update

+

Find me in app/views/billing_data/update.html.erb

diff --git a/app/views/categories/_form.html.erb b/app/views/categories/_form.html.erb new file mode 100644 index 0000000000..89e797aa32 --- /dev/null +++ b/app/views/categories/_form.html.erb @@ -0,0 +1,8 @@ + + + <%= form_for @category do |f| %> + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.submit "submit", class:"button"%> + <% end %> diff --git a/app/views/categories/create.html.erb b/app/views/categories/create.html.erb new file mode 100644 index 0000000000..63069b0005 --- /dev/null +++ b/app/views/categories/create.html.erb @@ -0,0 +1,2 @@ +

Categories#create

+

Find me in app/views/categories/create.html.erb

diff --git a/app/views/categories/destroy.html.erb b/app/views/categories/destroy.html.erb new file mode 100644 index 0000000000..a6ac971f4c --- /dev/null +++ b/app/views/categories/destroy.html.erb @@ -0,0 +1,2 @@ +

Categories#destroy

+

Find me in app/views/categories/destroy.html.erb

diff --git a/app/views/categories/edit.html.erb b/app/views/categories/edit.html.erb new file mode 100644 index 0000000000..3b8dca3af4 --- /dev/null +++ b/app/views/categories/edit.html.erb @@ -0,0 +1,2 @@ +

Categories#edit

+

Find me in app/views/categories/edit.html.erb

diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..b2d17b5e38 --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,16 @@ +

Browse by Category

+ +
+ +<% if @user != nil %> + <%= link_to("Create Category", new_category_path) %> +<% end %> + +<% @categories.each do |category| %> +<%# category.products.to_json %> + +<% end %> + +
diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000000..86b0c5c19b --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1,4 @@ +

Create a New Category!

+ + +<%= render partial: "form", locals: {button_name: "New Category"} %> diff --git a/app/views/categories/show.html.erb b/app/views/categories/show.html.erb new file mode 100644 index 0000000000..0e6c625344 --- /dev/null +++ b/app/views/categories/show.html.erb @@ -0,0 +1,9 @@ +

Shop by Category

+ +

<%=@category.name%>

+ +<% @category.products.show_available.each do |product| %> + +<% end %> diff --git a/app/views/categories/update.html.erb b/app/views/categories/update.html.erb new file mode 100644 index 0000000000..13b85657ff --- /dev/null +++ b/app/views/categories/update.html.erb @@ -0,0 +1,2 @@ +

Categories#update

+

Find me in app/views/categories/update.html.erb

diff --git a/app/views/items/create.html.erb b/app/views/items/create.html.erb new file mode 100644 index 0000000000..8587edb798 --- /dev/null +++ b/app/views/items/create.html.erb @@ -0,0 +1,2 @@ +

Items#create

+

Find me in app/views/items/create.html.erb

diff --git a/app/views/items/destroy.html.erb b/app/views/items/destroy.html.erb new file mode 100644 index 0000000000..73d722058f --- /dev/null +++ b/app/views/items/destroy.html.erb @@ -0,0 +1,2 @@ +

Items#destroy

+

Find me in app/views/items/destroy.html.erb

diff --git a/app/views/items/edit.html.erb b/app/views/items/edit.html.erb new file mode 100644 index 0000000000..22db65db6e --- /dev/null +++ b/app/views/items/edit.html.erb @@ -0,0 +1,2 @@ +

Items#edit

+

Find me in app/views/items/edit.html.erb

diff --git a/app/views/items/index.html.erb b/app/views/items/index.html.erb new file mode 100644 index 0000000000..f2c7d9dfbc --- /dev/null +++ b/app/views/items/index.html.erb @@ -0,0 +1,2 @@ +

Items#index

+

Find me in app/views/items/index.html.erb

diff --git a/app/views/items/new.html.erb b/app/views/items/new.html.erb new file mode 100644 index 0000000000..014c188862 --- /dev/null +++ b/app/views/items/new.html.erb @@ -0,0 +1,2 @@ +

Items#new

+

Find me in app/views/items/new.html.erb

diff --git a/app/views/items/show.html.erb b/app/views/items/show.html.erb new file mode 100644 index 0000000000..5b60ef3f9a --- /dev/null +++ b/app/views/items/show.html.erb @@ -0,0 +1,2 @@ +

Items#show

+

Find me in app/views/items/show.html.erb

diff --git a/app/views/items/update.html.erb b/app/views/items/update.html.erb new file mode 100644 index 0000000000..4ca8103407 --- /dev/null +++ b/app/views/items/update.html.erb @@ -0,0 +1,2 @@ +

Items#update

+

Find me in app/views/items/update.html.erb

diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000000..140d6328cd --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,74 @@ + + + + + + <%= content_for?(:title) ? yield(:title) : "Northwesty" %> + + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> + + + + + + + + + + + + + + +
+ <% flash.each do |name, message| %> +
<%= message %>
+ <% end %> +
+ +<%= yield %> + + + + + diff --git a/app/views/layouts/mailer.html.erb b/app/views/layouts/mailer.html.erb new file mode 100644 index 0000000000..cbd34d2e9d --- /dev/null +++ b/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/app/views/layouts/mailer.text.erb b/app/views/layouts/mailer.text.erb new file mode 100644 index 0000000000..37f0bddbd7 --- /dev/null +++ b/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/app/views/main_page/index.html.erb b/app/views/main_page/index.html.erb new file mode 100644 index 0000000000..d0bb5c17bc --- /dev/null +++ b/app/views/main_page/index.html.erb @@ -0,0 +1,3 @@ + +
diff --git a/app/views/orders/checkout.html.erb b/app/views/orders/checkout.html.erb new file mode 100644 index 0000000000..12eb9f7bef --- /dev/null +++ b/app/views/orders/checkout.html.erb @@ -0,0 +1,41 @@ +

Order Completed!

+ +

+ Your order has been completed! The status is: <%= @pending_order.order_status %>. Your products should ship shortly! Thanks for shopping at NorthWesty! +

+ + + + + + + + + + + + <% @cart.order_products.each do |entry| %> + + + + + + + <% end %> + + + + + + + + +
ItemQuantityCart SubtotalShipment Status
<%= link_to entry.product.name, product_path(entry.product.id)%><%= entry.quantity %> <%= readable_money(entry.product.price.round(2))%> <%= @items_for_purchase.first.shipping_status %>
<%= @cart.taxed_total%>
+ + + + diff --git a/app/views/orders/create.html.erb b/app/views/orders/create.html.erb new file mode 100644 index 0000000000..295bd84094 --- /dev/null +++ b/app/views/orders/create.html.erb @@ -0,0 +1,2 @@ +

Orders#create

+

Find me in app/views/orders/create.html.erb

diff --git a/app/views/orders/destroy.html.erb b/app/views/orders/destroy.html.erb new file mode 100644 index 0000000000..d14d0a3508 --- /dev/null +++ b/app/views/orders/destroy.html.erb @@ -0,0 +1,2 @@ +

Orders#destroy

+

Find me in app/views/orders/destroy.html.erb

diff --git a/app/views/orders/edit.html.erb b/app/views/orders/edit.html.erb new file mode 100644 index 0000000000..7de9049bee --- /dev/null +++ b/app/views/orders/edit.html.erb @@ -0,0 +1,2 @@ +

Orders#edit

+

Find me in app/views/orders/edit.html.erb

diff --git a/app/views/orders/index.html.erb b/app/views/orders/index.html.erb new file mode 100644 index 0000000000..d63a69fb54 --- /dev/null +++ b/app/views/orders/index.html.erb @@ -0,0 +1,2 @@ +

Orders#index

+

Find me in app/views/orders/index.html.erb

diff --git a/app/views/orders/new.html.erb b/app/views/orders/new.html.erb new file mode 100644 index 0000000000..1bc27609ce --- /dev/null +++ b/app/views/orders/new.html.erb @@ -0,0 +1,2 @@ +

Orders#new

+

Find me in app/views/orders/new.html.erb

diff --git a/app/views/orders/show.html.erb b/app/views/orders/show.html.erb new file mode 100644 index 0000000000..fffef13dd6 --- /dev/null +++ b/app/views/orders/show.html.erb @@ -0,0 +1,64 @@ + +
+ <% if @cart.order_products.length == 0 %> + <%= "Get to shopping! Your cart is empty!" %> + <% else %> + + + +
+

Your Order

+ + + + + + + + + + + + + <% @cart.order_products.each do |entry| %> + + + + + + + + + + + <% end %> + +
ProductUnit CostQuantityProduct SubtotalUpdate QuantityDelete Item
<%= entry.product.name %><%= readable_money(entry.product.price.round(2)) %><%= entry.quantity %><%=readable_money(entry.subtotal.round(2)) %><%= form_for entry, url: order_product_path(entry.id), method: :patch do |f| %> + <%# f.label :quantity %> + <%= f.text_field :quantity %> + <%= f.submit "Update Quantity", class:"button"%> + <% end %> + <%= link_to "Delete Item", order_product_path(entry.id), method: :delete, data: {confirm: "Are you sure you want to remove #{entry.product.name} from cart?"}, class:"button" %>
+ + + +
  • + <%# if session[:user_id] %> + <%# @user = User.find_by(id: session[:user_id]) %> + <%#if @user.billing_datum_id %> + + <%#= link_to("Proceed to Checkout", edit_billing_datum_path(@user.billing_datum_id), class:'button') %> + <%# end %> + <%#elsif @pending_order.billing_datum_id %> + <%#= link_to("Proceed to checkout", edit_billing_datum_path(@pending_order.billing_datum_id), class:"button")%> + <%#else%> + <%= link_to "Proceed to Checkout", new_billing_datum_path, class: 'button' %> + <%#end %> + <%end%> +
  • +
    diff --git a/app/views/orders/update.html.erb b/app/views/orders/update.html.erb new file mode 100644 index 0000000000..21caac1f70 --- /dev/null +++ b/app/views/orders/update.html.erb @@ -0,0 +1,2 @@ +

    Orders#update

    +

    Find me in app/views/orders/update.html.erb

    diff --git a/app/views/orders/view.html.erb b/app/views/orders/view.html.erb new file mode 100644 index 0000000000..75a3cc5f97 --- /dev/null +++ b/app/views/orders/view.html.erb @@ -0,0 +1,48 @@ +

    Order #<%=@order_for_view.id %>

    + + + + + + + + + + + + + + + + + + + + + + +
    + Name: + + <%= @order_for_view.billing_datum.credit_card_name %> +
    + Email: + + <%= @order_for_view.billing_datum.email %> +
    + Mailing Address: + + <%= @order_for_view.billing_datum.mailing_address %> +
    + Last 4 Digits of Credit Card: + + <%=@order_for_view.billing_datum.credit_card_number.last(4)%> +
    + Credit Card Expiration Date: + + <%if @order_for_view.billing_datum.expiration_date != nil%> + <%= @order_for_view.billing_datum.expiration_date %> + <% else %> + this billing info was created before expiration date was collected + <% end %> +
    diff --git a/app/views/products/_form.html.erb b/app/views/products/_form.html.erb new file mode 100644 index 0000000000..26f307c16e --- /dev/null +++ b/app/views/products/_form.html.erb @@ -0,0 +1,34 @@ + +<%= form_for @product do |f| %> + + <%= f.hidden_field :user_id, value: session[:user_id] %> + + <%= f.label :name %> + <%= f.text_field :name %> + + <%= f.label :price %> + <%= f.text_field :price %> + + <%= f.label :description %> + <%= f.text_field :description %> + + <%= f.label "Product photo (paste image URL below)" %> + <%= f.text_field :product_photo %> + + + + <% Category.all.each do |category| %> + <%= f.label :to, category.name, class:"checkbox"%> + <%= f.check_box(:category_ids, {:multiple => true}, category.id, nil) %> + <%# f.check_box 'to[]', category.name, class:"checkbox"%> + + + <%# check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") public %> + + <% end %> + + <%= f.submit "submit" %> +<% end %> diff --git a/app/views/products/create.html.erb b/app/views/products/create.html.erb new file mode 100644 index 0000000000..3da139dc2f --- /dev/null +++ b/app/views/products/create.html.erb @@ -0,0 +1,6 @@ +

    Products#create

    +

    Find me in app/views/products/create.html.erb

    + +<%= params %> +

    product

    +<%= @product %> diff --git a/app/views/products/destroy.html.erb b/app/views/products/destroy.html.erb new file mode 100644 index 0000000000..d5c678b499 --- /dev/null +++ b/app/views/products/destroy.html.erb @@ -0,0 +1,2 @@ +

    Products#destroy

    +

    Find me in app/views/products/destroy.html.erb

    diff --git a/app/views/products/edit.html.erb b/app/views/products/edit.html.erb new file mode 100644 index 0000000000..004ea0b165 --- /dev/null +++ b/app/views/products/edit.html.erb @@ -0,0 +1,3 @@ +

    Edit Your Product:

    + +<%= render partial: "form", locals: {button_name: "Update product"} %> diff --git a/app/views/products/home.html.erb b/app/views/products/home.html.erb new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/views/products/index.html.erb b/app/views/products/index.html.erb new file mode 100644 index 0000000000..e74add8920 --- /dev/null +++ b/app/views/products/index.html.erb @@ -0,0 +1,32 @@ + + + + + <%# Category.all.each do |category| %> + <%# link_to category.name, category_path(category.id) %> + <%# end %> + + + + +
    + +

    All Products

    + + <% @products.each do |product| %> + +
    + > +

    <%= link_to product.name, product_path(product.id) %>

    +
      +
    • Price: $<%= product.price %>
    • +
    • Number Available: <%= product.items.where(purchase_status:false).count %>
    • +
    +
    + + <% end %> +
    diff --git a/app/views/products/new.html.erb b/app/views/products/new.html.erb new file mode 100644 index 0000000000..6de455abfa --- /dev/null +++ b/app/views/products/new.html.erb @@ -0,0 +1,3 @@ +

    Create A New Product

    + +<%= render partial: "form", locals: {button_name: "New product"} %> diff --git a/app/views/products/show.html.erb b/app/views/products/show.html.erb new file mode 100644 index 0000000000..dbea08c89f --- /dev/null +++ b/app/views/products/show.html.erb @@ -0,0 +1,46 @@ +
    + + + + + +
    + +
    +

    What People are Saying?

    + <% if @current_user_is_not_product_owner %> +
    <%= link_to "Leave a Review!", new_new_review_path(@product) %>
    + <% end %> + + + + + + + + + + <% @product.reviews.each do |review| %> + + + + + + <% end %> + +
    RatingReview Summary
    Rating: <%= review.rating %> / 5<%= review.text %>
    + +
    diff --git a/app/views/products/update.html.erb b/app/views/products/update.html.erb new file mode 100644 index 0000000000..039889ac02 --- /dev/null +++ b/app/views/products/update.html.erb @@ -0,0 +1,2 @@ +

    Products#update

    +

    Find me in app/views/products/update.html.erb

    diff --git a/app/views/reviews/_form.html.erb b/app/views/reviews/_form.html.erb new file mode 100644 index 0000000000..e30ebe5776 --- /dev/null +++ b/app/views/reviews/_form.html.erb @@ -0,0 +1,32 @@ +
    + +

    Leave a Review

    + +<%= form_for @review do |f| %> + + <%= f.hidden_field :product_id, value: params[:id]%> + + <%= f.hidden_field :user_id, value: session[:user_id] %> + + <%= f.label :enter_text_below %> + <%= f.text_field :text %> + + <%= f.radio_button :rating, 1 %> + <%= f.label :rating, "1", :value => 1 %> + + <%= f.radio_button :rating, 2 %> + <%= f.label :rating, "2", :value => 2 %> + + <%= f.radio_button :rating, 3 %> + <%= f.label :rating, "3", :value => 3 %> + + <%= f.radio_button :rating, 4 %> + <%= f.label :rating, "4", :value => 4 %> + + <%= f.radio_button :rating, 5 %> + <%= f.label :rating, "5", :value => 5 %> + + <%= f.submit "submit" %> + +<% end %> +
    diff --git a/app/views/reviews/create.html.erb b/app/views/reviews/create.html.erb new file mode 100644 index 0000000000..44bf11c2ed --- /dev/null +++ b/app/views/reviews/create.html.erb @@ -0,0 +1,2 @@ +

    Reviews#create

    +

    Find me in app/views/reviews/create.html.erb

    diff --git a/app/views/reviews/destroy.html.erb b/app/views/reviews/destroy.html.erb new file mode 100644 index 0000000000..df58c59d5c --- /dev/null +++ b/app/views/reviews/destroy.html.erb @@ -0,0 +1,2 @@ +

    Reviews#destroy

    +

    Find me in app/views/reviews/destroy.html.erb

    diff --git a/app/views/reviews/edit.html.erb b/app/views/reviews/edit.html.erb new file mode 100644 index 0000000000..28034f5e02 --- /dev/null +++ b/app/views/reviews/edit.html.erb @@ -0,0 +1,2 @@ +

    Reviews#edit

    +

    Find me in app/views/reviews/edit.html.erb

    diff --git a/app/views/reviews/index.html.erb b/app/views/reviews/index.html.erb new file mode 100644 index 0000000000..d19455779d --- /dev/null +++ b/app/views/reviews/index.html.erb @@ -0,0 +1,2 @@ +

    Reviews#index

    +

    Find me in app/views/reviews/index.html.erb

    diff --git a/app/views/reviews/new.html.erb b/app/views/reviews/new.html.erb new file mode 100644 index 0000000000..c25225e1f7 --- /dev/null +++ b/app/views/reviews/new.html.erb @@ -0,0 +1 @@ +<%= render partial: "form", locals: {button_name: "New Review"} %> diff --git a/app/views/reviews/show.html.erb b/app/views/reviews/show.html.erb new file mode 100644 index 0000000000..68d8d94c3b --- /dev/null +++ b/app/views/reviews/show.html.erb @@ -0,0 +1,2 @@ +

    Reviews#show

    +

    Find me in app/views/reviews/show.html.erb

    diff --git a/app/views/reviews/update.html.erb b/app/views/reviews/update.html.erb new file mode 100644 index 0000000000..7d46cbed5c --- /dev/null +++ b/app/views/reviews/update.html.erb @@ -0,0 +1,2 @@ +

    Reviews#update

    +

    Find me in app/views/reviews/update.html.erb

    diff --git a/app/views/users/create.html.erb b/app/views/users/create.html.erb new file mode 100644 index 0000000000..48ea02e600 --- /dev/null +++ b/app/views/users/create.html.erb @@ -0,0 +1,2 @@ +

    Users#create

    +

    Find me in app/views/users/create.html.erb

    diff --git a/app/views/users/destroy.html.erb b/app/views/users/destroy.html.erb new file mode 100644 index 0000000000..de4bd26343 --- /dev/null +++ b/app/views/users/destroy.html.erb @@ -0,0 +1,2 @@ +

    Users#destroy

    +

    Find me in app/views/users/destroy.html.erb

    diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb new file mode 100644 index 0000000000..1881fbdba0 --- /dev/null +++ b/app/views/users/edit.html.erb @@ -0,0 +1,2 @@ +

    Users#edit

    +

    Find me in app/views/users/edit.html.erb

    diff --git a/app/views/users/index.html.erb b/app/views/users/index.html.erb new file mode 100644 index 0000000000..22de8bc451 --- /dev/null +++ b/app/views/users/index.html.erb @@ -0,0 +1,9 @@ + +

    All Merchants

    +
    + <%@users.each do |user|%> +
    + <%=link_to user.username, user_path(user.id) %> +
    + <%end%> +
    diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb new file mode 100644 index 0000000000..c21a1adf19 --- /dev/null +++ b/app/views/users/new.html.erb @@ -0,0 +1,2 @@ +

    Users#new

    +

    Find me in app/views/users/new.html.erb

    diff --git a/app/views/users/order_fulfillment.html.erb b/app/views/users/order_fulfillment.html.erb new file mode 100644 index 0000000000..acacc7ca43 --- /dev/null +++ b/app/views/users/order_fulfillment.html.erb @@ -0,0 +1,238 @@ +

    Merchant Order Fulfillment Page

    + +

    Merchant Stats

    +

    Total Revenue <%= readable_money(@user.total_revenue.round(2)) %>

    + + + + + + + + + +
    + Paid Orders + + Shipped Orders + + Canceled Orders +
    + <%= readable_money(@user.paid_revenue.round(2)) %> + + <%= readable_money(@user.shipped_revenue.round(2)) %> + + <%= readable_money(@user.canceled_revenue.round(2)) %> +
    + +

    Total Orders

    + + + + + + + + + +
    + Paid Orders + + Shipped Orders + + Canceled Orders +
    + <%= @paid_entries ? @paid_entries.length : 0 %> + + <%= @shipped_entries ? @shipped_entries.length : 0%> + + <%= @canceled_entries ? @canceled_entries.length : 0%> +
    + +

    Purchased Orders

    +

    + These items have been purchased and need to be shipped. +

    +
    + <% if @paid_entries %> + + + + + + + + + + + + <% @paid_entries.each do |entry| %> + + + + + + + + + + + <% end %> +
    + Order Number + + Date of Order + + Product Name + + Quantity + + Subtotal + + Order Status: + + Shipping Action +
    + <%= link_to entry.order.id, view_order_path(entry.order.id) %> + + <%= readable_date(entry.order.updated_at) %> + + <%= link_to(entry.product.name, product_path(entry.product.id)) %> + + <%= entry.quantity %> + + <%= readable_money(entry.subtotal.round(2)) %> + + <%= entry.order.order_status %> + + <% if entry.items_shipped? %> + shipped + <% else %> + <%= link_to "Ship", ship_path(entry.id), method: :post, class:"button" %> + <% end %> +
    + <% else %> +

    + No orders currently require your attention. Check back later. +

    + <% end %> +

    Shipped Orders

    +

    + These items have been shipped +

    +
    + + <% if @shipped_entries %> + + + + + + + + + + <% @shipped_entries.each do |entry| %> + + + + + + + + + <% end %> +
    + Order Number + + Date of Order + + Product Name + + Quantity + + Subtotal + + Order Status: +
    + <%#= entry.order.id %> + <%= link_to entry.order.id, view_order_path(entry.order.id) %> + + <%= readable_date(entry.order.updated_at) %> + + <%= link_to(entry.product.name, product_path(entry.product.id)) %> + + <%= entry.quantity %> + + <%= readable_money(entry.subtotal.round(2)) %> + + <%= entry.order.order_status %> +
    + + + <% else %> +

    + No orders have been shipped. Check back later. +

    + <% end %> + +
    +

    Canceled Orders

    +

    + These are orders that were canceled. Yikes. +

    +
    + + <% if @canceled_entries %> + + + + + + + + + + + <% @shipped_entries.each do |entry| %> + + + + + + + + + <% end %> +
    + Order Number + + Date of Order + + Product Name + + Quantity + + Subtotal + + Order Status: +
    + <%#= entry.order.id %> + <%= link_to entry.order.id, order_path(entry.order.id) %> + + <%= readable_date(entry.order.updated_at) %> + + <%= link_to(entry.product.name, product_path(entry.product.id)) %> + + <%= entry.quantity %> + + <%= readable_money(entry.subtotal.round(2)) %> + + <%= entry.order.order_status %> +
    + <% else %> +

    + No orders have been canceled. Congrats! Check back later though. +

    + <% end %> +
    diff --git a/app/views/users/profile.html.erb b/app/views/users/profile.html.erb new file mode 100644 index 0000000000..64e62d803c --- /dev/null +++ b/app/views/users/profile.html.erb @@ -0,0 +1,82 @@ +

    Welcome, <%=@user.username%>

    +

    + +

    + + + +
    + + + + + + + + + + + + + + + + <% @user.products.order(:id).each do |product| %> + + + + + + + + + + + + + + <% end %> + +
    NamePhotoPriceDescriptionAmount in StockEditAdd InventoryReduce InventoryCurrently AvailableProduct Visibility
    <%= link_to product.name, product_path(product.id)%>
  • alt="product photo">
  • <%= product.price %>
  • <%= product.description %>
  • <%=product.items.where(purchase_status: false).count%>
  • <%= link_to "Edit this Product", edit_product_path(product.id), class:"button"%>
  • <%= button_to "Add Inventory", create_item_path(product.id), method: :post, class:"button"%>
  • <%= button_to "Reduce Inventory", destroy_item_path(product.id), method: :delete, class: "button" %>
  • <%= product.visibility %>
  • <%= button_to "Change Product Visibility", change_visibility_path(product.id), class:"button"%>
  • +
    + +
    +

    Your Past Purchases

    + <% if @user.has_past_orders? %> + + + + + + + + + + + + <% @user.orders.where(order_status: "paid").where(order_status: "canceled").where(order_status: "shipped").each do |order| %> + + + <% order.order_products.each do |order_product| %> + + + + + + + + + <% end %> + <% end %> + +
    OrderProductPhotoUnit PriceQuantityOrder Status
  • Order #<%= order.id %>
  • <%= link_to order_product.product.name, product_path(order_product.product.id)%>
  • alt=“product photo”>
  • <%= order_product.product.price %>
  • <%= order_product.quantity %>
  • <%= order_product.order.order_status %>
  • + <% else %> +

    + You do not have any past orders. Get shopping! +

    + <% end%> +
    diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb new file mode 100644 index 0000000000..1105361455 --- /dev/null +++ b/app/views/users/show.html.erb @@ -0,0 +1,29 @@ + +
    +
    +
    +

    <%=@user.username%>'s store

    +
    + <% @user.products.show_available.each do |product|%> + + <% end %> +
    + +
    +

    + Want to contact <%=@user.username%>? Email them at <%=link_to @user.email%> +

    +
    +
    diff --git a/app/views/users/update.html.erb b/app/views/users/update.html.erb new file mode 100644 index 0000000000..cabbde176a --- /dev/null +++ b/app/views/users/update.html.erb @@ -0,0 +1,2 @@ +

    Users#update

    +

    Find me in app/views/users/update.html.erb

    diff --git a/bin/bundle b/bin/bundle new file mode 100755 index 0000000000..66e9889e8b --- /dev/null +++ b/bin/bundle @@ -0,0 +1,3 @@ +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails new file mode 100755 index 0000000000..5badb2fde0 --- /dev/null +++ b/bin/rails @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake new file mode 100755 index 0000000000..d87d5f5781 --- /dev/null +++ b/bin/rake @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000000..78c4e861dc --- /dev/null +++ b/bin/setup @@ -0,0 +1,38 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # Install JavaScript dependencies if using Yarn + # system('bin/yarn') + + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/spring b/bin/spring new file mode 100755 index 0000000000..fb2ec2ebb4 --- /dev/null +++ b/bin/spring @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast. +# It gets overwritten when you run the `spring binstub` command. + +unless defined?(Spring) + require 'rubygems' + require 'bundler' + + lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) + spring = lockfile.specs.detect { |spec| spec.name == "spring" } + if spring + Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path + gem 'spring', spring.version + require 'spring/binstub' + end +end diff --git a/bin/update b/bin/update new file mode 100755 index 0000000000..a8e4462f20 --- /dev/null +++ b/bin/update @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +require 'pathname' +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/config.ru b/config.ru new file mode 100644 index 0000000000..f7ba0b527b --- /dev/null +++ b/config.ru @@ -0,0 +1,5 @@ +# This file is used by Rack-based servers to start the application. + +require_relative 'config/environment' + +run Rails.application diff --git a/config/application.rb b/config/application.rb new file mode 100644 index 0000000000..5f6ca0f9b2 --- /dev/null +++ b/config/application.rb @@ -0,0 +1,25 @@ +require_relative 'boot' + +require 'rails/all' + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Betsy + class Application < Rails::Application + config.generators do |g| + # Force new test files to be generated in the minitest-spec style + g.test_framework :minitest, spec: true + + # Always use .js files, never .coffee + g.javascript_engine :js + end + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.1 + + # Settings in config/environments/* take precedence over those specified here. + # Application configuration should go into files in config/initializers + # -- all .rb files in that directory are automatically loaded. + end +end diff --git a/config/boot.rb b/config/boot.rb new file mode 100644 index 0000000000..30f5120df6 --- /dev/null +++ b/config/boot.rb @@ -0,0 +1,3 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/config/cable.yml b/config/cable.yml new file mode 100644 index 0000000000..3cba994bb2 --- /dev/null +++ b/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: redis://localhost:6379/1 + channel_prefix: betsy_production diff --git a/config/database.yml b/config/database.yml new file mode 100644 index 0000000000..6903bb6083 --- /dev/null +++ b/config/database.yml @@ -0,0 +1,85 @@ +# PostgreSQL. Versions 9.1 and up are supported. +# +# Install the pg driver: +# gem install pg +# On OS X with Homebrew: +# gem install pg -- --with-pg-config=/usr/local/bin/pg_config +# On OS X with MacPorts: +# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config +# On Windows: +# gem install pg +# Choose the win32 build. +# Install PostgreSQL and put its /bin directory on your path. +# +# Configure Using Gemfile +# gem 'pg' +# +default: &default + adapter: postgresql + encoding: unicode + # For details on connection pooling, see Rails configuration guide + # http://guides.rubyonrails.org/configuring.html#database-pooling + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + +development: + <<: *default + database: betsy_development + + # The specified database role being used to connect to postgres. + # To create additional roles in postgres see `$ createuser --help`. + # When left blank, postgres will use the default role. This is + # the same name as the operating system user that initialized the database. + #username: betsy + + # The password associated with the postgres role (username). + #password: + + # Connect on a TCP socket. Omitted by default since the client uses a + # domain socket that doesn't need configuration. Windows does not have + # domain sockets, so uncomment these lines. + #host: localhost + + # The TCP port the server listens on. Defaults to 5432. + # If your server runs on a different port number, change accordingly. + #port: 5432 + + # Schema search path. The server defaults to $user,public + #schema_search_path: myapp,sharedapp,public + + # Minimum log levels, in increasing order: + # debug5, debug4, debug3, debug2, debug1, + # log, notice, warning, error, fatal, and panic + # Defaults to warning. + #min_messages: notice + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: betsy_test + +# As with config/secrets.yml, you never want to store sensitive information, +# like your database password, in your source code. If your source code is +# ever seen by anyone, they now have access to your database. +# +# Instead, provide the password as a unix environment variable when you boot +# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database +# for a full rundown on how to provide these environment variables in a +# production deployment. +# +# On Heroku and other platform providers, you may have a full connection URL +# available as an environment variable. For example: +# +# DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" +# +# You can use this database configuration with: +# +# production: +# url: <%= ENV['DATABASE_URL'] %> +# +production: + <<: *default + database: betsy_production + username: betsy + password: <%= ENV['BETSY_DATABASE_PASSWORD'] %> diff --git a/config/environment.rb b/config/environment.rb new file mode 100644 index 0000000000..426333bb46 --- /dev/null +++ b/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb new file mode 100644 index 0000000000..5187e22186 --- /dev/null +++ b/config/environments/development.rb @@ -0,0 +1,54 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded on + # every request. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + if Rails.root.join('tmp/caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Debug mode disables concatenation and preprocessing of assets. + # This option may cause significant delays in view rendering with a large + # number of complex assets. + config.assets.debug = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/config/environments/production.rb b/config/environments/production.rb new file mode 100644 index 0000000000..5721384187 --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,95 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + config.serve_static_assets = true + config.assets.compile = true + + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Attempt to read encrypted secrets from `config/secrets.yml.enc`. + # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or + # `config/secrets.yml.key`. + config.read_encrypted_secrets = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress JavaScripts and CSS. + config.assets.js_compressor = :uglifier + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "betsy_#{Rails.env}" + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000000..290f033254 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,44 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # The test environment is used exclusively to run your application's + # test suite. You never need to work with it otherwise. Remember that + # your test database is "scratch space" for the test suite and is wiped + # and recreated between test runs. Don't rely on the data there! + config.cache_classes = true + + # Do not eager load code on boot. This avoids loading your whole application + # just for the purpose of running a single test. If you are using a tool that + # preloads Rails for running tests, you may have to set it to true. + config.eager_load = false + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + + # Raise exceptions instead of rendering exception templates. + # config.action_dispatch.show_exceptions = false + + config.action_dispatch.show_exceptions = true + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb new file mode 100644 index 0000000000..89d2efab2b --- /dev/null +++ b/config/initializers/application_controller_renderer.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb new file mode 100644 index 0000000000..4b828e80cb --- /dev/null +++ b/config/initializers/assets.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +Rails.application.config.assets.version = '1.0' + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path +# Add Yarn node_modules folder to the asset load path. +Rails.application.config.assets.paths << Rails.root.join('node_modules') + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000000..59385cdf37 --- /dev/null +++ b/config/initializers/backtrace_silencers.rb @@ -0,0 +1,7 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. +# Rails.backtrace_cleaner.remove_silencers! diff --git a/config/initializers/cookies_serializer.rb b/config/initializers/cookies_serializer.rb new file mode 100644 index 0000000000..5a6a32d371 --- /dev/null +++ b/config/initializers/cookies_serializer.rb @@ -0,0 +1,5 @@ +# Be sure to restart your server when you modify this file. + +# Specify a serializer for the signed and encrypted cookie jars. +# Valid options are :json, :marshal, and :hybrid. +Rails.application.config.action_dispatch.cookies_serializer = :json diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000000..4a994e1e7b --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb new file mode 100644 index 0000000000..ac033bf9dc --- /dev/null +++ b/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, '\1en' +# inflect.singular /^(ox)en/i, '\1' +# inflect.irregular 'person', 'people' +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym 'RESTful' +# end diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb new file mode 100644 index 0000000000..dc1899682b --- /dev/null +++ b/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/config/initializers/omniauth.rb b/config/initializers/omniauth.rb new file mode 100644 index 0000000000..c653e28f42 --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,9 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email" +end + + +# Rails.application.config.middleware.use OmniAuth::Builder do +# provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], +# {:client_options => {:ssl => {:ca_file => ‘/usr/lib/ssl/certs/ca-certificates.crt’}}} +# end diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000000..bbfc3961bf --- /dev/null +++ b/config/initializers/wrap_parameters.rb @@ -0,0 +1,14 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end + +# To enable root element in JSON for ActiveRecord objects. +# ActiveSupport.on_load(:active_record) do +# self.include_root_in_json = true +# end diff --git a/config/locales/en.yml b/config/locales/en.yml new file mode 100644 index 0000000000..decc5a8573 --- /dev/null +++ b/config/locales/en.yml @@ -0,0 +1,33 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t 'hello' +# +# In views, this is aliased to just `t`: +# +# <%= t('hello') %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# To learn more, please read the Rails Internationalization guide +# available at http://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 0000000000..1e19380dcb --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,56 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted, this block will be run. If you are using the `preload_app!` +# option, you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, as Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end +# + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb new file mode 100644 index 0000000000..f2f345dda0 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,111 @@ +Rails.application.routes.draw do + root to: "main_page#index" + + resources :categories do + resources :products + end + + resources :reviews + post 'orders/add-product/:id', to: 'orders#add_product', as: 'add_product' + get '/checkout', to: 'orders#checkout', as: 'checkout' + + get '/reviews/new/:id', to: 'reviews#new', as: 'new_new_review' + get '/users/profile', to: 'users#profile', as: 'profile' + get '/order_fulfillment', to: 'users#order_fulfillment', as: 'order_fulfillment' + resources :users + resources :orders + resources :items, except: [:create, :destroy] + + post '/items/:id', to: 'items#create', as: 'create_item' + delete '/items/:id', to: 'items#destroy', as: 'destroy_item' + + + resources :billing_data + + resources :products + + post 'products/visibility/:id', to: 'products#change_visibility', as: 'change_visibility' + + get 'login', to: 'users#login', as: 'login' + get 'logout', to: 'sessions#logout', as: 'logout' + get '/auth/:provider/callback', to: 'sessions#create', as: 'auth_callback' + post 'products/:id', to: 'products#add_to_order', as: 'add_to_order' + + resources :order_products + get '/cart', to: 'orders#show', as: 'cart' + + post '/ship/:id', to: 'order_products#ship', as: 'ship' + + get '/view/:id', to: 'orders#view', as: 'view_order' + + + + # post 'order-product/:id', to: 'orderproducts#create', as: 'order_product' + + # get 'items/index' + # get 'items/show' + # get 'items/edit' + # get 'items/update' + # get 'items/new' + # get 'items/create' + # get 'items/destroy' + + # get 'main_page/index' + # get 'categories/index' + # get 'categories/show' + # get 'categories/edit' + # get 'categories/update' + # get 'categories/new' + # get 'categories/create' + # get 'categories/destroy' + + # get 'reviews/index' + # get 'reviews/show' + # get 'reviews/edit' + # get 'reviews/update' + # get 'reviews/new' + # get 'reviews/create' + # get 'reviews/destroy' + + # get 'billing_data/index' + # get 'billing_data/show' + # get 'billing_data/edit' + # get 'billing_data/update' + # get 'billing_data/new' + # get 'billing_data/create' + # get 'billing_data/destroy' + + # get 'entries/index' + # get 'entries/show' + # get 'entries/edit' + # get 'entries/update' + # get 'entries/new' + # get 'entries/create' + # get 'entries/destroy' + + # get 'orders/index' + # get 'orders/show' + # get 'orders/edit' + # get 'orders/update' + # get 'orders/new' + # get 'orders/create' + # get 'orders/destroy' + + # get 'products/index' + # get 'products/show' + # get 'products/edit' + # get 'products/update' + # get 'products/new' + # get 'products/create' + # get 'products/destroy' + + # get 'product/index' + # get 'product/show' + # get 'product/edit' + # get 'product/update' + # get 'product/new' + # get 'product/create' + # get 'product/destroy' + + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html +end diff --git a/config/secrets.yml b/config/secrets.yml new file mode 100644 index 0000000000..6788b5599b --- /dev/null +++ b/config/secrets.yml @@ -0,0 +1,32 @@ +# Be sure to restart your server when you modify this file. + +# Your secret key is used for verifying the integrity of signed cookies. +# If you change this key, all old signed cookies will become invalid! + +# Make sure the secret is at least 30 characters and all random, +# no regular words or you'll be exposed to dictionary attacks. +# You can use `rails secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +# Shared secrets are available across all environments. + +# shared: +# api_key: a1B2c3D4e5F6 + +# Environmental secrets are only available for that specific environment. + +development: + secret_key_base: d77e7ad142b9041bfd42818492cc553fc443b983696130db61833a73371d4607e4b89961720dfbf5274343401869746af04e1980bf2ee13c6aabc2fccd9397cb + +test: + secret_key_base: 9656394f19ed89bae1bfe0926671449e62a2b462145b1139adb88af47f558138e25932a282106abe55578595092ca23fd815e49c6f69d91241b048090f4fd97f + +# Do not keep production secrets in the unencrypted secrets file. +# Instead, either read values from the environment. +# Or, use `bin/rails secrets:setup` to configure encrypted secrets +# and move the `production:` environment over there. + +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/config/spring.rb b/config/spring.rb new file mode 100644 index 0000000000..c9119b40c0 --- /dev/null +++ b/config/spring.rb @@ -0,0 +1,6 @@ +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/coverage/.last_run.json b/coverage/.last_run.json new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/coverage/.last_run.json @@ -0,0 +1 @@ + diff --git a/coverage/.resultset.json b/coverage/.resultset.json new file mode 100644 index 0000000000..5519ab7b3c --- /dev/null +++ b/coverage/.resultset.json @@ -0,0 +1,2468 @@ +{ + "MiniTest": { + "coverage": { + "/Users/canaan/Desktop/betsy/app/helpers/application_helper.rb": [ + 1, + 1, + 0, + null, + null, + null, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/billing_data_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/categories_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/items_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/main_page_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/order_products_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/orders_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/products_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/reviews_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/sessions_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/helpers/users_helper.rb": [ + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/application_controller.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 119, + 36, + null, + null, + null, + null, + null, + 1, + 121, + 38, + 38, + 38, + null, + 5, + 5, + 5, + 5, + null, + null, + 83, + 4, + null, + null, + 79, + 79, + null, + 79, + 79, + null, + null, + null, + null, + 1, + 119, + 119, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 18, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/billing_data_controller_test.rb": [ + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0, + 0, + null, + 0, + 0, + null, + null, + 0, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/billing_data_controller.rb": [ + 1, + 1, + 1, + null, + null, + 1, + 2, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 2, + 1, + 1, + 1, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + 1, + 1, + 3, + null, + null, + 1, + 1, + 1, + 0, + 0, + 0, + null, + null, + 1, + 1, + null, + null, + 1, + 2, + null, + null, + 1, + 3, + 2, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/categories_controller_test.rb": [ + 1, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 3, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + 1, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/categories_controller.rb": [ + 1, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 2, + 2, + 1, + 1, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + 2, + 2, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 3, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/items_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/items_controller.rb": [ + 1, + 1, + 1, + null, + null, + null, + 1, + 2, + 2, + null, + null, + null, + 2, + 1, + 1, + null, + null, + null, + 1, + 1, + null, + null, + 1, + null, + null, + null, + null, + 2, + null, + null, + 2, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + null, + 2, + 1, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + null, + null, + 1, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/main_page_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/main_page_controller.rb": [ + 1, + 1, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/order_products_controller_test.rb": [ + 1, + null, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 0, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + null, + null, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/order_products_controller.rb": [ + 1, + 1, + 4, + 4, + 1, + 1, + null, + 3, + 0, + 0, + null, + 3, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 4, + 4, + 4, + 1, + 1, + null, + 3, + 3, + 3, + 2, + 2, + 2, + 2, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 0, + 0, + 0, + null, + null, + null, + 1, + 4, + 4, + 2, + 2, + null, + 2, + 2, + 2, + 2, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 12, + null, + null, + 1, + 3, + 3, + 3, + 3, + 2, + null, + 3, + 2, + 2, + 2, + null, + 2, + null, + 2, + 2, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/orders_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 4, + 4, + 4, + null, + 1, + 1, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/orders_controller.rb": [ + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 2, + null, + null, + null, + 1, + 3, + 2, + 2, + 2, + 2, + 2, + 2, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 3, + 3, + 3, + null, + 3, + 3, + 1, + 1, + 1, + 1, + null, + 2, + 2, + null, + 2, + 2, + null, + null, + null, + 4, + null, + null, + 2, + null, + 2, + 2, + null, + null, + 0, + 0, + null, + null, + 0, + null, + null, + null, + null, + null, + 1, + null, + 1, + null, + null, + null, + null, + 1, + 6, + 1, + null, + null, + null, + 1, + 2, + 2, + 4, + null, + 2, + 4, + 2, + 1, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/products_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + 1, + 3, + 3, + 3, + 3, + null, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + 1, + 1, + null, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + null, + null, + 1, + null, + 1, + 1, + null, + null, + 1, + null, + null, + 1, + 0, + null, + 0, + 0, + 0, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/products_controller.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 2, + null, + null, + 1, + 4, + 1, + null, + 4, + null, + 3, + null, + null, + 1, + 1, + 0, + null, + null, + null, + 1, + 1, + 0, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + 1, + null, + null, + 1, + null, + null, + null, + 5, + 4, + 1, + 1, + 1, + null, + 3, + 3, + 3, + 3, + null, + null, + null, + 1, + null, + 1, + 1, + 1, + null, + 0, + null, + null, + 1, + 0, + 0, + null, + 0, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 0, + 0, + 0, + 0, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 6, + null, + null, + 1, + null, + null, + null, + null, + 1, + 13, + null, + null, + null, + 1, + 16, + 4, + null, + null, + null, + 1, + 5, + 3, + null, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/reviews_controller_test.rb": [ + null, + 1, + null, + 1, + 1, + 1, + 2, + null, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/reviews_controller.rb": [ + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + 1, + null, + null, + null, + null, + 1, + 1, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + 0, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + 1, + 2, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/sessions_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + null, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/sessions_controller.rb": [ + 1, + null, + null, + 1, + null, + null, + 1, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + null, + 0, + 0, + 0, + 0, + 0, + null, + 0, + 0, + 0, + 0, + null, + null, + null, + null, + 1, + 30, + null, + null, + 30, + null, + 30, + 29, + 29, + null, + null, + 1, + 1, + 1, + 1, + 1, + null, + 0, + null, + null, + 30, + null, + null, + 1, + 1, + 1, + 1, + null, + 1, + null, + null + ], + "/Users/canaan/Desktop/betsy/test/controllers/users_controller_test.rb": [ + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + null, + 1, + 1, + null, + 1, + null, + null, + 1, + 1, + 1, + null, + 1, + null, + 1, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + null, + 1, + 1, + null, + null, + 1, + 1, + null, + null, + null, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/controllers/users_controller.rb": [ + 1, + 1, + null, + null, + null, + null, + null, + 1, + 1, + 1, + 4, + 2, + null, + null, + 1, + null, + null, + 1, + 2, + null, + null, + 2, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 1, + null, + null, + 1, + 2, + 2, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + null, + null, + null, + null, + null, + 1, + 5, + 2, + null, + null, + null, + 1, + 2, + null, + null, + 1, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/billing_datum.rb": [ + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/application_record.rb": [ + 1, + 1, + null + ], + "/Users/canaan/Desktop/betsy/app/models/category.rb": [ + 1, + null, + 1, + 1, + 1, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/item.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + 1, + 2, + 0, + 0, + null, + 2, + 2, + 2, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/order_product.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 8, + 8, + 8, + 8, + 5, + null, + 3, + null, + 3, + null, + null, + 1, + 27, + null, + 27, + 18, + null, + 9, + null, + null, + null, + 1, + 3, + 3, + 3, + null, + 0, + null, + null, + null, + 1, + 2, + 2, + 0, + null, + 2, + null, + null, + null, + 1, + 3, + 3, + 0, + null, + 3, + null, + null, + null, + 1, + 3, + null, + null, + 1, + 4, + 4, + 4, + 4, + 2, + null, + 4, + 4, + 2, + null, + null, + 4, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/order.rb": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + null, + null, + null, + 1, + 12, + 12, + 12, + 12, + 12, + 12, + null, + 12, + null, + null, + 1, + 6, + 6, + 6, + null, + null, + 1, + 4, + 4, + 4, + null, + null, + 1, + 206, + 2, + null, + null, + null, + 1, + 206, + 206, + 0, + null, + null, + null, + 1, + 0, + 0, + 0, + 0, + null, + 0, + 0, + null, + null, + 0, + null, + 0, + null, + 0, + null, + null, + null, + 1, + 2, + 1, + null, + null, + null, + null, + 1, + 1, + 1, + 1, + null, + 0, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/product.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + 1, + 1, + 1, + 1, + null, + 1, + 1, + null, + 1, + 21, + 21, + 14, + null, + 7, + null, + null, + null, + 1, + 23, + 23, + 69, + null, + 23, + 7, + null, + null, + 1, + 4, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/review.rb": [ + 1, + 1, + 1, + 1, + 1, + null, + null, + null + ], + "/Users/canaan/Desktop/betsy/app/models/user.rb": [ + 1, + 1, + 1, + 1, + null, + 1, + null, + 1, + 1, + 1, + null, + 1, + 15, + 15, + 15, + 27, + 54, + null, + 15, + 6, + null, + null, + 1, + 5, + 5, + 5, + 3, + 3, + null, + 3, + 0, + null, + null, + 1, + 5, + 5, + 5, + 3, + 3, + null, + 3, + 3, + null, + null, + 1, + 3, + 3, + 3, + 2, + 2, + null, + 2, + 2, + null, + null, + 1, + 2, + 2, + 2, + 0, + 0, + null, + null, + 2, + null, + null, + 1, + 4, + 4, + 4, + 0, + 0, + null, + null, + 4, + null, + null, + null, + 1, + 4, + 4, + 4, + 2, + 2, + null, + null, + 4, + null, + null, + 1, + 2, + 2, + 2, + 2, + 2, + null, + null, + 1, + 38, + 38, + 69, + 33, + null, + null, + null, + null, + 38, + 33, + null, + 5, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1, + 0, + null, + null + ] + }, + "timestamp": 1509130561 + } +} diff --git a/coverage/index.html b/coverage/index.html new file mode 100644 index 0000000000..578a665dfc --- /dev/null +++ b/coverage/index.html @@ -0,0 +1,15535 @@ + + + + Code coverage for Betsy + + + + + + + + +
    + loading +
    + + + diff --git a/db/.DS_Store b/db/.DS_Store new file mode 100644 index 0000000000..deb5dbab71 Binary files /dev/null and b/db/.DS_Store differ diff --git a/db/migrate/20171018013812_create_categories.rb b/db/migrate/20171018013812_create_categories.rb new file mode 100644 index 0000000000..5bef4913b8 --- /dev/null +++ b/db/migrate/20171018013812_create_categories.rb @@ -0,0 +1,9 @@ +class CreateCategories < ActiveRecord::Migration[5.1] + def change + create_table :categories do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/db/migrate/20171018013932_create_products.rb b/db/migrate/20171018013932_create_products.rb new file mode 100644 index 0000000000..120964d4e2 --- /dev/null +++ b/db/migrate/20171018013932_create_products.rb @@ -0,0 +1,11 @@ +class CreateProducts < ActiveRecord::Migration[5.1] + def change + create_table :products do |t| + t.string :name + t.decimal :price + t.string :description + + t.timestamps + end + end +end diff --git a/db/migrate/20171018015818_create_users.rb b/db/migrate/20171018015818_create_users.rb new file mode 100644 index 0000000000..1c030efc19 --- /dev/null +++ b/db/migrate/20171018015818_create_users.rb @@ -0,0 +1,10 @@ +class CreateUsers < ActiveRecord::Migration[5.1] + def change + create_table :users do |t| + t.string :username + t.string :email + + t.timestamps + end + end +end diff --git a/db/migrate/20171018020128_create_entries.rb b/db/migrate/20171018020128_create_entries.rb new file mode 100644 index 0000000000..b45ea4d2d5 --- /dev/null +++ b/db/migrate/20171018020128_create_entries.rb @@ -0,0 +1,10 @@ +class CreateEntries < ActiveRecord::Migration[5.1] + def change + create_table :entries do |t| + t.boolean :shipping_status + t.boolean :purchase_status + + t.timestamps + end + end +end diff --git a/db/migrate/20171018020224_create_reviews.rb b/db/migrate/20171018020224_create_reviews.rb new file mode 100644 index 0000000000..b87cd41667 --- /dev/null +++ b/db/migrate/20171018020224_create_reviews.rb @@ -0,0 +1,10 @@ +class CreateReviews < ActiveRecord::Migration[5.1] + def change + create_table :reviews do |t| + t.string :text + t.string :rating + + t.timestamps + end + end +end diff --git a/db/migrate/20171018020331_create_orders.rb b/db/migrate/20171018020331_create_orders.rb new file mode 100644 index 0000000000..625b6ce834 --- /dev/null +++ b/db/migrate/20171018020331_create_orders.rb @@ -0,0 +1,9 @@ +class CreateOrders < ActiveRecord::Migration[5.1] + def change + create_table :orders do |t| + t.string :order_status + + t.timestamps + end + end +end diff --git a/db/migrate/20171018021031_create_billing_data.rb b/db/migrate/20171018021031_create_billing_data.rb new file mode 100644 index 0000000000..f5f969052e --- /dev/null +++ b/db/migrate/20171018021031_create_billing_data.rb @@ -0,0 +1,14 @@ +class CreateBillingData < ActiveRecord::Migration[5.1] + def change + create_table :billing_data do |t| + t.string :email + t.string :mailing_address + t.string :credit_card_name + t.string :credit_card_number + t.string :credit_card_cvv + t.string :billing_zip_code + + t.timestamps + end + end +end diff --git a/db/migrate/20171018030251_rename_entries_to_items.rb b/db/migrate/20171018030251_rename_entries_to_items.rb new file mode 100644 index 0000000000..eb49bb7889 --- /dev/null +++ b/db/migrate/20171018030251_rename_entries_to_items.rb @@ -0,0 +1,5 @@ +class RenameEntriesToItems < ActiveRecord::Migration[5.1] + def change + rename_table :entries, :items + end +end diff --git a/db/migrate/20171018030912_add_foreign_keys_to_models.rb b/db/migrate/20171018030912_add_foreign_keys_to_models.rb new file mode 100644 index 0000000000..6f05b5bbf4 --- /dev/null +++ b/db/migrate/20171018030912_add_foreign_keys_to_models.rb @@ -0,0 +1,13 @@ +class AddForeignKeysToModels < ActiveRecord::Migration[5.1] + def change + add_reference :billing_data, :user, foreign_key: true + add_reference :orders, :user, foreign_key: true + add_reference :orders, :billing_data, foreign_key: true + add_reference :reviews, :user, foreign_key: true + add_reference :reviews, :product, foreign_key: true + add_reference :products, :category, foreign_key: true + add_reference :products, :user, foreign_key: true + add_reference :items, :product, foreign_key: true + add_reference :items, :order, foreign_key: true + end +end diff --git a/db/migrate/20171018031258_create_order_products.rb b/db/migrate/20171018031258_create_order_products.rb new file mode 100644 index 0000000000..c19a58c563 --- /dev/null +++ b/db/migrate/20171018031258_create_order_products.rb @@ -0,0 +1,9 @@ +class CreateOrderProducts < ActiveRecord::Migration[5.1] + def change + create_table :order_products do |t| + t.string :quantity + + t.timestamps + end + end +end diff --git a/db/migrate/20171018031324_add_order_product_columns.rb b/db/migrate/20171018031324_add_order_product_columns.rb new file mode 100644 index 0000000000..92fef844ff --- /dev/null +++ b/db/migrate/20171018031324_add_order_product_columns.rb @@ -0,0 +1,7 @@ +class AddOrderProductColumns < ActiveRecord::Migration[5.1] + def change + remove_column(:order_products, :quantity) + add_reference :order_products, :order, foreign_key: true + add_reference :order_products, :product, foreign_key: true + end +end diff --git a/db/migrate/20171018034456_add_quantity_to_order_products.rb b/db/migrate/20171018034456_add_quantity_to_order_products.rb new file mode 100644 index 0000000000..fb0e5b951d --- /dev/null +++ b/db/migrate/20171018034456_add_quantity_to_order_products.rb @@ -0,0 +1,5 @@ +class AddQuantityToOrderProducts < ActiveRecord::Migration[5.1] + def change + add_column :order_products, :quantity, :Integer + end +end diff --git a/db/migrate/20171018161814_categories_products_join.rb b/db/migrate/20171018161814_categories_products_join.rb new file mode 100644 index 0000000000..b06bcebb5e --- /dev/null +++ b/db/migrate/20171018161814_categories_products_join.rb @@ -0,0 +1,10 @@ +class CategoriesProductsJoin < ActiveRecord::Migration[5.1] + def change + create_table :categories_products do |t| + t.belongs_to :category, index: :true + t.belongs_to :product, index: :true + + t.timestamps + end + end +end diff --git a/db/migrate/20171018194354_add_session_id_to_order.rb b/db/migrate/20171018194354_add_session_id_to_order.rb new file mode 100644 index 0000000000..c62513f6bf --- /dev/null +++ b/db/migrate/20171018194354_add_session_id_to_order.rb @@ -0,0 +1,5 @@ +class AddSessionIdToOrder < ActiveRecord::Migration[5.1] + def change + add_column :orders, :session_id, :string + end +end diff --git a/db/migrate/20171018194851_change_defaults_items.rb b/db/migrate/20171018194851_change_defaults_items.rb new file mode 100644 index 0000000000..e3bb6eca8c --- /dev/null +++ b/db/migrate/20171018194851_change_defaults_items.rb @@ -0,0 +1,6 @@ +class ChangeDefaultsItems < ActiveRecord::Migration[5.1] + def change + change_column_default(:items, :shipping_status, false) + change_column_default(:items, :purchase_status, false) + end +end diff --git a/db/migrate/20171018204317_add_reference_to_billing_datain_user.rb b/db/migrate/20171018204317_add_reference_to_billing_datain_user.rb new file mode 100644 index 0000000000..6e4349aec1 --- /dev/null +++ b/db/migrate/20171018204317_add_reference_to_billing_datain_user.rb @@ -0,0 +1,5 @@ +class AddReferenceToBillingDatainUser < ActiveRecord::Migration[5.1] + def change + add_reference :users, :billing_datum, foreign_key: true + end +end diff --git a/db/migrate/20171019015943_remove_timestamps_from_categories_products.rb b/db/migrate/20171019015943_remove_timestamps_from_categories_products.rb new file mode 100644 index 0000000000..a1ae1fd37f --- /dev/null +++ b/db/migrate/20171019015943_remove_timestamps_from_categories_products.rb @@ -0,0 +1,6 @@ +class RemoveTimestampsFromCategoriesProducts < ActiveRecord::Migration[5.1] + def change + remove_column :categories_products, :created_at, :datetime + remove_column :categories_products, :updated_at, :datetime + end +end diff --git a/db/migrate/20171019162128_remove_fk_category_id_from_products.rb b/db/migrate/20171019162128_remove_fk_category_id_from_products.rb new file mode 100644 index 0000000000..30b249fc93 --- /dev/null +++ b/db/migrate/20171019162128_remove_fk_category_id_from_products.rb @@ -0,0 +1,5 @@ +class RemoveFkCategoryIdFromProducts < ActiveRecord::Migration[5.1] + def change + remove_column :products, :category_id + end +end diff --git a/db/migrate/20171020002826_add_required_to_product_user.rb b/db/migrate/20171020002826_add_required_to_product_user.rb new file mode 100644 index 0000000000..b0b7dcbf9f --- /dev/null +++ b/db/migrate/20171020002826_add_required_to_product_user.rb @@ -0,0 +1,5 @@ +class AddRequiredToProductUser < ActiveRecord::Migration[5.1] + def change + change_column_null :products, :user_id, false + end +end diff --git a/db/migrate/20171020174948_remove_billing_data_reference_from_order.rb b/db/migrate/20171020174948_remove_billing_data_reference_from_order.rb new file mode 100644 index 0000000000..a5015bc0ab --- /dev/null +++ b/db/migrate/20171020174948_remove_billing_data_reference_from_order.rb @@ -0,0 +1,5 @@ +class RemoveBillingDataReferenceFromOrder < ActiveRecord::Migration[5.1] + def change + remove_reference(:orders, :billing_data, foreign_key: true) + end +end diff --git a/db/migrate/20171020175115_add_billing_datum_reference_to_order.rb b/db/migrate/20171020175115_add_billing_datum_reference_to_order.rb new file mode 100644 index 0000000000..7e333c3b4e --- /dev/null +++ b/db/migrate/20171020175115_add_billing_datum_reference_to_order.rb @@ -0,0 +1,5 @@ +class AddBillingDatumReferenceToOrder < ActiveRecord::Migration[5.1] + def change + add_reference :orders, :billing_datum, foreign_key: true + end +end diff --git a/db/migrate/20171020181604_add_default_order_status_to_order.rb b/db/migrate/20171020181604_add_default_order_status_to_order.rb new file mode 100644 index 0000000000..fd3b1938b1 --- /dev/null +++ b/db/migrate/20171020181604_add_default_order_status_to_order.rb @@ -0,0 +1,5 @@ +class AddDefaultOrderStatusToOrder < ActiveRecord::Migration[5.1] + def change + change_column_default(:orders, :order_status, "pending") + end +end diff --git a/db/migrate/20171020203929_add_uid_to_users.rb b/db/migrate/20171020203929_add_uid_to_users.rb new file mode 100644 index 0000000000..c0341c5ef3 --- /dev/null +++ b/db/migrate/20171020203929_add_uid_to_users.rb @@ -0,0 +1,5 @@ +class AddUidToUsers < ActiveRecord::Migration[5.1] + def change + add_column :users, :uid, :integer + end +end diff --git a/db/migrate/20171020204319_add_null_to_uid_column.rb b/db/migrate/20171020204319_add_null_to_uid_column.rb new file mode 100644 index 0000000000..fa8a62a821 --- /dev/null +++ b/db/migrate/20171020204319_add_null_to_uid_column.rb @@ -0,0 +1,4 @@ +class AddNullToUidColumn < ActiveRecord::Migration[5.1] + def change + end +end diff --git a/db/migrate/20171020204606_add_provider_to_users.rb b/db/migrate/20171020204606_add_provider_to_users.rb new file mode 100644 index 0000000000..85cd0892fb --- /dev/null +++ b/db/migrate/20171020204606_add_provider_to_users.rb @@ -0,0 +1,5 @@ +class AddProviderToUsers < ActiveRecord::Migration[5.1] + def change + add_column :users, :provider, :string + end +end diff --git a/db/migrate/20171023221926_add_visibility_column_products.rb b/db/migrate/20171023221926_add_visibility_column_products.rb new file mode 100644 index 0000000000..4fa019e45a --- /dev/null +++ b/db/migrate/20171023221926_add_visibility_column_products.rb @@ -0,0 +1,5 @@ +class AddVisibilityColumnProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :visibility, :boolean, :default => true + end +end diff --git a/db/migrate/20171025185951_add_exp_date_to_billing_datum.rb b/db/migrate/20171025185951_add_exp_date_to_billing_datum.rb new file mode 100644 index 0000000000..f6a697b0bf --- /dev/null +++ b/db/migrate/20171025185951_add_exp_date_to_billing_datum.rb @@ -0,0 +1,5 @@ +class AddExpDateToBillingDatum < ActiveRecord::Migration[5.1] + def change + add_column :billing_data, :expiration_date, :string + end +end diff --git a/db/migrate/20171025212948_add_photo_to_products.rb b/db/migrate/20171025212948_add_photo_to_products.rb new file mode 100644 index 0000000000..fd2089786c --- /dev/null +++ b/db/migrate/20171025212948_add_photo_to_products.rb @@ -0,0 +1,5 @@ +class AddPhotoToProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :product_photo, :string, :default => "https://i.imgur.com/M8g4Cdu.jpg?1" + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..66a16094fd --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,122 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.rb definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using db:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 20171025212948) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "billing_data", force: :cascade do |t| + t.string "email" + t.string "mailing_address" + t.string "credit_card_name" + t.string "credit_card_number" + t.string "credit_card_cvv" + t.string "billing_zip_code" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "user_id" + t.string "expiration_date" + t.index ["user_id"], name: "index_billing_data_on_user_id" + end + + create_table "categories", force: :cascade do |t| + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + create_table "categories_products", force: :cascade do |t| + t.bigint "category_id" + t.bigint "product_id" + t.index ["category_id"], name: "index_categories_products_on_category_id" + t.index ["product_id"], name: "index_categories_products_on_product_id" + end + + create_table "items", force: :cascade do |t| + t.boolean "shipping_status", default: false + t.boolean "purchase_status", default: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "product_id" + t.bigint "order_id" + t.index ["order_id"], name: "index_items_on_order_id" + t.index ["product_id"], name: "index_items_on_product_id" + end + + create_table "order_products", force: :cascade do |t| + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "order_id" + t.bigint "product_id" + t.integer "quantity" + t.index ["order_id"], name: "index_order_products_on_order_id" + t.index ["product_id"], name: "index_order_products_on_product_id" + end + + create_table "orders", force: :cascade do |t| + t.string "order_status", default: "pending" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "user_id" + t.string "session_id" + t.bigint "billing_datum_id" + t.index ["billing_datum_id"], name: "index_orders_on_billing_datum_id" + t.index ["user_id"], name: "index_orders_on_user_id" + end + + create_table "products", force: :cascade do |t| + t.string "name" + t.decimal "price" + t.string "description" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "user_id", null: false + t.boolean "visibility", default: true + t.string "product_photo", default: "https://i.imgur.com/M8g4Cdu.jpg?1" + t.index ["user_id"], name: "index_products_on_user_id" + end + + create_table "reviews", force: :cascade do |t| + t.string "text" + t.string "rating" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "user_id" + t.bigint "product_id" + t.index ["product_id"], name: "index_reviews_on_product_id" + t.index ["user_id"], name: "index_reviews_on_user_id" + end + + create_table "users", force: :cascade do |t| + t.string "username" + t.string "email" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "billing_datum_id" + t.integer "uid" + t.string "provider" + t.index ["billing_datum_id"], name: "index_users_on_billing_datum_id" + end + + add_foreign_key "billing_data", "users" + add_foreign_key "items", "orders" + add_foreign_key "items", "products" + add_foreign_key "order_products", "orders" + add_foreign_key "order_products", "products" + add_foreign_key "orders", "billing_data" + add_foreign_key "orders", "users" + add_foreign_key "products", "users" + add_foreign_key "reviews", "products" + add_foreign_key "reviews", "users" + add_foreign_key "users", "billing_data" +end diff --git a/db/seed_data/.DS_Store b/db/seed_data/.DS_Store new file mode 100644 index 0000000000..5008ddfcf5 Binary files /dev/null and b/db/seed_data/.DS_Store differ diff --git a/db/seed_data/billing_data_seeds.csv b/db/seed_data/billing_data_seeds.csv new file mode 100644 index 0000000000..2446de66a3 --- /dev/null +++ b/db/seed_data/billing_data_seeds.csv @@ -0,0 +1,4 @@ +billing_data_id,user_id,email,mailing_address,credit_card_name,credit_card_number,credit_card_cvv,billing_zip_code,expiration_date +1,2,"selliot@gmail.com","123 Wallingford Ave., Seattle, WA","Sage Elliot","7777 5555 4444 2222","444","98115","12/12/2019" +2,7,"janep@gmail.com","724 Pine St., Seattle, WA","Jane Pine","1212 3434 5656 7878","121","98107","10/11/2020" +3,10,"amelia@hotmail.com","123 Yesler Way, Seattle, WA","Amelia Yesler","1234 5678 9101 1234","999","98101","10/11/2020" diff --git a/db/seed_data/category_seeds.csv b/db/seed_data/category_seeds.csv new file mode 100644 index 0000000000..2c2a27dbae --- /dev/null +++ b/db/seed_data/category_seeds.csv @@ -0,0 +1,8 @@ +category_id,name +1,clothing, +2,tour, +3,class, +4,collectible, +5,cabin gear, +6,music, +7,dog gear diff --git a/db/seed_data/items_seeds.csv b/db/seed_data/items_seeds.csv new file mode 100644 index 0000000000..72da77d495 --- /dev/null +++ b/db/seed_data/items_seeds.csv @@ -0,0 +1,49 @@ +item_id,product_id,purchase_status,shipping_status +1,1,FALSE,FALSE, +2,1,FALSE,FALSE, +3,1,FALSE,FALSE, +4,1,FALSE,FALSE, +5,1,FALSE,FALSE, +6,2,FALSE,FALSE, +7,2,FALSE,FALSE, +8,2,FALSE,FALSE, +9,2,FALSE,FALSE, +10,2,FALSE,FALSE, +11,2,FALSE,FALSE, +12,2,FALSE,FALSE, +13,2,FALSE,FALSE, +14,2,FALSE,FALSE, +15,3,FALSE,FALSE, +16,3,FALSE,FALSE, +17,3,FALSE,FALSE, +18,3,FALSE,FALSE, +19,3,FALSE,FALSE, +20,3,FALSE,FALSE, +21,4,FALSE,FALSE, +22,4,FALSE,FALSE, +23,4,FALSE,FALSE, +24,4,FALSE,FALSE, +25,5,FALSE,FALSE, +26,5,FALSE,FALSE, +27,5,FALSE,FALSE, +28,5,FALSE,FALSE, +29,6,FALSE,FALSE, +30,6,FALSE,FALSE, +31,7,FALSE,FALSE, +32,7,FALSE,FALSE, +33,7,FALSE,FALSE, +34,7,FALSE,FALSE, +35,8,FALSE,FALSE, +36,8,FALSE,FALSE, +37,9,TRUE,FALSE, +38,10,FALSE,FALSE, +39,10,FALSE,FALSE, +40,10,FALSE,FALSE, +41,10,FALSE,FALSE, +42,10,FALSE,FALSE, +43,10,FALSE,FALSE, +44,10,FALSE,FALSE, +45,10,FALSE,FALSE, +46,10,FALSE,FALSE, +47,10,FALSE,FALSE, +48,10,FALSE,FALSE diff --git a/db/seed_data/order_products_seeds.csv b/db/seed_data/order_products_seeds.csv new file mode 100644 index 0000000000..a92dc33069 --- /dev/null +++ b/db/seed_data/order_products_seeds.csv @@ -0,0 +1,9 @@ +order_product_id,order_id,product_id,quantity +1,1,1,4, +2,1,2,5, +3,1,3,1, +4,2,4,3, +5,2,5,2, +6,2,6,2, +7,2,7,1, +8,3,9,1 diff --git a/db/seed_data/order_seeds.csv b/db/seed_data/order_seeds.csv new file mode 100644 index 0000000000..235503dba3 --- /dev/null +++ b/db/seed_data/order_seeds.csv @@ -0,0 +1,4 @@ +order_id,session_id,user_id,order_status,billing_data_id +1,89,5,pending,2, +2,32,2,pending,3, +3,867,2,paid,1, diff --git a/db/seed_data/product_seeds.csv b/db/seed_data/product_seeds.csv new file mode 100644 index 0000000000..00839591d9 --- /dev/null +++ b/db/seed_data/product_seeds.csv @@ -0,0 +1,11 @@ +product_id,category_id,user_id,name,price,description +1,6,1,Mack Daddy,12.99,"Mack Daddy is the third album by Sir Mix-a-Lot, and his first album with a Parental Advisory label. It was released on February 4, 1992, on Def American Recordings. The album is particularly notable for the hit single Baby Got Back.", +2,6,1,Nevermind,9.95,"Nevermind is the second studio album by American grunge rock band Nirvana, released on September 24, 1991 by DGC Records. Produced by Butch Vig, Nevermind was the band's first release on DGC. It was also their first album to feature drummer Dave Grohl.", +3,1,2,Red Plaid Shirt- Size S,49.95,"Classic lumberjack shirt that you wear to the bar, of course.", +4,1,2,Red Plaid Shirt- Size M,49.95,"Classic lumberjack shirt that you wear to the bar, of course.", +5,1,2,Red Plaid Shirt- Size L,49.95,"Classic lumberjack shirt that you wear to the bar, of course.", +6,4,7,Framed Bigfoot Sighting Photo,119.5,"Proof that Sasquatch is real.", +7,4,10,Sasquatch Action Figure,14.99,"Plastic figurine", +8,7,8,Red Plaid Dog Bandana,5.25,"Every PNW dog needs one of these!", +9,6,4,Crash,8.5,"Crash is the second studio album by American rock group Dave Matthews Band, released on April 30, 1996. By March 16, 2000, the album had sold seven million copies, and was certified 7_ platinum by the RIAA.[1] This is currently Dave Matthews Band's best-selling album.", +10,6,4,Live at Red Rocks,15,"Live at Red Rocks 8.15.95 is an album by the Dave Matthews Band, released on October 28, 1997. It was recorded live at Red Rocks Amphitheatre in Morrison, Colorado on August 15, 1995.", diff --git a/db/seed_data/reviews_seeds.csv b/db/seed_data/reviews_seeds.csv new file mode 100644 index 0000000000..2da653cc6a --- /dev/null +++ b/db/seed_data/reviews_seeds.csv @@ -0,0 +1,7 @@ +review_id,user_id,product_id,text,rating +1,1,7,Great to use to make fake bigfoot photos throughout the PNW. It lives on my dashboard!,5, +2,1,5,Fits perfect but wish it had elbow patches.,4, +3,3,7,My daughter broke it within 5 seconds of opening it. Cheap plastic!,1, +4,5,6,Awesome conversation piece.,5, +5,7,10,DMB forever! I see him at the Wallingford QFC all the time.,5, +6,8,8,Fell off my dog all the time because there isn't enough velcro on the clasp. But very cute.,2 diff --git a/db/seed_data/user_seeds.csv b/db/seed_data/user_seeds.csv new file mode 100644 index 0000000000..422f9f253e --- /dev/null +++ b/db/seed_data/user_seeds.csv @@ -0,0 +1,11 @@ +user_id,username,email +1,sir_mixalot,mixalot@google.com, +2,sage_elliot,selliot@gmail.com, +3,jhendrix,hendrix@outlook.com, +4,dmatthews,dmatthews@google.com, +5,quincy-jones,qjones@yahoo.com, +6,KennyG,Kgorelick@hotmail.com, +7,Jane Pine,janep@gmail.com, +8,Jack Union,jacku@yahoo.com, +9,Trey Smith,SmithT@gmail.com, +10,Amelia Yesler,amelia@hotmail.com diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000000..9680440fee --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,235 @@ +#This file should contain all the record creation needed to seed the database with its default values. +#The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). + + +require 'csv' + +USER_FILE = Rails.root.join('db', 'seed_data', 'user_seeds.csv') +puts "Loading raw user data from #{USER_FILE}" + +user_failures = [] +CSV.foreach(USER_FILE, :headers => true) do |row| + user = User.new + user.id = row['user_id'] + user.username = row['username'] + user.email = row['email'] + puts "Created user: #{user.inspect}" + successful = user.save + if !successful + user_failures << user + end +end + +puts "Added #{User.count} user records" +puts "#{user_failures.length} users failed to save" + +user_failures.each do |failure| + failure.errors.each do |error, message| + puts "Error: #{error}; Message: #{message}" + end +end + +puts " " +puts "--------------------------------------" +puts " " + +PRODUCT_FILE = Rails.root.join('db', 'seed_data', 'product_seeds.csv') +puts "Loading raw work data from #{PRODUCT_FILE}" + +product_failures = [] +CSV.foreach(PRODUCT_FILE, :headers => true) do |row| + product = Product.new + product.id = row['product_id'] + product.name = row['name'] + product.price = row['price'] + product.description = row['description'] + product.user_id = row['user_id'] + + puts "Created product: #{product.inspect}" + successful = product.save + if !successful + product_failures << product + end +end + +puts "Added #{Product.count} product records" +puts "#{product_failures.length} product failed to save" +product_failures.each do |failure| + failure.errors.each do |error, message| + puts "Error: #{error}; Message: #{message}" + end +end + +puts " " +puts "--------------------------------------" +puts " " + + +CATEGORY_FILE = Rails.root.join('db', 'seed_data', 'category_seeds.csv') +puts "Loading raw category data from #{CATEGORY_FILE}" + +category_failures = [] +CSV.foreach(CATEGORY_FILE, :headers => true) do |row| + category = Category.new + category.id = row['category_id'] + category.name = row['name'] + puts "Created category: #{category.inspect}" + successful = category.save + if !successful + category_failures << category + end +end + +puts "Added #{Category.count} category records" +puts "#{category_failures.length} categories failed to save" + +puts " " +puts "--------------------------------------" +puts " " + + +REVIEW_FILE = Rails.root.join('db', 'seed_data', 'reviews_seeds.csv') +puts "Loading raw review data from #{REVIEW_FILE}" + +review_failures = [] +CSV.foreach(REVIEW_FILE, :headers => true) do |row| + review = Review.new + review.id = row['review_id'] + review.text = row['text'] + review.rating = row['rating'] + review.user_id = row['user_id'] + review.product_id = row['product_id'] + puts "Created review: #{review.inspect}" + successful = review.save + if !successful + review_failures << review + end +end + +puts "Added #{Review.count} review records" +puts "#{review_failures.length} review failed to save" + +puts " " +puts "--------------------------------------" +puts " " + + +BILLING_DATA_FILE = Rails.root.join('db', 'seed_data', 'billing_data_seeds.csv') +puts "Loading raw billing_data data from #{BILLING_DATA_FILE}" + +billing_data_failures = [] +CSV.foreach(BILLING_DATA_FILE, :headers => true) do |row| + billing_datum = BillingDatum.new + billing_datum.id = row['billing_data_id'] + billing_datum.email = row['email'] + billing_datum.mailing_address = row['mailing_address'] + billing_datum.credit_card_name = row['credit_card_name'] + billing_datum.credit_card_number = row['credit_card_number'] + billing_datum.credit_card_cvv = row['credit_card_cvv'] + billing_datum.billing_zip_code = row['billing_zip_code'] + billing_datum.user_id = row['user_id'] + billing_datum.expiration_date = row['expiration_date'] + + puts "Created billing_datum: #{billing_datum.inspect}" + successful = billing_datum.save + if !successful + billing_data_failures << billing_datum + end +end + +puts "Added #{BillingDatum.count} billing_data records" +puts "#{billing_data_failures.length} billing_data records failed to save" + +puts " " +puts "--------------------------------------" +puts " " + + +ORDER_FILE = Rails.root.join('db', 'seed_data', 'order_seeds.csv') +puts "Loading raw order data from #{ORDER_FILE}" + +order_failures = [] +CSV.foreach(ORDER_FILE, :headers => true) do |row| + order = Order.new + order.id = row['order_id'] + order.order_status = row['order_status'] + order.user_id = row['user_id'] + order.session_id = row['session_id'] + order.billing_datum_id = row['billing_data_id'] + puts "Created order: #{order.inspect}" + successful = order.save + if !successful + order_failures << order + end +end + +puts "Added #{Order.count} order records" +puts "#{order_failures.length} order failed to save" + +puts " " +puts "--------------------------------------" +puts " " + + +ORDER_PRODUCTS_FILE = Rails.root.join('db', 'seed_data', 'order_products_seeds.csv') +puts "Loading raw order_product data from #{ORDER_PRODUCTS_FILE}" + +order_product_failures = [] +CSV.foreach(ORDER_PRODUCTS_FILE, :headers => true) do |row| + order_product = OrderProduct.new + order_product.id = row['order_product_id'] + order_product.order_id = row['order_id'] + order_product.product_id = row['product_id'] + order_product.quantity = row['quantity'] + puts "Created review: #{order_product.inspect}" + successful = order_product.save + if !successful + order_product_failures << order_product + end +end + +puts "Added #{OrderProduct.count} order_product records" +puts "#{order_product_failures.length} order_products failed to save" + + +puts " " +puts "--------------------------------------" +puts " " + + +ITEM_FILE = Rails.root.join('db', 'seed_data', 'items_seeds.csv') +puts "Loading raw item data from #{ITEM_FILE}" + +item_failures = [] +CSV.foreach(ITEM_FILE, :headers => true) do |row| + item = Item.new + item.id = row['item_id'] + item.shipping_status = row['shipping_status'] + item.purchase_status = row['purchase_status'] + item.product_id = row['product_id'] + item.order_id = row['order_id'] + + puts "Created item: #{item.inspect}" + successful = item.save + if !successful + item_failures << item + end +end + +puts "Added #{Item.count} item records" +puts "#{item_failures.length} item records failed to save" + +puts " " +puts "--------------------------------------" +puts " " +# +# # Since we set the primary key (the ID) manually on each of the +# # tables, we've got to tell postgres to reload the latest ID +# # values. Otherwise when we create a new record it will try +# # to start at ID 1, which will be a conflict. +puts "Manually resetting PK sequence on each table" +ActiveRecord::Base.connection.tables.each do |t| + ActiveRecord::Base.connection.reset_pk_sequence!(t) +end + +puts "done" diff --git a/feedback.md b/feedback.md deleted file mode 100644 index b958bb8713..0000000000 --- a/feedback.md +++ /dev/null @@ -1,42 +0,0 @@ -# bEtsy -## What We're Looking For - -| Feature | Feedback | -| :------------- | :------------- | -| **Baseline** | | -| Appropriate Git Usage with all members contributing | | -| Answered comprehension questions | | -| Trello board is created and utilized in project management | | -| Heroku instance is online | | -| **General** | | -| Nested routes follow RESTful conventions | | -| oAuth used for User authentication | | -| Functionality restricted based on user roles | | -| Products can be added and removed from cart | | -| Users can view past orders | | -| Merchants can add, edit and view their products | | -| Errors are reported to the user | | -| **Order Functionality** | | -| Reduces products' inventory | | -| Cannot order products that are out of stock | | -| Changes order state | | -| Clears current cart | | -| **Database** | | -| ERD includes all necessary tables and relationships | | -| Table relationships | | -| **Models** | | -| Validation rules for Models | | -| Business logic is in the models | | -| **Controllers** | | -| Controller Filters used to DRY up controller code | | -| **Testing** | | -| Model Testing | | -| Controller Testing | | -| Session Testing | | -| SimpleCov at 90% for controller and model tests | | -| **Front-end** | | -| The app is styled to create an attractive user interface | | -| The app layout uses Foundation's Grid | | -| Content is organized with HTML5 semantic tags | | -| CSS is DRY | | -| **Overall** | | diff --git a/lib/assets/.keep b/lib/assets/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/lib/tasks/.keep b/lib/tasks/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/log/.keep b/log/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/package.json b/package.json new file mode 100644 index 0000000000..f874acf437 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "name": "betsy", + "private": true, + "dependencies": {} +} diff --git a/public/404.html b/public/404.html new file mode 100644 index 0000000000..2be3af26fc --- /dev/null +++ b/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
    +
    +

    The page you were looking for doesn't exist.

    +

    You may have mistyped the address or the page may have moved.

    +
    +

    If you are the application owner check the logs for more information.

    +
    + + diff --git a/public/422.html b/public/422.html new file mode 100644 index 0000000000..c08eac0d1d --- /dev/null +++ b/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
    +
    +

    The change you wanted was rejected.

    +

    Maybe you tried to change something you didn't have access to.

    +
    +

    If you are the application owner check the logs for more information.

    +
    + + diff --git a/public/500.html b/public/500.html new file mode 100644 index 0000000000..78a030af22 --- /dev/null +++ b/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
    +
    +

    We're sorry, but something went wrong.

    +
    +

    If you are the application owner check the logs for more information.

    +
    + + diff --git a/public/apple-touch-icon-precomposed.png b/public/apple-touch-icon-precomposed.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000..e69de29bb2 diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000000..37b576a4a0 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1 @@ +# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb new file mode 100644 index 0000000000..d19212abd5 --- /dev/null +++ b/test/application_system_test_case.rb @@ -0,0 +1,5 @@ +require "test_helper" + +class ApplicationSystemTestCase < ActionDispatch::SystemTestCase + driven_by :selenium, using: :chrome, screen_size: [1400, 1400] +end diff --git a/test/controllers/.keep b/test/controllers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/controllers/application_controller_test.rb b/test/controllers/application_controller_test.rb new file mode 100644 index 0000000000..d9581e8be8 --- /dev/null +++ b/test/controllers/application_controller_test.rb @@ -0,0 +1,47 @@ +require 'test_helper' + +describe ApplicationController do + it "should find an existing user if user is logged in" do + start_count = User.count + user = users(:mia) + + log_in(user, :github) + + must_respond_with :redirect + must_redirect_to root_path + User.count.must_equal start_count + session[:user_id].must_equal user.id + end + + it "should find a pending order for an existing user that is logged in" do + get root_path + user = users(:mia) + guest_cart_id = session[:pending_order_id] + log_in(user, :github) + get root_path + # binding.pry + + session[:user_id].must_equal user.id + session[:pending_order_id].must_be :!=, guest_cart_id + session[:pending_order_id].must_equal orders(:mias_pending_order).id + end + + it "should create a new pending_order for a guest user" do + get root_path + guest_cart_id = session[:pending_order_id] + # puts session + # binding.pry + guest_cart_id.must_be :!=, nil + end + + it "should assign pending order from guest session to logged in user if they do not have pending orders" do + user = users(:sophie_no_pending_order) + get root_path + guest_session_id = session[:session_id] + log_in(user, :github) + get root_path + session[:user_id].must_equal user.id + # binding.pry + (Order.find(session[:pending_order_id])).session_id.must_equal guest_session_id + end +end diff --git a/test/controllers/billing_data_controller_test.rb b/test/controllers/billing_data_controller_test.rb new file mode 100644 index 0000000000..e9d0dcca86 --- /dev/null +++ b/test/controllers/billing_data_controller_test.rb @@ -0,0 +1,114 @@ +require 'test_helper' + +#IF IT'S COMMENTED OUT, IT'S GOT ERRORS +describe BillingDataController do + describe "Index" do + it "should not show a list of all billing data" do + get billing_data_path + must_respond_with :not_found + end + end + + describe "creating new billing information" do + it "it should produce a form for entering payment information" do + get new_billing_datum_path + must_respond_with :success + end + + it "should create new billing information with valid information" do + billing_data = { + billing_datum: { + email: "test@testdata.com", + mailing_address: "2200 New Street, Seattle, WA, 09020", + credit_card_name: "test card", + credit_card_number: "4332 2321 1213 1241", + credit_card_cvv: "333", + billing_zip_code: "09020", + expiration_date: "121" + } + } + proc {post billing_data_path, params: billing_data}.must_change 'BillingDatum.count', 1 + + must_respond_with :redirect + end + + it "should not create new billing information when valid data isn't present" do + billing_data = { + billing_datum: { + email: "test@testdata.com", + mailing_address: "2200 New Street, Seattle, WA, 09020", + credit_card_name: "test card", + credit_card_number: "4332 2321 1213 1241", + credit_card_cvv: "333", + billing_zip_code: "09020", + expiration_date: "211" + } + } + + billing_data.each do |key, value| + billing_data[key] = nil + + proc {post billing_data_path, params: billing_data}.must_change 'BillingDatum.count', 0 + must_respond_with :bad_request + end + end + end + + it "!!!should produce an edit form for billing data" do + #issue connecting user to data + log_in(users(:carl), :github) + session[:user_id].must_equal users(:carl).id + + get edit_billing_datum_path(billing_data(:carl_billing_datum)) + must_respond_with :success + end + + it "should update billing information" do + person_data = billing_data(:carl_billing_datum) + user = User.find_by(id: person_data.user_id) + log_in( user, :github) + + + billing_data = { + billing_datum: { + email: "test@testdata.com", + mailing_address: "2200 New Street, Seattle, WA, 09020", + credit_card_name: "test card", + credit_card_number: "4332 2321 1213 1241", + credit_card_cvv: "333", + billing_zip_code: "09020", + expiration_date: "121" + } + } + + session[:user_id].must_equal User.users(:carl).id + session[:user_id].must_equal BillingDatum.find_by(id: billing_data(:carl_billing_datum)).user_id + + put billing_datum_path(person_data), params: billing_data + must_respond_with :redirect + + + must_redirect_to billing_info_path(billing_data(:carl_billing_datum)) + # should redirect to the "show billing info/confirm purchase" + end + + describe "#SHOW" do + it "shows a logged in user her billing information" do + log_in(users(:carl), :github) + #there is a problem with the connection between user and user id + get billing_datum_path(billing_data(:carl_billing_datum).id) + must_respond_with :success + end + + it "does not show billing information to anyone not tied to it through a product" do + get billing_data_path(billing_data(:carl_billing_datum).id) + must_respond_with :not_found + end + + it "doesn't show billing data that doesn't exist" do + + get billing_datum_path(BillingDatum.last.id+1) + must_redirect_to root_path + end + end +end diff --git a/test/controllers/categories_controller_test.rb b/test/controllers/categories_controller_test.rb new file mode 100644 index 0000000000..44701a0da9 --- /dev/null +++ b/test/controllers/categories_controller_test.rb @@ -0,0 +1,87 @@ +require "test_helper" + +describe CategoriesController do + + describe "index" do + # it "succeeds when there are categories" do + # get categories_path + # must_respond_with :success + # end + + it "succeeds when there are no categories" do + Category.all.each do |category| + category.destroy + end + get categories_path + must_respond_with :success + end + end + + describe "show" do + it "can show one category" do + get category_path(categories(:music).id) + must_respond_with :success + end + + it "cannot show a category that does not exist" do + category_id = Category.last.id + 1 + get category_path(category_id) + #add test for flash message here + must_respond_with :redirect + must_redirect_to root_path + end + end + + + describe "new" do + it "can reach a new category" do + get new_category_path + must_respond_with :success + end + end + + describe "create" do + it "Can create a new category" do + proc { + post categories_path, params: {category: {name: "socks"} } + }.must_change 'Category.count', 1 + + must_respond_with :redirect + must_redirect_to categories_path + end + + + it "does not create a new category if a duplicate category is entered" do + proc { + post categories_path, params: {category: {name: "shoes"} } + }.must_change 'Category.count', 0 + + must_respond_with :success + + end + end + + describe "edit" do + it "should be able to successfully update a category name" do + put category_path( categories(:shoes) ), params: { category: { name: "footwear" } } + + updated_category = Category.find( categories(:shoes).id ) + + updated_category.name.must_equal "footwear" + + must_redirect_to categories_path + end + end + + describe "destroy" do + it "succeeds for an extant category ID" do + category_id = Category.first.id + + delete category_path(category_id) + must_redirect_to categories_path + + # The category should really be gone + Category.find_by(id: category_id).must_be_nil + end + end +end diff --git a/test/controllers/items_controller_test.rb b/test/controllers/items_controller_test.rb new file mode 100644 index 0000000000..5afc0d2f5f --- /dev/null +++ b/test/controllers/items_controller_test.rb @@ -0,0 +1,88 @@ +require "test_helper" + +describe ItemsController do + describe "Index" do + it "should get index" do + get items_path + must_respond_with :success + end + end + + describe "show" do + it "should be able to show an item" do + get item_path(items(:converse_no_order).id) + must_respond_with :success + end + + it "Cannot show an Item that does not exist" do + item_id = Item.last.id + 1 + get item_path(item_id) + + # must_respond_with :not_found + must_respond_with :redirect + must_redirect_to root_path + + + end + end + + describe "New" do + it "should get new" do + get new_item_path + must_respond_with :success + end + end + + + # TODO + describe "Create" do + it "Should be able to create a new item" do + proc { + post create_item_path, params: {item: {shipping_status: false, purchase_status: false, product_id: products[:converse].id, order_id: nil }}}.must_change 'Item.count', 1 + + must_respond_with :redirect + must_redirect_to root_path + + end + end + + describe "Create" do + it "Should be able to create a new item" do + + # user = users(:carl) + # log_in(user, :github) + + proc { + post create_item_path(products(:converse).id) }.must_change 'Item.count', 1 + + must_respond_with :redirect + must_redirect_to root_path + + end + + it "should respond with bad request if you try to make an item with bad data" do + post create_item_path("not good") + + must_respond_with :bad_request + end + end + + + describe "Destroy" do + it "Should be able to delete an item" do + proc { + delete item_path(products(:converse).id)}.must_change 'Item.count', -1 + + must_respond_with :redirect + must_redirect_to root_path + end + + it "should respond with bad request if there are no items to destroy for that item" do + product = products(:out_of_stock) + start_count = Item.count + delete item_path(product.id) + must_respond_with :bad_request + Item.count.must_equal start_count + end + end +end diff --git a/test/controllers/main_page_controller_test.rb b/test/controllers/main_page_controller_test.rb new file mode 100644 index 0000000000..052e518a77 --- /dev/null +++ b/test/controllers/main_page_controller_test.rb @@ -0,0 +1,9 @@ +require "test_helper" + +describe MainPageController do + it "should get index" do + get main_page_path + must_respond_with :success + end + +end diff --git a/test/controllers/order_products_controller_test.rb b/test/controllers/order_products_controller_test.rb new file mode 100644 index 0000000000..53aebb8af1 --- /dev/null +++ b/test/controllers/order_products_controller_test.rb @@ -0,0 +1,173 @@ +require "test_helper" + +describe OrderProductsController do + # let(:entry) = {order_products(:mias_pending_products) } + describe "ship" do + it "should return 404 if entry does not exist" do + + post ship_path(100000) + must_respond_with :not_found + end + it "should return 404 if the items for that entry are already shipped" do + shipped_order = orders(:shipped_order) + product = products(:chocolate) + one_single_chocolate = Item.new + one_single_chocolate.order = shipped_order + one_single_chocolate.product = product + one_single_chocolate.shipping_status = true + one_single_chocolate.save + entry = OrderProduct.new + entry.product = product + entry.order = shipped_order + entry.quantity = 1 + entry.save + # binding.pry + post ship_path(entry.id) + must_respond_with :not_found + end + it "should redirect to order_fulfillment if successful" do + shipped_order = orders(:shipped_order) + product = products(:chocolate) + one_single_chocolate = Item.new + one_single_chocolate.order = shipped_order + one_single_chocolate.product = product + one_single_chocolate.save + entry = OrderProduct.new + entry.product = product + entry.order = shipped_order + entry.quantity = 1 + entry.save + + post ship_path(entry.id) + must_respond_with :redirect + end + + it "should respond with success if items get shipped" do + shipped_order = orders(:shipped_order) + product = products(:chocolate) + one_single_chocolate = Item.new + one_single_chocolate.order = shipped_order + one_single_chocolate.product = product + one_single_chocolate.save + entry = OrderProduct.new + entry.product = product + entry.order = shipped_order + entry.quantity = 1 + entry.save + + post ship_path(entry.id) + assert_redirected_to order_fulfillment_path + end + + it "should redirect to order fulfillment path if shipping an order without items" do + entry = order_products(:entry_without_items) + + post ship_path(entry.id) + must_respond_with :redirect + flash[:result_text].must_equal "There was an error with updating entry #{entry.id}. There are no items associated with this order. Sorry." + end + + end + # describe "create" do + # # i think we never use this lol + # it "creates an orderproduct with valid data for an order" do + # product = products(:converse) + # get root_path + # start_count = OrderProduct.count + # get product_path(product.id) + # # order = orders(:mias_pending_order) + # # entry_data = { + # # id: + # # } + # # } + # # start_count = OrderProduct.count + # + # post order_products_path + # must_respond_with :redirect + # + # OrderProduct.count.must_equal start_count + 1 + # end + # end + + describe "update" do + it "succeeds for valid data and an existing order id" do + entry = order_products(:existing_tea_entry) + # first_quantity = entry.quantity + entry_data = { + order_product: { + quantity: 2 + } + } + + patch order_product_path(entry.id), params: entry_data + must_redirect_to cart_path + + # Verify the DB was really modified + OrderProduct.find(entry.id).quantity.must_equal entry_data[:order_product][:quantity] + end + + it "should render 404 for fake entry" do + patch order_product_path("fake_entry") + must_respond_with :not_found + end + + it "shouldn't accept strings as input" do + entry = order_products(:existing_tea_entry) + # first_quantity = entry.quantity + entry_data = { + order_product: { + quantity: "hey what is this" + } + } + + patch order_product_path(entry.id), params: entry_data + flash[:result_text].must_equal "Could not update #{entry.product.name}. Make sure you are entering a number greater than 0. If you wanted to delete it, click delete from cart." + must_respond_with :bad_request + end + + it "shouldn't accept 0 as input" do + entry = order_products(:existing_tea_entry) + # first_quantity = entry.quantity + entry_data = { + order_product: { + quantity: 0 + } + } + + patch order_product_path(entry.id), params: entry_data + flash[:result_text].must_equal "Could not update #{entry.product.name}. Make sure you are entering a number greater than 0. If you wanted to delete it, click delete from cart." + must_respond_with :bad_request + end + end + describe "destroy" do + it "AuthUser: should succeed for an extant Order Product" do + user = users(:mia) + log_in(user, :github) + get root_path + get cart_path + entry = order_products(:mias_pending_products).id + delete order_product_path(entry) + must_respond_with :redirect + end + it "should succeed for an existant orderproduct" do + entry = order_products(:existing_tea_entry) + + delete order_product_path(entry.id) + must_redirect_to cart_path + + OrderProduct.find_by(id: entry.id).must_be_nil + + end + + it "should render 404 and not update the database for fake orderproduct" do + start_count = OrderProduct.count + + delete order_product_path("fake thing") + delete order_product_path(938408) + + must_respond_with :not_found + OrderProduct.count.must_equal start_count + end + end + +end diff --git a/test/controllers/orders_controller_test.rb b/test/controllers/orders_controller_test.rb new file mode 100644 index 0000000000..a9bc7f97f0 --- /dev/null +++ b/test/controllers/orders_controller_test.rb @@ -0,0 +1,124 @@ +require "test_helper" + +describe OrdersController do + describe "view" do + it "should successfully let an auth user to view billing data info for an order" do + user = users(:carl) + log_in(user, :github) + pending_order = orders(:mias_pending_order) + get view_order_path(pending_order.id) + must_respond_with :success + end + + it "should render 404 for a guest" do + pending_order = orders(:mias_pending_order) + get root_path + get view_order_path(pending_order.id) + must_respond_with :not_found + end + it "should render 404 for a user without access" do + user = users(:no_access) + log_in(user, :github) + pending_order = orders(:mias_pending_order) + get root_path + + get view_order_path(pending_order.id) + must_respond_with :not_found + end + end + describe "show" do + # GM: how to test instance variables ?? )-': + it "should find cart" do + user = users(:mia) + log_in(user, :github) + get cart_path + # assigns(:cart) + # assigns(:cart).must_equal orders(:mias_pending_order) + must_respond_with :success + end + end + describe "checkout" do + it "should be successful with a valid order" do + user = users(:mia) + log_in(user, :github) + get root_path + session[:pending_order_id].must_equal orders(:mias_pending_order).id + get checkout_path + must_respond_with :success + end + + it "should change available_items for a product" do + user = users(:mia) + log_in(user, :github) + get root_path + session[:pending_order_id].must_equal orders(:mias_pending_order).id + previous = products(:converse).num_available + get checkout_path + + result = Product.find(products(:converse).id).num_available + + result.must_equal (previous - 1) + end + it "should respond with an error if the product's stock no longer matches the entry" do + user = users(:mia) + log_in(user, :github) + get root_path + session[:pending_order_id].must_equal orders(:mias_pending_order).id + product = products(:converse) + product.items.each do |item| + item.purchase_status = true + item.order_id = orders(:out_of_stock).id + item.save + end + get checkout_path + must_respond_with :bad_request + flash[:result_text].must_include "There was an error; you could not be checked out at this time" + end + end + + + + # it "should post to add_product" do + # product = products(:converse) + # # user = users(:mia) + # # log_in(user, :github) + # proc { + # post add_product_path(product.id) + # }.must_change 'OrderProduct.count', 0 + # must_respond_with :redirect + # must_redirect_to root_path + # flash[:result_text].must_equal "Could not add that product to your cart" + # + # + # end + # it "should get show" do + # get orders_show_url + # value(response).must_be :success? + # end + # + # it "should get edit" do + # get orders_edit_url + # value(response).must_be :success? + # end + # + # it "should get update" do + # get orders_update_url + # value(response).must_be :success? + # end + # + # it "should get new" do + # get orders_new_url + # value(response).must_be :success? + # end + # + # it "should get create" do + # get orders_create_url + # value(response).must_be :success? + # end + # + # it "should get destroy" do + # get orders_destroy_url + # value(response).must_be :success? + # end + +end diff --git a/test/controllers/products_controller_test.rb b/test/controllers/products_controller_test.rb new file mode 100644 index 0000000000..fe7f4ce967 --- /dev/null +++ b/test/controllers/products_controller_test.rb @@ -0,0 +1,255 @@ +require "test_helper" +#IF IT'S COMMENTED OUT, IT'S FAILING! +describe ProductsController do + describe "index" do + it "can display a list of all products available on the website" do + get products_path + must_respond_with :success + end + + it "can display index page with no products" do + #not destroying products! + OrderProduct.destroy_all + OrderProduct.count.must_equal 0 + + Item.destroy_all + Item.count.must_equal 0 + + Product.destroy_all + Product.count.must_equal 0 + + get products_path + must_respond_with :success + end + + # + describe "Show" do + it "shows an existing product" do + get product_path(products(:converse)) + must_respond_with :success + end + + # + it "responds with 404 for non-existing product" do + get product_path(Product.last.id + 1) + must_respond_with :not_found + end + + it "users cannot leave reviews for their products" do + user = users(:carl) + log_in(user, :github) + + get product_path(products(:converse).id) + + controller.instance_variable_get("@current_user_is_not_product_owner").must_equal false + + end + end + + + + describe "edit" do + it "logged in owner can see an edit form for their product " do + user = users(:carl) + log_in(user, :github) + session[:user_id].must_equal user.id + get edit_product_path(products(:converse)) + must_respond_with :success + end + + + # it "responds with 404 for non-existing product" do + # get product_path(Product.last.id + 1) + # must_respond_with :bad_request + # end + + + it "must be the creator of a product to edit it" do + get edit_product_path(products(:converse)) + must_respond_with :not_found + end + + it "does not produce an edit form for a product a user doesn't own" do + user = users(:mia) + log_in(user, :github) + + get edit_product_path(products(:converse)) + must_respond_with :not_found + end + + + it "does not produce an edit form for bogus data" do + user = users(:carl) + log_in(user, :github) + nonexistant_data = Product.last.id + 1 + + get edit_product_path(nonexistant_data) + must_respond_with :not_found + end + end + + + describe "update" do + it "a product cannot be updated, except by the owner" do + product = products(:converse) + product_datum = { + product: { + name: product.name + " updated" + } + } + patch product_path(product), params: product_datum + must_respond_with :not_found + end + + it "can update an existing work with valid data" do + user = users(:carl) + log_in(user, :github) + product = products(:converse) + product_datum = { + product: { + name: product.name + " updated" + } + } + patch product_path(product), params: product_datum + end + + it "cannot update a work that does not exist" do + user = users(:carl) + log_in(user, :github) + product = (Product.last.id + 1) + product_datum = { + product: { + name: "Name updated" + } + } + patch product_path(product), params: product_datum + must_respond_with :not_found + end + end + + describe "new" do + it "it should get a new form when a user is logged in" do + log_in(users(:carl), :github) + get new_product_path + must_respond_with :success + end + + it "shouldn't get a new product form when no user is logged in" do + get new_product_path + must_respond_with 404 + end + end + + describe "create" do + it "should create a new product when given valid data" do + user = users(:carl) + log_in(user, :github) + + product_data = { + product: { + name: "God Ugly Converse", + price: 99, + description: "Great pink shoes!", + user_id: user.id + } + } + post products_path, params: product_data + must_respond_with :redirect + must_redirect_to profile_path(user) + end + + it "should throw an error when not given valid data" do + user = users(:carl) + log_in(user, :github) + product_data = { + product: { + name: "God Ugly Converse", + price: 99, + user_id: user.id + } + } + + + nil_product = product_data.deep_dup + + product_data[:product].each do |key, value| + nil_product = product_data.deep_dup + nil_product[:product][key] = nil + post products_path, params: nil_product + must_respond_with :bad_request + end + end + + it "should throw 404 when no user is logged in" do + user = users(:carl) + product_data = { + product: { + name: "God Ugly Converse", + price: 99, + description: "Great pink shoes!", + user_id: user.id + } + } + post products_path, params: product_data + must_respond_with :not_found + end + end + + describe "change_visibility" do + it "allows a user to change the visibility of a product they own" do + user = users(:carl) + log_in(user, :github) + + product = products(:flats) + + product.visibility.must_equal true + + post change_visibility_path(product.id) + product = Product.find_by(id: product.id) + #fixtures is weird and needs scaffolding. hence line 190 + product.visibility.must_equal false + end + end + + describe "add_to_order" do + it "should change number of order products" do + user = users(:mia) + product = products(:converse) + log_in(user, :github) + + proc { + post products_path(product.id), params: {quantity: "3"} + }.must_change 'OrderProduct.count', 1 + end + + it "should add an orderproduct to current pending order for auth user" do + user = users(:mia) + product = products(:converse) + quantity_data = { + quantity: "5" + } + + start_count = OrderProduct.count + # pending_order = orders(:mias_pending_order) + + log_in(user, :github) + + get product_path(product.id) + pending_order = Order.find(session[:pending_order_id]) + # session[:pending_order_id].must_equal pending_order.id + + post product_path(product.id), params: quantity_data + + + OrderProduct.count.must_equal (start_count + 1) + pending_order.order_products.length.must_equal 2 + + pending_order.order_products.each do |entry| + entry.product_id.must_equal product.id + entry.order_id.must_equal pending_order.id + end + end + + end + end +end diff --git a/test/controllers/reviews_controller_test.rb b/test/controllers/reviews_controller_test.rb new file mode 100644 index 0000000000..a8c18f03e2 --- /dev/null +++ b/test/controllers/reviews_controller_test.rb @@ -0,0 +1,33 @@ + +require "test_helper" + +describe ReviewsController do + describe "Guest (Unauthenticated)" do + describe "NEW" do + let(:product) { products(:converse) } + + it "Should be able to get to the new review form" do + get new_review_path(product) + must_respond_with :success + end + end + + describe "CREATE" do + it "Guests can leave reviews for any product" do + proc { + post reviews_path, params: {review: {text: "sample review", rating: 5, user_id: nil, product_id: products(:converse).id } } + }.must_change 'Review.count', 1 + + must_respond_with :redirect + must_redirect_to product_path(products(:converse).id) + end + + it "If correct info is not provided, render new" do + r = reviews(:one) + r.valid? + r.rating = 10 + r.valid?.must_equal false + end + end + end +end diff --git a/test/controllers/sessions_controller_test.rb b/test/controllers/sessions_controller_test.rb new file mode 100644 index 0000000000..c527cc5dea --- /dev/null +++ b/test/controllers/sessions_controller_test.rb @@ -0,0 +1,41 @@ +require "test_helper" + +describe SessionsController do + describe "auth_callback" do + it "should log in an existing user and redirects them back to the homepage" do + start_count = User.count + user = users(:carl) + + #Action + log_in(user, :github) + #Assert + must_respond_with :redirect + must_redirect_to root_path + User.count.must_equal start_count + session[:user_id].must_equal user.id + end + + it "can log in a new user" do + start_count = User.count + user = User.new username: "Greg", provider: 'github', email: 'RapMonster@naver.com' + user.uid = 901 + log_in(user, :github) + + #Assert + must_respond_with :redirect + must_redirect_to root_path + User.count.must_equal (start_count + 1) + saved_user = User.find_by(username: "Greg") + session[:user_id].must_equal saved_user.id + end + + it "can log a user out" do + log_in(users(:carl), :github) + session[:user_id].must_equal users(:carl).id + + get logout_path + must_respond_with :redirect + must_redirect_to root_path + end + end +end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb new file mode 100644 index 0000000000..f25d02d12c --- /dev/null +++ b/test/controllers/users_controller_test.rb @@ -0,0 +1,102 @@ +require "test_helper" + +describe UsersController do + describe "order_fulfillment" do + it "should get order_fulfillment page for logged in user" do + user = users(:mia) + log_in(user, :github) + + get order_fulfillment_path + + must_respond_with :success + + end + it "should respond with an error if not logged in " do + get order_fulfillment_path + + must_respond_with :not_found + end + #GM how to test instance variables )-': + it "should populate with entries with user has sold products" do + user = users(:sophie_no_pending_order) + log_in(user, :github) + + get order_fulfillment_path + + must_respond_with :success + end + end + describe "INDEX" do + it "should get index" do + get users_path + must_respond_with :success + end + end + + describe "SHOW" do + it "should get show" do + get user_path(users(:carl).id) + must_respond_with :success + end + + + it "Cannot show a user that doesnt exist" do + # User.last gives the user with the highest ID + user_id = User.last.id + 1 + get user_path(user_id) + # must_respond_with :not_found + + must_respond_with :redirect + must_redirect_to root_path + end + end + + describe "profile" do + it "auth users should successfully get profile_path" do + user = users(:mia) + log_in(user, :github) + get profile_path + must_respond_with :success + end + it "should respond with 404 for guests" do + get profile_path + must_respond_with :not_found + end + end + + + # it "should successfully create a new user" do + # #GM: Should users be successfully created through user controller? + # #Or should this be limited to sessions#login? + # proc { + # post users_path, params: {users: {username: "Test", email: "test@test.com"}}}.must_change 'User.count', 1 + # + # must_respond_with :redirect + # must_redirect_to root_path + # end + # + # it "should be able to update a user" do + # log_in(users(:carl), :github) + # put user_path(users(:carl)), params: {user: {username: "Karl"} } + # user = User.find(users(:carl).id) + # user.username = "Karl" + # user.username.must_equal "Karl" + # + # must_respond_with :redirect + # must_redirect_to root_path + # end + + + + # it "Should be able to delete a user" do + # proc { + # delete user_path(users(:carl).id)}.must_change 'User.count', - 1 + # + # must_respond_with :redirect + # must_redirect_to root_path + # end + + + # it "should get edit" do + # end +end diff --git a/test/fixtures/.keep b/test/fixtures/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/billing_data.yml b/test/fixtures/billing_data.yml new file mode 100644 index 0000000000..60378ff2d9 --- /dev/null +++ b/test/fixtures/billing_data.yml @@ -0,0 +1,33 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +carl_billing_datum: + email: carl@carlcarle.com + mailing_address: 4223 Carl Street, Seattle, Washington 98112 + credit_card_name: Carl Carle + credit_card_number: 2423 2211 3231 2121 + credit_card_cvv: 344 + billing_zip_code: 98112 + expiration_date: 1111 + user_id: carl + +mia_billing_datum: + email: mia@mommamia.com + mailing_address: 2929 Mia Street, Tacoma, Washington 02020 + credit_card_name: Momma Mia + credit_card_number: 2392 2932 1010 2020 + credit_card_cvv: 232 + billing_zip_code: 02020 + expiration_date: 1111 + user_id: mia + + +guest_billing_datum: + email: star@lightbright.com + mailing_address: 2929 StarLight Street, Tacoma, Washington 02020 + credit_card_name: StarLight StarBright + credit_card_number: 2392 2932 1010 2020 + credit_card_cvv: 232 + billing_zip_code: 02020 + expiration_date: 12/1/2025 + expiration_date: 1111 + user_id: diff --git a/test/fixtures/categories.yml b/test/fixtures/categories.yml new file mode 100644 index 0000000000..b177015f11 --- /dev/null +++ b/test/fixtures/categories.yml @@ -0,0 +1,10 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +clothes: + name: clothes + +shoes: + name: shoes + +music: + name: music diff --git a/test/fixtures/categories_products.yml b/test/fixtures/categories_products.yml new file mode 100644 index 0000000000..aece7da884 --- /dev/null +++ b/test/fixtures/categories_products.yml @@ -0,0 +1,8 @@ + +one: + category_id: converse + product_id: shoes + +two: + category_id: converse + product_id: clothes diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/fixtures/items.yml b/test/fixtures/items.yml new file mode 100644 index 0000000000..8171e53e67 --- /dev/null +++ b/test/fixtures/items.yml @@ -0,0 +1,46 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +converse_no_order: + shipping_status: false + purchase_status: false + product: converse + order: one + +converse_shipped_one: + shipping_status: true + purchase_status: false + product: converse + order: two + +converse_shipped_two: + shipping_status: true + purchase_status: false + product: converse + order: two + +converse_ordered: + shipping_status: false + purchase_status: true + product: converse + order: two + +flats_no_order: + shipping_status: false + purchase_status: false + product: flats + order: + +flats_ordered_shipped: + shipping_status: true + purchase_status: true + product: flats + order: two + +tea_1: + product: sleepytime + +tea_2: + product: sleepytime + +tea_3: + product: sleepytime diff --git a/test/fixtures/order_products.yml b/test/fixtures/order_products.yml new file mode 100644 index 0000000000..4f07025930 --- /dev/null +++ b/test/fixtures/order_products.yml @@ -0,0 +1,57 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + quantity: 2 + product: converse + order: one + +two: + quantity: 1 + product: flats + order: four + +three: + quantity: 2 + product: converse + order: two + +four: + quantity: 5 + product: flats + order: guest_pending_order + +mias_pending_products: + quantity: 1 + product: converse + order: mias_pending_order + +guest_pending_products: + quantity: 1 + product: pencil + order: guest_pending_order + +pencil_paid_order: + quantity: 1 + product: pencil + order: paid_order + +guest_pencil_paid_order: + quantity: 100 + product: pencil + order: guest_paid_order + + +existing_tea_entry: + quantity: 1 + product: sleepytime + order: guest_sleepytime_order + +entry_without_items: + quantity: 1 + product: out_of_stock + order: out_of_stock + +guest2_paid_order: + quantity: 1 + product: sleepytime + order: guest2_paid_order diff --git a/test/fixtures/orders.yml b/test/fixtures/orders.yml new file mode 100644 index 0000000000..2781a7bfea --- /dev/null +++ b/test/fixtures/orders.yml @@ -0,0 +1,78 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + order_status: pending + user_id: carl + billing_datum_id: one + session_id: orderone + +two: + order_status: paid + user_id: mia + billing_datum_id: two + session_id: ordertwo + +three: + order_status: shipped + user_id: carl + billing_datum_id: one + session_id: orderthree + +four: + order_status: canceled + user_id: + billing_datum_id: three + session_id: orderfour + +pending_order: + order_status: pending + user: carl + billing_datum_id: + session_id: orderpending_order + +paid_order: + order_status: paid + user: mia + billing_datum: mia_billing_datum + session_id: orderpaid_order + +shipped_order: + order_status: shipped + user: carl + billing_datum: one + session_id: ordershipped_order + +canceled_order: + order_status: canceled + user: + billing_datum: three + session_id: ordercanceled_order + +guest_pending_order: + order_status: pending + user_id: + billing_datum: + session_id: orderguest_pending_order + +mias_pending_order: + order_status: pending + user: mia + billing_datum: mia_billing_datum + session_id: ordermias_pending_order + +guest_paid_order: + order_status: paid + user_id: + billing_datum: guest_billing_datum + session_id: guest_paid_order + +guest_sleepytime_order: + session_id: "it's sleepy" + +out_of_stock: + session_id: "out of stock order no items" + +guest2_paid_order: + order_status: paid + billing_datum: guest_billing_datum + session_id: guest2_paid_order diff --git a/test/fixtures/products.yml b/test/fixtures/products.yml new file mode 100644 index 0000000000..505ff75bad --- /dev/null +++ b/test/fixtures/products.yml @@ -0,0 +1,51 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +converse: + name: converse + price: 10 + description: some black converses + user: carl + +flats: + name: flats + price: 9 + description: a pair of yellow flats + user: carl + visibility: true + +coffee: + name: coffee + price: 3 + description: it's coffee + user: carl + +pencil: + name: blackwing pencil + price: 5 + description: it's a pencil + user: carl + +chocolate: + name: dark chocolate + price: 200 + description: it's good + user: sophie_no_pending_order + + +sleepytime: + name: sleepytime + price: 2.50 + description: it's sleepytime + user: sophie_no_pending_order + +out_of_stock: + name: it's out_of_stock + price: 100 + description: too bad + user: sophie_no_pending_order + +lamp: + name: lamp + price: 300 + description: let there be light + user: carl diff --git a/test/fixtures/reviews.yml b/test/fixtures/reviews.yml new file mode 100644 index 0000000000..c1ad5d28bc --- /dev/null +++ b/test/fixtures/reviews.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + text: + rating: 4 + user_id: mia + product_id: converse + +two: + text: A good product + rating: 5 + user_id: carl + product_id: flats diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000000..43cc8a376d --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,21 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +carl: + username: carl carle + email: carl@carlcarle.me + uid: 100 + +mia: + username: momma mia + email: mia@mommamia.com + uid: 200 + +sophie_no_pending_order: + username: s0phie + email: sophie@sophie.net + uid: 300 + +no_access: + username: who + email: email + uid: 400 diff --git a/test/helpers/.keep b/test/helpers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/integration/.keep b/test/integration/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/mailers/.keep b/test/mailers/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/models/.keep b/test/models/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/models/billing_datum_test.rb b/test/models/billing_datum_test.rb new file mode 100644 index 0000000000..cb4bceb573 --- /dev/null +++ b/test/models/billing_datum_test.rb @@ -0,0 +1,45 @@ +require "test_helper" + +describe BillingDatum do + let(:datum) { billing_data(:carl_billing_datum) } + + it "billing data should be valid" do + datum.must_be :valid? + end + + it "Should return invalid without an email address" do + datum.valid?.must_equal true + datum.email = nil + datum.valid?.must_equal false + end + + it "Should return invalid without a mailing address" do + datum.valid?.must_equal true + datum.mailing_address = nil + datum.valid?.must_equal false + end + + it "Should return invalid without a credit card name " do + datum.valid?.must_equal true + datum.credit_card_name = nil + datum.valid?.must_equal false + end + + it "Should return invalid without a credit card number " do + datum.valid?.must_equal true + datum.credit_card_number = nil + datum.valid?.must_equal false + end + + it "Should return invalid without a credit card cvv " do + datum.valid?.must_equal true + datum.credit_card_cvv = nil + datum.valid?.must_equal false + end + + it "Should return invalid without a billing zipcode " do + datum.valid?.must_equal true + datum.billing_zip_code = nil + datum.valid?.must_equal false + end +end diff --git a/test/models/category_test.rb b/test/models/category_test.rb new file mode 100644 index 0000000000..d8f6ed5054 --- /dev/null +++ b/test/models/category_test.rb @@ -0,0 +1,19 @@ +require "test_helper" + +describe Category do + + describe "validation" do + it "should be valid" do + categories(:clothes).must_be :valid? + end + + it "should have a unique name" do + categories(:clothes).must_be :valid? + new_clothes = Category.new + new_clothes.name = "clothes" + new_clothes.save + new_clothes.valid?.must_equal false + end + end + +end diff --git a/test/models/item_test.rb b/test/models/item_test.rb new file mode 100644 index 0000000000..35fef95792 --- /dev/null +++ b/test/models/item_test.rb @@ -0,0 +1,76 @@ +require "test_helper" + +describe Item do + let(:item) { items(:converse_no_order) } + + it "item should be valid" do + item.valid?.must_equal true + end + + it "Item should be invlaid without a shipping_status" do + item.valid?.must_equal true + item.shipping_status = nil + item.valid?.must_equal false + end + + it "Item should be invlaid without a shipping_status" do + item.valid?.must_equal true + item.purchase_status = nil + item.valid?.must_equal false + end + + describe "purchase" do + it "should be truthy if successful" do + item = items(:converse_no_order) + order = orders(:mias_pending_order) + result = item.purchase(order.id) + + result.must_equal true + + + end + it "should return false with item that is already purchased" do + item = items(:converse_ordered) + order = orders(:mias_pending_order) + result = item.purchase(order.id) + + result.must_equal false + end + + end + + describe "ship" do + it "should return true if successful" do + item = items(:converse_no_order) + order = orders(:mias_pending_order) + result = item.purchase(order.id) + + result.must_equal true + + result = item.ship(order.id) + result.must_equal true + end + + it "should return false if item is not purchased" do + item = items(:converse_no_order) + order = orders(:mias_pending_order) + + result = item.ship(order.id) + + result.must_equal false + end + + it "should return false if input order id does not match it's order id" do + item = items(:converse_no_order) + order = orders(:mias_pending_order) + result = item.purchase(order.id) + + result.must_equal true + + result = item.ship("false_id") + result.must_equal false + end + + end + +end diff --git a/test/models/order_product_test.rb b/test/models/order_product_test.rb new file mode 100644 index 0000000000..9fa82516bf --- /dev/null +++ b/test/models/order_product_test.rb @@ -0,0 +1,142 @@ +require "test_helper" + +describe OrderProduct do + let(:order_product) { OrderProduct.new } + + describe "validations" do + it "requires an order_id, product_id, quantity and items_available to be valid" do + entry = OrderProduct.find_by(id: order_products(:two).id) + entry.valid?.must_equal true + end + end + + describe "relations" do + + end + + # describe "paid?" do + # it "returns true for paid orders and false for unpaid orders" do + # orders(:pending_order).paid?.must_equal false + # orders(:pending_order).order_status = "paid" + # orders(:pending_order).paid?.must_equal true + # end + # end + + + describe "items_available?" do + it "should return true if product has available inventory" do + entry = OrderProduct.find_by(id: order_products(:mias_pending_products).id) + result = entry.items_available? + result.must_equal true + end + + it "should return false if product is out of stock" do + entry = OrderProduct.find_by(id: order_products(:guest_pending_products).id) + result = entry.items_available? + result.must_equal true + entry.product.items.first.shipping_status = "true" + entry.items_available?.must_equal false + + end + end + + describe "pending?" do + it "should return true if it's order is pending" do + entry = order_products(:mias_pending_products) + result = entry.pending? + result.must_equal true + end + + it "should return false if it's order is not pending" do + entry = order_products(:pencil_paid_order) + order = entry.order + order.must_equal orders(:paid_order) + result = entry.pending? + # binding.pry + result.must_equal false + end + end + + describe "paid?" do + it "should return true if it's order is paid" do + entry = order_products(:three) + entry.order_id.must_equal orders(:two).id + result = entry.paid? + result.must_equal true + end + + it "should return false if it's order is not paid" do + entry = order_products(:mias_pending_products) + order = entry.order + order.must_equal orders(:mias_pending_order) + result = entry.paid? + # binding.pry + result.must_equal false + end + end + + describe "canceled?" do + it "should return true if it's order is canceled" do + entry = order_products(:two) + entry.order_id.must_equal orders(:four).id + result = entry.canceled? + result.must_equal true + end + + it "should return false if it's order is not canceled" do + entry = order_products(:mias_pending_products) + order = entry.order + order.must_equal orders(:mias_pending_order) + result = entry.canceled? + # binding.pry + result.must_equal false + end + end + + describe "shipped?" do + it "should return true if it's order is shipped" do + entry = order_products(:shipped_order_product) + entry.order_id.must_equal orders(:three).id + result = entry.shipped? + result.must_equal true + end + + it "should return false if it's order is not shipped" do + entry = order_products(:mias_pending_products) + order = entry.order + order.must_equal orders(:mias_pending_order) + result = entry.shipped? + # binding.pry + result.must_equal false + end + end + + describe "items_shipped?" do + it "returns true if all order_products in an order have been shipped" do + order_products(:three).items_shipped?.must_equal true + + end + + it "returns false if not all order_products in an order have not been shipped" do + order_products(:shipped_lamp).items_shipped?.must_equal false + end + end + + describe "subtotal" do + it "should return a number" do + order_products(:one).subtotal.must_be_instance_of BigDecimal + end + + it "should return the correct subtotal" do + order_products(:one).subtotal.must_equal order_products(:one).quantity * order_products(:one).product.price + end + + it "should return false if missing a quantity or price" do + # order_products(:one).quantity = 0 + # order_products(:one).subtotal.must_equal false + end + end + + + +end diff --git a/test/models/order_test.rb b/test/models/order_test.rb new file mode 100644 index 0000000000..e561cf199c --- /dev/null +++ b/test/models/order_test.rb @@ -0,0 +1,164 @@ + +require "test_helper" +require "pry" + +describe Order do + let(:order) { Order.new } + let(:order2) { Order.new } + let(:order3) { Order.new } + let(:pending_order) { orders(:pending_order)} + let(:paid_order) { orders(:paid_order) } + let(:shipped_order) { orders(:shipped_order)} + let(:canceled_order) { orders(:canceled_order)} + let(:guest_pending_order) { orders(:guest_pending_order)} + + describe "relations" do + it "has a nil user if not logged in" do + result = guest_pending_order.user + result.must_be :==, nil + + end + + it "has a user if authenticated user is logged in" do + result = pending_order.user + result.must_be_instance_of User + + end + + it "has a billing datum if paid, shipped or canceled" do + # binding.pry + order.session_id = "test session" + order.order_status = "paid" + (order.valid?).must_equal false + order.errors.must_include :billing_datum_id + order.errors[:billing_datum_id].must_equal ["is missing. Please entire valid billing information."] + order.billing_datum_id = billing_data(:guest_billing_datum).id + (order.valid?).must_equal true + order.billing_datum.must_be_instance_of BillingDatum + + + end + + it "does not need to have billing data if pending" do + order.order_status.must_equal "pending" + order.billing_datum.must_be :==, nil + order.session_id = "fake session" + order.valid?.must_equal true + + end + it "should have a collection of order_products" do + # binding.pry + order.order_products.length.must_equal 0 + paid_order.order_products.length.must_be :>, 0 + paid_order.order_products.each do |entry| + entry.must_be_instance_of OrderProduct + end + guest_pending_order.order_products.length.must_be :>, 0 + guest_pending_order.order_products.each do |entry| + entry.must_be_instance_of OrderProduct + end + end + end + + + + describe "validations" do + it "must have session_id" do + order.session_id.must_be :==, nil + order.valid?.must_equal false + end + + + it "must have an order order_status of pending, paid, shipped or canceled" do + orders.each do |test_order| + ["pending","paid", "shipped", "canceled"].must_include test_order.order_status + test_order.valid?.must_equal true + test_order.order_status = nil + test_order.valid?.must_equal false + test_order.errors.must_include :order_status + #not sure what message would be + # test_order.errors[:order_status].must_equal "something" + test_order.order_status = "" + test_order.valid?.must_equal false + test_order.order_status = 39085 + test_order.valid?.must_equal false + test_order.order_status = "pending" + test_order.valid?.must_equal true + end + + + end + + + it "new orders should have order_status of pending" do + order.order_status.must_equal "pending" + another_order = Order.new + another_order.order_status.must_equal "pending" + end + + + it "must have a user if authenticated user is logged in" do + #TODO: maybe this should be in the controller instead? + + end + + it "must have an associated billing datum if paid, shipped or canceled" do + order.session_id = "test session" + ["paid", "shipped", "canceled"].each do |test_order_status| + order.order_status = test_order_status + order.valid?.must_equal false + # binding.pry + order.billing_datum = billing_data(:guest_billing_datum) + order.valid?.must_equal true + order.billing_datum = nil + end + + end + + end + + describe "model methods" do + describe "sub_total, tax_amount and taxed_total methods" do + it "returns a number value" do + orders(:unshipped_paid_order).sub_total.must_be_instance_of BigDecimal + orders(:unshipped_paid_order).taxed_total.must_be_instance_of BigDecimal + end + + it "correctly calculates the cost of all items in an order" do + #order_products: shipped_lamp and shipped pencil + orders(:unshipped_paid_order).sub_total.must_equal 605 + end + + it "correctly calculates the cost of all items in an order WITH TAX!" do + #order_products: shipped_lamp and shipped pencil + orders(:unshipped_paid_order).taxed_total.must_equal 658.6635 + end + end + + describe "has_invalid_entries?" do + it "returns false if it has only valid entries (i.e. order_products) and true if has invalid entries" do + order = orders(:unshipped_paid_order) + order.has_invalid_entries?.must_equal false + # binding.pry + items = order.order_products.first.product.items + items.first.shipping_status = "true" + order.has_invalid_entries?.must_equal true + end + end + + describe "check_for_duplicates" do + it "returns a order_product object if there is an entry in the cart with the same user_id. otherwise it returns false" do + orders(:one).check_for_duplicates(products(:converse).id).must_be_instance_of OrderProduct + pencil_order = orders(:guest_pending_order) + result = pencil_order.check_for_duplicates(products(:converse).id) + result.must_equal false + end + + + end + + end + + + +end diff --git a/test/models/product_test.rb b/test/models/product_test.rb new file mode 100644 index 0000000000..2fb51a1cbd --- /dev/null +++ b/test/models/product_test.rb @@ -0,0 +1,63 @@ +require "test_helper" + +describe Product do + let(:converse) { products(:converse) } + let(:coffee) { products(:coffee) } + + describe "available_items" do + it "should give an array" do + converse.available_items.must_be_instance_of Array + converse.available_items.length.must_equal 1 + end + it "should return false if none are available" do + coffee.available_items.must_equal false + end + + end + + describe "num_available" do + it "should return a number of items available" do + converse.num_available.must_equal 1 + + end + it "should return 0 if no items are available" do + coffee.num_available.must_equal 0 + + end + end + it "A product should be valid when given complete data" do + converse.valid?.must_equal true + end + + it "A product must have a name to be valid" do + converse.name = nil + converse.valid?.must_equal false + end + + it "A product must have a unique name to be valid" do + converse.name = "flats" + converse.valid?.must_equal false + end + + it "A product must have a numeric price to be valid" do + converse.price = nil + converse.valid?.must_equal false + + converse.price = 9 + converse.valid?.must_equal true + + converse.price = "nine" + converse.valid?.must_equal false + end + + it "Must have an associated user id" do + converse.user = nil + converse.valid?.must_equal false + end + + describe "relationship to items" do + it "can have many items" do + + end + end +end diff --git a/test/models/review_test.rb b/test/models/review_test.rb new file mode 100644 index 0000000000..cfe3a2dbad --- /dev/null +++ b/test/models/review_test.rb @@ -0,0 +1,9 @@ +# require "test_helper" +# +# describe Review do +# let(:review) { Review.new } +# +# it "must be valid" do +# value(review).must_be :valid? +# end +# end diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 0000000000..a59ac8b493 --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,122 @@ +require "test_helper" + +describe User do + let(:user) { User.new } + let(:carl) { users(:carl) } + + describe "merchant_entries" do + it "should return an array" do + result = carl.merchant_entries + result.must_be_instance_of Array + end + + it "everything in the array should be an OrderProduct" do + result = carl.merchant_entries + result.each do |entry| + entry.must_be_instance_of OrderProduct + end + end + + it "every order should have product tied to merchant" do + result = carl.merchant_entries + # binding.pry + result.each do |entry| + [products(:converse), products(:flats), products(:coffee), products(:pencil), products(:lamp)].must_include entry.product + end + end + + it "every entry should be tied to an order that is not pending" do + result = carl.merchant_entries + failed_entries = [] + result.each do |entry| + failed_entries << entry if entry.order.order_status == "pending" + end + failed_entries.length.must_equal 0 + end + + it "returns false if there are no merchant entries" do + result = carl.merchant_entries + result.each do |entry| + entry.destroy + end + carl.merchant_entries.must_equal false + end + + end + + +describe "User Model Validity" do + + it "must be valid with username and email" do + carl.must_be :valid? + a = User.new + a.username = "Annie" + a.email = "AnnieHall@yahoo.com" + a.save.must_equal true + a.must_be :valid? + end + + it "Should return invalid without a username" do + carl.valid?.must_equal true + carl.username = nil + carl.valid?.must_equal false + end + + it "Should be invalid without an email" do + carl.valid?.must_equal true + carl.email = nil + carl.valid?.must_equal false + end + + it "Should not allow two users to have the same email" do + carl.valid?.must_equal true + new_user = User.new(username: "Mr Magoo", email: "carl@carlcarle.me") + + carl.valid?.must_equal true + new_user.valid?.must_equal false + end + + it "Username must be unique" do + carl.valid?.must_equal true + new_user = User.new(username: "carl carle", email: "sample@sample.com") + + carl.valid?.must_equal true + new_user.valid?.must_equal false + + end + + it "Can be associated with billing data" do + + end +end + +describe "find_pending_order" do + it "if a user has a single pending order, it should return one pending order" do + result = users(:mia).find_pending_order + result.must_be_instance_of Order + + end + + it "should return false if a user does not have a pending order" do + result = users(:sophie_no_pending_order).find_pending_order + result.must_equal false + end + + it "if a user has multiple pending orders, it should return one pending order" do + result = users(:carl).find_pending_order + result.must_be_instance_of Order + end + + # it "if a user has multiple pending orders, it should return a combination of the two orders" do + # + # end + # + # it "if a user has multiple pending orders, it should combine them and delete the other ones?" do + # + # end + describe "show_available" do + + end + +end +end diff --git a/test/system/.keep b/test/system/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 0000000000..f4a1ada645 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,52 @@ +require 'simplecov' +ENV["RAILS_ENV"] = "test" +require File.expand_path("../../config/environment", __FILE__) +require "rails/test_help" +SimpleCov.start + +require "minitest/rails" +# require "minitest/skip_dsl" +require "minitest/reporters" # for Colorized output + +# For colorful output! +Minitest::Reporters.use!( + Minitest::Reporters::SpecReporter.new, + ENV, + Minitest.backtrace_filter +) +require 'simplecov' +SimpleCov.start + +# To add Capybara feature tests add `gem "minitest-rails-capybara"` +# to the test group in the Gemfile and uncomment the following: +# require "minitest/rails/capybara" + +# Uncomment for awesome colorful output +# require "minitest/pride" + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + # Add more helper methods to be used by all tests here...xxx + + def setup #runs once at the beginning of testing + OmniAuth.config.test_mode = true + end + + def mock_auth_hash(user) + return { + provider: user.provider, + uid: user.uid, + info: { + email: user.email, + nickname: user.username + } + } + end + + def log_in(user, provider) + OmniAuth.config.mock_auth[:github] = OmniAuth::AuthHash.new(mock_auth_hash(user)) + get auth_callback_path(provider) + end + +end diff --git a/tmp/.keep b/tmp/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/vendor/.keep b/vendor/.keep new file mode 100644 index 0000000000..e69de29bb2