diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000..62160c7d8d Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..aa08e89ccf --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +/node_modules +/yarn-error.log + +.byebug_history +.env +.bundle + +.coverage +coverage diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..1eb5b1bbc9 --- /dev/null +++ b/Gemfile @@ -0,0 +1,78 @@ +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 'simplecov', :require => false, :group => :test +# 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 +gem 'pry-rails' +# 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 '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' + +# Use Capistrano for deployment +# gem 'capistrano-rails', group: :development + +gem 'jquery-rails' + +gem 'money' + + +gem 'foundation-rails', '~> 6.3.1' + +gem 'omniauth' +gem 'omniauth-github' + +group :development, :test do + # Call 'byebug' anywhere in the code to stop execution and get a debugger console + gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] + # Adds support for Capybara system testing and selenium driver + gem 'capybara', '~> 2.13' + gem 'selenium-webdriver' +end + +group :development do + # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. + gem 'web-console', '>= 3.3.0' + gem 'listen', '>= 3.0.5', '< 3.2' + # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring + gem 'spring' + gem 'spring-watcher-listen', '~> 2.0.0' + + gem 'dotenv-rails' +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] + +gem 'jquery-turbolinks' +group :development do + gem 'better_errors' + gem 'pry-rails' + 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..7daa132c57 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,284 @@ +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) + 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) + ffi (1.9.18-x86-mingw32) + foundation-rails (6.3.1.0) + 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 + money (5.0.0) + i18n (~> 0.4) + json + 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) + nokogiri (1.8.1-x86-mingw32) + 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) + pg (0.21.0-x86-mingw32) + pry (0.11.1) + 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.0) + 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) + tzinfo-data (1.2017.2) + tzinfo (>= 1.0.0) + 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 + x86-mingw32 + +DEPENDENCIES + better_errors + binding_of_caller + byebug + capybara (~> 2.13) + dotenv-rails + foundation-rails (~> 6.3.1) + jbuilder (~> 2.5) + jquery-rails + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + money + 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.15.4 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/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000000..299f8d4e1c Binary files /dev/null and b/app/.DS_Store differ diff --git a/app/assets/.DS_Store b/app/assets/.DS_Store new file mode 100644 index 0000000000..6ccb3ec1b1 Binary files /dev/null and b/app/assets/.DS_Store differ 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/.DS_Store b/app/assets/images/.DS_Store new file mode 100644 index 0000000000..75d69909ac Binary files /dev/null and b/app/assets/images/.DS_Store differ 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/BlueJay.jpg b/app/assets/images/BlueJay.jpg new file mode 100755 index 0000000000..9939709246 Binary files /dev/null and b/app/assets/images/BlueJay.jpg differ diff --git a/app/assets/images/Canary.jpg b/app/assets/images/Canary.jpg new file mode 100755 index 0000000000..7fd06f68e5 Binary files /dev/null and b/app/assets/images/Canary.jpg differ diff --git a/app/assets/images/Cockatoo.jpg b/app/assets/images/Cockatoo.jpg new file mode 100755 index 0000000000..71e4b1dbbc Binary files /dev/null and b/app/assets/images/Cockatoo.jpg differ diff --git a/app/assets/images/Eagle.jpg b/app/assets/images/Eagle.jpg new file mode 100755 index 0000000000..c0de1d380e Binary files /dev/null and b/app/assets/images/Eagle.jpg differ diff --git a/app/assets/images/Flamingo.jpg b/app/assets/images/Flamingo.jpg new file mode 100755 index 0000000000..07d81a9ca6 Binary files /dev/null and b/app/assets/images/Flamingo.jpg differ diff --git a/app/assets/images/Goldfinch.jpg b/app/assets/images/Goldfinch.jpg new file mode 100755 index 0000000000..cb1b9f4b61 Binary files /dev/null and b/app/assets/images/Goldfinch.jpg differ diff --git a/app/assets/images/Hawk.jpg b/app/assets/images/Hawk.jpg new file mode 100755 index 0000000000..17847ba577 Binary files /dev/null and b/app/assets/images/Hawk.jpg differ diff --git a/app/assets/images/Hummingbird.jpg b/app/assets/images/Hummingbird.jpg new file mode 100755 index 0000000000..929fccbe28 Binary files /dev/null and b/app/assets/images/Hummingbird.jpg differ diff --git a/app/assets/images/Owl.jpg b/app/assets/images/Owl.jpg new file mode 100755 index 0000000000..f9465f1cd4 Binary files /dev/null and b/app/assets/images/Owl.jpg differ diff --git a/app/assets/images/Pelican.jpg b/app/assets/images/Pelican.jpg new file mode 100755 index 0000000000..5e2b598864 Binary files /dev/null and b/app/assets/images/Pelican.jpg differ diff --git a/app/assets/images/birds.png b/app/assets/images/birds.png new file mode 100644 index 0000000000..f109c78800 Binary files /dev/null and b/app/assets/images/birds.png differ diff --git a/app/assets/images/birdsy.png b/app/assets/images/birdsy.png new file mode 100644 index 0000000000..d1fa50afa9 Binary files /dev/null and b/app/assets/images/birdsy.png differ diff --git a/app/assets/images/cart-icon.png b/app/assets/images/cart-icon.png new file mode 100644 index 0000000000..a50c021885 Binary files /dev/null and b/app/assets/images/cart-icon.png differ diff --git a/app/assets/images/phone.png b/app/assets/images/phone.png new file mode 100644 index 0000000000..facc46d7fd Binary files /dev/null and b/app/assets/images/phone.png differ diff --git a/app/assets/images/sad-bird.png b/app/assets/images/sad-bird.png new file mode 100644 index 0000000000..b7274e756f Binary files /dev/null and b/app/assets/images/sad-bird.png differ diff --git a/app/assets/images/truck-1.gif b/app/assets/images/truck-1.gif new file mode 100644 index 0000000000..bed690e3c2 Binary files /dev/null and b/app/assets/images/truck-1.gif differ diff --git a/app/assets/images/truck.png b/app/assets/images/truck.png new file mode 100644 index 0000000000..fa5143034f Binary files /dev/null and b/app/assets/images/truck.png differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000000..36ab0137bf --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,19 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's +// vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +// +//= require jquery +//= require turbolinks +//= require rails-ujs +//= require foundation +//= require_tree . + +$(function(){ $(document).foundation(); }); diff --git a/app/assets/javascripts/cable.js b/app/assets/javascripts/cable.js new file mode 100644 index 0000000000..739aa5f022 --- /dev/null +++ b/app/assets/javascripts/cable.js @@ -0,0 +1,13 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the `rails generate channel` command. +// +//= require action_cable +//= require_self +//= require_tree ./channels + +(function() { + this.App || (this.App = {}); + + App.cable = ActionCable.createConsumer(); + +}).call(this); diff --git a/app/assets/javascripts/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/main.js b/app/assets/javascripts/main.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/main.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/merchants.js b/app/assets/javascripts/merchants.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/merchants.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/order_items.js b/app/assets/javascripts/order_items.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/order_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/orders.js b/app/assets/javascripts/orders.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/orders.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/products.js b/app/assets/javascripts/products.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/products.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/reviews.js b/app/assets/javascripts/reviews.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/reviews.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/_settings.scss b/app/assets/stylesheets/_settings.scss new file mode 100644 index 0000000000..af784b6d68 --- /dev/null +++ b/app/assets/stylesheets/_settings.scss @@ -0,0 +1,620 @@ +// 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. Forms +// 20. Label +// 21. Media Object +// 22. Menu +// 23. Meter +// 24. Off-canvas +// 25. Orbit +// 26. Pagination +// 27. Progress Bar +// 28. Responsive Embed +// 29. Reveal +// 30. Slider +// 31. Switch +// 32. Table +// 33. Tabs +// 34. Thumbnail +// 35. Title Bar +// 36. Tooltip +// 37. Top Bar + +@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-weight-normal: normal; +$global-weight-bold: bold; +$global-radius: 0; +$global-text-direction: ltr; +$global-flexbox: false; +$print-transparent-backgrounds: true; + +@include add-foundation-colors; + +// 2. Breakpoints +// -------------- + +$breakpoints: ( + small: 0, + medium: 640px, + large: 1024px, + xlarge: 1200px, + xxlarge: 1440px, +); +$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; +$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-arrows: true; +$accordionmenu-arrow-color: $primary-color; +$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-slash: true; + +// 11. Button +// ---------- + +$button-padding: 0.85em 1em; +$button-margin: 0 0 $global-margin 0; +$button-fill: solid; +$button-background: $primary-color; +$button-background-hover: scale-color($button-background, $lightness: -15%); +$button-color: $white; +$button-color-alt: $black; +$button-radius: $global-radius; +$button-sizes: ( + tiny: 0.6rem, + small: 0.75rem, + default: 0.9rem, + large: 1.25rem, +); +$button-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: $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-arrow-color: $primary-color; +$drilldown-arrow-size: 6px; +$drilldown-background: $white; + +// 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-min-width: 200px; +$dropdownmenu-background: $white; +$dropdownmenu-border: 1px solid $medium-gray; + +// 19. Forms +// --------- + +$fieldset-border: 1px solid $medium-gray; +$fieldset-padding: rem-calc(20); +$fieldset-margin: rem-calc(18 0); +$legend-padding: rem-calc(0 3); +$form-spacing: rem-calc(16); +$helptext-color: $black; +$helptext-font-size: rem-calc(13); +$helptext-font-style: italic; +$input-prefix-color: $black; +$input-prefix-background: $light-gray; +$input-prefix-border: 1px solid $medium-gray; +$input-prefix-padding: 1rem; +$form-label-color: $black; +$form-label-font-size: rem-calc(14); +$form-label-font-weight: $global-weight-normal; +$form-label-line-height: 1.8; +$select-background: $white; +$select-triangle-color: $dark-gray; +$select-radius: $global-radius; +$input-color: $black; +$input-placeholder-color: $medium-gray; +$input-font-family: inherit; +$input-font-size: rem-calc(16); +$input-font-weight: $global-weight-normal; +$input-background: $white; +$input-background-focus: $white; +$input-background-disabled: $light-gray; +$input-border: 1px solid $medium-gray; +$input-border-focus: 1px solid $dark-gray; +$input-shadow: inset 0 1px 2px rgba($black, 0.1); +$input-shadow-focus: 0 0 5px $medium-gray; +$input-cursor-disabled: not-allowed; +$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out; +$input-number-spinners: true; +$input-radius: $global-radius; +$form-button-radius: $global-radius; + +// 20. 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; + +// 21. Media Object +// ---------------- + +$mediaobject-margin-bottom: $global-margin; +$mediaobject-section-padding: $global-padding; +$mediaobject-image-width-stacked: 100%; + +// 22. Menu +// -------- + +$menu-margin: 0; +$menu-margin-nested: 1rem; +$menu-item-padding: 0.7rem 1rem; +$menu-item-color-active: $white; +$menu-item-background-active: get-color(primary); +$menu-icon-spacing: 0.25rem; +$menu-item-background-hover: $light-gray; +$menu-border: $light-gray; + +// 23. Meter +// --------- + +$meter-height: 1rem; +$meter-radius: $global-radius; +$meter-background: $medium-gray; +$meter-fill-good: $success-color; +$meter-fill-medium: $warning-color; +$meter-fill-bad: $alert-color; + +// 24. Off-canvas +// -------------- + +$offcanvas-size: 250px; +$offcanvas-vertical-size: 250px; +$offcanvas-background: $light-gray; +$offcanvas-shadow: 0 0 10px rgba($black, 0.7); +$offcanvas-push-zindex: 1; +$offcanvas-overlap-zindex: 10; +$offcanvas-reveal-zindex: 1; +$offcanvas-transition-length: 0.5s; +$offcanvas-transition-timing: ease; +$offcanvas-fixed-reveal: true; +$offcanvas-exit-background: rgba($white, 0.25); +$maincontent-class: 'off-canvas-content'; + +// 25. Orbit +// --------- + +$orbit-bullet-background: $medium-gray; +$orbit-bullet-background-active: $dark-gray; +$orbit-bullet-diameter: 1.2rem; +$orbit-bullet-margin: 0.1rem; +$orbit-bullet-margin-top: 0.8rem; +$orbit-bullet-margin-bottom: 0.8rem; +$orbit-caption-background: rgba($black, 0.5); +$orbit-caption-padding: 1rem; +$orbit-control-background-hover: rgba($black, 0.5); +$orbit-control-padding: 1rem; +$orbit-control-zindex: 10; + +// 26. Pagination +// -------------- + +$pagination-font-size: rem-calc(14); +$pagination-margin-bottom: $global-margin; +$pagination-item-color: $black; +$pagination-item-padding: rem-calc(3 10); +$pagination-item-spacing: rem-calc(1); +$pagination-radius: $global-radius; +$pagination-item-background-hover: $light-gray; +$pagination-item-background-current: $primary-color; +$pagination-item-color-current: $white; +$pagination-item-color-disabled: $medium-gray; +$pagination-ellipsis-color: $black; +$pagination-mobile-items: false; +$pagination-mobile-current-item: false; +$pagination-arrows: true; + +// 27. Progress Bar +// ---------------- + +$progress-height: 1rem; +$progress-background: $medium-gray; +$progress-margin-bottom: $global-margin; +$progress-meter-background: $primary-color; +$progress-radius: $global-radius; + +// 28. Responsive Embed +// -------------------- + +$responsive-embed-margin-bottom: rem-calc(16); +$responsive-embed-ratios: ( + default: 4 by 3, + widescreen: 16 by 9, +); + +// 29. 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); + +// 30. 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; + +// 31. 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; + +// 32. 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; + +// 33. 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; + +// 34. 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; + +// 35. 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; + +// 36. Tooltip +// ----------- + +$has-tip-font-weight: $global-weight-bold; +$has-tip-border-bottom: dotted 1px $dark-gray; +$tooltip-background-color: $black; +$tooltip-color: $white; +$tooltip-padding: 0.75rem; +$tooltip-font-size: $small-font-size; +$tooltip-pip-width: 0.75rem; +$tooltip-pip-height: $tooltip-pip-width * 0.866; +$tooltip-radius: $global-radius; + +// 37. 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; diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..413e194be2 --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,395 @@ +/* + * 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 + + */ + + /*green header&footer #66ad1f;*/ + /*orange nav buttons #ff8533;*/ + /*dark orange on hover #e65c00;*/ + /*yellow #ffd24d;*/ + /*green for text #009933;*/ + /*grey border #cccccc;*/ + /*grey category buttons #a6a6a6;*/ + /*dark grey for text #666666;*/ + /*very light grey status button, flash #f2f2f2;*/ + /*dark yellow on cart hover #cca300;*/ + + /** { + border: 1px solid red; + }*/ + + .page-header { + background-color: #66ad1f; + max-width: 100%; + } + + .nav a, .nav p { + margin: .5rem .1rem; + background-color: #ff8533; + font-weight: bold; + } + + .nav a:hover, .nav p:hover { + background-color: #e65c00; + } + + .cart { + margin: .5rem .1rem; + background-color: #ffd24d; + font-weight: bold; + } + +/*not working*/ + /*.cart a:hover { + background-color: #cca300; + }*/ + + .flash { + background-color: #f2f2f2; + } + + .flash p { + margin: 1rem; + } + + /*drop down menu*/ + +/* The container
- needed to position the dropdown content */ +.dropdown { + position: relative; + display: inline-block; +} + +/* Dropdown Content (Hidden by Default) */ +.dropdown-content { + display: none; + position: absolute; + right: 0; + min-width: 100%; + z-index: 100; +} + +/* Links inside the dropdown */ +.dropdown-content a { + text-decoration: none; + display: block; + color: #fff; + font-weight: bold; +} + +.dropdown-content a:first-of-type { + margin-top: 0; +} + +/* Change color of dropdown links on hover */ +.dropdown-content a:hover { + background-color: #e65c00; +} + +/* Show the dropdown menu on hover */ +.dropdown:hover .dropdown-content { + display: block; +} + +/*main page*/ + .ads { + height: 7rem; + padding: 1rem; + margin: 3% 0; + color: #fff; + font-weight: bold; + } + + .ads:first-of-type { + margin-left: 5.5%; + background-color: #ffd24d; + } + + .ads:last-of-type { + margin-right: 5.5%; + background-color: #66ad1f; + } + + .ads p { + text-align: center; + margin: 0; + } + + .ads h3 { + margin: 0; + } + + aside li img { + width: 60px; + margin-right: .5rem; + } + + aside ul { + margin: 0 0 1rem 0; + } + + aside li { + border-bottom: 1px solid #cccccc; + } + + aside li:first-of-type { + border-top: 1px solid #cccccc; + } + + .main-buttons { + width: 270px; + background-color: #ff8533; + font-weight: bold; + } + +/*product show page*/ + .show-im { + padding: 1rem 0; + text-align: center; + } + + .show-im img { + margin-top: 2rem; + } + + .show-desc { + margin-top: 1.3rem; + } + + .show-desc li { + list-style-type: none; + margin-right: 5rem; + } + + .rating { + border-bottom: 1px solid #cccccc; + } + + .green { + color: #009933; + font-weight: bold; + } + + .product { + border-bottom: 1px solid #cccccc; + } + + .media-highlight img { + margin-bottom: 1.5rem; + } + + aside li, .merchant-show li { + list-style-type: none; + } + +.product { + margin-top: 1rem; +} + +.grey { + color: red; + font-weight: bold; + margin: .3rem; +} + + footer { + height: 5rem; + margin-top: 4rem; + background-color: #66ad1f; + text-align: center; + color: #fff; + font-weight: bold; + } + + footer p { + padding: 2rem; + } + + .categories a { + margin-top: 1rem; + color: #fff; + font-weight: bold; + } + + .categories .button { + background-color: #a6a6a6; + } + + .banner { + background-color: #ccc; + } + + .banner h5 { + padding: 1rem; + text-align: center; + color: #666666; + } + +/*merchant show page*/ +.merchant-show section:last-of-type { + border-left: 1px solid #cccccc; +} + +.merchant-show li:nth-child(-n+2) { + font-weight: bold; +} + +.merchant-show li { + margin: .3rem; +} + +.merchant-show .button { + background-color: #ffd24d; + font-weight: bold; +} + +.merchant-show table th, .merchant-show table td:nth-last-child(-n+3) { + text-align: center; +} + +.merchant-show table .button { + margin: 0; +} + +.merchant-show .total { + font-weight: bold; +} + +.merchant-show .total td:first-child { + text-align: left; +} + +.merchant-show { + margin-top: 1rem; +} + +#merchant { + line-height: 1px; +} + +.show-desc form { + margin-top: 2rem; +} + +.show-desc select { + width: 100px; + margin: .5rem .1rem; + height: 40.469px; +} + + #status { + background-color: #f2f2f2; + color: #000; + width: 80px; +} + +/*reviews*/ +/*stars*/ +.zero-stars, .zero-stars a { + color: lightgrey; +} + +.one-star, .one-star a { + color: #cc0000; +} + +.two-stars, .two-stars a { + color: #ff8533; +} + +.three-stars, .three-stars a { + color: #ffcc00; +} + +.four-stars, .four-stars a { + color: #99db70; +} + +.five-stars, .five-stars a { + color: #33AC33; +} + +.reviews section { + border-bottom: 1px solid #cccccc; +} + +/*shopping cart*/ +.shopping-cart select { + width: 80px; + height: 42px; +} + +.shopping-cart li { + list-style-type: none; +} + +.shopping-cart td, .shopping-cart th { + border-bottom: 1px solid #cccccc; +} + +.shopping-cart h5 { + display: inline-block; +} + +.products { + margin-top: 1rem; +} + +.merchant-order section:first-of-type { + border-right: 1px solid #cccccc; +} + +/*404 page*/ +/*#four { + width: 100% +} +.overlay-container { + position: relative; +} + +.overlay-container .overlay { + position: absolute; + bottom: 50%; + left: 0; + right: 0; + text-align: center; + padding: 0.4rem; +} + +.overlay h1 { + font-size: 5rem; + font-weight: bolder; +}*/ + +.huge, .big, .med { + font-weight: lighter; + text-align: center; +} + +.huge { + font-size: 9rem; + padding: 0; + margin: 0; +} + +.big { + font-size: 5rem; + line-height: 5rem; +} + +.sad-bird img { + height: 400px; +} 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..2066155081 --- /dev/null +++ b/app/assets/stylesheets/foundation_and_overrides.scss @@ -0,0 +1,53 @@ +@charset 'utf-8'; + +@import 'settings'; +@import 'foundation'; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @import 'motion-ui/motion-ui'; + +// We include everything by default. To slim your CSS, remove components you don't use. + +@include foundation-global-styles; +@include foundation-grid; +@include foundation-typography; +@include foundation-button; +@include foundation-forms; +@include foundation-visibility-classes; +@include foundation-float-classes; +@include foundation-accordion; +@include foundation-accordion-menu; +@include foundation-badge; +@include foundation-breadcrumbs; +@include foundation-button-group; +@include foundation-callout; +@include foundation-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; diff --git a/app/assets/stylesheets/main.scss b/app/assets/stylesheets/main.scss new file mode 100644 index 0000000000..a0d94c17c1 --- /dev/null +++ b/app/assets/stylesheets/main.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the main 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/merchants.scss b/app/assets/stylesheets/merchants.scss new file mode 100644 index 0000000000..2327c00afe --- /dev/null +++ b/app/assets/stylesheets/merchants.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the merchants controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/order_items.scss b/app/assets/stylesheets/order_items.scss new file mode 100644 index 0000000000..584862de9b --- /dev/null +++ b/app/assets/stylesheets/order_items.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the OrderItems 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..3b0428a94e --- /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..89e2e8db07 --- /dev/null +++ b/app/assets/stylesheets/products.scss @@ -0,0 +1,3 @@ +// 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/ diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss new file mode 100644 index 0000000000..6ea2454d26 --- /dev/null +++ b/app/assets/stylesheets/reviews.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the reviews controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/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/.DS_Store b/app/controllers/.DS_Store new file mode 100644 index 0000000000..e1f29d509b Binary files /dev/null and b/app/controllers/.DS_Store differ diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb new file mode 100644 index 0000000000..c820790235 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,39 @@ +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + rescue_from ActiveRecord::RecordNotFound, :with => :render_404 + + before_action :require_login, except: [:render_404] + + + def render_404 + # render :file => "#{Rails.root}/public/404.html", :status => 404 + render :file => "../views/layouts/404.html.erb", :status => 404 + + # raise ActionController::RoutingError.new('Not Found') + end + + def require_login + @merchant = Merchant.find_by(id: session[:merchant_id]) + unless @merchant + flash[:status] = :failure + flash[:message] = "You must be logged in to do that" + redirect_to root_path + end + end + +private + def allowed_user(merchant_id) + merchant_id = merchant_id.to_i + + if session[:merchant_id] != merchant_id + flash[:status] = :failure + flash[:message] = "Failure: You cannot access account pages for other users" + redirect_to root_path + return false + else + return true + end + end + + +end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..b9a6c301b2 --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,46 @@ +class CategoriesController < ApplicationController + + def new + @category = Category.new + unless allowed_user(params[:merchant_id]) + return + end + @merchant = Merchant.find_by(id: params[:merchant_id]) + end + + def index + if params[:merchant_id] + unless allowed_user(params[:merchant_id]) + return + end + end + @categories = Category.all + @merchant = Merchant.find_by(id: params[:merchant_id]) + end + + def create + @category = Category.new(category_params) + @merchant = Merchant.find_by(id: session[:merchant_id]) + + if Category.all.find_by(name: @category.name) + flash[:status] = :failure + flash[:message] = "Category already exist" + redirect_to new_merchant_category_path(@merchant.id) + elsif @category.save + flash[:status] = :success + flash[:message] = "Successfully created category: #{@category.name}" + redirect_to merchant_categories_path(@merchant.id) + else + flash[:status] = :failure + flash[:message] = "Could not create category" + flash[:messages] = @category.errors.messages + redirect_to new_merchant_category_path(@merchant.id) + end + 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/main_controller.rb b/app/controllers/main_controller.rb new file mode 100644 index 0000000000..4e4ed12524 --- /dev/null +++ b/app/controllers/main_controller.rb @@ -0,0 +1,9 @@ +class MainController < ApplicationController + skip_before_action :require_login + + def index + @products = Product.random_products(6) + @new_products = Product.new_products(5) + @best_sellers = Product.bestseller(5) + end +end diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb new file mode 100644 index 0000000000..3bfe63b3e6 --- /dev/null +++ b/app/controllers/merchants_controller.rb @@ -0,0 +1,53 @@ +class MerchantsController < ApplicationController + skip_before_action :require_login, only: [:login, :logout] + + def show + @merchant = Merchant.find_by(id: params[:id]) + if @merchant == nil + render_404 + else + if allowed_user(@merchant.id) + @products = @merchant.products + end + end + end + + def login + auth_hash = request.env['omniauth.auth'] + + if auth_hash['uid'] + merchant = Merchant.find_by(uid: auth_hash[:uid], provider: params[:provider]) + if merchant.nil? + merchant = Merchant.from_auth_hash(params[:provider], auth_hash) + if merchant.save + flash[:status] = :success + flash[:message] = "Logged in successfully as new merchant #{merchant.username}" + else + flash[:status] = :failure + flash[:message] = "Could not log in" + end + else + if session[:merchant_id] == merchant.id + flash[:status] = :failure + flash[:message] = "You're already logged in" + else + flash[:status] = :success + flash[:message] = "Logged in successfully as existing merchant #{merchant.username}" + end + end + session[:merchant_id] = merchant.id + else + flash[:status] = :failure + flash[:message] = "Could not log in" + end + redirect_to root_path + end + + def logout + session[:merchant_id] = nil + flash[:status] = :success + flash[:message] = "Successfully logged out" + redirect_to root_path + end + +end diff --git a/app/controllers/order_items_controller.rb b/app/controllers/order_items_controller.rb new file mode 100644 index 0000000000..c8d28b9fc7 --- /dev/null +++ b/app/controllers/order_items_controller.rb @@ -0,0 +1,112 @@ +class OrderItemsController < ApplicationController + skip_before_action :require_login + + + def index + @order_items = OrderItem.where(order_id: session[:order_id]) + end + +#if you have a problem with the shopping cart right after resetting the database, try resetting you session[:order_id] = nil. + def create + #if there is already an open order, set the order_item order_id to that order. Otherwise make a new order + if session[:order_id] == nil + @order = Order.create(status: "pending") + session[:order_id] = @order.id + end + + #if an order_item for the same product already exists in the order, update that order_item by adding the new quantity to that order item. + if consoldate_order_items(session[:order_id],params[:order_item][:product_id], params[:order_item][:quantity]) + redirect_to order_items_path + return + end + + #if the request is a the first order for a shopping cart, make the orderitem and set the session_id + @order_item = OrderItem.new(order_item_params) + @order_item[:order_id] = session[:order_id] + if @order_item.save + flash[:status] = :success + flash[:message] = "Successfully added #{@order_item.product.name} to your cart" + redirect_to order_items_path + else + flash[:status] = :failure + flash[:message] = "Could not add that product to your cart" + redirect_to root_path + end + end + + + def update + @order_item = OrderItem.find(params[:id]) + @order_item.update_attributes(order_item_params) + if @order_item.save + flash[:status] = :success + flash[:message] = "Successfully updated order item" + redirect_back(fallback_location: order_items_path) + else + puts "update failed" + flash[:status] = :failure + flash[:message] = "Failed to update order item" + redirect_back(fallback_location: order_items_path) + end + end + + def destroy + #Normal case: if there is an order delete the order item + if @order_item = OrderItem.find_by(id: params[:id]) + order = @order_item.order_id + if @order_item.destroy + flash[:status] = :success + flash[:message] = "Successfully removed #{@order_item.product.name} from your cart" + other_items_in_cart = OrderItem.where(order_id: order) + redirect_to order_items_path + return + end + end + + #if the orderitem does not exists, or the delete fails for some other reason, return that you can not delete the item + flash[:status] = :failure + flash[:message] = "Problem encountered when attempting to remove this product from your cart" + redirect_to order_items_path + end + + + private + + def consoldate_order_items(order_id, product_id, quantity) + @order_items = OrderItem.where(order_id: order_id) + product_id = product_id.to_i + quantity = quantity.to_i + @order_items.each do |order_item| + if order_item.product_id == product_id + order_item.quantity += quantity + order_item.save + flash[:status] = :success + flash[:message] = "Successfully added products to your cart" + #if the user requests more items than we have in stock + if order_item.quantity > order_item.product.stock + flash[:status] = :failure + flash[:message] = "There are only #{order_item.product.stock} of that items in stock. The quanitity of #{order_item.product.name}s has been set to the max value." + order_item.quantity = order_item.product.stock + order_item.save + puts order_item.quantity + end + return true #if there was a repeat order + end + end + return false # there was not repeat order + end + + def order_item_params + return params.require(:order_item).permit(:product_id, :quantity, :status) + end + + #this is no longer nessesary but used to be useful: + # def retired? + # if @product.retired == true + # flash[:status] = :failure + # flash[:message] = "You can not order a retired item" + # redirect_to product_path(@product) + # end + # end + +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 0000000000..1799c7fe3e --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,89 @@ +class OrdersController < ApplicationController + + skip_before_action :require_login, except: [:index] + + def index + if params[:merchant_id] + unless allowed_user(params[:merchant_id]) + return + end + @merchant = Merchant.find_by(id: params[:merchant_id]) + if params[:status_id] == "paid" + @order_items = @merchant.order_items_by_status("paid") + elsif params[:status_id] == "pending" + @order_items = @merchant.order_items_by_status("pending") + else + params[:status_id] == "all" + @order_items = @merchant.order_items + end + render :merchant_orders + end + end + + def create + @order = Order.new(status: "pending") + @order.save + redirect_to orders_path + end + + def update + #binding.pry + @order = Order.find(params[:id]) + + @order.customer_name = params[:order][:customer_name] + @order.customer_email = params[:order][:customer_email] + @order.customer_address = params[:order][:customer_address] + @order.cc_number = params[:order][:cc_number] + @order.cc_expiration = params[:order][:cc_expiration] + @order.cc_ccv = params[:order][:cc_ccv] + @order.zip_code = params[:order][:zip_code] + + params[:order].each do |key, value| + if value == "" + flash[:status] = :failure + flash[:message] = "Any of required fields can't be empty" + redirect_to edit_order_path(@order) + return + end + end + + if @order.save! + flash[:status] = :success + flash[:message] = "Your order has been placed" + @order.status = "paid" + @order.save + + @order_items = OrderItem.where(order_id: "#{session[:order_id]}") + + @order.order_items.each do |item| + @product = Product.find(item.product_id) + @product.stock -= item.quantity + @product.save + end + + session[:order_id] = nil + else + flash[:status] = :failure + flash[:message] = "Something went wrong. Please place your order again" + end + end + + def edit + @order = Order.find(params[:id]) + end + + def show + @order = Order.find(params[:id]) + if params[:merchant_id] + @order_items = @order.order_items.find_all{ |order_item| order_item.merchant == Merchant.find_by(id: params[:merchant_id]) } + if @order_items.empty? + redirect_to merchant_path(params[:merchant_id]), status: :bad_request + else + render :merchant_order, status: :ok + end + #looks like we do not need this + # else + # @order_items = OrderItem.where(order_id: params[:id]) + end + end +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..db23972389 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,118 @@ +class ProductsController < ApplicationController + skip_before_action :require_login, only: [:show, :index, :index_by_merchant, :index_by_category] + + def new + @product = Product.new + end + + def create + @product = Product.new(product_params) + @product[:merchant_id] = session[:merchant_id] + @product[:retired] = false + if @product.save + flash[:status] = :success + flash[:message] = "Successfully created new product #{@product.name}, ID number #{@product.id}" + redirect_to merchant_products_path(session[:merchant_id]) + else + flash.now[:status] = :failure + flash.now[:message] = "Could not create new product #{@product.name}" + flash.now[:messages] = @product.errors.messages + render :new + end + end + + def edit + product = Product.find(params[:id]) + unless allowed_user(product.merchant.id) + return + end + @product = product + + end + + def show + @product = Product.find_by(id: params[:id]) + if @product == nil + render_404 + else + @order_item = OrderItem.new(product_id: params[:id]) + end + end + + def update + product = Product.find(params[:id]) + puts product.merchant.id + puts session[:merchant_id] + unless allowed_user(product.merchant.id) + return + end + @product = product + @product.update_attributes(product_params) + puts @product.inspect + if @product.save + flash[:status] = :success + flash[:message] = "Successfully updated #{@product.name}, ID number #{@product.id}" + redirect_to merchant_products_path(session[:merchant_id]) + else + flash.now[:status] = :failure + flash.now[:message] = "Could not updated #{@product.name}, ID number #{@product.id}" + flash.now[:messages] = @product.errors.messages + render :new, status: :bad_request + end + end + + + def index + #puts "I am in regular index" + if params[:merchant_id] + unless allowed_user(params[:merchant_id]) + return + end + end + #puts "I made it past the allowed_user check" + #puts "these are my params: #{params}" + + #The below is nessesary for the merchant user stories. + if params[:merchant_id] && params[:category_id] + #puts "I have a merchant id and a category id" + @merchant = Merchant.find_by(id: params[:merchant_id]) + @category = Category.find_by(id: params[:category_id]) + @products = @category.products.where(merchant: @merchant) + elsif params[:category_id] + #puts "I only have a category id" + category = Category.find_by(id: params[:category_id]) + @products = category.products + elsif params[:merchant_id] + puts "I only have a merchant id" + @merchant = Merchant.find_by(id: params[:merchant_id]) + @products = @merchant.products + + render :merchant_products, status: :ok + # @merchant_id = params[:merchant_id] + #merchant_id: @merchant.id + else + #puts "I got nothing" + @products = Product.all + end + end + + #if we have time, add a render 404 for bogus merchants + def index_by_merchant + @merchant = Merchant.find_by(id: params[:id]) + @products = @merchant.products + render :index + end + + #if we have time, add a render 404 for bogus categories + def index_by_category + @category = Category.find_by(id: params[:id]) + @products = @category.products + render :index + end + + private + + def product_params + params.require(:product).permit(:name, :stock, :price, :retired, :description, :image_url, category_ids: []) + end +end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..80e3fce70d --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,37 @@ +class ReviewsController < ApplicationController + + skip_before_action :require_login + + def new + @review = Review.new(product_id: params[:id]) + if restrict_merchants(@review) + flash[:status] = :failure + flash[:message] = "Failure: Merchants can not review their own products" + redirect_to product_path(@review.product) + end + end + + def create + @review = Review.new(review_params) + if @review.save + flash[:status] = :success + flash[:message] = "Successfully created new review" + redirect_to product_path(@review.product) + else + flash[:status] = :failure + flash[:message] = "Failure: Could not create new review" + flash[:messages] = @review.errors.messages + render :new, status: :bad_request + end + end + + private + + def restrict_merchants(review) + return review.product.merchant.id == session[:merchant_id] + end + + def review_params + params.require(:review).permit(:rating, :text, :product_id) + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000000..e1fa307179 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,28 @@ +module ApplicationHelper + def set_class(rating) + case rating + when 0 + "zero-stars" + when 1 + "one-star" + when 2 + "two-stars" + when 3 + "three-stars" + when 4 + "four-stars" + when 5 + "five-stars" + end + end + + def readable_date(date) + ("" + date.strftime("%b. %d, %Y %I:%M %p (%Z)") + "").html_safe + end + + def format_money(amount) + Money.new(amount, "USD").format + end + + module_function :set_class +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/main_helper.rb b/app/helpers/main_helper.rb new file mode 100644 index 0000000000..826effed96 --- /dev/null +++ b/app/helpers/main_helper.rb @@ -0,0 +1,2 @@ +module MainHelper +end diff --git a/app/helpers/merchants_helper.rb b/app/helpers/merchants_helper.rb new file mode 100644 index 0000000000..5337747b0f --- /dev/null +++ b/app/helpers/merchants_helper.rb @@ -0,0 +1,2 @@ +module MerchantsHelper +end diff --git a/app/helpers/order_items_helper.rb b/app/helpers/order_items_helper.rb new file mode 100644 index 0000000000..e197528ae1 --- /dev/null +++ b/app/helpers/order_items_helper.rb @@ -0,0 +1,2 @@ +module OrderItemsHelper +end diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb new file mode 100644 index 0000000000..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/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/category.rb b/app/models/category.rb new file mode 100644 index 0000000000..c6a8c69b0a --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,5 @@ +class Category < ApplicationRecord + has_and_belongs_to_many :products + validates :name, presence: true + validates :name, uniqueness: true +end diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/models/merchant.rb b/app/models/merchant.rb new file mode 100644 index 0000000000..b4de1740de --- /dev/null +++ b/app/models/merchant.rb @@ -0,0 +1,48 @@ +class Merchant < ApplicationRecord + has_many :products + has_many :order_items, through: :products + has_many :orders, through: :products + # has_many :orders, :through => :products + + validates :provider, presence: true + validates :uid, presence: true, uniqueness: true + validates :username, presence: true, uniqueness: true + validates :email, presence: true, uniqueness: true + + + def self.from_auth_hash(provider, auth_hash) + merchant = new + merchant.provider = provider + merchant.uid = auth_hash['uid'] + merchant.email = auth_hash['info']['email'] + merchant.username = auth_hash['info']['nickname'] + + return merchant + end + + def order_items_quantity + sum = 0 + order_items.each do | order_item | + sum += order_item.quantity + end + return sum + end + + def order_items_total + sum = 0 + order_items.each do | order_item | + sum += order_item.total + end + return sum + end + + def order_items_by_status(status) + order_items = self.order_items.find_all { |order_item| order_item.order.status == status } + return order_items + end + + def self.revenue_by_status(collection) + return collection.inject(0) { |sum, order_item| sum + order_item.total } + end + +end diff --git a/app/models/order.rb b/app/models/order.rb new file mode 100644 index 0000000000..3d6929bde6 --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,14 @@ +class Order < ApplicationRecord + + + #has_many :products + has_many :order_items + has_many :merchants, through: :products + has_many :products, through: :order_items + + validates :status, presence: true + # :customer_name, :customer_email, :customer_address, + # :cc_number,:cc_expiration, :cc_ccv, + # :zip_code, presence: true + +end diff --git a/app/models/order_item.rb b/app/models/order_item.rb new file mode 100644 index 0000000000..509af440ae --- /dev/null +++ b/app/models/order_item.rb @@ -0,0 +1,36 @@ +class OrderItem < ApplicationRecord + belongs_to :order + belongs_to :product + has_one :merchant, :through => :product + + + validates :quantity, presence: true, numericality: { only_integer: true, greater_than: 0 } + +#calculates the total cost of an order item, call it on an instance of order_item +#if we have time, choose between this and subtotal and use just one of them since they serve the same function. + def total + sum = product.price * quantity + return sum + end + +# calculates the total cost of an order_item, but you pass in the order item. +#if we have time, choose between this and subtotal and use just one of them since they serve the same function. + def self.subtotal(order_item) + result = order_item.quantity * order_item.product.price + return result + end + +# this calculates the cost of a collection of items (i.e. an order) + def self.total_cost(collection) + total = 0 + collection.each do |order_item| + total += subtotal(order_item) + end + if total < 5000 + total += 1000 + end + return total + end + + +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000000..bdf6b2223f --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,33 @@ +class Product < ApplicationRecord + + has_and_belongs_to_many :categories + belongs_to :merchant + has_many :reviews + has_many :order_items + has_many :orders, through: :order_items + + validates :name, presence: true, uniqueness: true + validates :price, presence: true + validates :price, numericality: { greater_than: 0 } + validates :stock, presence: true, numericality: { only_integer: true, greater_than: 0 } + + + def self.random_products(number) + products = Product.where(retired: false) + return products.sample(number) + end + + def self.new_products(number) + products = Product.where(retired: false) + return products.order(:created_at).reverse.first(5) + end + + def average_rating + return reviews.average(:rating).to_i + end + + def self.bestseller(number) + return Product.all.sort_by { |product| -product.orders.count }.first(number) + end + +end diff --git a/app/models/review.rb b/app/models/review.rb new file mode 100644 index 0000000000..2282e54378 --- /dev/null +++ b/app/models/review.rb @@ -0,0 +1,8 @@ +class Review < ApplicationRecord + + belongs_to :product + + validates :rating, presence: true + validates :rating, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 5, message: "Please enter a rating from 1 to 5" } + +end diff --git a/app/views/.DS_Store b/app/views/.DS_Store new file mode 100644 index 0000000000..743c2e3769 Binary files /dev/null and b/app/views/.DS_Store differ diff --git a/app/views/categories/index.html.erb b/app/views/categories/index.html.erb new file mode 100644 index 0000000000..151e77a1e9 --- /dev/null +++ b/app/views/categories/index.html.erb @@ -0,0 +1,28 @@ +
+ <%= render partial: "merchants/nav_aside" %> +
+ <%= link_to "New Product", new_product_path, class: "button" %> + <%= link_to "New Category", new_merchant_category_path, class: "button" %> + +

Available Categories

+ + + + + + + + + + <% @categories.each do |category| %> + + + + + + <% end %> + +
CategoryProductsMy Products
<%= link_to category.name, category_products_path(category.id) %><%= link_to category.products.count, category_products_path(category.id) %><%= link_to category.products.where(merchant: @merchant).count, merchant_category_products_path(@merchant.id, category.id)%>
+
+ +
diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000000..097d323c01 --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1,14 @@ +
+ <%= render partial: "merchants/nav_aside" %> + +
+

Create new category

+ + <%= form_for @category do |f| %> + <%=f.label :name %> + <%=f.text_field :name %> + + <%= f.submit class: "button cart" %> + <%end%> +
+
diff --git a/app/views/layouts/.DS_Store b/app/views/layouts/.DS_Store new file mode 100644 index 0000000000..aa87d117f8 Binary files /dev/null and b/app/views/layouts/.DS_Store differ diff --git a/app/views/layouts/404.html.erb b/app/views/layouts/404.html.erb new file mode 100644 index 0000000000..1be267d2b6 --- /dev/null +++ b/app/views/layouts/404.html.erb @@ -0,0 +1,21 @@ + + +
+
+

SORRY

+

we couldn't find that page

+

Try going to <%= link_to "Birdsy's home page", root_path %>

+
+
+ <%= image_tag('sad-bird.png') %> +
+
diff --git a/app/views/layouts/_stars.html.erb b/app/views/layouts/_stars.html.erb new file mode 100644 index 0000000000..83b8ba4247 --- /dev/null +++ b/app/views/layouts/_stars.html.erb @@ -0,0 +1,5 @@ + + <%= '★' * rating %><%= '☆' * (5 - rating) %> + diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb new file mode 100644 index 0000000000..8f3c1c0b6d --- /dev/null +++ b/app/views/layouts/application.html.erb @@ -0,0 +1,83 @@ + + + + + + + <%= content_for?(:title) ? yield(:title) : "Untitled" %> + + <%= stylesheet_link_tag "application" %> + <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> + <%= csrf_meta_tags %> + + + +
+ + + +
+ +
+ <% if !flash.empty? %> +
+ <% if flash[:message].present? %> +

<%= flash[:message] %>

+ <% end %> + <% if flash[:messages].present? %> +
    + <% flash[:messages].each do |field, problems| %> + <% problems.each do |problem| %> +
  • + <%= field %>: + + <%= problem %> +
  • + <% end %> + <% end %> +
+ <% end %> +
+ <% 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/.DS_Store b/app/views/main/.DS_Store new file mode 100644 index 0000000000..ee4fb87b16 Binary files /dev/null and b/app/views/main/.DS_Store differ diff --git a/app/views/main/_aside_products.html.erb b/app/views/main/_aside_products.html.erb new file mode 100644 index 0000000000..67278dd449 --- /dev/null +++ b/app/views/main/_aside_products.html.erb @@ -0,0 +1,5 @@ +<% products.each do |product| %> +
  • <%= link_to image_tag(product.image_url), product_path(product.id) %> + <%= link_to product.name, product_path(product.id) %> + <%= format_money(product.price) %>
  • + <% end %> diff --git a/app/views/main/_random_products.html.erb b/app/views/main/_random_products.html.erb new file mode 100644 index 0000000000..ba1581c916 --- /dev/null +++ b/app/views/main/_random_products.html.erb @@ -0,0 +1,9 @@ +<% if products.present? %> + <% products.each do |product| %> +
    + <%= link_to image_tag(product.image_url), product_path(product) %> + <%= link_to product.name, product_path(product) %> + <%= format_money(product.price) %> +
    + <% end %> +<% end %> diff --git a/app/views/main/index.html.erb b/app/views/main/index.html.erb new file mode 100644 index 0000000000..f86a1e2f91 --- /dev/null +++ b/app/views/main/index.html.erb @@ -0,0 +1,60 @@ +
    + <%= image_tag "birds.png" %> +
    + +
    + + +
    +
    + <%if @products.present? %> +
    + <%= render partial: "random_products", locals: { products: @products.first(3) } %> +
    + <%end%> +
    +
    +
    +
    + <%= image_tag "truck.png" %> +
    +
    +

    FREE SHIPPING

    +

    on order over $50

    +
    +
    +
    +
    + <%= image_tag "phone.png" %> +
    +
    +

    GIVE US A CALL

    +

    1-800-00-BIRDS

    +
    +
    +
    +
    + <%if @products.present? %> +
    + <%= render partial: "random_products", locals: { products: @products[3..-1] } %> +
    + <%end%> +
    + +
    + +
    diff --git a/app/views/merchants/_nav_aside.html.erb b/app/views/merchants/_nav_aside.html.erb new file mode 100644 index 0000000000..f970f64029 --- /dev/null +++ b/app/views/merchants/_nav_aside.html.erb @@ -0,0 +1,12 @@ +
    + <% if @merchant %> + + <% end %> +
    diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb new file mode 100644 index 0000000000..be689655de --- /dev/null +++ b/app/views/merchants/index.html.erb @@ -0,0 +1,16 @@ +

    Shop by merchant

    + + +<%unless @merchants.count == 0 %> +