+ Cart +
+-
+
- + + + +
+ Your cart is empty! +
+diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..7791f3bd5a --- /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' + +.env + +#Ignore simplecov coverage results +coverage + +# Ignore bundler config. +/.bundle + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +/node_modules +/yarn-error.log + +.byebug_history diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..02f3d64ad7 --- /dev/null +++ b/Gemfile @@ -0,0 +1,58 @@ +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 "omniauth" +gem "omniauth-github" + +gem 'rails', '~> 5.1.4' +gem 'pg', '~> 0.18' +gem 'puma', '~> 3.7' +gem 'sass-rails', '~> 5.0' +gem 'uglifier', '>= 1.3.0' + +gem 'turbolinks', '~> 5' +gem 'jbuilder', '~> 2.5' +gem 'aws-sdk', '< 3.0' +gem 'paperclip' +gem 'figaro' +gem 'will_paginate', '~> 3.1.0' + +group :development, :test do + gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] + gem 'capybara', '~> 2.13' + gem 'selenium-webdriver' + gem 'dotenv-rails' + gem 'aws-sdk', '< 3.0' + gem 'paperclip' + gem 'figaro' +end + +group :development do + gem 'web-console', '>= 3.3.0' + gem 'listen', '>= 3.0.5', '< 3.2' + gem 'spring' + gem 'spring-watcher-listen', '~> 2.0.0' +end + +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] +gem 'jquery-turbolinks' +gem 'foundation-rails', '6.4.1.2' + + +group :development do + gem 'better_errors' + gem 'pry-rails' + gem 'binding_of_caller' + gem 'rails-erd', require: false +end + +group :test do + gem 'minitest-rails' + gem 'minitest-reporters' + gem 'simplecov', :require => false +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..6e14a3d6b9 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,302 @@ +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) + aws-sdk (2.10.71) + aws-sdk-resources (= 2.10.71) + aws-sdk-core (2.10.71) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-resources (2.10.71) + aws-sdk-core (= 2.10.71) + aws-sigv4 (1.0.2) + 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) + choice (0.2.0) + climate_control (0.2.0) + cocaine (0.5.8) + climate_control (>= 0.0.3, < 1.0) + 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) + figaro (1.1.1) + thor (~> 0.14) + 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) + jmespath (1.3.1) + 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) + mimemagic (0.3.2) + 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) + paperclip (5.1.0) + activemodel (>= 4.2.0) + activesupport (>= 4.2.0) + cocaine (~> 0.5.5) + mime-types + mimemagic (~> 0.3.0) + pg (0.21.0) + 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-erd (1.5.2) + activerecord (>= 3.2) + activesupport (>= 3.2) + choice (~> 0.2.0) + ruby-graphviz (~> 1.2) + 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-graphviz (1.2.3) + 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) + 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) + will_paginate (3.1.6) + xpath (2.1.0) + nokogiri (~> 1.3) + +PLATFORMS + ruby + +DEPENDENCIES + aws-sdk (< 3.0) + better_errors + binding_of_caller + byebug + capybara (~> 2.13) + dotenv-rails + figaro + foundation-rails (= 6.4.1.2) + jbuilder (~> 2.5) + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + omniauth + omniauth-github + paperclip + pg (~> 0.18) + pry-rails + puma (~> 3.7) + rails (~> 5.1.4) + rails-erd + 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) + will_paginate (~> 3.1.0) + +BUNDLED WITH + 1.16.0.pre.3 diff --git a/README.md b/README.md index 1b10607db1..85d2877d27 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# bEtsy +# bEtsy Completed - See it here >>>> https://glitzy-store.herokuapp.com/ [b]Etsy will be an online store where a wide variety of products can be listed and sold by any user. In this project we will focus on reinforcing the major components of Rails, Model Validation, as well as introducing some more complex logic such as user authentication. This is a [Stage 3](https://github.com/Ada-Developers-Academy/pedagogy/blob/master/rule-of-three.md) project requiring you to expand upon what you have learned in class. 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/.DS_Store b/app/assets/.DS_Store new file mode 100644 index 0000000000..cd3a2cf86a 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..9ecbdb4d85 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/cart.png b/app/assets/images/cart.png new file mode 100644 index 0000000000..eacf342870 Binary files /dev/null and b/app/assets/images/cart.png differ diff --git a/app/assets/images/favicon.ico b/app/assets/images/favicon.ico new file mode 100644 index 0000000000..5bd4c429f9 Binary files /dev/null and b/app/assets/images/favicon.ico differ diff --git a/app/assets/images/glitzy_default.png b/app/assets/images/glitzy_default.png new file mode 100644 index 0000000000..c3b2f6ef7b Binary files /dev/null and b/app/assets/images/glitzy_default.png differ diff --git a/app/assets/images/shopper.jpeg b/app/assets/images/shopper.jpeg new file mode 100644 index 0000000000..73ddf04495 Binary files /dev/null and b/app/assets/images/shopper.jpeg differ diff --git a/app/assets/images/thankyou.jpeg b/app/assets/images/thankyou.jpeg new file mode 100644 index 0000000000..8b056bae8f Binary files /dev/null and b/app/assets/images/thankyou.jpeg differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000000..4f2cc0f55a --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,18 @@ +// 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 rails-ujs +//= require foundation +//= require turbolinks +//= 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/orders.js b/app/assets/javascripts/orders.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/orders.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/products.js b/app/assets/javascripts/products.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/products.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/reviews.js b/app/assets/javascripts/reviews.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/reviews.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/sessions.js b/app/assets/javascripts/sessions.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/sessions.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/static_pages.js b/app/assets/javascripts/static_pages.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/static_pages.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..23f1d8574d --- /dev/null +++ b/app/assets/stylesheets/application.scss @@ -0,0 +1,456 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any 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 foundation_and_overrides +//= require_tree . +//= require_self + */ + + #glitzy { + font-family: 'Bungee Shade', cursive; + } +/*------------------------------------*\ + $NAV +\*------------------------------------*/ + +.nav{ + list-style:none; + margin-left:0; + float:left; +} + .nav > li, + .nav > li > a{ + display:inline-block; + *display:inline; + zoom:1; + font-family: 'Raleway'; + } + + .stacked > li{ + display:list-item; + } + .stacked > li > a{ + display:block; + } + +/*------------------------------------*\ + $FLYOUT +\*------------------------------------*/ + +.flyout, +.flyout-alt{ + position:relative; +} + .flyout-content{ + /* Position the flyouts off-screen. This is typically better than `display:none;`. */ + position: absolute; + top:100%; + left:-99999px; + height:0; + overflow:hidden; + z-index: 100; + } + .flyout:hover > .flyout-content{ + left:0; + } + + .flyout:hover > .flyout-content, + .flyout-alt:hover > .flyout-content{ + /* Give the flyouts their height back once they come into view. */ + height:auto; + overflow:visible; + } +.site-nav{ + font-size:1em; + font-family:sans-serif; +} + .site-nav a{ + line-height:1; + padding:1em; + background-color: #405b7a; + color:#fff; + white-space:nowrap; + } +.site-nav .flyout:hover > a /* [1] */, +.site-nav .flyout-alt:hover > a /* [1] */, +.site-nav a:hover{ + color: white; + background-color:#d469e5; + +} +.site-nav a, +.site-nav .flyout-content{ + border: none; + background: #16ad57; +} +.site-nav > li > a{ + border: none; +} +/*------------------------------------*\ + END DROPDOWN +\*------------------------------------*/ + + .edit_order { + display: block; + box-sizing: border-box; + width: 50%; + margin: 0 0 1rem; + padding: 0.5rem; + box-shadow: inset 0 1px 2px rgba(10, 10, 10, 0.1); + font-family: inherit; + font-size: 1rem; + font-weight: bold; + line-height: 1.5; + color: #0a0a0a; + + .inputs { + opacity: 0.7; + } + + input { + font-weight: 300; + } + + label{ + font-weight: 800; + color: black ; + text-shadow: 4px 1px 6px white ; + font-family: 'Playfair Display'; + } +} + +$primary-font: 'Raleway', sans-serif; +$secondary-font:'Raleway', serif; + + +$pink: #d469e5; +$secondary-color: #405b7a; +$light-gray: #EEEEEE; +$dark-gray: #424242; +$gold: #FF5722; + +$default-border: 2px solid; + +@import url('https://fonts.googleapis.com/css?family=Raleway'); +@import url('https://fonts.googleapis.com/css?family=Leckerli+One'); +@import url('https://fonts.googleapis.com/css?family=Ubuntu'); +@import url('https://fonts.googleapis.com/css?family=Bungee+Shade'); +@import url('https://fonts.googleapis.com/css?family=Playfair+Display:700'); + +.cart { + display: inline-block; + height: 4em; + padding-bottom: 35px; +} +body, h1, h2 { + font-family: $primary-font; +} + +body, h3, h4, h5 { + font-family: $secondary-font; +} + +small { + font-family: 'Leckerli One', cursive; + text-shadow: 0 0 4px $pink; + color: white; +} + +h1, h2, h3, h4, h5 { + font-weight: bold; +} + + body small { + color: white; + } + + a, h3 { + color: black; + } + + a:hover { + color: $pink; + } + +.button { + background-color: #405b7a; + display: inline-block; + height: 3em; + margin: 2px; + font-weight: bold; + + &:hover { + background-color: $pink; + } +} +.featured-item { + font-family: 'Leckerli One'; + color: #233a75; + text-shadow: 6px 6px 10px snow; +} +.main-content { + padding-left: 20px; + padding-right: 20px; + max-height: 80vh; + overflow: scroll; + ul{ + background-color: #405b7a; + opacity: 0.8; + max-width: 500px; + height: 130px; + overflow: scroll; + border-radius: 15px; + padding: 5px; + text-decoration: none; + }li{ + color: white; + font-weight: bold; + } + h3{ + font-family: $primary-font; + color: black; + text-shadow: 6px 6px 20px snow; + } + + + + .new-product { + height: 650px; + max-width: 800px; + opacity: 0.9; + padding:20px; + label, input { + font-weight: bold; + } + .checkbox{ + display: inline-table; + margin:10px; + text-align: center; + } + .button{ + background-color: green; + } + } + + +.new-review{ + height:500px; + overflow: scroll; + max-width: 600px; + opacity: 0.9; +.button{ + background-color: green; +} +} + + .revenue { + height:200px; + max-width: 600px; + } + .user-order { + display:inline-block; + background-color: #405b7a; + padding:20px; + color: white; + opacity:0.9; + margin-top: 30px; + margin-bottom: 10px; + + strong{ + font-family: 'Playfair Display'; + font-size: 1.2em; + } + } + .bottom-buttons{ + display: table-cell; + } +} + +.cart-page li { + list-style-type: none; + text-align: left; + margin: 5px; + font-weight: bold; + color: white; + h4{ + font-family: 'Leckerli One'; + font-weight: lighter; + color: $pink; + } +} + + + +.cart-page ul { + padding-top: 20px; + padding-bottom: 20px; + border-bottom: 2px solid #405b7a; + background-color: #405b7a; + max-width: 450px; + border-radius: 15px 50px 30px; + height: 500px; + overflow: scroll; + padding-left: 25px; +} + + .page-header { + max-width: 100%; + padding: 25px 20px 10px 20px; + border-bottom: black 1px dotted; + h2 { + text-align: center; + margin: 25px auto 40px auto; + a { + color: $gold; + padding-right: 25px; + margin-right: 15px; + border-right: white 2px solid; + } + small { + color: white; + } + } + p { + margin-bottom: 5px; + } + } + + .top-ten { + h3 { + border-bottom: $default-border; + border-bottom-color: $secondary-color; + } + } + + section.spotlight > div { + padding: 0 2rem 2rem 2rem; + } + + .root-hr { + margin: 0px auto 75px auto; + color: $light-gray; + } + +main { + padding-top: 2rem; + padding-bottom: 2rem; +} + +.thank-you { + text-align: center; +} + +// products main table index + +.all-products section table { + background-color: #405b7a; + +} + +.medium-image img { + display: block; + padding: 10px; +} + +.items { + width: 400px; + height: 400px; + margin: 20px; + border: 3px solid #0c0c0c; + display: inline-table; + text-align: center; + padding: 10px; + background-color: #405b7a; + opacity: 0.9; + color: snow; + max-height: 30vh; + overflow: scroll; + +} + +.items a { + text-decoration: none; + color: white; +} + +.items img { + width: 70%; + max-height: 230px; +} + +.items img:hover { + -webkit-filter: drop-shadow(0px 0px 8px rgba(255, 255, 255, 0.8)); +} + +.home-pg { + background-color: rgba(254,245,242, 0.8); + padding: 10px; + max-width: 500px; + border-radius: 15px; + border-style: solid; + outline: none; + // border-color: #9ecaed; + border-color: white; + border-color: #FEF5F2; + box-shadow: 0 0 10px #9ecaed; + // box-shadow: 0 0 10px #FFFFFF; + box-shadow: 0px 0px 20px #9ecaed; + filter:progid:DXImageTransform.Microsoft.Glow(Color=black,Strength=20); + text-align: center; +} + +.home-pg h2, h3, .featured-item, .shop-now { + color: #34495e; + animation: fade 2s; +} + +.home p { + font-weight: bolder; + font-size: 4em; + padding-left: 20px; + animation: fade 2s +} + +.shop-now { + font-weight: bolder; + font-size: 2em; + padding-top: 15px; +} + +.home-pg article { + padding: 10px; +} + +.home-banner { + // background-color: rgba(255, 255, 255, 0.5); + padding: 20px 40px; + // border-top-style: solid; + // border-top-color: white; + // border-bottom-style: solid; + // border-bottom-color: white; + // margin-top: 34em; + +} + +.main-content h1, h2 { + padding-left: 20px; + color: #34495e; +} + +@keyframes fade { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} diff --git a/app/assets/stylesheets/categories.scss b/app/assets/stylesheets/categories.scss new file mode 100644 index 0000000000..ef1657f8c9 --- /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..7ea2975d7e --- /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'; + +// 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; +@import 'motion-ui/motion-ui'; +@include motion-ui-transitions; +@include motion-ui-animations; + diff --git a/app/assets/stylesheets/order_items.scss b/app/assets/stylesheets/order_items.scss new file mode 100644 index 0000000000..c713a059fb --- /dev/null +++ b/app/assets/stylesheets/order_items.scss @@ -0,0 +1,11 @@ +// 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/ + +.new_order_item { + width: 300px; + + input[type="number"] { + width: 75px; + } +} 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/place_order.scss b/app/assets/stylesheets/place_order.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss new file mode 100644 index 0000000000..17ce12137b --- /dev/null +++ b/app/assets/stylesheets/products.scss @@ -0,0 +1,75 @@ +// 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/ + +#show-page-content { + max-height: 75vh; + overflow: scroll; +} + +.medium-image, .product-info { + display: inline-block; + margin: 0px auto; + max-height: 45vh; + padding: 10px; +} + +// .medium-image, { +// padding-top: 10px; +// } + +// .show-product-view { +// text-align: center; +// } +.product-info .button { + margin: 0px auto; + width: 100%; +} + +.product-info { + vertical-align: top; + // background-color: rgba(255,255,255,0.2); +} + +.show-product-review, .show-product-view { + margin: 0px auto; + text-align: center; + max-width: 60vw; + background-color: rgba(255,255,255,0.8); +} + +.show-product-view { + min-height: 40vh; + margin-top: 3vh; +} + +.show-product-view ul { + text-align: left; +} +#show-review, #product-details { + display: block; + margin: 0px auto 5px auto; +} + +#show-review { + text-align:left; + background-color: white; + padding-left: 10px; + max-height: 15vh; +} + +#show-review li, #product-details li { + color: black; +} + +#reviews { + max-height: 30vh; + overflow: scroll; +} + +#product-details { + max-height: 40vh; + text-align:left; + background-color: transparent; + max-height: 20vh; +} diff --git a/app/assets/stylesheets/receipt.scss b/app/assets/stylesheets/receipt.scss new file mode 100644 index 0000000000..f34778c9f0 --- /dev/null +++ b/app/assets/stylesheets/receipt.scss @@ -0,0 +1,82 @@ +/* RECEIPT */ + +#content-receipt { + height: 300px; + width: 100%; + margin: 0 0 30px 0; + position: relative; +} + +#receipt-container { + position: relative; + width: 50%; + height: 100%; + background: white; + margin: 0 auto 0 auto; + box-shadow: 0px -5px 5px 0px rgba(0, 0, 0, 0.2); + z-index: 1; +} + +.dotmatrix { + background: url('../img/dot-matrix.svg') 50% 0% repeat-y #fff; + height: 100%; + background-size: 50%; + width: 10%; + position: absolute; +} + +.dotmatrix.left { + border-right: 1px dotted #ccc; + left: 0px; +} + +.dotmatrix.right { + border-left: 1px dotted #ccc; + right: 0px; +} + +#receipt-content { + position: absolute; + left: 0px; + top: 0px; + padding: 15px 15%; + width: 100%; + color: #666; +} + +#receipt-title { + font-weight: 800; + border-bottom: 1px dotted #ccc; + padding-bottom: 10px; + margin-bottom: 10px; + font-family: 'Leckerli One'; +} + +#receipt-shadow { + position: absolute; + width: 60%; + height: 20px; + border-radius: 20px; + background: #1779ba; + left: 50%; + -webkit-transform: translate(-50%,-15px); + transform: translate(-50%,-15px); + box-shadow: inset 0px 5px 5px 0px rgba(0, 0, 0, 0.5); +} + +#receipt-footer { + padding-top: 15px; + margin-top: 15px; + border-top: 1px dotted #ccc; +} + +#receipt-footer small { + font-size: 10px; + font-weight: 300; +} + +.receipt-details-container { + width: 100%; + height: 100px; + overflow: scroll; +} diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss new file mode 100644 index 0000000000..11bbb12cd5 --- /dev/null +++ b/app/assets/stylesheets/reviews.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Reviews controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000000..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/static_pages.scss b/app/assets/stylesheets/static_pages.scss new file mode 100644 index 0000000000..26eca4ccbd --- /dev/null +++ b/app/assets/stylesheets/static_pages.scss @@ -0,0 +1,37 @@ +// Place all the styles related to the static_pages controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ + +@import url('https://fonts.googleapis.com/css?family=Codystar'); + +html, body { + margin:0; + padding:0; + height:100%; +} + +.shopper-bg { + background-image: image-url("shopper.jpeg"); + background-position: center; + background-repeat: no-repeat; + background-size: cover; + h3{ + font-family: 'Playfair Display'; + } + table{ + opacity: 0.9; + color: maroon; + font-weight: bold; + thead{ + font-family: 'Playfair Display'; + } + } + +} + +.thank-you-bg { + background-image: image-url("thankyou.jpeg"); + background-position: left; + background-repeat: no-repeat; + background-size: cover; +} diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss new file mode 100644 index 0000000000..1a2a392169 --- /dev/null +++ b/app/assets/stylesheets/users.scss @@ -0,0 +1,78 @@ +// 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/ +#order-fulfillment-content { + max-height: 75vh; + overflow: scroll; + background-color: rgba(255,255,255,0.9); + +} + +#order-fulfillment-content h2 { + padding: 5px; +} + + +#user-orders, #summaries { + display: block; + max-width: 75vw; + margin: 0px auto; + padding: 5px; +} + +#summaries { + text-align: center; +} + +#user-orders { + border-top: black solid 1px; + margin-top: 10px; +} + +#user-orders a { + text-decoration: underline; + text-decoration-style: solid; +} + +#user-orders.button a { + color: snow; +} + +.orders-summary, .revenue-summary { + margin: 0px auto; + text-align: left; + max-width: 30vw; + display: inline-block; + border: black solid .5px; + padding: 10px; +} + +.orders-summary { + margin-left: 20px; +} + +#summaries h3 { + padding-left: 10px; +} + +#summaries ul { + width: 100%; + background-color: transparent; + text-align: left; +} + +#summaries li { + color: black; +} + +#user-orders h3 { + text-align: center; +} + +h6 { + font-size: 1.2rem; +} + +h5 { + font-size: 1.8rem; +} 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..53c2666e7d --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,49 @@ +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + + before_action :find_user + + before_action :current_order + + def render_404 + render file: "#{Rails.root}/public/404.html" , status: :not_found + end + + private + def find_user + if session[:user_id] + @login_user = User.find_by(id: session[:user_id]) + end + end + + def authenticate + unless session[:user_id] + redirect_to root_path + end + end + + def current_order + if session[:order_id] == nil + create_new_order + else + + @order = Order.find_by(id: session[:order_id]) + if @order + if @order.status == "paid" + create_new_order + end + return + else + create_new_order + end + end + end + + def create_new_order + @order = Order.new + @order.status = "incomplete" + @order.save + session[:order_id] = @order.id + session[:order_items_count] = 0 + end +end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..f09ba0c448 --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,25 @@ +class CategoriesController < ApplicationController + before_action :find_user,:authenticate + + def new + @category = Category.new + end + + def create + @category = Category.new(category_params) + if @category.save + flash[:success] = "New #{@category.name} category has been successfully created" + redirect_to user_account_path(@login_user.id) + else + flash[:error] = "Category could not be created" + @category.errors.messages + render 'new' + end + end + + private + + def category_params + 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/order_items_controller.rb b/app/controllers/order_items_controller.rb new file mode 100644 index 0000000000..623fb88dbf --- /dev/null +++ b/app/controllers/order_items_controller.rb @@ -0,0 +1,97 @@ +class OrderItemsController < ApplicationController + + def new + @order_item = OrderItem.new + @product = Product.find_by(id: params[:product_id]) + + end + + def create + + @product = Product.find_by(id: params[:product_id]) + @order_item = OrderItem.new(order_item_params) + @order_item.product_id = @product.id + @order_item.order_id = @order.id + + if @order_item.save + status = :success + flash[:result_text] = "#{@order_item.quantity} #{@order_item.product.name} have been added to your order!" + redirect_to products_path + else + status = :bad_request + flash[:result_text] = "Error - products not added to your order" + render :new, status: status + end + end + + def edit + @order_item = OrderItem.find_by(id: params[:id]) + @product = @order_item.product + end + + def update + @order_item = OrderItem.find_by(id: params[:id]) + @order = @order_item.order + @product = @order_item.product + + unless @order.status == "incomplete" + flash[:status] = :failure + flash[:result_text] = "Your order cannot be edited as its status is already paid." + redirect_to root_path + return #need to refactor, this may break + end + + if order_item_params[:quantity].to_i > @product.quantity + flash[:status] = :failure + flash[:result_text] = "Error: You must choose a quantity less than or equal to the available quantity (#{@product.quantity})" + render :edit, status: :bad_request + else + @order_item.update_attributes(order_item_params) + if @order_item.save + flash[:status] = :success + flash[:result_text] = "Order Item has updated." + redirect_to order_path(@order.id) + else + flash[:status] = :failure + flash[:result_text] = "Error: Could not update your order_item" + flash[:messages] = @order_item.errors.messages + render :edit, status: :bad_request + end + end + end + + def destroy + @order_item = OrderItem.find_by(id: params[:id]) + @order = @order_item.order + + if @order.status == "incomplete" + @order_item.destroy + flash[:status] = :success + flash[:result_text] = "Order Item has been removed from cart." + else + flash[:status] = :failure + flash[:result_text] = "Error: Could not update your order_item.}" + flash[:messages] = @order.errors.messages + end + + redirect_to order_path(@order.id) + end + + def mark_shipped + item = OrderItem.find_by_id(params[:id]) + if item.shipped == "not shipped" + item.shipped = "shipped" + else + item.shipped = "not shipped" + end + + if item.save + redirect_to order_fulfillment_path(item.product.user_id) + end + end + + private + def order_item_params + params.require(:order_item).permit(:quantity, :product_id) + end +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 0000000000..1a48ecebd4 --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,72 @@ +class OrdersController < ApplicationController + + def index + @orders = Order.all + end + + def show + @order = Order.find_by(id: params[:id]) + if !@order + render_404 + return + elsif @order.status == "paid" + create_new_order + end + end + + def new + unless @order = Order.new + render_404 + end + end + + def edit + @order = Order.find_by(id: params[:id]) + unless @order + render_404 + end + end + + def update + end + + def place_order + @order = Order.find_by_id(session[:order_id]) + unless @order + render_404 + end + @order.update_attributes(order_params) + @order.user_id = session[:user_id] + + if @order.order_items.empty? + flash.now[:error] = "You must add items to your cart in order to checkout" + redirect_to root_path + return + elsif @order.inventory_adjust + @order.status = "paid" + if @order.save + session[:order_items_count] = 0 + else + flash.now[:error] = "Error has occured!" + render :edit + end + end + end + + def user_order + @user_order = Order.find_by_id(params[:id]) + @user = User.find_by_id(params[:user_id]) + render_404 unless @user + unless @user.id == session[:user_id] && Order.by_user(@user).include?(@user_order) + flash[:error] = "You are not authorized to see this page!" + redirect_to root_path + end + end + + private + + def order_params + params.require(:order).permit(:status, :total, :customer_name, :email, :mailing_address, :zipcode, :cc_number, :cc_expiration_date, :cc_cvv) + end + +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..cd33568ea5 --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,87 @@ + +class ProductsController < ApplicationController + before_action :find_product, only: [:show, :edit, :update, :destroy] + + def index + @products = Product.find_instock + end + + def show + render_404 unless @product + end + + def new + @product = Product.new + end + + def create + + categories = Category.clean_up(params[:product][:categories]) + + @product= Product.new product_params + @product.user_id = session[:user_id] + categories.each do |category| + @product.categories << category + end + + if @product.save + flash[:status] = :success + redirect_to product_path(@product.id) + else + flash[:status] = :failure + flash.now[:result_text] = "Error: Product was not added" + render :new + end + + end + + def edit + render_404 unless @product + end + + def update + categories = Category.clean_up(params[:product][:categories]) + + @product.update_attributes(product_params) + categories.each do |category| + @product.categories << category + end + + if @product.save + flash[:status] = :success + flash[:result_text] = "Successfully updated #{@product.name}" + redirect_to product_path(@product.id) + else + flash.now[:status] = :failure + flash.now[:result_text] = "Could not update #{@product.name}" + flash.now[:messages] = @product.errors.messages + render :edit, status: :not_found + end + end + + def destroy + @product.destroy + flash[:status] = :success + flash[:result_text] = "Successfully destroyed #{@product.name}" + redirect_to root_path + end + + def by_category + @products_by_category = Product.to_category_hash + end + + def by_merchant + @products_by_merchant = Product.to_merchant_hash + end + + private + + def find_product + @product = Product.find_by_id(params[:id]) + end + + def product_params + params.require(:product).permit(:name, :description, :price, :quantity, :stock, :photo) + end + +end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..6846e8f9d6 --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,99 @@ +class ReviewsController < ApplicationController + before_action :find_review, only: [:show, :edit, :update, :destroy] + + def index + @reviews= Review.all + end + + def new + @review = Review.new + @product = Product.find_by(id: params[:product_id]) + end + + def create + @product = Product.find_by(id: params[:product_id]) + if session[:user_id] == @product.user.id + flash[:status] = :failure + flash[:result_text] = "Edit Permissions Denied: As a merchant, you cannot review your own products." + redirect_to product_path(@product.id) and return + end + @review = Review.new(review_params) + @review.product_id = @product.id + @review.user_id = session[:user_id] + if @review.save + flash[:status] = :success + flash[:result_text] = "Successfully created your review!" + redirect_to review_path(@review.id) + else + flash[:status] = :failure + flash[:result_text] = "Error: Could not create your review." + flash[:messages] = @review.errors.messages + render :new, status: :bad_request + end + end + + def show + end + + def edit + end + + def update + if session[:user_id].nil? + flash[:status] = :failure + flash[:result_text] = "Access Denied: To edit, you must have logged in to edit your own review." + redirect_to review_path(@review) + + elsif session[:user_id] == @review.product.user_id + flash[:status] = :failure + flash[:result_text] = "Edit Permissions Denied: As a merchant, you cannot review your own products." + redirect_to review_path(@review) + + elsif session[:user_id] == @review.user_id + @review.update_attributes(review_params) + + if @review.save + flash[:status] = :success + flash[:result_text] = "Successfully updated your review." + + redirect_to review_path(@review.id) + else + flash.now[:status] = :failure + flash.now[:result_text] = "Error: Could not successfully update your review." + render :edit, status: :bad_request + end + else + flash[:status] = :failure + flash[:result_text] = "Access Denied: You may not edit another user's review." + redirect_to review_path(@review) + end + end#of_update + + def destroy + if session[:user_id].nil? + flash[:status] = :failure + flash[:result_text] = "Access Denied: To delete, please log in as a user to delete your own review." + redirect_to review_path(@review) + elsif session[:user_id] == @review.user_id + @review = Review.find_by(id: params[:id]).destroy + flash[:status] = :success + flash[:result_text] = "Successfully deleted your review!" + redirect_to root_path + else + flash[:status] = :failure + flash[:result_text] = "Access Denied: You may not delete another user's review." + redirect_to root_path + end + end + + private + + def find_review + @review = Review.find_by_id(params[:id]) + render_404 unless @review + end + + def review_params + params.require(:review).permit(:rating, :text_review) + end +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000000..b1f522a18c --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,42 @@ +class SessionsController < ApplicationController + def login_form + end + + def login + end + + def create + @auth_hash = request.env['omniauth.auth'] + + @user = User.find_by(uid: @auth_hash['uid'], provider: @auth_hash['provider']) + + if @user + @user.merchant_status = true + session[:user_id] = @user.id + session[:user_name] = @user.name + flash[:success] = "#{@user.name} is logged in" + else + @user = User.new uid: @auth_hash['uid'], provider: @auth_hash['provider'], name: @auth_hash['info']['nickname'], email: @auth_hash['info']['email'] + @user.merchant_status = true + end + if @user.save + session[:user_id] = @user.id + session[:user_name] = @user.name + flash[:success] = "Welcome #{@user.name}" + else + flash[:error] = "Unable to save user!" + redirect_to root_path, status: :bad_request + return + end + redirect_to root_path + end + + def logout + session[:user_id] = nil + session[:user_name] = nil + flash[:status] = :success + flash[:result_text] = "Successfully logged out" + redirect_to root_path + end + +end diff --git a/app/controllers/static_pages_controller.rb b/app/controllers/static_pages_controller.rb new file mode 100644 index 0000000000..043f2f66ba --- /dev/null +++ b/app/controllers/static_pages_controller.rb @@ -0,0 +1,5 @@ +class StaticPagesController < ApplicationController + def home + @showcase = Product.all.sample(3) + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000000..154011ea03 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,26 @@ +class UsersController < ApplicationController + def index + end + + def show + end + + def edit + end + + def update + end + + def account + end + + def order_fulfillment + @user = User.find_by_id(params[:id]) + if @login_user == nil || (@login_user.id != @user.id) + render_404 + end + + @user_orders = Order.by_user(@user) + end + +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000000..9370368afd --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,17 @@ +module ApplicationHelper + def current_order + if !session[:order_id].nil? + Order.find(session[:order_id]) + else + Order.new + end + end + + def print_categories(product) + to_print = [] + product.categories.each do |category| + to_print << category.name.capitalize + end + return to_print.join(", ") + end +end diff --git a/app/helpers/categories_helper.rb b/app/helpers/categories_helper.rb new file mode 100644 index 0000000000..e06f31554c --- /dev/null +++ b/app/helpers/categories_helper.rb @@ -0,0 +1,2 @@ +module CategoriesHelper +end diff --git a/app/helpers/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/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/static_pages_helper.rb b/app/helpers/static_pages_helper.rb new file mode 100644 index 0000000000..2d63e79e61 --- /dev/null +++ b/app/helpers/static_pages_helper.rb @@ -0,0 +1,2 @@ +module StaticPagesHelper +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/category.rb b/app/models/category.rb new file mode 100644 index 0000000000..66aba4d916 --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,12 @@ +class Category < ApplicationRecord + has_and_belongs_to_many :products + + validates :name, presence: true, uniqueness: true + + def self.clean_up(params) + categories = params.map do |c| + Category.find_by(id: c) + end.compact + 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/order.rb b/app/models/order.rb new file mode 100644 index 0000000000..7713bb8f2e --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,61 @@ +class Order < ApplicationRecord + + STATUS = ["incomplete", "paid", "complete"] + + has_many :order_items + + validates :status, presence: true, inclusion: { in: STATUS, allow_nil: false} + + def total_cost + total = 0.0 + + self.order_items.each do |item| + product = Product.find_by_id(item.product_id) + total += (product.price * item.quantity) + end + return total.round(2) + end + + def self.by_user(user) + if !User.all.include?(user) + return [] + else + + user.order_items.map {|order_item| order_item.order } + + end + + end + + def inventory_check + unavailable_items = [] + + self.order_items.each do |item| + if item.available? + next + else + unavailable_items << item.product.name + end + end + + return unavailable_items + end + + def inventory_adjust + unavailable = self.inventory_check + if unavailable.empty? + self.order_items.each do |item| + product = Product.find_by_id(item.product_id) + product.quantity -= item.quantity + product.save + end + else + return false + end + end + + def self.by_status(status, orders) + return orders.select {|ord| ord.status == status } + end + +end diff --git a/app/models/order_item.rb b/app/models/order_item.rb new file mode 100644 index 0000000000..e8f0cfb805 --- /dev/null +++ b/app/models/order_item.rb @@ -0,0 +1,19 @@ +class OrderItem < ApplicationRecord + belongs_to :product + belongs_to :order + + validates :quantity, presence: true, numericality: {only_integer: true, greater_than: 0} + + def available? + product = self.product + + if self.quantity > product.quantity + return false + else + return true + end + end + + + +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000000..7ddb5f6a87 --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,94 @@ +class Product < ApplicationRecord + + STOCK = ["In Stock", "Out of Stock"] + has_attached_file :photo, + :default_url => 'glitzy_default.png', + styles: { + thumb: '100x100>', + square: '200x200>', + medium: '300x300>', + large: '400x400>' + } + + validates_attachment_content_type :photo, :content_type => /\Aimage\/.*\Z/ + + has_many :reviews + has_many :order_items + belongs_to :user + + has_and_belongs_to_many :categories + + validates :name, presence: true + validates_uniqueness_of :name, scope: [:category] + validates :price, presence: true, numericality: true, + :format => { :with => /^\d{1,4}(\.\d{0,2})?$/, multiline: true } + validates :quantity, presence: true, numericality: {only_integer: true, greater_than_or_equal_to: 0} + + def self.to_category_hash + data = {} + Category.all.each do |cat| + data[cat.name] = by_category(cat) + end + return data + end + + def self.to_merchant_hash + data = {} + merchants_with_products= (User.all).select{|merchant| merchant.products.count > 0} + + merchants_with_products.each do |merchant| + data[merchant.name] = by_merchant(merchant) + end + return data + end + + def self.by_category(category) + if !Category.all.include?(category) + return [] + else + return category.products.select {|prod| prod.instock } + end + end + + def self.by_merchant(merchant) + if !User.all.include?(merchant) + return [] + else + return merchant.products.select {|prod| prod.instock } + end + end + + + def avg_rating + if (self.reviews).count > 0 + product_reviews = self.reviews + sum_ratings = 0.0 + product_reviews.each do |review| + sum_ratings += review.rating + end + avg = sum_ratings/(product_reviews.count) + return avg + else + return 0 + end + end + + def instock + if self.quantity > 0 && self.stock == "In Stock" + return true + else + return false + end + end + + def self.find_instock + @products = [] + Product.all.each do |prod| + if prod.quantity > 0 && prod.stock == "In Stock" + @products << prod + end + end + return @products + end + +end diff --git a/app/models/review.rb b/app/models/review.rb new file mode 100644 index 0000000000..17598b83e1 --- /dev/null +++ b/app/models/review.rb @@ -0,0 +1,8 @@ +class Review < ApplicationRecord + belongs_to :product + + validates :rating, presence: true, numericality: true + + validates_inclusion_of :rating, in: 1..5 + +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000000..aa5759be86 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,35 @@ +class User < ApplicationRecord + has_many :reviews + has_many :products + has_many :order_items, through: :products + + validates :uid, uniqueness: true, presence: true + validates :email, uniqueness: true, presence: true + validates :provider, presence: true, inclusion: { in: %w(github) } + + def total_revenue_by_status(status) + @order_items = self.order_items + @revenue = 0.0 + @order_items.each do |item| + if item.order.status == status + @revenue += item.quantity * item.product.price + end + end + return @revenue + end + + def total_revenue + @total_revenue = 0.0 + + statuses = Order::STATUS + statuses.each do |status| + @total_revenue += self.total_revenue_by_status(status) + end + return @total_revenue + end + + def user_orders + self.order_items.map {|order_item| order_item.order} + end + +end diff --git a/app/views/categories/new.html.erb b/app/views/categories/new.html.erb new file mode 100644 index 0000000000..d3e05ada46 --- /dev/null +++ b/app/views/categories/new.html.erb @@ -0,0 +1,12 @@ +
+ Your cart is empty! +
++ Your cart is empty! +
+<%= link_to "#{item.product.name}", product_path(item.product.id) %>
+<%= link_to "Click Here to Browse Products", products_path, class: "button"%>
+ +<% else %> +Order ID: <%="#{@user_order.id}"%>
+Customer name: <%="#{@user_order.customer_name}"%>
+Customer Email: <%="#{@user_order.email}"%>
+Mailing address: <%="#{@user_order.mailing_address}"%>, <%="#{@user_order.zipcode}"%>
+CC : <%="#{@user_order.cc_number.gsub!(/.(?=....)/, '*')}"%>
+CC Exp : <%="#{@user_order.cc_expiration_date}"%>
+ORDER STATUS : <%="#{@user_order.status}"%>
+<%= product.description %>
+$<%= sprintf('%.2f', product.price) %>
+<%= product.description %>
+$<%= sprintf('%.2f', product.price) %>
+<%= product.description %>
+$<%= sprintf('%.2f', product.price) %>
+Average Rating: <%= "#{@product.avg_rating.round(1)} stars" %>
++ <%= f.label :text_review %> + <%= f.text_area :text_review, size: '50x10' %> +
+ + <%= f.submit class: "button" %> + <% end %> +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 @@ +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..6db0844b74 --- /dev/null +++ b/app/views/reviews/edit.html.erb @@ -0,0 +1,13 @@ ++ ID + | ++ Product + | ++ Rating + | ++ User + | ++ Review Text + | +
---|---|---|---|---|
+ <%= link_to "#{review.id}", review_path(review.id)%> + | ++ <%= link_to "#{review.product.name}", product_path(review.product.id) %> + | ++ <%= review.rating %> + | ++ REVIEW'S USER NAME + | ++ <%= review.text_review %> + | +
Find me in app/views/reviews/update.html.erb
diff --git a/app/views/sessions/login_form.html.erb b/app/views/sessions/login_form.html.erb new file mode 100644 index 0000000000..bb5fe3bff8 --- /dev/null +++ b/app/views/sessions/login_form.html.erb @@ -0,0 +1 @@ ++ Product Picture + | +Product Name | +Date Added | +Product Category | +Status | +Edit Product | +
---|---|---|---|---|---|
+ <%= image_tag product.photo(:thumb) %> + | +<%= link_to "#{product.name}", product_path(product.id) %> | +<%= (product.created_at).strftime('%b %m, %Y') %> | +<%= print_categories(product) %> + | +<%= product.stock == "In Stock" ? "In Stock" : "Out of Stock" %> | +<%= link_to "Edit Product", edit_product_path(product.id), alt: "link to edit product page", class: "button" %> | +
Find me in app/views/users/index.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..2e197df87f --- /dev/null +++ b/app/views/users/order_fulfillment.html.erb @@ -0,0 +1,103 @@ ++ Order Item ID + | ++ Order Item Product + | ++ Order Item Price + | ++ Order Item Quantity + | ++ Subtotal + | ++ Item Shipping Status + | +
---|---|---|---|---|---|
+ <%= item.id%> + | ++ <%= link_to "#{item.product.name}", product_path(item.product.id)%> + | ++ <%= "$#{sprintf('%.2f', item.product.price)}" %> + | ++ <%= item.quantity%> + | ++ <%= "$#{sprintf('%.2f', (item.quantity * item.product.price))}" %> + | ++ <% if item.shipped == "not shipped" %> + <%= link_to("Mark As Shipped", item_shipped_path(item.id), method: :patch, class: "button")%> + <% else %> + <%= "Shipped on: #{Date.current}" %> + <% end %> + | +
Find me in app/views/users/show.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/bin/yarn b/bin/yarn new file mode 100755 index 0000000000..c2bacef836 --- /dev/null +++ b/bin/yarn @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +VENDOR_PATH = File.expand_path('..', __dir__) +Dir.chdir(VENDOR_PATH) do + begin + exec "yarnpkg #{ARGV.join(" ")}" + rescue Errno::ENOENT + $stderr.puts "Yarn executable was not detected in the system." + $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +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..a47233460d --- /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..fc10d8bc4d --- /dev/null +++ b/config/environments/production.rb @@ -0,0 +1,102 @@ +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # 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 + + config.paperclip_defaults = { + storage: :s3, + s3_credentials: { + bucket: ENV.fetch('S3_BUCKET_NAME'), + access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'), + secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'), + s3_region: ENV.fetch('AWS_REGION'), + s3_host_name: "s3-#{ENV['AWS_REGION']}.amazonaws.com", + } + } +end diff --git a/config/environments/test.rb b/config/environments/test.rb new file mode 100644 index 0000000000..8e5cbde533 --- /dev/null +++ b/config/environments/test.rb @@ -0,0 +1,42 @@ +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 + + # 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..fd4416122a --- /dev/null +++ b/config/initializers/omniauth.rb @@ -0,0 +1,3 @@ +Rails.application.config.middleware.use OmniAuth::Builder do + provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user:email" +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..fde5f11779 --- /dev/null +++ b/config/routes.rb @@ -0,0 +1,49 @@ +Rails.application.routes.draw do + + root 'static_pages#home' + + get "/products/category/", to: "products#by_category", as: 'products_by_category' + + get "/products/merchant/", to: "products#by_merchant", as: 'products_by_merchant' + + get "/users/:id/orders", to: "users#order_fulfillment", as: 'order_fulfillment' #order_fulfillment_path + + get "/users/:user_id/orders/:id", to: "orders#user_order",as: "user_order" + + resources :products do + resources :reviews, only: [:new, :create] + resources :order_items, only: [:new, :create] + end + + resources :carts, except: [:destroy, :index, :new] + + resources :order_items, except: [:new, :create] + + resources :users do + resources :orders, only: [:index] + resources :order_items, only: [:index, :show, :edit, :update] + end + + resources :users, only: [:index, :show, :edit, :update] + + resources :reviews, except: [:new, :create] + + resources :orders + patch '/orders', to: 'orders#place_order', as: 'place_order' + + get '/login', to: 'sessions#login_form', as: 'login' + post '/login', to: 'sessions#login' + post '/logout', to: 'sessions#logout', as: 'logout' + + get "/auth/:provider/callback", to: "sessions#create", as: "auth_callback" + + get '/users/:id/products', to: 'users#account', as: 'user_account' + + resources :categories, only: [:create, :new, :index] do + get '/products', to: 'product#index' + end + + patch '/order_item/:id/mark_shipped', to: 'order_items#mark_shipped', as: 'item_shipped' + + # 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..4215c21055 --- /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: e582c5a9c9425906d57670eb87588e61de7c2ed8d89128a3a884d42569b3706e63be023df9fdee9c2a43af871860edc705f8fe0f2d9ee659b4a36618689944f8 + +test: + secret_key_base: d41428ecfc558490ca4878123f3f0c2ef4b2e36e2bc9d9e603480f00d8371a039ff5caa8d86a12cf3b71c7a2c2a2474373db2d2a1bc2820919e22e7834e62272 + +# 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/db/.DS_Store b/db/.DS_Store new file mode 100644 index 0000000000..4d909151fb Binary files /dev/null and b/db/.DS_Store differ diff --git a/db/migrate/20171017193934_create_products.rb b/db/migrate/20171017193934_create_products.rb new file mode 100644 index 0000000000..74426a5c00 --- /dev/null +++ b/db/migrate/20171017193934_create_products.rb @@ -0,0 +1,13 @@ +class CreateProducts < ActiveRecord::Migration[5.1] + def change + create_table :products do |t| + t.string :name + t.string :category + t.text :description + t.decimal :price + t.integer :quantity + + t.timestamps + end + end +end diff --git a/db/migrate/20171017195248_create_users.rb b/db/migrate/20171017195248_create_users.rb new file mode 100644 index 0000000000..b4c05914ad --- /dev/null +++ b/db/migrate/20171017195248_create_users.rb @@ -0,0 +1,15 @@ +class CreateUsers < ActiveRecord::Migration[5.1] + def change + create_table :users do |t| + t.string :name + t.string :email + t.string :mailing_address + t.string :cc_number + t.date :cc_expiration_date + t.integer :cc_cvv + t.string :zipcode + + t.timestamps + end + end +end diff --git a/db/migrate/20171017195841_create_reviews.rb b/db/migrate/20171017195841_create_reviews.rb new file mode 100644 index 0000000000..824d97cf47 --- /dev/null +++ b/db/migrate/20171017195841_create_reviews.rb @@ -0,0 +1,10 @@ +class CreateReviews < ActiveRecord::Migration[5.1] + def change + create_table :reviews do |t| + t.integer :rating + t.text :text_review + + t.timestamps + end + end +end diff --git a/db/migrate/20171017201702_create_orders.rb b/db/migrate/20171017201702_create_orders.rb new file mode 100644 index 0000000000..8d3698575f --- /dev/null +++ b/db/migrate/20171017201702_create_orders.rb @@ -0,0 +1,9 @@ +class CreateOrders < ActiveRecord::Migration[5.1] + def change + create_table :orders do |t| + t.string :status + + t.timestamps + end + end +end diff --git a/db/migrate/20171017205926_add_user_i_dto_reviews.rb b/db/migrate/20171017205926_add_user_i_dto_reviews.rb new file mode 100644 index 0000000000..512ad9ca74 --- /dev/null +++ b/db/migrate/20171017205926_add_user_i_dto_reviews.rb @@ -0,0 +1,5 @@ +class AddUserIDtoReviews < ActiveRecord::Migration[5.1] + def change + add_reference :reviews, :user, foreign_keys: true + end +end diff --git a/db/migrate/20171017210230_add_product_i_dto_reviews.rb b/db/migrate/20171017210230_add_product_i_dto_reviews.rb new file mode 100644 index 0000000000..902c02b81a --- /dev/null +++ b/db/migrate/20171017210230_add_product_i_dto_reviews.rb @@ -0,0 +1,5 @@ +class AddProductIDtoReviews < ActiveRecord::Migration[5.1] + def change + add_reference :reviews, :product, foreign_keys: true + end +end diff --git a/db/migrate/20171017210850_add_foreign_keyto_product.rb b/db/migrate/20171017210850_add_foreign_keyto_product.rb new file mode 100644 index 0000000000..05fe3da402 --- /dev/null +++ b/db/migrate/20171017210850_add_foreign_keyto_product.rb @@ -0,0 +1,5 @@ +class AddForeignKeytoProduct < ActiveRecord::Migration[5.1] + def change + add_reference :products, :user, foreign_keys: true + end +end diff --git a/db/migrate/20171017211008_add_foreign_keyto_order.rb b/db/migrate/20171017211008_add_foreign_keyto_order.rb new file mode 100644 index 0000000000..f7ff6113fb --- /dev/null +++ b/db/migrate/20171017211008_add_foreign_keyto_order.rb @@ -0,0 +1,6 @@ +class AddForeignKeytoOrder < ActiveRecord::Migration[5.1] + def change + add_reference :orders, :user, foreign_keys: true + add_reference :orders, :cart, foreign_keys: true + end +end diff --git a/db/migrate/20171017232721_add_merchant_column.rb b/db/migrate/20171017232721_add_merchant_column.rb new file mode 100644 index 0000000000..5aff7b2941 --- /dev/null +++ b/db/migrate/20171017232721_add_merchant_column.rb @@ -0,0 +1,5 @@ +class AddMerchantColumn < ActiveRecord::Migration[5.1] + def change + add_column(:users, :merchant_status, :boolean) + end +end diff --git a/db/migrate/20171017234725_add_ui_dand_provider_to_users.rb b/db/migrate/20171017234725_add_ui_dand_provider_to_users.rb new file mode 100644 index 0000000000..92f8cb4676 --- /dev/null +++ b/db/migrate/20171017234725_add_ui_dand_provider_to_users.rb @@ -0,0 +1,6 @@ +class AddUiDandProviderToUsers < ActiveRecord::Migration[5.1] + def change + add_column :users, :uid, :string, null: false + add_column :users, :provider, :string, null: false + end +end diff --git a/db/migrate/20171019011348_create_order_items.rb b/db/migrate/20171019011348_create_order_items.rb new file mode 100644 index 0000000000..db8b5cfa57 --- /dev/null +++ b/db/migrate/20171019011348_create_order_items.rb @@ -0,0 +1,9 @@ +class CreateOrderItems < ActiveRecord::Migration[5.1] + def change + create_table :order_items do |t| + t.integer :quantity + + t.timestamps + end + end +end diff --git a/db/migrate/20171019165620_remove_userid_from_order.rb b/db/migrate/20171019165620_remove_userid_from_order.rb new file mode 100644 index 0000000000..b978c70eb0 --- /dev/null +++ b/db/migrate/20171019165620_remove_userid_from_order.rb @@ -0,0 +1,6 @@ +class RemoveUseridFromOrder < ActiveRecord::Migration[5.1] + def change + remove_column :orders, :user_id, :string + + end +end diff --git a/db/migrate/20171019165910_add_userid_to_order.rb b/db/migrate/20171019165910_add_userid_to_order.rb new file mode 100644 index 0000000000..3f13cb18ca --- /dev/null +++ b/db/migrate/20171019165910_add_userid_to_order.rb @@ -0,0 +1,5 @@ +class AddUseridToOrder < ActiveRecord::Migration[5.1] + def change + add_column :orders, :user_id, :bigint + end +end diff --git a/db/migrate/20171019172247_remove_cart_id_association_orders.rb b/db/migrate/20171019172247_remove_cart_id_association_orders.rb new file mode 100644 index 0000000000..e6b24adc04 --- /dev/null +++ b/db/migrate/20171019172247_remove_cart_id_association_orders.rb @@ -0,0 +1,5 @@ +class RemoveCartIdAssociationOrders < ActiveRecord::Migration[5.1] + def change + remove_column :orders, :cart_id + end +end diff --git a/db/migrate/20171019203518_create_categories.rb b/db/migrate/20171019203518_create_categories.rb new file mode 100644 index 0000000000..5bef4913b8 --- /dev/null +++ b/db/migrate/20171019203518_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/20171019213116_create_products_categories_join.rb b/db/migrate/20171019213116_create_products_categories_join.rb new file mode 100644 index 0000000000..3d5f210962 --- /dev/null +++ b/db/migrate/20171019213116_create_products_categories_join.rb @@ -0,0 +1,9 @@ +class CreateProductsCategoriesJoin < ActiveRecord::Migration[5.1] + def change + create_table :products_categories do |t| + t.belongs_to :product, index: true + t.belongs_to :category, index: true + t.timestamps + end + end +end diff --git a/db/migrate/20171019225654_rename_category_product_join_table.rb b/db/migrate/20171019225654_rename_category_product_join_table.rb new file mode 100644 index 0000000000..b04a2416e9 --- /dev/null +++ b/db/migrate/20171019225654_rename_category_product_join_table.rb @@ -0,0 +1,5 @@ +class RenameCategoryProductJoinTable < ActiveRecord::Migration[5.1] + def change + rename_table :products_categories, :categories_products + end +end diff --git a/db/migrate/20171020021626_add_order_i_dto_order_items.rb b/db/migrate/20171020021626_add_order_i_dto_order_items.rb new file mode 100644 index 0000000000..806d91f37b --- /dev/null +++ b/db/migrate/20171020021626_add_order_i_dto_order_items.rb @@ -0,0 +1,6 @@ +class AddOrderIDtoOrderItems < ActiveRecord::Migration[5.1] + def change + # add_column :order_items, :order_id, :bigint + add_reference :order_items, :order, foreign_keys: true + end +end diff --git a/db/migrate/20171020025105_add_user_info_to_order.rb b/db/migrate/20171020025105_add_user_info_to_order.rb new file mode 100644 index 0000000000..e89e5a5dd7 --- /dev/null +++ b/db/migrate/20171020025105_add_user_info_to_order.rb @@ -0,0 +1,11 @@ +class AddUserInfoToOrder < ActiveRecord::Migration[5.1] + def change + add_column :orders, :customer_name, :string + add_column :orders, :email, :string + add_column :orders, :mailing_address, :string + add_column :orders, :cc_number, :string + add_column :orders, :cc_expiration_date, :string + add_column :orders, :cc_cvv, :string + add_column :orders, :zipcode, :string + end +end diff --git a/db/migrate/20171024170127_add_stock_and_photo_ur_lto_products.rb b/db/migrate/20171024170127_add_stock_and_photo_ur_lto_products.rb new file mode 100644 index 0000000000..b9f5667a21 --- /dev/null +++ b/db/migrate/20171024170127_add_stock_and_photo_ur_lto_products.rb @@ -0,0 +1,6 @@ +class AddStockAndPhotoUrLtoProducts < ActiveRecord::Migration[5.1] + def change + add_column :products, :stock, :string + add_column :products, :photo_url, :string + end +end diff --git a/db/migrate/20171024233848_add_image_to_products.rb b/db/migrate/20171024233848_add_image_to_products.rb new file mode 100644 index 0000000000..fa440a9afd --- /dev/null +++ b/db/migrate/20171024233848_add_image_to_products.rb @@ -0,0 +1,13 @@ +class AddImageToProducts < ActiveRecord::Migration[5.1] + def change + add_attachment :products, :photo + end + + def self.up + add_attachment :products, :photo + end + + def self.down + remove_attachment :products, :photo + end +end diff --git a/db/migrate/20171024234020_add_shipped_to_order_items.rb b/db/migrate/20171024234020_add_shipped_to_order_items.rb new file mode 100644 index 0000000000..36b06ac9ab --- /dev/null +++ b/db/migrate/20171024234020_add_shipped_to_order_items.rb @@ -0,0 +1,5 @@ +class AddShippedToOrderItems < ActiveRecord::Migration[5.1] + def change + add_column :order_items, :shipped, :string + end +end diff --git a/db/migrate/20171025100622_remove_extras_from_users.rb b/db/migrate/20171025100622_remove_extras_from_users.rb new file mode 100644 index 0000000000..57558167e6 --- /dev/null +++ b/db/migrate/20171025100622_remove_extras_from_users.rb @@ -0,0 +1,9 @@ +class RemoveExtrasFromUsers < ActiveRecord::Migration[5.1] + def change + remove_column :users, :mailing_address, :string + remove_column :users, :cc_number, :string + remove_column :users, :cc_expiration_date, :date + remove_column :users, :cc_cvv, :integer + remove_column :users, :zipcode, :string + end +end diff --git a/db/migrate/20171025101959_add_default_to_shipped_orderitem.rb b/db/migrate/20171025101959_add_default_to_shipped_orderitem.rb new file mode 100644 index 0000000000..d3dd037c4c --- /dev/null +++ b/db/migrate/20171025101959_add_default_to_shipped_orderitem.rb @@ -0,0 +1,5 @@ +class AddDefaultToShippedOrderitem < ActiveRecord::Migration[5.1] + def change + change_column_default :order_items, :shipped, "not shipped" + end +end diff --git a/db/migrate/20171025102333_add_default_to_product_stock.rb b/db/migrate/20171025102333_add_default_to_product_stock.rb new file mode 100644 index 0000000000..b89c93cca1 --- /dev/null +++ b/db/migrate/20171025102333_add_default_to_product_stock.rb @@ -0,0 +1,5 @@ +class AddDefaultToProductStock < ActiveRecord::Migration[5.1] + def change + change_column_default :products, :stock, "In Stock" + end +end diff --git a/db/migrate/20171025103400_add_default_to_order_status.rb b/db/migrate/20171025103400_add_default_to_order_status.rb new file mode 100644 index 0000000000..603466a226 --- /dev/null +++ b/db/migrate/20171025103400_add_default_to_order_status.rb @@ -0,0 +1,5 @@ +class AddDefaultToOrderStatus < ActiveRecord::Migration[5.1] + def change + change_column_default :orders, :status, "incomplete" + end +end diff --git a/db/migrate/20171025104952_remove_photourl_from_products.rb b/db/migrate/20171025104952_remove_photourl_from_products.rb new file mode 100644 index 0000000000..293f91047f --- /dev/null +++ b/db/migrate/20171025104952_remove_photourl_from_products.rb @@ -0,0 +1,5 @@ +class RemovePhotourlFromProducts < ActiveRecord::Migration[5.1] + def change + remove_column :products, :photo_url, :string + end +end diff --git a/db/schema.rb b/db/schema.rb new file mode 100644 index 0000000000..f49db81f87 --- /dev/null +++ b/db/schema.rb @@ -0,0 +1,96 @@ +# 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: 20171025104952) do + + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + 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 "product_id" + t.bigint "category_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + 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 "order_items", force: :cascade do |t| + t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "product_id" + t.bigint "order_id" + t.string "shipped", default: "not shipped" + t.index ["order_id"], name: "index_order_items_on_order_id" + t.index ["product_id"], name: "index_order_items_on_product_id" + end + + create_table "orders", force: :cascade do |t| + t.string "status", default: "incomplete" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "user_id" + t.string "customer_name" + t.string "email" + t.string "mailing_address" + t.string "cc_number" + t.string "cc_expiration_date" + t.string "cc_cvv" + t.string "zipcode" + end + + create_table "products", force: :cascade do |t| + t.string "name" + t.string "category" + t.text "description" + t.decimal "price" + t.integer "quantity" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.bigint "user_id" + t.string "stock", default: "In Stock" + t.string "photo_file_name" + t.string "photo_content_type" + t.integer "photo_file_size" + t.datetime "photo_updated_at" + t.index ["user_id"], name: "index_products_on_user_id" + end + + create_table "reviews", force: :cascade do |t| + t.integer "rating" + t.text "text_review" + 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 "name" + t.string "email" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "merchant_status" + t.string "uid", null: false + t.string "provider", null: false + end + +end diff --git a/db/seed_data/categories.csv b/db/seed_data/categories.csv new file mode 100644 index 0000000000..8d9f2472e8 --- /dev/null +++ b/db/seed_data/categories.csv @@ -0,0 +1,4 @@ +id,name +1,food +2,cosmetics +3,clothing diff --git a/db/seed_data/product_seeds.csv b/db/seed_data/product_seeds.csv new file mode 100644 index 0000000000..b02e88ebcb --- /dev/null +++ b/db/seed_data/product_seeds.csv @@ -0,0 +1,15 @@ +category,name,price,quantity,user_id,stock,description +food,Franz Chocolates,199.99,30,999,In Stock,An Obama family favorite. +food,Countdown to Ecstasy,500.00,5,999,In Stock,A guaranteed trip to flavor town. +food,Pretzel Logic,100.00,10,999,In Stock,Pretzels that temporarily make you smarter +food,Snickers,150.00,100,999,In Stock,The classic +cosmetics,Polygraph Perfume,1000.00,3,1000,In Stock,Spritz this for the Truth. +cosmetics,Luxe Lipstick,150.00,10,1000,In Stock,The most luxurious feeling and looking lipstick on the market. +cosmetics,Bashful Blush,100.00,20,1000,In Stock,For a light and charming flush of color. +cosmetics,Eyeluring Eyeliner,120.00,10,1000,In Stock,Make eyes and catch eyes. +cosmetics,Flawless Foundation,180.00,15,1000,In Stock, For flawless skin +clothing,The Perfect Tee,100.00,80,1001,In Stock,Basic tee that looks flattering on everybody. +clothing,Blazing Bolo,500.00,3,1001,In Stock,Bolos that give the illusion that they are on fire. +clothing,Never-Stretch Leggings,300.00,18,1001,In Stock,Leggings that will never lose their shape. +clothing,Perfect Pants,700.00,20,1001,In Stock,Pants that look flattering on everybody. +clothing,Punchy Poncho,550.00,3,1001,In Stock,The punchiest poncho to add oomph to any outfit. diff --git a/db/seed_data/users.csv b/db/seed_data/users.csv new file mode 100644 index 0000000000..2d62193fb5 --- /dev/null +++ b/db/seed_data/users.csv @@ -0,0 +1,4 @@ +id,name,email,merchant_status,uid,provider +999,Nina Hintz,hintz@ada.com,true,999999,github +1000,Florence Fisher,fisher@ada.com,true,999998,github +1001,Glitzy Team, glitzy@ada.com,true,999997,github diff --git a/db/seeds.rb b/db/seeds.rb new file mode 100644 index 0000000000..dc1d459889 --- /dev/null +++ b/db/seeds.rb @@ -0,0 +1,142 @@ +# 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). +# +# Examples: +# +# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) +# Character.create(name: 'Luke', movie: movies.first) + +require 'csv' + +#--------------------------------------------------- +CATEGORY_FILE = Rails.root.join('db', 'seed_data', 'categories.csv') +puts "Loading raw work data from #{CATEGORY_FILE}" + +category_failures = [] +CSV.foreach(CATEGORY_FILE, :headers => true) do |row| + category = Category.new + category.id = row['id'] + category.name = row['name'] + + puts "Created work: #{category.inspect}" + successful = category.save + if !successful + category_failures << category + puts category.errors + puts "----------" + category.errors.each do |column, message| + puts "#{column}: #{message}" + end + puts "----------" + end + +end + +puts "Added #{Category.count} category records" +puts "#{category_failures.length} category failed to save" + + +# 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" + + +#--------------------------------------------------- +USER_FILE = Rails.root.join('db', 'seed_data', 'users.csv') +puts "Loading raw work data from #{USER_FILE}" + +user_failures = [] +CSV.foreach(USER_FILE, :headers => true) do |row| + user = User.new + user.id = row['id'] + user.name = row['name'] + user.email = row['email'] + user.merchant_status = row['merchant_status'] + user.uid = row['uid'] + user.provider = row['provider'] + puts "Created work: #{user.inspect}" + successful = user.save + if !successful + user_failures << user + puts user.errors + puts "----------" + user.errors.each do |column, message| + puts "#{column}: #{message}" + end + puts "----------" + end + +end + +puts "Added #{User.count} user records" +puts "#{user_failures.length} user failed to save" + + +# 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" + + +#--------------------------------------------------- +PRODUCT_FILE = Rails.root.join('db', 'seed_data', 'product_seeds.csv') +puts "Loading raw work data from #{PRODUCT_FILE}" + + +i = 1000 +product_failures = [] +CSV.foreach(PRODUCT_FILE, :headers => true) do |row| + product = Product.new + product.id = i + product.user_id = row['user_id'] + product.category = row['category'] + product.name = row['name'] + product.price = row['price'] + product.quantity = row['quantity'] + product.description = row['description'] + product.stock = row['stock'] + + puts "Created work: #{product.inspect}" + successful = product.save + product.categories << Category.find_by(name: product.category) + + if !successful + product_failures << product + puts product.errors + puts "----------" + product.errors.each do |column, message| + puts "#{column}: #{message}" + end + puts "----------" + end + + i += 1 +end + +puts "Added #{Product.count} product records" +puts "#{product_failures.length} products failed to save" + + +# 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/delete_me.html.erb b/delete_me.html.erb new file mode 100644 index 0000000000..4250abab12 --- /dev/null +++ b/delete_me.html.erb @@ -0,0 +1,72 @@ ++ Product name + | ++ Category + | ++ Description + | ++ Price + | ++ Available Quantity + | ++ + | +
---|---|---|---|---|---|
+ <%= link_to "#{product.name}", product_path(product.id)%> + | ++ <%= print_categories(product) %> + | ++ <%= product.description %> + | ++ <%= product.price %> + | ++ <%= product.quantity %> + | ++ <%= image_tag product.photo(:thumb) %> + | +
You may have mistyped the address or the page may have moved.
+If you are the application owner check the logs for more information.
+Maybe you tried to change something you didn't have access to.
+If you are the application owner check the logs for more information.
+If you are the application owner check the logs for more information.
+