Commit 048a291e by Tran Hoang Viet

VietTH: Implement breadcrumb, add to cart, checkout

Conflicts:
	app/views/layouts/_breadcrumb.html.haml
parent 8f5bb1b4
......@@ -13,4 +13,6 @@
*= require_self
*= require bootstrap_and_overrides
*= require layout
*= require product
*= require cart
*/
#cart-info{
margin-bottom: 30px;
}
\ No newline at end of file
#product-detail{
.product-image img{
width: 110px;
height: 86px;
float: left;
margin: 0 20px 20px 0;
}
.product-title{
font-size: 16px;
}
}
\ No newline at end of file
......@@ -5,17 +5,18 @@ class ApplicationController < ActionController::Base
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :get_sidebar_categories
protected
def params_permitted data = nil
data ||= self.class::PERMIT
params.require(data.keys.first).permit(data.values.first)
end
def get_sidebar_categories
unless devise_controller?
@sidebar_categories = Category.limit(Settings.limit_category).select(Category::JSON_DEFAULT)
def add_breadcrumb(title, url = nil)
@breadcrumbs = [] if @breadcrumbs.blank?
@breadcrumbs.push({title: title, url: url})
end
def add_breadcrumb_home
add_breadcrumb('Home', root_path)
end
end
\ No newline at end of file
class CartsController < ApplicationController
include CartsManagement
def index
@cart = Cart.new
end
def create
cart = current_user.carts.build(cart_params)
product_ids = []
quantites = {}
cart_params['cart_items_attributes'].each do |item|
id = item.last['product_id']
product_ids << id
quantites[id] = item.last['quantity']
end
products = Product.where(id: [product_ids]).select(:id, :price)
total = products.inject(0) do |sum, product|
sum + (product.price.to_i * quantites[product.id.to_s].to_i)
end
cart.total = total
if cart.save
clear_cart
redirect_to root_path
else
render :index
end
end
private
def cart_params
params.require(:cart).permit(:total, cart_items_attributes: [:product_id, :quantity])
end
end
\ No newline at end of file
module CartsManagement extend ActiveSupport::Concern
included do
def add_to_cart product
cart_item = {
'id' => product.id,
'title' => product.title,
'price' => product.price,
'quantity' => 1
}
unless session['cart_info']['items'].include?(cart_item)
session['cart_info']['items'].push(cart_item)
session['cart_info']['total'] += 1
end
end
def clear_cart
session['cart_info'] = nil
end
def session_cart
session['cart_info'].with_indifferent_access
end
end
end
\ No newline at end of file
class HomeController < ApplicationController
before_action :add_breadcrumb_home
def index
@recommended_items = Product.recommended
@newest_items = Product.newest
......
class ProductsController < ApplicationController
before_action :set_product, only: :new
before_action :set_categories, only: [:new, :create]
include CartsManagement
before_action :set_product, only: [:show, :add_cart]
before_action :set_categories, only: [:new]
before_action :add_breadcrumb_home
PERMIT = { product: %i(title price category_id image) }
def new
@product = Product.new
add_breadcrumb('New product')
end
def create
@product = Product.create(params_permitted)
if @product.valid?
@product = Product.new(params_permitted)
if @product.save
redirect_to root_path
else
render :new
end
end
def show
add_breadcrumb(@product.category.decorate.title, category_path(@product.category))
add_breadcrumb(@product.title)
end
def add_cart
# clear_cart
add_to_cart @product
redirect_to @product
end
private
def set_product
@product = Product.find_by(id: params[:id]) || Product.new
@product = Product.find_by(id: params[:id])
end
def set_categories
@categories = Category.all.limit(Settings.limit_category)
end
end
\ No newline at end of file
......@@ -4,4 +4,16 @@ class ProductDecorator < Draper::Decorator
def price
return object.price || 'Contact'
end
def image_sm_url
object.amazon? ? object.image_sm_url : object.image.small.url
end
def image_md_url
object.amazon? ? object.image_md_url : object.image.medium.url
end
def image_lg_url
object.amazon? ? object.image_lg_url : object.image.large.url
end
end
\ No newline at end of file
module ApplicationHelper
def session_cart
(session[:cart_info] ||= {items: [], total: 0}).with_indifferent_access
end
end
class Cart < ActiveRecord::Base
belongs_to :user
has_many :cart_items, dependent: :destroy
accepts_nested_attributes_for :cart_items
end
class CartItem < ActiveRecord::Base
belongs_to :cart
belongs_to :product
end
class User < ActiveRecord::Base
has_many :carts
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
......
#checkout-cart
= form_for @cart do |f|
%table.table
%thead
%tr
%td.text-right #
%td Title
%td Price
%td Quantity
%tbody
- session_cart[:items].each_with_index do |cart_item, index|
%tr
%td.number.text-right
= index + 1
%td.title
= link_to cart_item[:title], product_path(cart_item[:id])
= hidden_field_tag "cart[cart_items_attributes][#{index}][product_id]", cart_item[:id]
%td.price
= cart_item[:price]
%td.quantity
= text_field_tag "cart[cart_items_attributes][#{index}][quantity]", cart_item[:quantity]
%tfoot
%tr
%td.text-right{colspan: 4}
= f.submit 'Checkout', class: 'btn btn-primary'
......@@ -3,5 +3,5 @@
.product-title
= link_to product.title, product
.product-image.img-thumbnail
= image_tag(product.image_md_url)
= image_tag product.decorate.image_md_url
%ul.breadcrumb
%li
%a{href: '#'}
Home
%li
%a{href: '#'}
Cate 1
\ No newline at end of file
- if @breadcrumbs.present?
%ul.breadcrumb
- @breadcrumbs.each do |breadcrumb|
%li= link_to_if breadcrumb[:url].present?, breadcrumb[:title], breadcrumb[:url]
\ No newline at end of file
#cart-info
%h3.title Category
= "Total: #{pluralize(session_cart[:total], 'item')}"
= link_to 'Checkout', carts_path, class: 'btn btn-default pull-right'
\ No newline at end of file
%h3.title Category
%ul.nav.nav-sidebar
= render @sidebar_categories
\ No newline at end of file
= render Category.limit(Settings.limit_category).select(Category::JSON_DEFAULT)
\ No newline at end of file
......@@ -21,7 +21,13 @@
#content.row
.col-md-2.sidebar
.row
.col-md-12
= render 'layouts/sidebar'
.row
.col-md-12
= render 'layouts/cart'
.col-md-10
= yield
......
.row.product-item
.col-md-1
.product-image.img-thumbnail
%img{src: product.image_sm_url}
%img{src: product.decorate.image_sm_url}
.col-md-9
.product-title
= link_to product.title, product_path(product)
......
#product-detail
.product-title
%h4= @product.title
.product-image
= image_tag @product.decorate.image_lg_url, class: 'img-thumbnail'
.product-id
Item ID:
= @product.id
.product-price
Price:
= @product.decorate.price
.product-date
Date:
= l(@product.created_at)
.clearfix
.product-addto-cart
= link_to 'Buy', add_cart_product_path(@product), class: 'btn btn-primary'
\ No newline at end of file
......@@ -21,3 +21,6 @@
en:
hello: "Hello world"
time:
formats:
default: "%d/%m/%Y"
......@@ -2,6 +2,13 @@ Rails.application.routes.draw do
devise_for :users
root 'home#index'
resources :products
resources :products do
member do
get :add_cart
end
end
resources :categories
resources :carts
end
\ No newline at end of file
class CreateCarts < ActiveRecord::Migration
def change
create_table :carts do |t|
t.timestamps null: false
t.references :user, index: true, null: false
t.decimal :total, default: 0
end
end
end
class CreateCartItems < ActiveRecord::Migration
def change
create_table :cart_items do |t|
t.timestamps null: false
t.references :cart, index: true
t.references :product, index: true
t.integer :quantity, default: 1
t.decimal :price, default: 0
end
end
end
class ChangeDefaultValueToProductPrice < ActiveRecord::Migration
def up
change_column :products, :price, :decimal, default: 0
end
def down
change_column :products, :price, :decimal
end
end
......@@ -11,7 +11,28 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150703074751) do
ActiveRecord::Schema.define(version: 20150706090027) do
create_table "cart_items", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "cart_id", limit: 4
t.integer "product_id", limit: 4
t.integer "quantity", limit: 4, default: 1
t.decimal "price", precision: 10, default: 0
end
add_index "cart_items", ["cart_id"], name: "index_cart_items_on_cart_id", using: :btree
add_index "cart_items", ["product_id"], name: "index_cart_items_on_product_id", using: :btree
create_table "carts", force: :cascade do |t|
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id", limit: 4, null: false
t.decimal "total", precision: 10, default: 0
end
add_index "carts", ["user_id"], name: "index_carts_on_user_id", using: :btree
create_table "categories", force: :cascade do |t|
t.datetime "created_at", null: false
......@@ -29,7 +50,7 @@ ActiveRecord::Schema.define(version: 20150703074751) do
t.string "image_lg_url", limit: 255
t.string "image_md_url", limit: 255
t.string "image_sm_url", limit: 255
t.decimal "price", precision: 10
t.decimal "price", precision: 10, default: 0
t.integer "category_id", limit: 4, null: false
t.integer "product_type", limit: 4, default: 0
t.string "image", limit: 255
......
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