diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..743a7f05ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep +tmp +log + +/node_modules +/yarn-error.log + +.byebug_history + + +.env + +/coverage/* + +log/ +tmp/ +.DS_Store diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..bea56a7878 --- /dev/null +++ b/Gemfile @@ -0,0 +1,82 @@ +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 + + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.1.6' +# Use postgresql as the database for Active Record +gem 'pg', '>= 0.18', '< 2.0' +# Use Puma as the app server +gem 'puma', '~> 3.7' +# Use SCSS for stylesheets +gem 'sass-rails', '~> 5.0' +# Use Uglifier as compressor for JavaScript assets +gem 'uglifier', '>= 1.3.0' +# See https://github.com/rails/execjs#readme for more supported runtimes +# gem 'therubyracer', platforms: :ruby + +# Use CoffeeScript for .coffee assets and views +gem 'coffee-rails', '~> 4.2' +# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks +gem 'turbolinks', '~> 5' +# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder +gem 'jbuilder', '~> 2.5' +# Use Redis adapter to run Action Cable in production +# gem 'redis', '~> 4.0' +# Use ActiveModel has_secure_password +# gem 'bcrypt', '~> 3.1.7' + +# Use Capistrano for deployment +# gem 'capistrano-rails', group: :development + +# OAuth authorization +gem "omniauth" +gem "omniauth-github" + +group :development, :test do + # Call 'byebug' anywhere in the code to stop execution and get a debugger console + gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] + # Adds support for Capybara system testing and selenium driver + gem 'capybara', '~> 2.13' + gem 'selenium-webdriver' +end + +group :development do + # Access an IRB console on exception pages or by using <%= console %> anywhere in the code. + gem 'web-console', '>= 3.3.0' + gem 'listen', '>= 3.0.5', '< 3.2' + # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring + gem 'spring' + gem 'spring-watcher-listen', '~> 2.0.0' + + gem 'seed_dump' + gem 'dotenv-rails' +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] + +gem 'jquery-turbolinks' +gem 'jquery-rails' +gem 'foundation-rails' +gem 'foundation-icons-sass-rails' +gem 'normalize-rails' +group :development, :test do + gem 'pry-rails' +end + +group :development do + gem 'better_errors' + gem 'binding_of_caller' +end + +group :test do + gem 'minitest-rails' + gem 'minitest-reporters' + gem 'simplecov' + gem 'simplecov-console' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..4c9d77cc07 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,294 @@ +GEM + remote: https://rubygems.org/ + specs: + actioncable (5.1.6) + actionpack (= 5.1.6) + nio4r (~> 2.0) + websocket-driver (~> 0.6.1) + actionmailer (5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (5.1.6) + actionview (= 5.1.6) + activesupport (= 5.1.6) + rack (~> 2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (5.1.6) + activesupport (= 5.1.6) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.0.3) + activejob (5.1.6) + activesupport (= 5.1.6) + globalid (>= 0.3.6) + activemodel (5.1.6) + activesupport (= 5.1.6) + activerecord (5.1.6) + activemodel (= 5.1.6) + activesupport (= 5.1.6) + arel (~> 8.0) + activesupport (5.1.6) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + ansi (1.5.0) + arel (8.0.0) + babel-source (5.8.35) + babel-transpiler (0.7.0) + babel-source (>= 4.0, < 6) + execjs (~> 2.0) + better_errors (2.4.0) + coderay (>= 1.0.0) + erubi (>= 1.0.0) + rack (>= 0.9.0) + bindex (0.5.0) + binding_of_caller (0.8.0) + debug_inspector (>= 0.0.1) + builder (3.2.3) + byebug (10.0.2) + capybara (2.18.0) + addressable + mini_mime (>= 0.1.3) + nokogiri (>= 1.3.3) + rack (>= 1.0.0) + rack-test (>= 0.5.4) + xpath (>= 2.0, < 4.0) + childprocess (0.9.0) + ffi (~> 1.0, >= 1.0.11) + coderay (1.1.2) + coffee-rails (4.2.2) + coffee-script (>= 2.2.0) + railties (>= 4.0.0) + coffee-script (2.4.1) + coffee-script-source + execjs + coffee-script-source (1.12.2) + concurrent-ruby (1.0.5) + crass (1.0.4) + debug_inspector (0.0.3) + docile (1.3.0) + dotenv (2.2.2) + dotenv-rails (2.2.2) + dotenv (= 2.2.2) + railties (>= 3.2, < 6.0) + erubi (1.7.1) + execjs (2.7.0) + faraday (0.12.2) + multipart-post (>= 1.2, < 3) + ffi (1.9.23) + foundation-icons-sass-rails (3.0.0) + railties (>= 3.1.1) + sass-rails (>= 3.1.1) + foundation-rails (6.4.3.0) + railties (>= 3.1.0) + sass (>= 3.3.0, < 3.5) + sprockets-es6 (>= 0.9.0) + globalid (0.4.1) + activesupport (>= 4.2.0) + hashie (3.5.7) + hirb (0.7.3) + i18n (1.0.1) + concurrent-ruby (~> 1.0) + jbuilder (2.7.0) + activesupport (>= 4.2.0) + multi_json (>= 1.2) + jquery-rails (4.3.3) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + jquery-turbolinks (2.1.0) + railties (>= 3.1.0) + turbolinks + json (2.1.0) + jwt (1.5.6) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + loofah (2.2.2) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.0) + mini_mime (>= 0.1.1) + method_source (0.9.0) + mini_mime (1.0.0) + mini_portile2 (2.3.0) + minitest (5.11.3) + minitest-rails (3.0.0) + minitest (~> 5.8) + railties (~> 5.0) + minitest-reporters (1.2.0) + ansi + builder + minitest (>= 5.0) + ruby-progressbar + multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + nio4r (2.3.0) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + normalize-rails (4.1.1) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + omniauth (1.8.1) + hashie (>= 3.4.6, < 3.6.0) + rack (>= 1.6.2, < 3) + omniauth-github (1.3.0) + omniauth (~> 1.5) + omniauth-oauth2 (>= 1.4.0, < 2.0) + omniauth-oauth2 (1.5.0) + oauth2 (~> 1.1) + omniauth (~> 1.2) + pg (1.0.0) + pry (0.11.3) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + pry-rails (0.3.6) + pry (>= 0.10.4) + public_suffix (3.0.2) + puma (3.11.4) + rack (2.0.5) + rack-test (1.0.0) + rack (>= 1.0, < 3) + rails (5.1.6) + actioncable (= 5.1.6) + actionmailer (= 5.1.6) + actionpack (= 5.1.6) + actionview (= 5.1.6) + activejob (= 5.1.6) + activemodel (= 5.1.6) + activerecord (= 5.1.6) + activesupport (= 5.1.6) + bundler (>= 1.3.0) + railties (= 5.1.6) + sprockets-rails (>= 2.0.0) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.0.4) + loofah (~> 2.2, >= 2.2.2) + railties (5.1.6) + actionpack (= 5.1.6) + activesupport (= 5.1.6) + method_source + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (12.3.1) + rb-fsevent (0.10.3) + rb-inotify (0.9.10) + ffi (>= 0.5.0, < 2) + ruby-progressbar (1.9.0) + ruby_dep (1.5.0) + rubyzip (1.2.1) + sass (3.4.25) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) + seed_dump (3.2.4) + activerecord (>= 4) + activesupport (>= 4) + selenium-webdriver (3.11.0) + childprocess (~> 0.5) + rubyzip (~> 1.2) + simplecov (0.16.1) + docile (~> 1.1) + json (>= 1.8, < 3) + simplecov-html (~> 0.10.0) + simplecov-console (0.4.2) + ansi + hirb + simplecov + simplecov-html (0.10.2) + spring (2.0.2) + activesupport (>= 4.2) + spring-watcher-listen (2.0.1) + listen (>= 2.7, < 4.0) + spring (>= 1.2, < 3.0) + sprockets (3.7.1) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-es6 (0.9.2) + babel-source (>= 5.8.11) + babel-transpiler + sprockets (>= 3.0.0) + sprockets-rails (3.2.1) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + thor (0.20.0) + thread_safe (0.3.6) + tilt (2.0.8) + turbolinks (5.1.1) + turbolinks-source (~> 5.1) + turbolinks-source (5.1.0) + tzinfo (1.2.5) + thread_safe (~> 0.1) + uglifier (4.1.9) + execjs (>= 0.3.0, < 3) + web-console (3.6.0) + actionview (>= 5.0) + activemodel (>= 5.0) + bindex (>= 0.4.0) + railties (>= 5.0) + websocket-driver (0.6.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.3) + xpath (3.0.0) + nokogiri (~> 1.8) + +PLATFORMS + ruby + +DEPENDENCIES + better_errors + binding_of_caller + byebug + capybara (~> 2.13) + coffee-rails (~> 4.2) + dotenv-rails + foundation-icons-sass-rails + foundation-rails + jbuilder (~> 2.5) + jquery-rails + jquery-turbolinks + listen (>= 3.0.5, < 3.2) + minitest-rails + minitest-reporters + normalize-rails + omniauth + omniauth-github + pg (>= 0.18, < 2.0) + pry-rails + puma (~> 3.7) + rails (~> 5.1.6) + sass-rails (~> 5.0) + seed_dump + selenium-webdriver + simplecov + simplecov-console + spring + spring-watcher-listen (~> 2.0.0) + turbolinks (~> 5) + tzinfo-data + uglifier (>= 1.3.0) + web-console (>= 3.3.0) + +BUNDLED WITH + 1.16.1 diff --git a/README.md b/README.md index 2758975bf5..7db80e4ca1 100644 --- a/README.md +++ b/README.md @@ -1,205 +1,24 @@ -# bEtsy -[Much like other e-commerce platforms](https://www.etsy.com/), your team will make an online store where a wide variety of products can be listed and sold by any user. This project focuses on reinforcing the major components of Rails, model validations, testing, and more complex logic such as user authentication. +# README -This is a [Stage 3](https://github.com/Ada-Developers-Academy/pedagogy/blob/master/rule-of-three.md) project requiring you to expand upon what you have learned in class. +This README would normally document whatever steps are necessary to get the +application up and running. -## Project Learning Goals -- Core comprehension of: - - Routes - - Controllers - - Models - - Views -- User based application logic -- User authentication -- Testing on models and controllers -- Agile practices -- Feature branch management with Git -- Group project ownership +Things you may want to cover: -## Guidelines -- Groups of three or four will collaborate in pairs or individually and will report to their assigned Project Manager (one of the instructors) -- Use a task manager like [Trello](http://trello.com) to track your team's efforts -- Build a logical user-flow that moves across multiple controllers and models -- Use HTML/CSS and Foundation to style your website +* Ruby version -## Getting Started -1. As a group decide on an app name (this may help lead the aesthetic) -1. As a group decide on a team name (this will amuse your instructors) -1. Have one person on your team fork/clone the project master as per usual - 1. Create a new rails app using `rails new .` - 1. Add all other team members as collaborators - 1. Each team member should clone the repo to their computer -1. Figure out your workflow for the project, re: Git and Task management - 1. Do you want to use git branches? Pull requests? - 1. Determine who will be the Stand Up Leader and Task Leader for the first week -1. Create a Trello board to use as a Kanban board and ensure that all team members and instructors have access -1. Review the User Stories below and create Trello tasks to represent them -1. Slack your team name, app name, and link to your Trello board to your Project Manager +* System dependencies -## Expectations -Build an online system for listing, selling, reviewing, and buying a wide variety of products listed by multiple merchants. +* Configuration -### General Requirements -- Unit tests and/or specs for - - Models - - Controllers -- Test code coverage (using SimpleCov - remember me!) - - 90% for all controller and model classes +* Database creation -### User Stories -#### Guest User (Unauthenticated) -As a guest to the website (not signed in) I **can**: +* Database initialization -- Browse all products -- Browse products by category -- Browse products by merchant (users) -- View any individual product with additional details -- Leave a review for a product providing: - - A text review - - A rating out of 5 -- Add in-stock products to my cart -- Remove products from my cart -- Change the quantity of an existing product in my cart -- Purchase the items in my cart, providing: - - Email Address - - Mailing Address - - Name on credit card - - Credit card number - - Credit cart expiration - - Credit Card CVV (security code) - - Billing zip code -- Purchasing an order makes the following changes: - - Reduces the number of inventory for each product - - Changes the order state from "pending" to "paid" - - Clears the current cart -- After purchasing an order, I can view a confirmation screen including: - - Each item in the order with a quantity and line-item subtotal - - A link to the item description page - - Order total price - - Date/time the order was placed - - The current status of the order -- Sign up to be a merchant using OAuth - - Every merchant must have a username -- Sign in to my merchant account using OAuth +* How to run the test suite -As a guest I **cannot**: +* Services (job queues, cache servers, search engines, etc.) -- Add products to the cart that are out of stock -- View any link or page to manage any products -- View any of the account pages +* Deployment instructions -#### Authenticated Users -As a signed-in user, I **can**: - -- Do everything a guest user can do except for sign up and sign in -- Sign out -- Create new categories (categories are shared between all merchants) -- Create a new product providing: - - name - - description - - price - - photo URL - - stock -- Assign my products to any number of categories -- Retire a product from being sold, which hides it from browsing -- View an account page to edit/update my existing products -- View an account page showing my order fulfillment -- On the order fulfillment page: - - Total Revenue - - Total Revenue by status - - Total number of orders by status - - Filter orders displayed by status - - Link to each individual order - - A list of orders including at least one of my products: - - Each order item sold by me with a quantity and line-item subtotal - - A link to the item description page - - DateTime the order was placed - - Link to transition the order item to marked as shipped - - The current status of the order ("pending", "paid", "complete", "cancelled") -- View an individual order to see the user's: - - Name - - Email address - - Mailing address - - Last four digits of their credit card - - Credit card expiration date - -As a signed-in user, I **cannot**: - -- Review my own products -- View order items from a shared order that belong to another merchant -- View another user's private data (i.e. order fulfillment or product management) - -### Validations -Many of our models will have attributes that are required for our application to use and display data consistently. Each model will have attributes with requirements for a valid record. The requirements are summarized below: - -#### Merchant -- Username must be present -- Username must be unique -- Email Address must be present -- Email Address must be unique - -#### Product -- Name must be present -- Name must be unique -- Price must be present -- Price must be a number -- Price must be greater than 0 -- Product must belong to a User - -#### Order -- An Order must have one or more Order Items - -#### OrderItem -- Must belong to a Product -- Must belong to an Order -- Quantity must be present -- Quantity must be an integer -- Quantity must be greater than 0 - -#### Review -- Rating must be present -- Rating must be an integer -- Rating must be between 1 and 5 - -## Submission Guidelines -Your final project must be deployed to [Heroku](http://heroku.com). Your team will open a single pull request for the entire project. There are comprehension questions to answer with your submission that you should complete together as a group. Remember, you can submit a PR and still make some final changes to your code, so don't wait until the last minute. - -## Team Leaders -Each team will have team leaders who are responsible for keeping track of each team member's contributions. Rotate leader roles at the beginning of the second week; every team member should be in at least one leader role during the project. - -- **Stand Up Leader** - - Notifies team members about meeting schedule and ensures that everyone is present and ready - - Takes notes about each person's daily report in Stand Up - - Keeps the meeting moving -- **Task Leader** - - Leads discussion on task assignment and prioritization - - Decide if a task should be completed alone or in a pair - - Assign tasks based on... - - Individual comfort - - Desire - - Ability - - Ensures the Kanban board stays up to date - -## Stand Up Meetings -The Stand Up Leader should determine the daily time for your stand up meeting with the team. Once you come up with a time, confirm with your PM that this time will work for them. - -At the end of each day, your team's assigned Project Manager will review the Trello board to ensure it captures the updates that your team has made throughout the day. - -## Interim Demo -In a real world work environment, a team's success is measured by their product as opposed to each individual's contribution. - -Each team will present their progress and respond to questions from their Project Manager on the first Friday. Every team member will participate in these demos; the PM will ask specific questions regarding -1. The team's progress and plan for completing the project -1. The technical decisions and implementation -1. Every team member's understanding of the underlying technical structures - -## Final Presentation -Each team will present their product in a final presentation to the group on the final Friday. Your presentation should be no more than 7 minutes. The presentation should include every team member and: -- what you learned as individuals and as a group -- a short story-driven demo of interesting features - -## Due Date -This project is due EOD Apr 27 via PR against Ada-C9/betsy. - -## What Instructors Are Looking For -Check out the [feedback template](feedback.md) which lists the items instructors will be looking for as they evaluate your project. +* ... diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000000..e85f913914 --- /dev/null +++ b/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative 'config/application' + +Rails.application.load_tasks diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 0000000000..b16e53d6d5 --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,3 @@ +//= link_tree ../images +//= link_directory ../javascripts .js +//= link_directory ../stylesheets .css diff --git a/app/assets/images/.keep b/app/assets/images/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/assets/images/Failed.jpg b/app/assets/images/Failed.jpg new file mode 100644 index 0000000000..ca1ed80bf1 Binary files /dev/null and b/app/assets/images/Failed.jpg differ diff --git a/app/assets/images/aspirin.jpg b/app/assets/images/aspirin.jpg new file mode 100644 index 0000000000..5ff710c660 Binary files /dev/null and b/app/assets/images/aspirin.jpg differ diff --git a/app/assets/images/attorney_service_injury.jpeg b/app/assets/images/attorney_service_injury.jpeg new file mode 100644 index 0000000000..585fe33c5c Binary files /dev/null and b/app/assets/images/attorney_service_injury.jpeg differ diff --git a/app/assets/images/credit_repair_service.jpg b/app/assets/images/credit_repair_service.jpg new file mode 100644 index 0000000000..8452d1c875 Binary files /dev/null and b/app/assets/images/credit_repair_service.jpg differ diff --git a/app/assets/images/delorean.jpg b/app/assets/images/delorean.jpg new file mode 100644 index 0000000000..4b91f0341a Binary files /dev/null and b/app/assets/images/delorean.jpg differ diff --git a/app/assets/images/exit.jpg b/app/assets/images/exit.jpg new file mode 100644 index 0000000000..3ca5f01f37 Binary files /dev/null and b/app/assets/images/exit.jpg differ diff --git a/app/assets/images/favicon.png b/app/assets/images/favicon.png new file mode 100644 index 0000000000..27536776e7 Binary files /dev/null and b/app/assets/images/favicon.png differ diff --git a/app/assets/images/hangover_sunglasses.jpeg b/app/assets/images/hangover_sunglasses.jpeg new file mode 100644 index 0000000000..7fa4d4659c Binary files /dev/null and b/app/assets/images/hangover_sunglasses.jpeg differ diff --git a/app/assets/images/hg_wells_time_machine.jpg b/app/assets/images/hg_wells_time_machine.jpg new file mode 100644 index 0000000000..51e08aaf3b Binary files /dev/null and b/app/assets/images/hg_wells_time_machine.jpg differ diff --git a/app/assets/images/ice_pack.jpg b/app/assets/images/ice_pack.jpg new file mode 100644 index 0000000000..db66bc38db Binary files /dev/null and b/app/assets/images/ice_pack.jpg differ diff --git a/app/assets/images/kat_von_d_tattoo_cover_up.jpg b/app/assets/images/kat_von_d_tattoo_cover_up.jpg new file mode 100644 index 0000000000..723123b47b Binary files /dev/null and b/app/assets/images/kat_von_d_tattoo_cover_up.jpg differ diff --git a/app/assets/images/magic_eraser_sponges.jpeg b/app/assets/images/magic_eraser_sponges.jpeg new file mode 100644 index 0000000000..9798393de0 Binary files /dev/null and b/app/assets/images/magic_eraser_sponges.jpeg differ diff --git a/app/assets/images/mattress_pad.jpeg b/app/assets/images/mattress_pad.jpeg new file mode 100644 index 0000000000..1795484a19 Binary files /dev/null and b/app/assets/images/mattress_pad.jpeg differ diff --git a/app/assets/images/plan_b.jpeg b/app/assets/images/plan_b.jpeg new file mode 100644 index 0000000000..94a588c078 Binary files /dev/null and b/app/assets/images/plan_b.jpeg differ diff --git a/app/assets/images/regretsy_main_1.jpg b/app/assets/images/regretsy_main_1.jpg new file mode 100644 index 0000000000..7805c614f5 Binary files /dev/null and b/app/assets/images/regretsy_main_1.jpg differ diff --git a/app/assets/images/regretsy_main_2.png b/app/assets/images/regretsy_main_2.png new file mode 100644 index 0000000000..6138adee1c Binary files /dev/null and b/app/assets/images/regretsy_main_2.png differ diff --git a/app/assets/images/regretsy_main_3.jpg b/app/assets/images/regretsy_main_3.jpg new file mode 100644 index 0000000000..d54402bd7e Binary files /dev/null and b/app/assets/images/regretsy_main_3.jpg differ diff --git a/app/assets/images/shoppingcart.jpg b/app/assets/images/shoppingcart.jpg new file mode 100644 index 0000000000..92961896c6 Binary files /dev/null and b/app/assets/images/shoppingcart.jpg differ diff --git a/app/assets/images/shoppingtags.jpg b/app/assets/images/shoppingtags.jpg new file mode 100644 index 0000000000..c317bf17c3 Binary files /dev/null and b/app/assets/images/shoppingtags.jpg differ diff --git a/app/assets/images/site-icon.jpg b/app/assets/images/site-icon.jpg new file mode 100644 index 0000000000..f6bd24834a Binary files /dev/null and b/app/assets/images/site-icon.jpg differ diff --git a/app/assets/images/spot_robot_cleaner.jpg b/app/assets/images/spot_robot_cleaner.jpg new file mode 100644 index 0000000000..70989d2ad9 Binary files /dev/null and b/app/assets/images/spot_robot_cleaner.jpg differ diff --git a/app/assets/images/sunburn_cream.jpg b/app/assets/images/sunburn_cream.jpg new file mode 100644 index 0000000000..f5de3e5de6 Binary files /dev/null and b/app/assets/images/sunburn_cream.jpg differ diff --git a/app/assets/images/tardis_time_machine.jpg b/app/assets/images/tardis_time_machine.jpg new file mode 100644 index 0000000000..d01d5f8de2 Binary files /dev/null and b/app/assets/images/tardis_time_machine.jpg differ diff --git a/app/assets/images/tissue.jpg b/app/assets/images/tissue.jpg new file mode 100644 index 0000000000..bd7e6526c6 Binary files /dev/null and b/app/assets/images/tissue.jpg differ diff --git a/app/assets/images/ughmug.jpg b/app/assets/images/ughmug.jpg new file mode 100644 index 0000000000..22bd272df1 Binary files /dev/null and b/app/assets/images/ughmug.jpg differ diff --git a/app/assets/images/white_out.jpeg b/app/assets/images/white_out.jpeg new file mode 100644 index 0000000000..f2ccb0d643 Binary files /dev/null and b/app/assets/images/white_out.jpeg differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js new file mode 100644 index 0000000000..8626f9bbf7 --- /dev/null +++ b/app/assets/javascripts/application.js @@ -0,0 +1,19 @@ +// This is a manifest file that'll be compiled into application.js, which will include all the files +// listed below. +// +// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's +// vendor/assets/javascripts directory can be referenced here using a relative path. +// +// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the +// compiled file. JavaScript code in this file should be added after the last require_* statement. +// +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details +// about supported directives. +//= require jquery +$(document).foundation(); + +// +// = require rails-ujs +// = require foundation +//= require turbolinks +//= require_tree . 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/carts.js b/app/assets/javascripts/carts.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/carts.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/categories.js b/app/assets/javascripts/categories.js new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/categories.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/channels/.keep b/app/assets/javascripts/channels/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/assets/javascripts/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/sessions.js~HEAD b/app/assets/javascripts/sessions.js~HEAD new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/sessions.js~HEAD @@ -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~HEAD_0 b/app/assets/javascripts/sessions.js~HEAD_0 new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/sessions.js~HEAD_0 @@ -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~ke_mergemasterkerfluffle b/app/assets/javascripts/sessions.js~ke_mergemasterkerfluffle new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/sessions.js~ke_mergemasterkerfluffle @@ -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~ke_mergemasterkerfluffle_0 b/app/assets/javascripts/sessions.js~ke_mergemasterkerfluffle_0 new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/sessions.js~ke_mergemasterkerfluffle_0 @@ -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..e52c0d6ee4 --- /dev/null +++ b/app/assets/javascripts/users.js @@ -0,0 +1,4 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. + +$(document).foundation(); diff --git a/app/assets/javascripts/users.js~HEAD b/app/assets/javascripts/users.js~HEAD new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/users.js~HEAD @@ -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~ke_mergemasterkerfluffle b/app/assets/javascripts/users.js~ke_mergemasterkerfluffle new file mode 100644 index 0000000000..dee720facd --- /dev/null +++ b/app/assets/javascripts/users.js~ke_mergemasterkerfluffle @@ -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..eef18af806 --- /dev/null +++ b/app/assets/stylesheets/_settings.scss @@ -0,0 +1,867 @@ +// 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: #1c1c1f, + secondary: #A8D0E6, + success: #7bdec0, + warning: #F8E9A1, + alert: #F76C6C, +); +$light-gray: #e6e6e6; +$medium-gray: #cacaca; +$dark-gray: #8a8a8a; +$black: #0a0a0a; +$white: #fefefe; +$body-background: $white; +$body-font-color: $black; +$body-font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif; +$body-antialiased: true; +$global-margin: 1rem; +$global-padding: 1rem; +$global-position: 1rem; +$global-weight-normal: normal; +$global-weight-bold: bold; +$global-radius: 0; +$global-menu-padding: 0.7rem 1rem; +$global-menu-nested-margin: 1rem; +$global-text-direction: ltr; +$global-flexbox: true; +$global-prototype-breakpoints: false; +$global-button-cursor: auto; +$global-color-pick-contrast-tolerance: 0; +$print-transparent-backgrounds: true; + +@include add-foundation-colors; + +// 2. Breakpoints +// -------------- + +$breakpoints: ( + small: 0, + medium: 640px, + large: 1024px, + xlarge: 1200px, + xxlarge: 1440px, +); +$print-breakpoint: large; +$breakpoint-classes: (small medium large); + +// 3. The Grid +// ----------- + +$grid-row-width: $global-width; +$grid-column-count: 12; +$grid-column-gutter: ( + small: 20px, + medium: 30px, +); +$grid-column-align-edge: true; +$grid-column-alias: 'columns'; +$block-grid-max: 8; + +// 4. Base Typography +// ------------------ + +$header-font-family: $body-font-family; +$header-font-weight: $global-weight-normal; +$header-font-style: normal; +$font-family-monospace: Consolas, 'Liberation Mono', Courier, monospace; +$header-color: inherit; +$header-lineheight: 1.4; +$header-margin-bottom: 0.5rem; +$header-styles: ( + small: ( + 'h1': ('font-size': 24), + 'h2': ('font-size': 20), + 'h3': ('font-size': 19), + 'h4': ('font-size': 18), + 'h5': ('font-size': 17), + 'h6': ('font-size': 16), + ), + medium: ( + 'h1': ('font-size': 48), + 'h2': ('font-size': 40), + 'h3': ('font-size': 31), + 'h4': ('font-size': 25), + 'h5': ('font-size': 20), + 'h6': ('font-size': 16), + ), +); +$header-text-rendering: optimizeLegibility; +$small-font-size: 80%; +$header-small-font-color: $medium-gray; +$paragraph-lineheight: 1.6; +$paragraph-margin-bottom: 1rem; +$paragraph-text-rendering: optimizeLegibility; +$code-color: $black; +$code-font-family: $font-family-monospace; +$code-font-weight: $global-weight-normal; +$code-background: $light-gray; +$code-border: 1px solid $medium-gray; +$code-padding: rem-calc(2 5 1); +$anchor-color: $primary-color; +$anchor-color-hover: scale-color($anchor-color, $lightness: -14%); +$anchor-text-decoration: none; +$anchor-text-decoration-hover: none; +$hr-width: $global-width; +$hr-border: 1px solid $medium-gray; +$hr-margin: rem-calc(20) auto; +$list-lineheight: $paragraph-lineheight; +$list-margin-bottom: $paragraph-margin-bottom; +$list-style-type: disc; +$list-style-position: outside; +$list-side-margin: 1.25rem; +$list-nested-side-margin: 1.25rem; +$defnlist-margin-bottom: 1rem; +$defnlist-term-weight: $global-weight-bold; +$defnlist-term-margin-bottom: 0.3rem; +$blockquote-color: $dark-gray; +$blockquote-padding: rem-calc(9 20 0 19); +$blockquote-border: 1px solid $medium-gray; +$cite-font-size: rem-calc(13); +$cite-color: $dark-gray; +$cite-pseudo-content: '\2014 \0020'; +$keystroke-font: $font-family-monospace; +$keystroke-color: $black; +$keystroke-background: $light-gray; +$keystroke-padding: rem-calc(2 4 0); +$keystroke-radius: $global-radius; +$abbr-underline: 1px dotted $black; + +// 5. Typography Helpers +// --------------------- + +$lead-font-size: $global-font-size * 1.25; +$lead-lineheight: 1.6; +$subheader-lineheight: 1.4; +$subheader-color: $dark-gray; +$subheader-font-weight: $global-weight-normal; +$subheader-margin-top: 0.2rem; +$subheader-margin-bottom: 0.5rem; +$stat-font-size: 2.5rem; + +// 6. Abide +// -------- + +$abide-inputs: true; +$abide-labels: true; +$input-background-invalid: get-color(alert); +$form-label-color-invalid: get-color(alert); +$input-error-color: get-color(alert); +$input-error-font-size: rem-calc(12); +$input-error-font-weight: $global-weight-bold; + +// 7. Accordion +// ------------ + +$accordion-background: $white; +$accordion-plusminus: true; +$accordion-title-font-size: rem-calc(12); +$accordion-item-color: $primary-color; +$accordion-item-background-hover: $light-gray; +$accordion-item-padding: 1.25rem 1rem; +$accordion-content-background: $white; +$accordion-content-border: 1px solid $light-gray; +$accordion-content-color: $body-font-color; +$accordion-content-padding: 1rem; + +// 8. Accordion Menu +// ----------------- + +$accordionmenu-padding: $global-menu-padding; +$accordionmenu-nested-margin: $global-menu-nested-margin; +$accordionmenu-submenu-padding: $accordionmenu-padding; +$accordionmenu-arrows: true; +$accordionmenu-arrow-color: $primary-color; +$accordionmenu-item-background: null; +$accordionmenu-border: null; +$accordionmenu-submenu-toggle-background: null; +$accordion-submenu-toggle-border: $accordionmenu-border; +$accordionmenu-submenu-toggle-width: 40px; +$accordionmenu-submenu-toggle-height: $accordionmenu-submenu-toggle-width; +$accordionmenu-arrow-size: 6px; + +// 9. Badge +// -------- + +$badge-background: $primary-color; +$badge-color: $white; +$badge-color-alt: $black; +$badge-palette: $foundation-palette; +$badge-padding: 0.3em; +$badge-minwidth: 2.1em; +$badge-font-size: 0.6rem; + +// 10. Breadcrumbs +// --------------- + +$breadcrumbs-margin: 0 0 $global-margin 0; +$breadcrumbs-item-font-size: rem-calc(11); +$breadcrumbs-item-color: $primary-color; +$breadcrumbs-item-color-current: $black; +$breadcrumbs-item-color-disabled: $medium-gray; +$breadcrumbs-item-margin: 0.75rem; +$breadcrumbs-item-uppercase: true; +$breadcrumbs-item-separator: true; +$breadcrumbs-item-separator-item: '/'; +$breadcrumbs-item-separator-item-rtl: '\\'; +$breadcrumbs-item-separator-color: $medium-gray; + +// 11. Button +// ---------- + +$button-font-family: inherit; +$button-padding: 0.85em 1em; +$button-margin: 0 0 $global-margin 0; +$button-fill: solid; +$button-background: $primary-color; +$button-background-hover: scale-color($button-background, $lightness: -15%); +$button-color: $white; +$button-color-alt: $black; +$button-radius: $global-radius; +$button-hollow-border-width: 1px; +$button-sizes: ( + tiny: 0.6rem, + small: 0.75rem, + default: 0.9rem, + large: 1.25rem, +); +$button-palette: $foundation-palette; +$button-opacity-disabled: 0.25; +$button-background-hover-lightness: -20%; +$button-hollow-hover-lightness: -50%; +$button-transition: background-color 0.25s ease-out, color 0.25s ease-out; + +// 12. Button Group +// ---------------- + +$buttongroup-margin: 1rem; +$buttongroup-spacing: 1px; +$buttongroup-child-selector: '.button'; +$buttongroup-expand-max: 6; +$buttongroup-radius-on-each: true; + +// 13. Callout +// ----------- + +$callout-background: $white; +$callout-background-fade: 85%; +$callout-border: 1px solid rgba($black, 0.25); +$callout-margin: 0 0 1rem 0; +$callout-padding: 1rem; +$callout-font-color: $body-font-color; +$callout-font-color-alt: $body-background; +$callout-radius: $global-radius; +$callout-link-tint: 30%; + +// 14. Card +// -------- + +$card-background: $white; +$card-font-color: $body-font-color; +$card-divider-background: $light-gray; +$card-border: 1px solid $light-gray; +$card-shadow: none; +$card-border-radius: $global-radius; +$card-padding: $global-padding; +$card-margin-bottom: $global-margin; + +// 15. Close Button +// ---------------- + +$closebutton-position: right top; +$closebutton-offset-horizontal: ( + small: 0.66rem, + medium: 1rem, +); +$closebutton-offset-vertical: ( + small: 0.33em, + medium: 0.5rem, +); +$closebutton-size: ( + small: 1.5em, + medium: 2em, +); +$closebutton-lineheight: 1; +$closebutton-color: $dark-gray; +$closebutton-color-hover: $black; + +// 16. Drilldown +// ------------- + +$drilldown-transition: transform 0.15s linear; +$drilldown-arrows: true; +$drilldown-padding: $global-menu-padding; +$drilldown-nested-margin: 0; +$drilldown-background: $white; +$drilldown-submenu-padding: $drilldown-padding; +$drilldown-submenu-background: $white; +$drilldown-arrow-color: $primary-color; +$drilldown-arrow-size: 6px; + +// 17. Dropdown +// ------------ + +$dropdown-padding: 1rem; +$dropdown-background: $body-background; +$dropdown-border: 1px solid $medium-gray; +$dropdown-font-size: 1rem; +$dropdown-width: 300px; +$dropdown-radius: $global-radius; +$dropdown-sizes: ( + tiny: 100px, + small: 200px, + large: 400px, +); + +// 18. Dropdown Menu +// ----------------- + +$dropdownmenu-arrows: true; +$dropdownmenu-arrow-color: $anchor-color; +$dropdownmenu-arrow-size: 6px; +$dropdownmenu-arrow-padding: 1.5rem; +$dropdownmenu-min-width: 200px; +$dropdownmenu-background: $white; +$dropdownmenu-submenu-background: $dropdownmenu-background; +$dropdownmenu-padding: $global-menu-padding; +$dropdownmenu-nested-margin: 0; +$dropdownmenu-submenu-padding: $dropdownmenu-padding; +$dropdownmenu-border: 1px solid $medium-gray; +$dropdown-menu-item-color-active: get-color(primary); +$dropdown-menu-item-background-active: transparent; + +// 19. Flexbox Utilities +// --------------------- + +$flex-source-ordering-count: 6; +$flexbox-responsive-breakpoints: true; + +// 20. Forms +// --------- + +$fieldset-border: 1px solid $medium-gray; +$fieldset-padding: rem-calc(20); +$fieldset-margin: rem-calc(18 0); +$legend-padding: rem-calc(0 3); +$form-spacing: rem-calc(16); +$helptext-color: $black; +$helptext-font-size: rem-calc(13); +$helptext-font-style: italic; +$input-prefix-color: $black; +$input-prefix-background: $light-gray; +$input-prefix-border: 1px solid $medium-gray; +$input-prefix-padding: 1rem; +$form-label-color: $black; +$form-label-font-size: rem-calc(14); +$form-label-font-weight: $global-weight-normal; +$form-label-line-height: 1.8; +$select-background: $white; +$select-triangle-color: $dark-gray; +$select-radius: $global-radius; +$input-color: $black; +$input-placeholder-color: $medium-gray; +$input-font-family: inherit; +$input-font-size: rem-calc(16); +$input-font-weight: $global-weight-normal; +$input-line-height: $global-lineheight; +$input-background: $white; +$input-background-focus: $white; +$input-background-disabled: $light-gray; +$input-border: 1px solid $medium-gray; +$input-border-focus: 1px solid $dark-gray; +$input-padding: $form-spacing / 2; +$input-shadow: inset 0 1px 2px rgba($black, 0.1); +$input-shadow-focus: 0 0 5px $medium-gray; +$input-cursor-disabled: not-allowed; +$input-transition: box-shadow 0.5s, border-color 0.25s ease-in-out; +$input-number-spinners: true; +$input-radius: $global-radius; +$form-button-radius: $global-radius; + +// 21. Label +// --------- + +$label-background: $primary-color; +$label-color: $white; +$label-color-alt: $black; +$label-palette: $foundation-palette; +$label-font-size: 0.8rem; +$label-padding: 0.33333rem 0.5rem; +$label-radius: $global-radius; + +// 22. Media Object +// ---------------- + +$mediaobject-margin-bottom: $global-margin; +$mediaobject-section-padding: $global-padding; +$mediaobject-image-width-stacked: 100%; + +// 23. Menu +// -------- + +$menu-margin: 0; +$menu-nested-margin: $global-menu-nested-margin; +$menu-items-padding: $global-menu-padding; +$menu-simple-margin: 1rem; +$menu-item-color-active: $white; +$menu-item-background-active: get-color(primary); +$menu-icon-spacing: 0.25rem; +$menu-item-background-hover: $light-gray; +$menu-state-back-compat: true; +$menu-centered-back-compat: true; +$menu-icons-back-compat: true; + +// 24. Meter +// --------- + +$meter-height: 1rem; +$meter-radius: $global-radius; +$meter-background: $medium-gray; +$meter-fill-good: $success-color; +$meter-fill-medium: $warning-color; +$meter-fill-bad: $alert-color; + +// 25. Off-canvas +// -------------- + +$offcanvas-sizes: ( + small: 250px, +); +$offcanvas-vertical-sizes: ( + small: 250px, +); +$offcanvas-background: $light-gray; +$offcanvas-shadow: 0 0 10px rgba($black, 0.7); +$offcanvas-inner-shadow-size: 20px; +$offcanvas-inner-shadow-color: rgba($black, 0.25); +$offcanvas-overlay-zindex: 11; +$offcanvas-push-zindex: 12; +$offcanvas-overlap-zindex: 13; +$offcanvas-reveal-zindex: 12; +$offcanvas-transition-length: 0.5s; +$offcanvas-transition-timing: ease; +$offcanvas-fixed-reveal: true; +$offcanvas-exit-background: rgba($white, 0.25); +$maincontent-class: 'off-canvas-content'; + +// 26. Orbit + +$orbit-bullet-background: $medium-gray; +$orbit-bullet-background-active: $dark-gray; +$orbit-bullet-diameter: 1.2rem; +$orbit-bullet-margin: 0.1rem; +$orbit-bullet-margin-top: 0.8rem; +$orbit-bullet-margin-bottom: 0.8rem; +$orbit-caption-background: rgba($black, 0.5); +$orbit-caption-padding: 1rem; +$orbit-control-background-hover: rgba($black, 0.5); +$orbit-control-padding: 1rem; +$orbit-control-zindex: 10; + +// 27. Pagination +// -------------- + +$pagination-font-size: rem-calc(14); +$pagination-margin-bottom: $global-margin; +$pagination-item-color: $black; +$pagination-item-padding: rem-calc(3 10); +$pagination-item-spacing: rem-calc(1); +$pagination-radius: $global-radius; +$pagination-item-background-hover: $light-gray; +$pagination-item-background-current: $primary-color; +$pagination-item-color-current: $white; +$pagination-item-color-disabled: $medium-gray; +$pagination-ellipsis-color: $black; +$pagination-mobile-items: false; +$pagination-mobile-current-item: false; +$pagination-arrows: true; + +// 28. Progress Bar +// ---------------- + +$progress-height: 1rem; +$progress-background: $medium-gray; +$progress-margin-bottom: $global-margin; +$progress-meter-background: $primary-color; +$progress-radius: $global-radius; + +// 29. Prototype Arrow +// ------------------- + +$prototype-arrow-directions: ( + down, + up, + right, + left +); +$prototype-arrow-size: 0.4375rem; +$prototype-arrow-color: $black; + +// 30. Prototype Border-Box +// ------------------------ + +$prototype-border-box-breakpoints: $global-prototype-breakpoints; + +// 31. Prototype Border-None +// ------------------------- + +$prototype-border-none-breakpoints: $global-prototype-breakpoints; + +// 32. Prototype Bordered +// ---------------------- + +$prototype-bordered-breakpoints: $global-prototype-breakpoints; +$prototype-border-width: rem-calc(1); +$prototype-border-type: solid; +$prototype-border-color: $medium-gray; + +// 33. Prototype Display +// --------------------- + +$prototype-display-breakpoints: $global-prototype-breakpoints; +$prototype-display: ( + inline, + inline-block, + block, + table, + table-cell +); + +// 34. Prototype Font-Styling +// -------------------------- + +$prototype-font-breakpoints: $global-prototype-breakpoints; +$prototype-wide-letter-spacing: rem-calc(4); +$prototype-font-normal: $global-weight-normal; +$prototype-font-bold: $global-weight-bold; + +// 35. Prototype List-Style-Type +// ----------------------------- + +$prototype-list-breakpoints: $global-prototype-breakpoints; +$prototype-style-type-unordered: ( + disc, + circle, + square +); +$prototype-style-type-ordered: ( + decimal, + lower-alpha, + lower-latin, + lower-roman, + upper-alpha, + upper-latin, + upper-roman +); + +// 36. Prototype Overflow +// ---------------------- + +$prototype-overflow-breakpoints: $global-prototype-breakpoints; +$prototype-overflow: ( + visible, + hidden, + scroll +); + +// 37. Prototype Position +// ---------------------- + +$prototype-position-breakpoints: $global-prototype-breakpoints; +$prototype-position: ( + static, + relative, + absolute, + fixed +); +$prototype-position-z-index: 975; + +// 38. Prototype Rounded +// --------------------- + +$prototype-rounded-breakpoints: $global-prototype-breakpoints; +$prototype-border-radius: rem-calc(3); + +// 39. Prototype Separator +// ----------------------- + +$prototype-separator-breakpoints: $global-prototype-breakpoints; +$prototype-separator-align: center; +$prototype-separator-height: rem-calc(2); +$prototype-separator-width: 3rem; +$prototype-separator-background: $primary-color; +$prototype-separator-margin-top: $global-margin; + +// 40. Prototype Shadow +// -------------------- + +$prototype-shadow-breakpoints: $global-prototype-breakpoints; +$prototype-box-shadow: 0 2px 5px 0 rgba(0,0,0,.16), + 0 2px 10px 0 rgba(0,0,0,.12); + +// 41. Prototype Sizing +// -------------------- + +$prototype-sizing-breakpoints: $global-prototype-breakpoints; +$prototype-sizing: ( + width, + height +); +$prototype-sizes: ( + 25: 25%, + 50: 50%, + 75: 75%, + 100: 100% +); + +// 42. Prototype Spacing +// --------------------- + +$prototype-spacing-breakpoints: $global-prototype-breakpoints; +$prototype-spacers-count: 3; + +// 43. Prototype Text-Decoration +// ----------------------------- + +$prototype-decoration-breakpoints: $global-prototype-breakpoints; +$prototype-text-decoration: ( + overline, + underline, + line-through, +); + +// 44. Prototype Text-Transformation +// --------------------------------- + +$prototype-transformation-breakpoints: $global-prototype-breakpoints; +$prototype-text-transformation: ( + lowercase, + uppercase, + capitalize +); + +// 45. Prototype Text-Utilities +// ---------------------------- + +$prototype-utilities-breakpoints: $global-prototype-breakpoints; +$prototype-text-overflow: ellipsis; + +// 46. Responsive Embed +// -------------------- + +$responsive-embed-margin-bottom: rem-calc(16); +$responsive-embed-ratios: ( + default: 4 by 3, + widescreen: 16 by 9, +); + +// 47. Reveal +// ---------- + +$reveal-background: $white; +$reveal-width: 600px; +$reveal-max-width: $global-width; +$reveal-padding: $global-padding; +$reveal-border: 1px solid $medium-gray; +$reveal-radius: $global-radius; +$reveal-zindex: 1005; +$reveal-overlay-background: rgba($black, 0.45); + +// 48. Slider +// ---------- + +$slider-width-vertical: 0.5rem; +$slider-transition: all 0.2s ease-in-out; +$slider-height: 0.5rem; +$slider-background: $light-gray; +$slider-fill-background: $medium-gray; +$slider-handle-height: 1.4rem; +$slider-handle-width: 1.4rem; +$slider-handle-background: $primary-color; +$slider-opacity-disabled: 0.25; +$slider-radius: $global-radius; + +// 49. Switch +// ---------- + +$switch-background: $medium-gray; +$switch-background-active: $primary-color; +$switch-height: 2rem; +$switch-height-tiny: 1.5rem; +$switch-height-small: 1.75rem; +$switch-height-large: 2.5rem; +$switch-radius: $global-radius; +$switch-margin: $global-margin; +$switch-paddle-background: $white; +$switch-paddle-offset: 0.25rem; +$switch-paddle-radius: $global-radius; +$switch-paddle-transition: all 0.25s ease-out; + +// 50. Table +// --------- + +$table-background: $white; +$table-color-scale: 5%; +$table-border: 1px solid smart-scale($table-background, $table-color-scale); +$table-padding: rem-calc(8 10 10); +$table-hover-scale: 2%; +$table-row-hover: darken($table-background, $table-hover-scale); +$table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale); +$table-is-striped: true; +$table-striped-background: smart-scale($table-background, $table-color-scale); +$table-stripe: even; +$table-head-background: smart-scale($table-background, $table-color-scale / 2); +$table-head-row-hover: darken($table-head-background, $table-hover-scale); +$table-foot-background: smart-scale($table-background, $table-color-scale); +$table-foot-row-hover: darken($table-foot-background, $table-hover-scale); +$table-head-font-color: $body-font-color; +$table-foot-font-color: $body-font-color; +$show-header-for-stacked: false; +$table-stack-breakpoint: medium; + +// 51. Tabs +// -------- + +$tab-margin: 0; +$tab-background: $white; +$tab-color: $primary-color; +$tab-background-active: $light-gray; +$tab-active-color: $primary-color; +$tab-item-font-size: rem-calc(12); +$tab-item-background-hover: $white; +$tab-item-padding: 1.25rem 1.5rem; +$tab-expand-max: 6; +$tab-content-background: $white; +$tab-content-border: $light-gray; +$tab-content-color: $body-font-color; +$tab-content-padding: 1rem; + +// 52. Thumbnail +// ------------- + +$thumbnail-border: solid 4px $white; +$thumbnail-margin-bottom: $global-margin; +$thumbnail-shadow: 0 0 0 1px rgba($black, 0.2); +$thumbnail-shadow-hover: 0 0 6px 1px rgba($primary-color, 0.5); +$thumbnail-transition: box-shadow 200ms ease-out; +$thumbnail-radius: $global-radius; + +// 53. Title Bar +// ------------- + +$titlebar-background: $black; +$titlebar-color: $white; +$titlebar-padding: 0.5rem; +$titlebar-text-font-weight: bold; +$titlebar-icon-color: $white; +$titlebar-icon-color-hover: $medium-gray; +$titlebar-icon-spacing: 0.25rem; + +// 54. Tooltip +// ----------- + +$has-tip-cursor: help; +$has-tip-font-weight: $global-weight-bold; +$has-tip-border-bottom: dotted 1px $dark-gray; +$tooltip-background-color: $black; +$tooltip-color: $white; +$tooltip-padding: 0.75rem; +$tooltip-max-width: 10rem; +$tooltip-font-size: $small-font-size; +$tooltip-pip-width: 0.75rem; +$tooltip-pip-height: $tooltip-pip-width * 0.866; +$tooltip-radius: $global-radius; + +// 55. Top Bar +// ----------- + +$topbar-padding: 0.5rem; +$topbar-background: $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; +$xy-block-grid-max: 8; diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css new file mode 100644 index 0000000000..9020a4792d --- /dev/null +++ b/app/assets/stylesheets/application.css @@ -0,0 +1,160 @@ +/* +* This is a manifest file that'll be compiled into application.css, which will include all the files +* listed below. +* +* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's +* vendor/assets/stylesheets directory can be referenced here using a relative path. +* +* You're free to add application-wide styles to this file and they'll appear at the bottom of the +* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS +* files in this directory. Styles in this file should be added after the last require_* statement. +* It is generally better to create a new file per style scope. +*= require normalize-rails + +* +*= require_tree . +*= require_self +*= require foundation_and_overrides + +*/ + + +* { + font-family: 'Roboto Condensed', sans-serif; +} + +body ul { + list-style-type: none; +} + +h1 img { + max-height: 50px; +} + +nav { + background-color: whitesmoke; +} + +nav ul { + list-style-type: none; + z-index: 8; +} + +@media (min-width: 800px) { + .menu{ + flex-direction: row; + justify-content: flex-end; + margin-right: 2em; + z-index: 8; + } + + .menu li:first-of-type { + align-self: flex-start; + z-index: 8; + } + + .menu-item-has-children > a:after{ + font-size: .75em; + content: '▼'; + padding: .5em; + position: relative; + } + + nav ul ul { + display: none; + position: absolute; + } +} + +@media (min-width: 800px) { + nav ul ul { + display: none; + position: absolute; + } +} + +nav ul li:hover > ul { + display:block; + padding-left: 0; +} + +@media (min-width: 800px) { + nav ul li:hover > ul { + padding-left:0; + background:hsl(0, 0%, 46%); + + } + + nav ul li:hover > ul a{ + color:hsl(0, 0%, 0%); + } + + .sub-menu li { + display:flex; + padding-right:2em; + } + + .sub-menu li:hover, li a:hover{ + background:hsl(0, 0%, 86%); + color:hsl(0, 0%, 46%); + } + + nav ul ul ul{ + margin:0 0 0 100%; + box-shadow: 0 0 2px hsla(0, 0%, 0%, 0.6); + } +} + +li > i:after { + font-size: .75em; + padding: .5em; +} + + +footer { + font-size: 0.5em; + display: flex; + justify-content: flex-end; +} + +.product-list { + background-color: whitesmoke; + width: 80%; + box-sizing: border-box; + display: flex; + flex-direction: row; + flex-wrap: wrap; + font-size: 1em; + justify-content: flex-start; + width: 100vw; +} + +.product-list article > img { + width: 20vw; + border-radius: 5%; + float: left; + padding: 10px; +} + +.product-list > section { + width: 600px; + margin: 5px; + padding: 10px; +} + +.product-item { + border: 2px groove lightgrey; + box-sizing: border-box; + background-color: white; +} + +.product-item input.number-field { + width: 100px; +} + + +div.caption-1 a, div.caption-2 a { + color: white; + background: hsla(300, 2%, 6%, .85); + padding: 2vh 4vw; +} diff --git a/app/assets/stylesheets/browserslist b/app/assets/stylesheets/browserslist new file mode 100644 index 0000000000..6019618a9a --- /dev/null +++ b/app/assets/stylesheets/browserslist @@ -0,0 +1,4 @@ +last 2 versions +ie >= 9 +Android >= 2.3 +ios >= 7 diff --git a/app/assets/stylesheets/carts.scss b/app/assets/stylesheets/carts.scss new file mode 100644 index 0000000000..f7fbe0efb7 --- /dev/null +++ b/app/assets/stylesheets/carts.scss @@ -0,0 +1,47 @@ +// Place all the styles related to the carts controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ + +td.img-thumbnail { + width: 30vw; + display: flex; + align-content: center; +} + +tr.cart-items { + height: 20vh; + border-bottom-color: rgb(35, 39, 42); +} + +tr.cart-items img { + height: 20vh; + padding: 2vh +} + +.checkout { + padding: 20px; + background-image: image-url('shoppingtags.jpg'); + background-position: right; + opacity: 0.65; +} + +.cart-products { + padding: 20px; + background-image: image-url('shoppingtags.jpg'); + background-position: left; + opacity: 0.65; +} + + + +.form { + width: 100%; + padding: 12px; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; + margin-top: 6px; + margin-bottom: 16px; + background-color: #f1f1f1; + +} diff --git a/app/assets/stylesheets/categories.scss b/app/assets/stylesheets/categories.scss new file mode 100644 index 0000000000..0b08e8448a --- /dev/null +++ b/app/assets/stylesheets/categories.scss @@ -0,0 +1,7 @@ +// 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/ + +body li { + list-style-type: none; +} diff --git a/app/assets/stylesheets/foundation_and_overrides.scss b/app/assets/stylesheets/foundation_and_overrides.scss new file mode 100644 index 0000000000..7baee0be26 --- /dev/null +++ b/app/assets/stylesheets/foundation_and_overrides.scss @@ -0,0 +1,89 @@ +@charset 'utf-8'; + +@import 'settings'; +@import 'foundation'; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @import 'motion-ui/motion-ui'; + +// We include everything by default. To slim your CSS, remove components you don't use. + +@include foundation-global-styles; +@include foundation-xy-grid-classes; +//@include foundation-grid; +//@include foundation-flex-grid; +@include foundation-flex-classes; +@include foundation-typography; +@include foundation-forms; +@include foundation-button; +@include foundation-accordion; +@include foundation-accordion-menu; +@include foundation-badge; +@include foundation-breadcrumbs; +@include foundation-button-group; +@include foundation-callout; +@include foundation-card; +@include foundation-close-button; +@include foundation-menu; +@include foundation-menu-icon; +@include foundation-drilldown-menu; +@include foundation-dropdown; +@include foundation-dropdown-menu; +@include foundation-responsive-embed; +@include foundation-label; +@include foundation-media-object; +@include foundation-off-canvas; +@include foundation-orbit; +@include foundation-pagination; +@include foundation-progress-bar; +@include foundation-slider; +@include foundation-sticky; +@include foundation-reveal; +@include foundation-switch; +@include foundation-table; +@include foundation-tabs; +@include foundation-thumbnail; +@include foundation-title-bar; +@include foundation-tooltip; +@include foundation-top-bar; +@include foundation-visibility-classes; +@include foundation-float-classes; + +// If you'd like to include motion-ui the foundation-rails gem comes prepackaged with it, uncomment the 3 @imports, if you are not using the gem you need to install the motion-ui sass package. +// +// @include motion-ui-transitions; +// @include motion-ui-animations; +@import 'motion-ui/motion-ui'; +@include motion-ui-transitions; +@include motion-ui-animations; + + +.status { + border-radius: 5px; + background-color: $light-gray; + padding: 20px 25px; + margin-top: 30px; +} + +.status.success { + h3 { + color: $dark-gray; + font-size: 1.25em; + font-weight: 300; + } +} + +.status.failure { + h3 { + color: #C70039; + } +} + +.status.failure, { + h3 { + font-weight: normal; + font-size: 1.25em; + font-weight: 300; + } +} diff --git a/app/assets/stylesheets/products.scss b/app/assets/stylesheets/products.scss new file mode 100644 index 0000000000..b56325b2b2 --- /dev/null +++ b/app/assets/stylesheets/products.scss @@ -0,0 +1,81 @@ +// 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/ + + +.parallax-1 { + /* The image used */ + background-image: image-url('ughmug.jpg'); + width: 100vw; + height: 500px; + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + position: relative; + opacity: 0.65; +} + +.parallax-2 { + background-image: image-url('shoppingcart.jpg'); + width: 100vw; + height: 500px; + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + position: relative; + opacity: 0.65; +} + +div { + display: inline-block; +} + +.caption-1 { + position: absolute; + left: 0; + top: 30%; + width: 100%; + text-align: center; + color: #000; + font-size: 2em; +} + +.caption-2 { + position: absolute; + left: 0; + top: 100%; + width: 100%; + text-align: center; + color: #000; + font-size: 2em; +} + +.parallax-3 { + background-image: image-url('Failed.jpg'); + width: 100vw; + height: 500px; + background-attachment: fixed; + background-position: center; + background-repeat: no-repeat; + background-size: cover; + position: relative; + opacity: 0.65; +} + +.product-show { + width: 80%; + padding: 12px; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; + margin-top: 6px; + margin-bottom: 16px; + background-color: #f1f1f1; + align-items: center; +} + +.product-show img { + width: 300px; +} diff --git a/app/assets/stylesheets/reviews.scss b/app/assets/stylesheets/reviews.scss new file mode 100644 index 0000000000..11bbb12cd5 --- /dev/null +++ b/app/assets/stylesheets/reviews.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Reviews controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/sessions.scss b/app/assets/stylesheets/sessions.scss new file mode 100644 index 0000000000..7bef9cf826 --- /dev/null +++ b/app/assets/stylesheets/sessions.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the sessions controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/users.scss b/app/assets/stylesheets/users.scss new file mode 100644 index 0000000000..83355389c1 --- /dev/null +++ b/app/assets/stylesheets/users.scss @@ -0,0 +1,131 @@ +// 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/ + +.user-info { + display: flex; + flex-direction: column; + justify-content: flex-start; + font-weight: bold; + color: #374785; + background-color: whitesmoke; + border: 1px solid lightgrey; + width: 30vw; + align-items: center; +} + +.user-info h3 { + padding: 2vw; +} + +.user-info p { + max-width: 300px; + text-align: center; +} + +.table { + padding-top: 10px; +} + +/* Tabbed Boxes */ +@media (min-width: 800px){ +.tabset > input[type="radio"] { + position: absolute; + left: -200vw; +} + +.tabset .tab-panel { + display: none; +} + +.tabset > input:first-child:checked ~ .tab-panels > .tab-panel:first-child, +.tabset > input:nth-child(3):checked ~ .tab-panels > .tab-panel:nth-child(2), +.tabset > input:nth-child(5):checked ~ .tab-panels > .tab-panel:nth-child(3), +.tabset > input:nth-child(7):checked ~ .tab-panels > .tab-panel:nth-child(4), +.tabset > input:nth-child(9):checked ~ .tab-panels > .tab-panel:nth-child(5), +.tabset > input:nth-child(11):checked ~ .tab-panels > .tab-panel:nth-child(6) { + display: block; +} + +/* + Styling +*/ + +.tabset > label { + position: relative; + display: inline-block; + padding: 15px 15px 25px; + border: 1px solid transparent; + border-bottom: 0; + cursor: pointer; + font-weight: 600; +} + +.tabset > label::after { + content: ""; + position: absolute; + left: 15px; + bottom: 10px; + width: 22px; + height: 4px; + background: #8d8d8d; +} + +.tabset > label:hover, +.tabset > input:focus + label { + color: #06c; +} + +.tabset > label:hover::after, +.tabset > input:focus + label::after, +.tabset > input:checked + label::after { + background: #06c; +} + +.tabset > input:checked + label { + border-color: #ccc; + border-bottom: 1px solid #fff; + margin-bottom: -1px; +} + +.tab-panel { + padding: 30px 0; + border-top: 1px solid #ccc; + max-width: 70vw; + min-width: 70vw; +} + +/* + Demo purposes only +*/ +// *, +// *:before, +// *:after { +// box-sizing: border-box; +// } +// +// body { +// padding: 30px; +// } +// +// .tabset { +// max-width: 65em; +// } +} + +// General Styling +section.merchant-display { + display: flex; + flex-flow: wrap row; + align-content: stretch; +} + +img.merchant-img { + border-radius: 80%; + max-width: 20vw; + margin: 5vh 0; +} + +.merchant-list { + margin: 10px; +} 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..f432698433 --- /dev/null +++ b/app/controllers/application_controller.rb @@ -0,0 +1,41 @@ +class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + + before_action :set_order + before_action :find_product + before_action :current_user + before_action :require_login + + def render_404 + raise ActionController::RoutingError.new('Not Found') + end + + def set_order + @order = Order.find_by(id: session[:order_id]) + if !@order || @order.status == "paid" + @order = Order.create(status: :pending) + session[:order_id] = @order.id + end + end + + def find_product + if params[:product_id] + @product = Product.where(retired: false).where(id: params[:product_id]).first + head :not_found unless @product + end + end + + def current_user + @login_user ||= User.find_by(id: session[:user_id]) if session[:user_id] + end + + def require_login + unless current_user + flash[:status] = :failure + flash[:result_text] = "You must log in to see this content" + redirect_back fallback_location: root_path + end + end + + +end diff --git a/app/controllers/carts_controller.rb b/app/controllers/carts_controller.rb new file mode 100644 index 0000000000..731a94ee3c --- /dev/null +++ b/app/controllers/carts_controller.rb @@ -0,0 +1,116 @@ +class CartsController < ApplicationController +before_action :reload_order, only: [:show] +skip_before_action :require_login + + def show + @order + @products = @order.products + @orderitems = @order.orderitems + end + + def edit; end + + def update + orderitem = @order.orderitems.find_by(product_id: params[:product_id]) + + orderitem.quantity = params[:quantity] + + if orderitem.save + flash[:status] = :success + if orderitem.quantity == 0 + orderitem.destroy + flash[:result_text] = "Removed #{@product.name}" + else + flash[:result_text] = "Successfully changed #{@product.name} quantity to #{params[:quantity]}." + end + else + flash.now[:status] = :failure + flash.now[:messages] = orderitem.errors.messages + render :show + end + redirect_to cart_path(@order) + end + + def add_to_cart + flash[:status] = :failure + quantity = params[:quantity].to_i + if @product.sufficient_stock(quantity) && quantity != 0 + orderitem = Orderitem.new(product: @product, order_id: @order.id, quantity: quantity) + orderitem = @order.find_existing(orderitem) + + if orderitem.save + flash[:status] = :success + flash[:result_text] = "Successfully added #{quantity} #{@product.name} to cart" + else + flash[:messages] = orderitem.errors.messages + end + else + flash[:result_text] = "Could not add #{quantity} quantity of #{@product.name} to cart" + flash[:messages] = @product.errors.messages + end + redirect_back fallback_location: product_path(@product) + end + + def checkout + + @paymentinfo = Buyerdetail.new + end + + def finalize + @paymentinfo = Buyerdetail.new(payment_params) + @paymentinfo.assign_attributes(order_id: @order.id) + + if @paymentinfo.save + @order.status = :paid + @order.assign_attributes(buyerdetail_id: @paymentinfo.id) + + if @order.save + @order.products.each do |product| + quantity = Orderitem.find_by(order_id: @order.id, product_id: product.id).quantity + product.decrement_stock(quantity) + end + flash[:status] = :success + flash[:result_text] = "Successfully completed Order # #{@order.id}" + + redirect_to order_path(@order) + else + flash.now[:status] = :failure + flash.now[:result_text] = "Could not complete order." + flash.now[:messages] = @paymentinfo.errors.messages && @order.errors.messages + render :checkout, status: :bad_request + end + end + end + + def order_details + @order = Order.find(params[:id]) + @products = @order.products + @orderitems = Orderitem.where(order_id: @order.id) + @customer = Buyerdetail.find_by(id: @order.buyerdetail_id) + end + + def order_status + @order = Order.find(params[:id]) + if @order.status != :complete + @order.status = params[:order][:status] + if @order.save + flash[:status] = :success + flash[:result_text] = "You have successfully cancelled this order." + else + flash[:status] = :failure + flash[:result_text] = "Could not cancel order." + flash[:messages] = @order.errors.messages + end + end + redirect_back fallback_location: order_path(@order) + end + + private + def payment_params + params.require(:buyerdetail).permit(:email, :mailing_address, :buyer_name, :card_number, :expiration, :cvv, :zipcode) + end + + def reload_order + @order.reload + end +end diff --git a/app/controllers/categories_controller.rb b/app/controllers/categories_controller.rb new file mode 100644 index 0000000000..c05321d358 --- /dev/null +++ b/app/controllers/categories_controller.rb @@ -0,0 +1,62 @@ +class CategoriesController < ApplicationController + before_action :require_login, only: [:new, :edit, :update, :destroy] + before_action :find_category, only: [:show, :edit, :update, :destroy] + + def index + @categories = Category.all + end + + def new + @category = Category.new + end + + def create + @category = Category.new(category_params) + + if @category.save + flash[:status] = :success + flash[:result_text] = "Successfully created #{@category.name}" + redirect_to categories_path + else + flash.now[:status] = :error + flash.now[:result_text] = "Validations failed" + flash.now[:messages] = @category.errors.messages + render :new, status: :bad_request + end + end + + def show; end + + def edit; end + + def update + @category.assign_attributes(category_params) + if @category.save + flash[:status] = :success + flash[:result_text] = "Successfully updated #{@category.name}" + redirect_to category_path(@category) + else + render :edit, status: :bad_request + end + end + + def destroy + @category.destroy + flash[:status] = :success + flash[:result_text] = "Successfully destroyed #{@category.name}" + redirect_to categories_path + end + + private + + def category_params + params.require(:category).permit(:name) + end + + def find_category + @category = Category.find_by(id: params[:id]) + + head :not_found unless @category + end + +end diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000000..c72163590c --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,75 @@ +class ProductsController < ApplicationController + before_action :find_product, only: [:show, :edit, :update, :delete] + skip_before_action :require_login, only: [:root, :index, :show] + + + + def root + @products = Product.all + end + + def index + if params[:category_id] + @category = Category.find(params[:category_id]) + @products = @category.products + elsif params[:user_id] + @merchant = User.find(params[:user_id]) + @products = @merchant.products + else + @products = Product.all + end + end + + def show + @review = Review.new + end + + def new + @product = Product.new(user_id: params[:user_id]) + end + + def create + @product = Product.new(product_params) + @product.user_id = @login_user.id + if @product.save + flash[:status] = :success + flash[:result_text] = "Product added successfully" + redirect_to products_path + else + flash.now[:status] = :failure + flash.now[:result_text] = "Could not add product" + render :new, status: :bad_request + end + end + + def edit; end + + def update + @product.assign_attributes(product_params) + + if @product.save + redirect_to product_path(@product) + else + render :edit, status: :bad_request + end + end + + def destroy + @product.destroy + redirect_to products_path + end + + + + + private + def product_params + params.require(:product).permit(:name,:description, :price, :stock, :url, :quantity, :retired) + end + + def find_product + @product = Product.find_by(id: params[:id]) + head :not_found unless @product + end + +end diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb new file mode 100644 index 0000000000..10dc486b46 --- /dev/null +++ b/app/controllers/reviews_controller.rb @@ -0,0 +1,37 @@ +class ReviewsController < ApplicationController + # before_action :find_product, only: [:new, :create] + skip_before_action :require_login + + def new + #needs validation on session[:user_id] to check that they aren't reviewing their own product they sell; is user_id on product the seller? + @review = Review.new + end + + def create + @review = Review.new(review_params) + + @review.product_id = @product.id + #added this line back + if session[:user_id] == @product.user_id + flash[:status] = :error + flash[:result_text] = "You can't review your own products!" + redirect_to product_path(@review.product_id) + + elsif @review.save + flash[:status] = :success + flash[:result_text] = "Successfully created review" + redirect_to product_path(@product) + else + flash.now[:status] = :error + flash.now[:result_text] = "Could not create Review" + render :new, status: :bad_request + end + end + + private + + def review_params + return params.require(:review).permit(:rating, :product_id, :review) + end + +end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb new file mode 100644 index 0000000000..d745b01fc7 --- /dev/null +++ b/app/controllers/sessions_controller.rb @@ -0,0 +1,40 @@ +class SessionsController < ApplicationController + skip_before_action :require_login + + def new + @user = User.new + end + + def create + auth_hash = request.env['omniauth.auth'] + + if auth_hash[:uid] + user = User.find_by(uid: auth_hash[:uid], provider: 'github') + if user.nil? + # User doesn't match anything in the DB + # Attempt to create a new user + user = User.build_from_github(auth_hash) + end + + # If we get here, we have the user instance + session[:user_id] = user.id + flash[:status] = :success + flash[:result_text] = "Logged in successfully" + redirect_to root_path + else + flash[:status] = :failure + flash[:result_text] = "Could not log in" + flash[:messages] = user.errors.messages + redirect_to root_path + end + end + + + def logout + if session[:user_id] + session.delete(:user_id) + flash[:result_text] = "Successfully logged out" + redirect_to root_path + end + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb new file mode 100644 index 0000000000..bb88486bf7 --- /dev/null +++ b/app/controllers/users_controller.rb @@ -0,0 +1,23 @@ +class UsersController < ApplicationController + before_action :require_login, only: [:show] + # def new + # @user = User.new + # end + def index + @merchants = User.all + end + + def show + @orders = @login_user.orders + @products = @login_user.products + @orders.each do |order| + @orderitem = Orderitem.where(order_id: order.id) + @customer = Buyerdetail.find_by(id: order.buyerdetail_id) + end + end + + private + def user_params + params.require(:user).permit(:name, :username, :password, :email) + end +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb new file mode 100644 index 0000000000..eaa8423a53 --- /dev/null +++ b/app/helpers/application_helper.rb @@ -0,0 +1,11 @@ +module ApplicationHelper + + def render_date(date) + date.strftime("%b %e, %Y") + end + + def image_url(product) + [", product.name,"].join.html_safe + end + +end diff --git a/app/helpers/carts_helper.rb b/app/helpers/carts_helper.rb new file mode 100644 index 0000000000..2baa4b377c --- /dev/null +++ b/app/helpers/carts_helper.rb @@ -0,0 +1,12 @@ +module CartsHelper + + #this needs a duck class + def product_details(item) + Product.find(item.product_id) + end + + def quantity_edit?(fullpath) + return true if fullpath == "/carts/#{@order.id}" + 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/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..f26500e8d0 --- /dev/null +++ b/app/helpers/reviews_helper.rb @@ -0,0 +1,8 @@ +module ReviewsHelper + + # TODO make this a loop + def ratings_options + return options_for_select([['💧', 1], ['💧💧', 2],['💧💧💧', 3], ['💧💧💧💧',4],['💧💧💧💧💧',5]]) + end + +end diff --git a/app/helpers/sessions_helper.rb b/app/helpers/sessions_helper.rb new file mode 100644 index 0000000000..309f8b2eb3 --- /dev/null +++ b/app/helpers/sessions_helper.rb @@ -0,0 +1,2 @@ +module SessionsHelper +end diff --git a/app/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/buyerdetail.rb b/app/models/buyerdetail.rb new file mode 100644 index 0000000000..b543889f66 --- /dev/null +++ b/app/models/buyerdetail.rb @@ -0,0 +1,3 @@ +class Buyerdetail < ApplicationRecord + belongs_to :order +end diff --git a/app/models/category.rb b/app/models/category.rb new file mode 100644 index 0000000000..c150d34a77 --- /dev/null +++ b/app/models/category.rb @@ -0,0 +1,5 @@ +class Category < ApplicationRecord + has_and_belongs_to_many :products + + validates :name, uniqueness: true, presence: true +end diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/models/order.rb b/app/models/order.rb new file mode 100644 index 0000000000..af6bd8af94 --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,44 @@ +class Order < ApplicationRecord + has_many :orderitems + has_many :products, through: :orderitems + has_many :users, through: :products + has_many :buyerdetails + + + def find_existing(orderitem) + result = orderitems.find_by(order_id: self.id, product_id: orderitem.product_id) + + if result + new_quantity = result.quantity + orderitem.quantity + orderitem = result + orderitem.assign_attributes(quantity: new_quantity) + end + return orderitem + end + + + + def subtotal(orderitem) + price = orderitem.product.price + + orderitem.quantity * price + end + + def total + raw_total = 0 + self.orderitems.each do |orderitem| + raw_total += subtotal(orderitem) + + end + raw_total.round(2) + end + + def tax + (total * 0.104).round(2) + end + + def order_total + total + tax + end + +end diff --git a/app/models/orderitem.rb b/app/models/orderitem.rb new file mode 100644 index 0000000000..fa9cb0fbeb --- /dev/null +++ b/app/models/orderitem.rb @@ -0,0 +1,18 @@ +class Orderitem < ApplicationRecord + belongs_to :product + belongs_to :order + + validates :quantity, numericality: { only_integer: true, greater_than: -1 } + + + # def self.find_orderitem + # result1 = Orderitem.find_by(order_id: orderitem.order_id, product_id: orderitem.product_id) + # + # if result + # result.quantity += orderitem.quantity + # return result + # else + # return orderitem + # end + # end +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000000..994a9e6259 --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,40 @@ +class Product < ApplicationRecord + + has_and_belongs_to_many :categories + has_many :orderitems + has_many :reviews + belongs_to :user + + validates :name, presence: true, uniqueness: true, format: { with: /[a-zA-Z_\s]*/ } + + # This price validation allows values with an optional decimal place (if the decimal is present, no more than 2 digits must follow) and it can be up to 20 digits long + validates :price, presence: true, numericality: { only_float: true, greater_than: 0 } + + + def sufficient_stock(quantity) + self.stock >= quantity + end + + def decrement_stock(quantity) + self.stock -= quantity + self.save + end + + def average_rating + average = 0 + count = 0 + reviews.each do |r| + if r.rating > 0 + count += 1 + average += r.rating + end + end + + return 0 if count == 0 + return average/count + end + + def retire + self.toggle! :retired + end +end diff --git a/app/models/review.rb b/app/models/review.rb new file mode 100644 index 0000000000..a49bc20024 --- /dev/null +++ b/app/models/review.rb @@ -0,0 +1,6 @@ +class Review < ApplicationRecord + belongs_to :product + + validates :rating, numericality: { only_integer: true, greater_than: 0, less_than: 6 } + validates :rating, presence: true +end diff --git a/app/models/session.rb b/app/models/session.rb new file mode 100644 index 0000000000..7ee335ad19 --- /dev/null +++ b/app/models/session.rb @@ -0,0 +1,9 @@ +class Session < ActiveRecord::Base + + def self.sweep(time = 24.hour) + if time.is_a?(String) + time = time.split.inject { |count, unit| count.to_i.send(unit) } + end + delete_all "updated_at < '#{time.ago.to_s(:db)}'" + end +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000000..86eaf7ef1e --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,36 @@ +class User < ApplicationRecord + before_validation :downcase_email + + has_many :products, dependent: :destroy + has_many :orderitems, through: :products + has_many :orders, through: :orderitems + + validates :username, presence: true, uniqueness: true + # validates :password, presence: true + # validates :email, uniqueness: { message: 'Email is already in use' } + # def user_name(auth_hash) + # return if auth_hash.nil? + # email = auth_hash.split('@') + # return email[0] + # end + + def self.build_from_github(auth_hash) + + user_data = { + uid: auth_hash[:uid], + username: auth_hash["info"]["nickname"], + email: auth_hash["info"]["email"], + provider: auth_hash[:provider] + } + + user = self.new(user_data) + if user.save + return user + end + end + + private + def downcase_email + self.email = email.downcase if email.present? + end +end diff --git a/app/views/carts/_modify.html.erb b/app/views/carts/_modify.html.erb new file mode 100644 index 0000000000..e32002e6b2 --- /dev/null +++ b/app/views/carts/_modify.html.erb @@ -0,0 +1,11 @@ +
+<%= f.label :products %> +<% @cart.products.each do |product| %> +<%= product.name %> +

quantity

+<% end %> +<%= f.submit %> + +<% end %> +
diff --git a/app/views/carts/checkout.html.erb b/app/views/carts/checkout.html.erb new file mode 100644 index 0000000000..918c6d112b --- /dev/null +++ b/app/views/carts/checkout.html.erb @@ -0,0 +1,31 @@ +
+<%= form_for @paymentinfo, url: checkout_path do |f| %> +

Personal Information

+
+ <%= f.label :buyer_name, 'Name' %> + <%= f.text_field :buyer_name %> + <%= f.label :email %> + <%= f.email_field :email %> + <%= f.label :mailing_address %> + <%= f.text_field :mailing_address %> +
+

Payment Information

+
+ <%= f.label :card_number %> + <%= f.number_field :card_number, pattern: '/[0-9]{12,19}/', message: 'CC must be a number, 12- 19 digits in length' %> + <%= f.label :expiration %> + <%= f.date_field :expiration, as: :date %> + + <%= f.label :cvv, 'CVV' %> + <%= f.text_field :cvv, pattern: '/[0-9]{,3}/', message: 'Must be three digits' %> + + <%= f.label :zipcode %> + <%= f.text_field :zipcode %> + + <%= f.hidden_field :order_id, value: @order.id %> + + <%= f.submit "Checkout"%> + + <% end %> +
+
diff --git a/app/views/carts/edit.html.erb b/app/views/carts/edit.html.erb new file mode 100644 index 0000000000..13c9bd65ba --- /dev/null +++ b/app/views/carts/edit.html.erb @@ -0,0 +1 @@ +<%= render partial: 'modify' %> diff --git a/app/views/carts/order_details.html.erb b/app/views/carts/order_details.html.erb new file mode 100644 index 0000000000..d3c3fc0bd0 --- /dev/null +++ b/app/views/carts/order_details.html.erb @@ -0,0 +1,42 @@ +

Order Details

+