diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..018f8ab Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 6a502e9..f7a9080 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ # Ignore all logfiles and tempfiles. /log/*.log /tmp +/public/uploads/* diff --git a/Gemfile b/Gemfile index fba3b4e..72cb227 100644 --- a/Gemfile +++ b/Gemfile @@ -26,6 +26,26 @@ gem 'sdoc', '~> 0.4.0', group: :doc # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring gem 'spring', group: :development + +gem 'devise' +gem 'bootstrap-sass' +gem "font-awesome-rails" + +gem 'carrierwave' +gem "mini_magick" + + +gem 'simple_form' +gem 'aasm' + +#debug +gem 'binding_of_caller' +gem 'better_errors' + + + + + # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' diff --git a/Gemfile.lock b/Gemfile.lock index 53538d9..2f58594 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,7 @@ GEM remote: https://rubygems.org/ specs: + aasm (3.2.0) actionmailer (4.1.0) actionpack (= 4.1.0) actionview (= 4.1.0) @@ -28,7 +29,21 @@ GEM thread_safe (~> 0.1) tzinfo (~> 1.1) arel (5.0.1.20140414130214) + bcrypt (3.1.7) + better_errors (1.1.0) + coderay (>= 1.0.0) + erubis (>= 2.6.6) + binding_of_caller (0.7.2) + debug_inspector (>= 0.0.1) + bootstrap-sass (3.2.0.0) + sass (~> 3.2) builder (3.2.2) + carrierwave (0.10.0) + activemodel (>= 3.2.0) + activesupport (>= 3.2.0) + json (>= 1.7) + mime-types (>= 1.16) + coderay (1.1.0) coffee-rails (4.0.1) coffee-script (>= 2.2.0) railties (>= 4.0.0, < 5.0) @@ -36,8 +51,17 @@ GEM coffee-script-source execjs coffee-script-source (1.7.0) + debug_inspector (0.0.2) + devise (3.2.4) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 3.2.6, < 5) + thread_safe (~> 0.1) + warden (~> 1.2.3) erubis (2.7.0) execjs (2.2.0) + font-awesome-rails (4.1.0.0) + railties (>= 3.2, < 5.0) hike (1.2.3) i18n (0.6.9) jbuilder (2.0.8) @@ -51,8 +75,11 @@ GEM mime-types (~> 1.16) treetop (~> 1.4.8) mime-types (1.25.1) + mini_magick (3.7.0) + subexec (~> 0.2.1) minitest (5.3.4) multi_json (1.10.1) + orm_adapter (0.5.0) polyglot (0.3.5) rack (1.5.2) rack-test (0.6.2) @@ -84,6 +111,9 @@ GEM sdoc (0.4.0) json (~> 1.8) rdoc (~> 4.0, < 5.0) + simple_form (3.0.2) + actionpack (~> 4.0) + activemodel (~> 4.0) spring (1.1.3) sprockets (2.11.0) hike (~> 1.2) @@ -95,6 +125,7 @@ GEM activesupport (>= 3.0) sprockets (~> 2.8) sqlite3 (1.3.9) + subexec (0.2.3) thor (0.19.1) thread_safe (0.3.4) tilt (1.4.1) @@ -108,17 +139,28 @@ GEM uglifier (2.5.0) execjs (>= 0.3.0) json (>= 1.8.0) + warden (1.2.3) + rack (>= 1.0) PLATFORMS ruby DEPENDENCIES + aasm + better_errors + binding_of_caller + bootstrap-sass + carrierwave coffee-rails (~> 4.0.0) + devise + font-awesome-rails jbuilder (~> 2.0) jquery-rails + mini_magick rails (= 4.1.0) sass-rails (~> 4.0.3) sdoc (~> 0.4.0) + simple_form spring sqlite3 turbolinks diff --git a/app/assets/javascripts/account/orderitems.js.coffee b/app/assets/javascripts/account/orderitems.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/account/orderitems.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/account/orders.js.coffee b/app/assets/javascripts/account/orders.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/account/orders.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/admin/orderitems.js.coffee b/app/assets/javascripts/admin/orderitems.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/admin/orderitems.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/admin/orders.js.coffee b/app/assets/javascripts/admin/orders.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/admin/orders.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/admin/products.js.coffee b/app/assets/javascripts/admin/products.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/admin/products.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index d6925fa..6ef63a6 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -14,3 +14,5 @@ //= require jquery_ujs //= require turbolinks //= require_tree . +//= require bootstrap + diff --git a/app/assets/javascripts/carts.js.coffee b/app/assets/javascripts/carts.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/carts.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/orders.js.coffee b/app/assets/javascripts/orders.js.coffee new file mode 100644 index 0000000..24f83d1 --- /dev/null +++ b/app/assets/javascripts/orders.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/account/orderitems.css.scss b/app/assets/stylesheets/account/orderitems.css.scss new file mode 100644 index 0000000..310587b --- /dev/null +++ b/app/assets/stylesheets/account/orderitems.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the account::orderitems controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/account/orders.css.scss b/app/assets/stylesheets/account/orders.css.scss new file mode 100644 index 0000000..782d07c --- /dev/null +++ b/app/assets/stylesheets/account/orders.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the account::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/admin/orderitems.css.scss b/app/assets/stylesheets/admin/orderitems.css.scss new file mode 100644 index 0000000..633e367 --- /dev/null +++ b/app/assets/stylesheets/admin/orderitems.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the admin::orderitems controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/admin/orders.css.scss b/app/assets/stylesheets/admin/orders.css.scss new file mode 100644 index 0000000..7ed90c7 --- /dev/null +++ b/app/assets/stylesheets/admin/orders.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the admin::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/admin/products.css.scss b/app/assets/stylesheets/admin/products.css.scss new file mode 100644 index 0000000..da8969d --- /dev/null +++ b/app/assets/stylesheets/admin/products.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the admin::products controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index a443db3..5844739 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -12,4 +12,6 @@ * *= require_tree . *= require_self + *= require bootstrap + *= require font-awesome */ diff --git a/app/assets/stylesheets/carts.css.scss b/app/assets/stylesheets/carts.css.scss new file mode 100644 index 0000000..62647c9 --- /dev/null +++ b/app/assets/stylesheets/carts.css.scss @@ -0,0 +1,3 @@ +// 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/ diff --git a/app/assets/stylesheets/orders.css.scss b/app/assets/stylesheets/orders.css.scss new file mode 100644 index 0000000..3b0428a --- /dev/null +++ b/app/assets/stylesheets/orders.css.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/controllers/account/orderitems_controller.rb b/app/controllers/account/orderitems_controller.rb new file mode 100644 index 0000000..970e7e5 --- /dev/null +++ b/app/controllers/account/orderitems_controller.rb @@ -0,0 +1,10 @@ +class Account::OrderitemsController < ApplicationController + before_action :authenticate_user! + + def show + @orders = Order.find(params[:id]) + @order_info = @orders.info + @items = @orders.items + end + +end diff --git a/app/controllers/account/orders_controller.rb b/app/controllers/account/orders_controller.rb new file mode 100644 index 0000000..f3c7e5d --- /dev/null +++ b/app/controllers/account/orders_controller.rb @@ -0,0 +1,12 @@ +class Account::OrdersController < ApplicationController + before_action :authenticate_user! + + def index + @order = current_user.orders.recent + end + + def show + #@order = Order.items.where(id: params[:id]) + end + +end diff --git a/app/controllers/admin/orderitems_controller.rb b/app/controllers/admin/orderitems_controller.rb new file mode 100644 index 0000000..9617cbe --- /dev/null +++ b/app/controllers/admin/orderitems_controller.rb @@ -0,0 +1,13 @@ +class Admin::OrderitemsController < ApplicationController + + before_action :authenticate_user! + before_action :admin_required + + def show + @orders = Order.find(params[:id]) + @order_info = @orders.info + @items = @orders.items + end + + +end diff --git a/app/controllers/admin/orders_controller.rb b/app/controllers/admin/orders_controller.rb new file mode 100644 index 0000000..ba69243 --- /dev/null +++ b/app/controllers/admin/orders_controller.rb @@ -0,0 +1,42 @@ +class Admin::OrdersController < ApplicationController + + before_action :authenticate_user! + before_action :admin_required + before_filter :find_order, :except => [:index] + + def index + @order = Order.recent + end + + def show + @order_info = @order.info + @order_items = @order.items + end + + def ship + @order.ship! + redirect_to :back + end + + def shipped + @order.deliver! + redirect_to :back + end + + def cancel + @order.cancell_order! + redirect_to :back + end + + def return + @order.return_good! + redirect_to :back + end + + protected + def find_order + @order = Order.find_by_token(params[:id]) + end + + +end diff --git a/app/controllers/admin/products_controller.rb b/app/controllers/admin/products_controller.rb new file mode 100644 index 0000000..2085c6f --- /dev/null +++ b/app/controllers/admin/products_controller.rb @@ -0,0 +1,58 @@ +class Admin::ProductsController < ApplicationController + + before_action :authenticate_user! + before_action :admin_required + + + def index + @products = Product.all + end + + def new + @product = Product.new + @photo = @product.photos.new + end + + def show + @product = Product.find(params[:id]) + end + + def edit + @product = Product.find(params[:id]) + @photos = @product.photos + end + + def update + @product = Product.find(params[:id]) + if @product.update(product_params) + redirect_to admin_products_path + else + render :edit + end + end + + + def destroy + @product = Product.find(params[:id]) + @product.destroy! + redirect_to admin_products_path + end + + def create + @product = Product.new(product_params) + if @product.save + redirect_to admin_products_path + else + render :new + end + end + + private + + def product_params + #params.require(:product).permit(:title,:description,:quantity, :price, :image) + params.require(:product).permit(:title,:description,:quantity, :price, :photos_attributes => [:image]) + end + + +end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e..077622e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -2,4 +2,27 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception + + def admin_required + current_user.is_admin? + end + + helper_method :current_cart + + def current_cart + @current_cart ||= find_Cart + end + + def find_Cart + cart = Cart.find_by(id: session[:cart_id]) + + unless cart.present? + cart = Cart.create + end + + session[:cart_id] = cart.id + cart + + end + end diff --git a/app/controllers/carts_controller.rb b/app/controllers/carts_controller.rb new file mode 100644 index 0000000..39e433c --- /dev/null +++ b/app/controllers/carts_controller.rb @@ -0,0 +1,35 @@ +class CartsController < ApplicationController + + before_action :authenticate_user!, :only => [:checkout] + + def index + end + + def checkout + + params['product'].keys.each do |id| + @item = current_cart.items.find(id.to_i) + @item.update_attribute(:quantity,params['product'][id]) + end + + @order = current_user.orders.build + @info = @order.build_info + end + + + + def deleteCart + # 可以用 clear,delete_all,destroy_all + #current_cart.items.destroy_all + current_cart.clear! + # cart = Cart.find_by(id: params[:cart_id]) + # if cart.present? + # cart.destroy + # end + # session[params[:cart_id]] = nil + redirect_to root_path + end + + + +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb new file mode 100644 index 0000000..a60c023 --- /dev/null +++ b/app/controllers/orders_controller.rb @@ -0,0 +1,41 @@ +class OrdersController < ApplicationController + + before_action :authenticate_user! + + def create + @order = current_user.orders.build(order_params) + + if @order.save + @order.build_item_cache_from_cart(current_cart) + @order.calculate_total!(current_cart) + + redirect_to order_path(@order.token) + else + render "carts/checkout" + end + end + + def show + @order = current_user.orders.find_by_token(params[:id]) + @order_info = @order.info + @order_items = @order.items + end + + def pay_with_credit_card + @order = current_user.orders.find_by_token(params[:id]) + @order.set_payment_with!("credit_card") + #@order.pay! + @order.make_payment! + redirect_to root_path flash[:notice] = "成功完成付款" + current_cart.clear! + end + + + + private + + def order_params + params.require(:order).permit(:info_attributes => [:billing_name, :billing_address,:shipping_name, :shipping_address] ) + end + +end diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb new file mode 100644 index 0000000..39af1aa --- /dev/null +++ b/app/controllers/products_controller.rb @@ -0,0 +1,36 @@ +class ProductsController < ApplicationController + + + def index + @products = Product.all + end + + def show + @product = Product.find(params[:id]) + @photos = @product.photos + end + + def add_to_cart + @product = Product.find(params[:id]) + + if !current_cart.items.include?(@product) + if @product.quantity > 0 + current_cart.add_product_to_cart(@product) + flash[:notice] = "你己經成功將 #{@product.title} 加入購物車" + else + flash[:warning] = "此物品已停止銷售,你無法將它加入購物車" + end + else + flash[:warning] = "你的購物車己存在此商品" + end + redirect_to :back + end + + def remove_from_cart + @product = Product.find(params[:id]) + current_cart.remove_product_from_cart(@product) + redirect_to root_path + end + + +end diff --git a/app/helpers/account/orderitems_helper.rb b/app/helpers/account/orderitems_helper.rb new file mode 100644 index 0000000..2220f4c --- /dev/null +++ b/app/helpers/account/orderitems_helper.rb @@ -0,0 +1,2 @@ +module Account::OrderitemsHelper +end diff --git a/app/helpers/account/orders_helper.rb b/app/helpers/account/orders_helper.rb new file mode 100644 index 0000000..518f008 --- /dev/null +++ b/app/helpers/account/orders_helper.rb @@ -0,0 +1,24 @@ +module Account::OrdersHelper + + def render_order_link(order) + link_to(order.token, order_path(order.token)) + end + + def render_admin_order_link(order) + link_to(order.token, admin_order_path(order.token)) + end + + def render_order_created_time(order) + order.created_at.to_s(:short) + end + + + def render_order_user_name(user) + user.email + end + + def render_order_state(order) + t("orders.order_state.#{order.aasm_state}") + end + +end diff --git a/app/helpers/admin/orderitems_helper.rb b/app/helpers/admin/orderitems_helper.rb new file mode 100644 index 0000000..5fcf7d4 --- /dev/null +++ b/app/helpers/admin/orderitems_helper.rb @@ -0,0 +1,2 @@ +module Admin::OrderitemsHelper +end diff --git a/app/helpers/admin/orders_helper.rb b/app/helpers/admin/orders_helper.rb new file mode 100644 index 0000000..863374f --- /dev/null +++ b/app/helpers/admin/orders_helper.rb @@ -0,0 +1,2 @@ +module Admin::OrdersHelper +end diff --git a/app/helpers/admin/products_helper.rb b/app/helpers/admin/products_helper.rb new file mode 100644 index 0000000..3c5a699 --- /dev/null +++ b/app/helpers/admin/products_helper.rb @@ -0,0 +1,10 @@ +module Admin::ProductsHelper + + # def redner_product_photo(photo) + # if photo.present? + # image_tag(photo.image) + # else + # end + # end + +end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be79..ab0d91d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,21 @@ module ApplicationHelper + + def notice_message + alert_types = { :notice => :success, :alert => :danger } + + close_button_options = { :class => "close", "data-dismiss" => "alert", "aria-hidden" => true } + close_button = content_tag(:button, "×", close_button_options) + + alerts = flash.map do |type, message| + alert_content = close_button + message + + alert_type = alert_types[type.to_sym] || type + alert_class = "alert alert-#{alert_type} alert-dismissable" + + content_tag(:div, alert_content, :class => alert_class) + end + + alerts.join("\n").html_safe + end + end diff --git a/app/helpers/carts_helper.rb b/app/helpers/carts_helper.rb new file mode 100644 index 0000000..a3429fd --- /dev/null +++ b/app/helpers/carts_helper.rb @@ -0,0 +1,10 @@ +module CartsHelper + + def cart_items_count(cart) + cart.cart_items.count + end + + def render_cart_total_price(current_cart) + current_cart.total_price + end +end diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb new file mode 100644 index 0000000..1674b16 --- /dev/null +++ b/app/helpers/orders_helper.rb @@ -0,0 +1,7 @@ +module OrdersHelper + + def render_order_options_for_admin(order) + render :partial => "admin/orders/state_option", :locals => { :order => order} + end + +end diff --git a/app/helpers/productsHelper.rb b/app/helpers/productsHelper.rb new file mode 100644 index 0000000..a559294 --- /dev/null +++ b/app/helpers/productsHelper.rb @@ -0,0 +1,26 @@ +module ProductsHelper + + def render_product_photo(photo, size = "thumb") + + if photo.present? + image_url = photo.image.send(size).url + else + + case size + when :medium + volume = "300x300" + else + volume = "200x200" + end + + image_url = "http://placehold.it/#{volume}&text=No Pic" + end + + image_tag(image_url, :class => "thumbnail") + + end + + + + +end diff --git a/app/models/cart.rb b/app/models/cart.rb new file mode 100644 index 0000000..502b701 --- /dev/null +++ b/app/models/cart.rb @@ -0,0 +1,24 @@ +class Cart < ActiveRecord::Base + + has_many :cart_items, :dependent => :destroy + has_many :items, :through => :cart_items , :source=> :product + + def add_product_to_cart(product) + items << product + end + + def remove_product_from_cart(product) + items.delete(product) + end + + def total_price + items.inject(0){|sum,item| sum+=item.price * item.quantity } + end + + def clear! + cart_items.delete_all + end + + + +end diff --git a/app/models/cart_item.rb b/app/models/cart_item.rb new file mode 100644 index 0000000..ddf0322 --- /dev/null +++ b/app/models/cart_item.rb @@ -0,0 +1,4 @@ +class CartItem < ActiveRecord::Base + belongs_to :cart + belongs_to :product +end diff --git a/app/models/order.rb b/app/models/order.rb new file mode 100644 index 0000000..ca44099 --- /dev/null +++ b/app/models/order.rb @@ -0,0 +1,75 @@ +class Order < ActiveRecord::Base + + belongs_to :user + has_many :items, :class_name => "OrderItem", :dependent => :destroy + has_one :info, :class_name => "OrderInfo", :dependent => :destroy + + accepts_nested_attributes_for :info + + + def build_item_cache_from_cart(cart) + cart.items.each do |cart_item| + item = items.build + item.product_name = cart_item.title + item.quantity = cart_item.quantity + item.price = cart_item.price + item.save + end + end + + def calculate_total!(current_cart) + self.total = current_cart.total_price + self.save + end + + before_create :generate_token + + def generate_token + self.token = SecureRandom.uuid + end + + + def set_payment_with!(method) + self.update_column(:payment_method, method) + end + + def pay! + self.update_column(:paid,true) + end + + scope :recent, ->{ + order("id desc") + } + + include AASM + + aasm do + state :order_placed, :initial => true + state :paid, :after_commit => :pay! + event :make_payment do + transitions :from => :order_placed, :to => :paid + end + + state :shipping + event :ship do + transitions :from => :paid, :to => :shipping + end + + state :shipped + event :deliver do + transitions :from => :shipping, :to => :shipped + end + + state :order_cancelled + event :cancell_order do + transitions :from => [:order_placed, :paid ], :to => :order_cancelled + end + + state :good_returned + event :return_good do + transitions :from => [:shipped ], :to => :good_returned + end + + end + +end diff --git a/app/models/order_info.rb b/app/models/order_info.rb new file mode 100644 index 0000000..5d73cfb --- /dev/null +++ b/app/models/order_info.rb @@ -0,0 +1,10 @@ +class OrderInfo < ActiveRecord::Base + belongs_to :order + + + validates :billing_name, :presence=>true + validates :billing_address, :presence=>true + validates :shipping_name, :presence=>true + validates :shipping_address, :presence=>true + +end diff --git a/app/models/order_item.rb b/app/models/order_item.rb new file mode 100644 index 0000000..7969164 --- /dev/null +++ b/app/models/order_item.rb @@ -0,0 +1,3 @@ +class OrderItem < ActiveRecord::Base + belongs_to :order +end diff --git a/app/models/photo.rb b/app/models/photo.rb new file mode 100644 index 0000000..3cd3964 --- /dev/null +++ b/app/models/photo.rb @@ -0,0 +1,6 @@ +class Photo < ActiveRecord::Base + belongs_to :product + + mount_uploader :image, ImageUploader + +end diff --git a/app/models/product.rb b/app/models/product.rb new file mode 100644 index 0000000..c289e0a --- /dev/null +++ b/app/models/product.rb @@ -0,0 +1,13 @@ +class Product < ActiveRecord::Base + has_many :photos + accepts_nested_attributes_for :photos + + validates :title, :presence=>true + validates :quantity, :presence=>true + + def default_photo + photos.first + end + + +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..633ed07 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,14 @@ +class User < ActiveRecord::Base + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable and :omniauthable + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :trackable, :validatable + + has_many :orders + + def is_admin? + is_admin + end + + +end diff --git a/app/uploaders/image_uploader.rb b/app/uploaders/image_uploader.rb new file mode 100644 index 0000000..a2c96b1 --- /dev/null +++ b/app/uploaders/image_uploader.rb @@ -0,0 +1,71 @@ +# encoding: utf-8 + +class ImageUploader < CarrierWave::Uploader::Base + + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + include CarrierWave::MiniMagick + + # Choose what kind of storage to use for this uploader: + storage :file + # storage :fog + + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + end + + + + + # Provide a default URL as a default if there hasn't been a file uploaded: + # def default_url + # # For Rails 3.1+ asset pipeline compatibility: + # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) + # + # "/images/fallback/" + [version_name, "default.png"].compact.join('_') + # end + + # Process files as they are uploaded: + # process :scale => [200, 300] + # + # def scale(width, height) + # # do something + # end + + # Create different versions of your uploaded files: + # version :thumb do + # process :resize_to_fit => [150, 150] + # end + + version :md do + process resize_to_fit: [700, 500] + end + + version :sm, from_version: :md do + process resize_to_fit: [300, 300] + end + + version :ss, from_version: :md do + process resize_to_fit: [100, 100] + end + + version :square, from_version: :sm do + process resize_to_fill: [220, 220] + end + + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + def extension_white_list + %w(jpg jpeg gif png) + end + + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + def filename + "image.jpg" if original_filename + end + + +end diff --git a/app/views/account/orderitems/show.html.erb b/app/views/account/orderitems/show.html.erb new file mode 100644 index 0000000..9f8a68e --- /dev/null +++ b/app/views/account/orderitems/show.html.erb @@ -0,0 +1,68 @@ + +
| 訂購人 | +
| + <%= @order_info.billing_name %> - <%= @order_info.billing_address %> + | +
| 收件人 | +
| + <%= @order_info.shipping_name %> - <%= @order_info.shipping_address %> + | +
| 產品名稱 | +訂貨價格 | +數量 | +
|---|---|---|
| <%= item.product_name%> | +<%= item.price %> | +<%= item.quantity%> | +
| 訂單編號 | +訂貨時間 | +訂單狀態 | +訂貨價格 | +付費方式 | +詳細資料 | +
|---|---|---|---|---|---|
| <%= order.id%> | +<%= render_order_created_time(order)%> | +<%= render_order_state(order)%> | +<%= order.total %> | +<%= order.payment_method %> | +<%= link_to "詳細資料",account_orderitem_path(order.id)%> | +
| 訂購人 | +
| + <%= @order_info.billing_name %> - <%= @order_info.billing_address %> + | +
| 收件人 | +
| + <%= @order_info.shipping_name %> - <%= @order_info.shipping_address %> + | +
| 產品名稱 | +訂貨價格 | +數量 | +
|---|---|---|
| <%= item.product_name%> | +<%= item.price %> | +<%= item.quantity%> | +
| 訂單編號 | +訂單日期 | +訂單狀態 | +訂貨價格 | +付費方式 | +詳細明細 | +
|---|---|---|---|---|---|
| <%= order.id%> | +<%= render_order_created_time(order)%> | +<%= render_order_user_name(order.user)%> | +<%= order.total %> | +<%= order.payment_method %> | +<%= link_to "詳細資料",admin_orderitem_path(order.id)%> | +
<%= product.description %>
+數量: <%= product.quantity %>
+價格: <%= product.price %>
+ <%= link_to "修改",edit_admin_product_path(product),:class=>'btn btn-primary' %> + <%= link_to "刪除",admin_product_path(product),:method=> :delete,:class=>'btn btn-danger' ,:confirm=> 'are you Sure!' %> +| 商品明細 | +單價 | +數量 | +
|---|---|---|
| + <%= link_to(product.title, admin_product_path(product)) %> + | +<%= product.price %> | +<%= product.quantity %> | +
| 商品資訊 | ++ | 單價 | +數量 | +小計 | +移除 | +
|---|---|---|---|---|---|
| <%= image_tag product.default_photo.image.url(:sm)%> | ++ <%= link_to(product.title, product_path(product)) %> + | +<%= product.price %> | ++ <%#= f.hidden_field :id, { :value => product.id } %> + <%= f.select product.id, options_for_select((1..10).collect{ |u| [u,u]}) %> + <%#= f.select :quantity, [1,2,3,4,5] %> + | ++ + | +<%= link_to "從購物車移除", remove_from_cart_product_path(product),:method=> :delete, :class=> "btn btn-danger btn-sm" %> | +
| 商品明細 | +單價 | +數量 | +
|---|---|---|
| + <%= order_item.product_name %> + | +<%= order_item.price %> | +<%= order_item.quantity %> | +
| 訂購人 | +
| + <%= @order_info.billing_name %> - <%= @order_info.billing_address %> + | +
| 訂購人 | +
| + <%= @order_info.billing_name %> - <%= @order_info.billing_address %> + | +
Welcome <%= @email %>!
+ +You can confirm your account email through the link below:
+ +<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb new file mode 100644 index 0000000..f667dc1 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -0,0 +1,8 @@ +Hello <%= @resource.email %>!
+ +Someone has requested a link to change your password. You can do this through the link below.
+ +<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
+ +If you didn't request this, please ignore this email.
+Your password won't change until you access the link above and create a new one.
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb new file mode 100644 index 0000000..41e148b --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -0,0 +1,7 @@ +Hello <%= @resource.email %>!
+ +Your account has been locked due to an excessive number of unsuccessful sign in attempts.
+ +Click the link below to unlock your account:
+ +<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>
diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 0000000..5535098 --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb @@ -0,0 +1,16 @@ +Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>
+ +<%= link_to "Back", :back %> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb new file mode 100644 index 0000000..234de91 --- /dev/null +++ b/app/views/devise/registrations/new.html.erb @@ -0,0 +1,18 @@ +