Commit 57588ebc by Hoang Phuc Do Committed by Hoang Phuc Do

Fix merger request #4

parent 7e199c12
//= require toastr
//= require bootstrap-touchspin
//= require cart/cart
//= require shop-14
\ No newline at end of file
//= require global
\ No newline at end of file
class CartsController < ApplicationController
include CartsHelper
include LineItemsHelper
before_action :set_cart
before_action :get_line_items
before_action :set_item, only: [:add_line_item, :update_line_item, :remove_line_item]
before_action -> { render_warning_notice('Please specify quantity') },
if: :quantity_equal_zero?, only: :add_line_item
rescue_from ActiveRecord::RecordNotFound, with: :invalid_cart
# GET /cart
def index
@line_items = @cart.products
end
# POST /cart/add/1
def add_line_item
unless @cart.can_add_product?(params[:id],
@cart.get_item_quantity(*cart_params.values))
return render_warning_notice('Product is out of stock')
end
@cart.add(params[:id],
@cart.get_item_quantity(*cart_params.values))
respond_to do |format|
notice_msg = { msg: "#{@item.title} was sucessfully added to your cart",
type: :success }
format.html { redirect_to cart_index_url, notice: notice_msg[:msg] }
format.js { @notice = { msg: notice_msg[:msg], type: notice_msg[:type] } }
end
end
# PUT/PATCH /cart/update/1
def update_line_item
unless @cart.can_add_product?(*cart_params.values)
return render_warning_notice('Product is out of stock')
end
@cart.update(*cart_params.values)
respond_to do |format|
notice_msg = { msg: "#{@item.title} was sucessfully updated",
type: :success }
format.html { redirect_to cart_index_url, notice: notice_msg[:msg] }
format.js { @notice = { msg: notice_msg[:msg], type: notice_msg[:type] }}
end
end
# DELETE /cart/1
def remove_line_item
@cart.remove_item(params[:id])
respond_to do |format|
notice_msg = "#{@item.title} was sucessfully removed from your cart"
format.html { redirect_to cart_index_url, notice: notice_msg }
end
end
# DELETE /cart/remove
def destroy
destroy_cart_session
......@@ -17,7 +65,27 @@ class CartsController < ApplicationController
private
def cart_params
params.permit(:id, :product_quantity)
end
def invalid_cart
destroy_cart_session
redirect_to root_url
end
def set_item
@item = Product.find(params[:id])
end
def quantity_equal_zero?
params[:product_quantity].to_i.zero?
end
def render_warning_notice(notice)
respond_to do |format|
format.html { redirect_to cart_index_url, notice: notice }
format.js { render 'warning_notice', locals: { notice: notice } }
end
end
end
\ No newline at end of file
class LineItemsController < ApplicationController
include CartsHelper
include LineItemsHelper
before_action :set_cart, only: [:create, :update, :destroy]
# We do not render line item details page
def show
redirect_to product_url(params[:id])
end
# POST /line_items
def create
return if params[:product_quantity].to_i.zero?
product = Product.find(params[:product_id])
product_is_in_stock = product_is_in_stock?(product,
get_line_item_quantity(product.id,
params[:product_quantity]))
add_to_cart(product.id, params[:product_quantity]) if product_is_in_stock
respond_to do |format|
notice_msg = get_create_notice_msg(product_is_in_stock, product)
notice_type = get_create_notice_type(product_is_in_stock)
format.html { redirect_to cart_index_url,
notice: notice_msg }
format.js { @notice = { msg: notice_msg, type: notice_type } }
end
end
# PATCH/PUT /line_items/1
def update
update_arg = update_params.to_h.values
product = Product.find(update_arg.first)
unless product_is_in_stock?(product, update_arg.last)
return respond_to do |format|
format.html { redirect_to cart_index_url, notice: "#{product.title} is out of stock" }
end
end
update_cart_item(*update_arg)
respond_to do |format|
format.html { redirect_to cart_index_url, notice: "#{product.title} was sucessfully updated" }
end
end
# DELETE /line_items/1
def destroy
remove_line_item_from_cart(params[:id])
product = Product.find(params[:id])
respond_to do |format|
format.html { redirect_to cart_index_url,
notice: "#{product.title} was sucessfully removed from your cart" }
end
end
private
# Never trust parameters from the scary internet, only allow the white list through.
def update_params
params.permit(:id, :qty_input)
end
def product_is_in_stock?(product, quantity)
product.quantity >= quantity.to_i
end
def get_create_notice_msg(result, product)
result ? "#{product.title} was sucessfully added to your cart" :
"#{product.title} is out of stock"
end
def get_create_notice_type(result)
result ? :success : :error
end
class LineItemsController < ApplicationController
end
\ No newline at end of file
class OrdersController < ApplicationController
include CartsHelper
include LineItemsHelper
before_action :authenticate_user!, only: :new
before_action :set_cart, only: [:new, :create]
before_action :get_line_items, only: :new
before_action :set_line_items, only: :new
# GET /orders/new
def new
......@@ -27,8 +26,14 @@ class OrdersController < ApplicationController
end
def create_line_items_for_order(order)
@cart.each do |product_id, product_attrs|
order.line_items.create(product_id: product_id, quantity: product_attrs['quantity'])
@cart.get_all_items.each do |_, attrs|
order.line_items.create(product: attrs[:product], quantity: attrs[:quantity])
end
end
private
def set_line_items
@line_items = @cart.get_all_items
end
end
\ No newline at end of file
......@@ -3,7 +3,7 @@ class UsersController < ApplicationController
# GET /users/1
def show
@user = User.find(current_user.id)
@user = current_user
end
# GET /users/products
......
......@@ -2,8 +2,4 @@ module ApplicationHelper
def active_class(page_name, class_name = 'active')
class_name if params[:action] == page_name
end
def user_own_product?(product)
current_user == product.user
end
end
module CartsHelper
def set_cart
session[:cart] ||= {}
@cart = session[:cart]
end
def add_to_cart(product_id, quantity)
return if quantity.to_i.zero?
if @cart.key?(product_id.to_s)
@cart[product_id.to_s][:quantity.to_s] += quantity.to_i
else
@cart[product_id.to_s] = { quantity: quantity.to_i }
end
end
def update_cart_item(product_id, quantity)
return unless @cart.key?(product_id)
if quantity.to_i.zero?
remove_line_item_from_cart(product_id)
else
@cart[product_id][:quantity.to_s] = quantity.to_i
end
end
def remove_line_item_from_cart(product_id)
@cart.tap { |cart| cart.delete(product_id) } if @cart.key?(product_id)
@cart = Cart.new(session[:cart])
end
def destroy_cart_session
......@@ -31,14 +9,10 @@ module CartsHelper
end
def cart_total_price
@cart.sum do |product_id, product_attrs|
product = Product.find(product_id)
product.price * product_attrs[:quantity.to_s].to_i
end
@cart.cal_total_price
end
def cart_total_items
return 0 if @cart.nil?
@cart.sum { |_, product_attrs| product_attrs[:quantity.to_s] || product_attrs[:quantity] }
@cart.cal_total_items
end
end
module LineItemsHelper
def get_line_items
@line_items = {}
@cart.each do |product_id, product_attrs|
@line_items[product_id] = { product: Product.find(product_id),
quantity: product_attrs['quantity'].to_i }
end
end
def get_line_item_quantity(product_id, new_quantity = 0)
return new_quantity.to_i if @cart.empty? || !@cart.key?(product_id.to_s)
old_quantity = @cart[product_id.to_s][:quantity] || @cart[product_id.to_s][:quantity.to_s]
new_quantity.to_i + old_quantity
end
end
\ No newline at end of file
......@@ -6,4 +6,12 @@ class Product < ApplicationRecord
validates :category_id, presence: true
validates :user_id, presence: true
def is_in_stock?(required_quantity)
quantity >= required_quantity.to_i
end
def belongs_to_user?(current_user)
current_user == user
end
end
class Cart
def initialize(cart_session = {})
@cart = cart_session
end
def add(item_id, quantity)
return if quantity.to_i.zero?
if @cart.key?(item_id.to_s)
@cart[item_id.to_s][:quantity.to_s] += quantity.to_i
else
@cart[item_id.to_s] = { quantity: quantity.to_i }
end
end
def update(item_id, quantity)
return unless @cart.key?(item_id)
if quantity.to_i.zero?
remove_item(item_id)
else
@cart[item_id][:quantity.to_s] = quantity.to_i
end
end
def get_item_quantity(item_id, new_quantity = 0)
return new_quantity.to_i if @cart.empty? || !@cart.key?(item_id.to_s)
old_quantity = @cart[item_id.to_s][:quantity] ||
@cart[item_id.to_s][:quantity.to_s]
new_quantity.to_i + old_quantity
end
def products
products = {}
@cart.each do |id, attrs|
products[id] = { product: Product.find(id),
quantity: attrs[:quantity.to_s].to_i }
end
products
end
def remove_item(item_id)
@cart.tap { |cart| cart.delete(item_id) } if @cart.key?(item_id)
end
def can_add_product?(product_id, quantity)
Product.find(product_id).is_in_stock?(quantity)
end
def cal_total_price
products.sum do |_, attrs|
attrs[:product].price * attrs[:quantity]
end
end
def cal_total_items
return 0 if @cart.nil?
@cart.sum { |_, attrs| attrs[:quantity] || attrs[:quantity.to_s] }
end
end
\ No newline at end of file
<tr>
<td colspan="6">
<%= link_to 'Continue shopping', root_url, class: 'btn btn-default hover-primary btn-continue' %>
<%= button_to 'Clear Shopping Cart', remove_cart_path, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default hover-primary btn-clear' %>
<%= button_to 'Clear Shopping Cart', cart_destroy_path, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-default hover-primary btn-clear' %>
</td>
</tr>
\ No newline at end of file
<tr>
<td class="product-action-td">
<%= link_to fa_icon('times'), line_item_path(id), method: :delete, data: { confirm: 'Are you sure?' } %>
<%= link_to fa_icon('times'), cart_remove_line_item_path(id), method: :delete, data: { confirm: 'Are you sure?' } %>
</td>
<td class="product-image-td"></td>
<td class="product-name-td">
......@@ -10,9 +10,9 @@
</td>
<td><%= number_to_currency(line_item[:product].price) %></td>
<td>
<%= form_tag line_item_path(id), method: :put do %>
<%= form_tag cart_update_line_item_path(id), method: :put do %>
<div class="qty-holder">
<%= number_field_tag :qty_input, line_item[:quantity], data: { product_id: id}, class: 'qty-input' %>
<%= number_field_tag :product_quantity, line_item[:quantity], id: nil, class: 'qty-input' %>
</div>
<% end %>
</td>
......
toastr.options.closeButton = true;
toastr.options.timeOut = 1000; // How long the toast will display without user interaction
toastr.options.extendedTimeOut = 2000; // How long the toast will display after a user hovers over it
<% if notice %>
toastr.warning('<%= notice %>');
<% end %>
\ No newline at end of file
......@@ -11,7 +11,7 @@
<div class="product-details-box col-sm-7">
<h1 class="product-name">
<%= product.title %>
<%= link_to fa_icon('pencil'), edit_product_path if user_own_product?(product) %>
<%= link_to fa_icon('pencil'), edit_product_path if product.belongs_to_user?(current_user) %>
</h1>
<div class="product-short-desc">
<%= product.description %>
......@@ -26,7 +26,7 @@
</p>
</div>
<div class="product-actions">
<%= form_tag line_items_path(product_id: product), remote: true do %>
<%= form_tag cart_add_line_item_path(product.id), remote: true do %>
<div class="product-detail-qty">
<%= number_field_tag :product_quantity, 1, min: 0, class: 'vertical-spinner' %>
</div>
......
......@@ -8,7 +8,7 @@
<div class="product-details-area">
<h2 class="product-name">
<%= link_to product.title, product_url(product) %>
<%= link_to fa_icon('pencil'), edit_product_path(product) if user_own_product?(product) %>
<%= link_to fa_icon('pencil'), edit_product_path(product) if product.belongs_to_user?(current_user) %>
</h2>
<div class="product-short-desc">
<%= product.description %>
......
......@@ -5,10 +5,15 @@ Rails.application.routes.draw do
resources :products
resources :orders, only: [:new, :create, :show]
resources :line_items
resources :cart, only: :index, controller: 'carts'
delete '/cart/remove', to: 'carts#destroy', as: 'remove_cart'
scope 'cart' do
get '/', to: 'carts#index', as: 'cart_index'
post '/add/:id', to: 'carts#add_line_item', as: 'cart_add_line_item'
put '/update/:id', to: 'carts#update_line_item', as: 'cart_update_line_item'
delete '/remove/:id', to: 'carts#remove_line_item', as: 'cart_remove_line_item'
delete '/remove', to: 'carts#destroy', as: 'cart_destroy'
end
devise_for :users
scope '/users' do
scope 'users' do
get '/', to: 'users#show', as: 'user_profile'
get '/products', to: 'users#products', as: 'user_products'
end
......
......@@ -12,11 +12,37 @@
ActiveRecord::Schema.define(version: 20170615035827) do
create_table "active_admin_comments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "namespace"
t.text "body"
t.string "resource_type"
t.bigint "resource_id"
t.string "author_type"
t.bigint "author_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["author_type", "author_id"], name: "index_active_admin_comments_on_author_type_and_author_id"
t.index ["namespace"], name: "index_active_admin_comments_on_namespace"
t.index ["resource_type", "resource_id"], name: "index_active_admin_comments_on_resource_type_and_resource_id"
end
create_table "categories", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "title"
t.text "description"
end
create_table "ckeditor_assets", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.string "data_file_name", null: false
t.string "data_content_type"
t.integer "data_file_size"
t.string "type", limit: 30
t.integer "width"
t.integer "height"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["type"], name: "index_ckeditor_assets_on_type"
end
create_table "line_items", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
t.integer "quantity", default: 1
t.bigint "product_id"
......@@ -62,6 +88,7 @@ ActiveRecord::Schema.define(version: 20170615035827) do
t.string "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "super_admin", default: false, null: false
t.string "username"
t.string "first_name"
t.string "last_name"
......@@ -69,4 +96,5 @@ ActiveRecord::Schema.define(version: 20170615035827) do
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end
add_foreign_key "products", "users"
end
class Cart
def abc
'hi'
end
end
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment