Commit 1eaeedd2 by Hoang Phuc Do Committed by Hoang Phuc

Add toast notification

parent 4f37530b
...@@ -52,6 +52,8 @@ gem 'font-awesome-rails', '~> 4.7', '>= 4.7.0.2' ...@@ -52,6 +52,8 @@ gem 'font-awesome-rails', '~> 4.7', '>= 4.7.0.2'
gem 'rails-assets-bootstrap-touchspin', source: 'https://rails-assets.org' gem 'rails-assets-bootstrap-touchspin', source: 'https://rails-assets.org'
# Simple, efficient background processing for Ruby. # Simple, efficient background processing for Ruby.
gem 'sidekiq', '~> 5.0', '>= 5.0.2' gem 'sidekiq', '~> 5.0', '>= 5.0.2'
# Toastr: Simple javascript toast notifications, plugged into the rails asset pipeline.
gem 'toastr-rails', '~> 1.0', '>= 1.0.3'
# Use Capistrano for deployment # Use Capistrano for deployment
# gem 'capistrano-rails', group: :development # gem 'capistrano-rails', group: :development
......
...@@ -225,6 +225,8 @@ GEM ...@@ -225,6 +225,8 @@ GEM
thor (0.19.4) thor (0.19.4)
thread_safe (0.3.6) thread_safe (0.3.6)
tilt (2.0.7) tilt (2.0.7)
toastr-rails (1.0.3)
railties (>= 3.1.0)
turbolinks (5.0.1) turbolinks (5.0.1)
turbolinks-source (~> 5) turbolinks-source (~> 5)
turbolinks-source (5.0.3) turbolinks-source (5.0.3)
...@@ -275,6 +277,7 @@ DEPENDENCIES ...@@ -275,6 +277,7 @@ DEPENDENCIES
sidekiq (~> 5.0, >= 5.0.2) sidekiq (~> 5.0, >= 5.0.2)
spring spring
spring-watcher-listen (~> 2.0.0) spring-watcher-listen (~> 2.0.0)
toastr-rails (~> 1.0, >= 1.0.3)
turbolinks (~> 5) turbolinks (~> 5)
tzinfo-data tzinfo-data
uglifier (>= 1.3.0) uglifier (>= 1.3.0)
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
// //
//= require jquery //= require jquery
//= require jquery_ujs //= require jquery_ujs
//= require bootstrap-touchspin
//# require rails-ujs //# require rails-ujs
//= require turbolinks //= require turbolinks
//# require_tree . //# require_tree .
//= require toastr
//= require bootstrap-touchspin
//= require cart/cart //= require cart/cart
\ No newline at end of file
...@@ -12,8 +12,5 @@ ...@@ -12,8 +12,5 @@
* *
*# require_tree . *# require_tree .
*= require_self *= require_self
*= require bootstrap-touchspin
*= require custom *= require custom
*= require main_style
*= require skin_14
*/ */
...@@ -2,3 +2,7 @@ ...@@ -2,3 +2,7 @@
@import "bootstrap-sprockets"; @import "bootstrap-sprockets";
@import "bootstrap"; @import "bootstrap";
@import "font-awesome"; @import "font-awesome";
@import "bootstrap-touchspin";
@import "toastr";
@import "main_style";
@import "skin_14";
\ No newline at end of file
...@@ -87,7 +87,14 @@ a { ...@@ -87,7 +87,14 @@ a {
padding-right: 12px; padding-right: 12px;
} }
} }
/*
* Notification
*/
.alert-notice {
color: #3c763d;
background-color: #dff0d8;
border-color: #d6e9c6;
}
/* /*
* Header * Header
*/ */
...@@ -183,7 +190,33 @@ a { ...@@ -183,7 +190,33 @@ a {
font-size: 14px; font-size: 14px;
font-weight: 600; font-weight: 600;
} }
#header .custom-block {
display: inline-block;
text-align: center;
font-size: 14px;
line-height: 39px;
font-weight: 400;
vertical-align: middle;
}
@media (max-width: 991px) {
#header .custom-block {
display: none;
}
}
#header .custom-block i {
margin-right: 5px;
}
#header .custom-block .split {
display: inline-block;
height: 14px;
width: 1px;
border-right: 1px solid #ccc;
vertical-align: middle;
margin: 0 10px;
}
#header .custom-block a {
font-size: 12px;
}
/* /*
* Button * Button
*/ */
...@@ -1331,3 +1364,153 @@ html .featured-box-primary .box-content { ...@@ -1331,3 +1364,153 @@ html .featured-box-primary .box-content {
.form-col .checkout-review-action h5 span { .form-col .checkout-review-action h5 span {
margin-left: 45px; margin-left: 45px;
} }
/*
* Panel box
*/
.panel-box {
margin-bottom: 30px;
}
.panel-box a {
color: #000;
}
.panel-box a:hover, .panel-box a:focus {
color: #0f0f0f;
}
.panel-box .panel-box-title {
padding: 10px 15px;
border: 1px solid #ddd;
background-color: #f5f5f5;
position: relative;
border-radius: 0 0 0 0;
}
.panel-box .panel-box-title:after {
content: '';
display: table;
clear: both;
}
.panel-box .panel-box-title h3, .panel-box .panel-box-title h4 {
float: left;
font-size: 13px;
font-weight: 700;
line-height: 18px;
text-transform: uppercase;
margin: 0;
color: #313131;
}
.panel-box .panel-box-title .panel-box-edit {
float: right;
line-height: 18px;
font-size: 12px;
}
.panel-box .panel-box-content {
padding: 20px 15px;
font-size: 13px;
border: 1px solid #ddd;
border-top: 0;
border-radius: 0 0 0 0;
background-color: #fbfbfb;
min-height: 135px;
}
/*
* Sidebar
*/
aside ul.nav-list > li > a {
font-size: 13px;
padding-left: 21px;
}
aside ul.nav-list > li > a:before {
margin-left: -11px;
}
aside ul.nav-list > li.active > a {
color: #000;
font-weight: 600;
}
aside ul.nav-list > li.active > a:before {
border-left-color: #000;
}
.sidebar h4 {
margin: 5px 0 10px;
line-height: 1.2;
font-size: 16px;
font-weight: bold;
color: #313131;
}
.sidebar .nav.nav-list {
margin-bottom: 30px;
}
/* Nav List */
ul.nav-list li {
margin: 0;
padding: 0;
display: block;
position: relative;
}
ul.nav-list li a {
-webkit-transition: background 0.1s;
-moz-transition: background 0.1s;
transition: background 0.1s;
border-bottom: 1px solid #EDEDDE;
padding: 8px 0 8px 18px;
display: block;
color: #666;
font-size: 0.9em;
text-decoration: none;
line-height: 20px;
}
ul.nav-list li a:before {
content: "";
display: inline-block;
width: 0;
height: 0;
border-top: 4px solid transparent;
border-bottom: 4px solid transparent;
border-left: 4px solid #333;
margin: 7px 0 0 -9px;
position: absolute;
}
ul.nav-list li a:hover {
background-color: #eee;
text-decoration: none;
}
ul.nav-list li.active > a {
font-weight: bold;
}
ul.nav-list li ul {
list-style: none;
margin: 0 0 0 25px;
padding: 0;
}
ul.nav-list.hide-not-active li ul {
display: none;
}
ul.nav-list.hide-not-active li.active ul {
display: block;
}
ul.nav-list.show-bg-active .active > a {
background-color: #f5f5f5;
}
ul.nav-list.show-bg-active .active > a:hover {
background-color: #eee;
}
ul.narrow li a {
padding: 4px 0;
}
ul.nav-pills > li.active > a {
background-color: #CCC;
}
ul.nav-pills > li.active > a:hover, ul.nav-pills > li.active > a:focus {
background-color: #CCC;
}
\ No newline at end of file
...@@ -11,17 +11,19 @@ class LineItemsController < ApplicationController ...@@ -11,17 +11,19 @@ class LineItemsController < ApplicationController
# POST /line_items # POST /line_items
def create def create
return if params[:product_quantity].to_i.zero?
product = Product.find(params[:product_id]) product = Product.find(params[:product_id])
product_is_in_stock = product_is_in_stock?(product, get_line_item_quantity(product.id, params[:product_quantity])) 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 add_to_cart(product.id, params[:product_quantity]) if product_is_in_stock
respond_to do |format| respond_to do |format|
if product_is_in_stock notice_msg = get_create_notice_msg(product_is_in_stock, product)
format.html { redirect_to cart_index_url, notice: "#{product.title} was sucessfully added to your cart" } notice_type = get_create_notice_type(product_is_in_stock)
format.js format.html { redirect_to cart_index_url,
else notice: notice_msg }
format.html { redirect_to cart_index_url, notice: "#{product.title} is out of stock" } format.js { @notice = { msg: notice_msg, type: notice_type } }
end
end end
end end
...@@ -47,7 +49,8 @@ class LineItemsController < ApplicationController ...@@ -47,7 +49,8 @@ class LineItemsController < ApplicationController
product = Product.find(params[:id]) product = Product.find(params[:id])
respond_to do |format| respond_to do |format|
format.html { redirect_to cart_index_url, notice: "#{product.title} was sucessfully removed from your cart" } format.html { redirect_to cart_index_url,
notice: "#{product.title} was sucessfully removed from your cart" }
end end
end end
...@@ -61,4 +64,13 @@ class LineItemsController < ApplicationController ...@@ -61,4 +64,13 @@ class LineItemsController < ApplicationController
def product_is_in_stock?(product, quantity) def product_is_in_stock?(product, quantity)
product.quantity >= quantity.to_i product.quantity >= quantity.to_i
end 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
end end
\ No newline at end of file
...@@ -14,18 +14,16 @@ class OrdersController < ApplicationController ...@@ -14,18 +14,16 @@ class OrdersController < ApplicationController
# POST /orders # POST /orders
def create def create
@order = current_user.orders.new @order = current_user.orders.create!
create_line_items_for_order(@order) create_line_items_for_order(@order)
respond_to do |format| respond_to do |format|
if @order.save
destroy_cart_session destroy_cart_session
OrderMailer.send_order_detail_to_user(current_user, @order).deliver_later OrderMailer.send_order_detail_to_user(current_user, @order).deliver_later
format.html { redirect_to root_url, notice: 'Your order is successfully created' } format.html { redirect_to root_url, notice: 'Your order is successfully created' }
else
format.html { redirect_to root_url, notice: 'Your order can not be created' }
end
end end
rescue ActiveRecord::RecordNotSaved
redirect_to root_url, notice: 'Your order can not be created'
end end
def create_line_items_for_order(order) def create_line_items_for_order(order)
......
class UsersController < ApplicationController
before_action :authenticate_user!
# GET /users/1
def show
@user = User.find(current_user.id)
end
# GET /users/products
def products
@products = current_user.products.page(params[:page]).per(5)
end
end
\ No newline at end of file
module ApplicationHelper 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 end
class LineItem < ApplicationRecord class LineItem < ApplicationRecord
belongs_to :product, optional: true belongs_to :product, optional: true
belongs_to :order, optional: true belongs_to :order, optional: true
after_create :update_product_quantity
def total_price def total_price
product.price * quantity product.price * quantity
end end
def update_product_quantity
product.update(quantity: product.quantity - quantity)
end
end end
\ No newline at end of file
...@@ -13,6 +13,30 @@ ...@@ -13,6 +13,30 @@
</h4> </h4>
<div class="row"> <div class="row">
<div class="col-md-6">
<div class="form-group">
<%= f.label :first_name %>
<%= f.text_field :first_name, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<%= f.label :last_name %>
<%= f.text_field :last_name, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<%= f.label :username %>
<%= f.text_field :username, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<div class="form-group"> <div class="form-group">
<%= f.label :email %> <%= f.label :email %>
...@@ -57,5 +81,8 @@ ...@@ -57,5 +81,8 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-md-3 col-md-pull-9">
<%= render 'shared/account_sidebar' %>
</div>
</div> </div>
</div> </div>
...@@ -11,6 +11,30 @@ ...@@ -11,6 +11,30 @@
<%= devise_error_messages! %> <%= devise_error_messages! %>
<div class="row"> <div class="row">
<div class="col-md-6">
<div class="form-group">
<%= f.label :first_name %>
<%= f.text_field :first_name, class: "form-control" %>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<%= f.label :last_name %>
<%= f.text_field :last_name, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<%= f.label :username %>
<%= f.text_field :username, class: "form-control" %>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<div class="form-group"> <div class="form-group">
<%= f.label :email %> <%= f.label :email %>
......
<section class="form-section"> <section class="form-section">
<div class="container"> <div class="container">
<h2 class="h2 heading-primary font-weight-normal mb-md mt-xlg"> <h2 class="h2 heading-primary font-weight-normal mb-md mt-xlg">
Welcome back! Sign in to your account Login or Create an Account
</h2> </h2>
<div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md"> <div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md">
<div class="box-content"> <div class="box-content">
<div class="row"> <div class="row">
<div class="col-md-6 col-md-offset-3"> <div class="col-sm-6">
<div class="form-content">
<h3 class="heading-text-color font-weight-normal">New Customers</h3>
<p>By creating an account with our store, you will be able to move through the checkout process faster,
store multiple shipping addresses, view and track your orders in your account and more.</p>
</div>
<div class="form-action clea rfix">
<%= link_to 'Create an Account', new_user_registration_path, class: 'btn btn-primary' %>
</div>
</div>
<div class="col-md-6">
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="form-content"> <div class="form-content">
<h3 class="heading-text-color font-weight-normal"> <h3 class="heading-text-color font-weight-normal">
...@@ -15,7 +25,7 @@ ...@@ -15,7 +25,7 @@
<div class="form-group"> <div class="form-group">
<%= f.label :login %> <%= f.label :login %>
<%= f.email_field :login, autofocus: true, class: "form-control" %> <%= f.text_field :login, autofocus: true, class: "form-control" %>
</div> </div>
<div class="form-group"> <div class="form-group">
...@@ -25,7 +35,7 @@ ...@@ -25,7 +35,7 @@
</div> </div>
<div class="form-action clearfix"> <div class="form-action clearfix">
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
<%= link_to "Lost your password?", new_password_path(resource_name), class: 'pull-left' %> <%# link_to "Lost your password?", new_password_path(resource_name), class: 'pull-left' %>
<% end -%> <% end -%>
<%= f.submit "Submit", class: "btn btn-primary" %> <%= f.submit "Submit", class: "btn btn-primary" %>
</div> </div>
......
...@@ -16,6 +16,17 @@ ...@@ -16,6 +16,17 @@
<div class="header-column"> <div class="header-column">
<div class="row"> <div class="row">
<div class="cart-area"> <div class="cart-area">
<div class="custom-block">
<% if user_signed_in? %>
<%= link_to 'MY PROFILE', user_profile_path %>
<span class="split"></span>
<%= link_to 'SIGN OUT', destroy_user_session_path, method: :delete %>
<% else %>
<%= link_to 'SIGN IN', new_user_session_path %>
<span class="split"></span>
<%= link_to 'SIGN UP', new_user_registration_path %>
<% end %>
</div>
<div class="cart-dropdown"> <div class="cart-dropdown">
<a href="<%= cart_index_url %>" class="cart-dropdown-icon"> <a href="<%= cart_index_url %>" class="cart-dropdown-icon">
<i class="minicart-icon"></i> <i class="minicart-icon"></i>
......
$('.cart-qty').html("<%= render 'carts/cart_quantity' %>"); $('.cart-qty').html("<%= render 'carts/cart_quantity' %>");
<% if @notice %>
toastr.<%= @notice[:type] %>('<%= @notice[:msg] %>');
<% end %>
\ No newline at end of file
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
<div class="product-details-box col-sm-7"> <div class="product-details-box col-sm-7">
<h1 class="product-name"> <h1 class="product-name">
<%= product.title %> <%= product.title %>
<%= link_to fa_icon('pencil'), edit_product_path if user_own_product?(product) %>
</h1> </h1>
<div class="product-short-desc"> <div class="product-short-desc">
<%= product.description %> <%= product.description %>
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<div class="product-details-area"> <div class="product-details-area">
<h2 class="product-name"> <h2 class="product-name">
<%= link_to product.title, product_url(product) %> <%= link_to product.title, product_url(product) %>
<%= link_to fa_icon('pencil'), edit_product_path(product) if user_own_product?(product) %>
</h2> </h2>
<div class="product-short-desc"> <div class="product-short-desc">
<%= product.description %> <%= product.description %>
......
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-9 col-md-push-3 create-product form-section"> <div class="col-md-12 create-product form-section">
<h1 class="h2 heading-primary font-weight-normal"> <h1 class="h2 heading-primary font-weight-normal">
Edit Product #<%= @product.id %> Edit Product #<%= @product.id %>
(<%= link_to 'Delete', @product, method: :delete, data: { confirm: 'Are your sure?' } %>) (<%= link_to 'Delete', @product, method: :delete, data: { confirm: 'Are your sure?' } %>)
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
<div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md"> <div class="featured-box featured-box-primary featured-box-flat featured-box-text-left mt-md">
<div class="box-content"> <div class="box-content">
<p><%= link_to 'Back to product', product_path %></p>
<%= render 'form' %> <%= render 'form' %>
</div> </div>
</div> </div>
......
<aisde class="sidebar">
<h4>My Account</h4>
<ul class="nav nav-list">
<li class="<%= active_class('show') %>">
<%= link_to 'My Dashboard', user_profile_path %>
</li>
<li class="<%= active_class('edit') %>">
<%= link_to 'Edit Account Information', edit_user_registration_path %>
</li>
<li class="<%= active_class('products') %>">
<%= link_to 'My Products', user_products_path %>
</li>
</ul>
</aisde>
\ No newline at end of file
<div class="container">
<div class="row">
<div class="col-md-9 col-md-push-3 my-account">
<h2 class="h2 heading-primary font-weight-normal">
My Products
</h2>
<%= render partial: 'products/product_list', locals: { products: @products } %>
<div class="toolbar-bottom">
<div class="toolbar">
<div class="sorter">
<%= paginate @products, theme: 'bootstrap' %>
</div>
</div>
</div>
</div>
<div class="col-md-3 col-md-pull-9">
<%= render 'shared/account_sidebar' %>
</div>
</div>
</div>
\ No newline at end of file
<div class="container">
<div class="row">
<div class="col-md-9 col-md-push-3 my-account">
<h2 class="h2 heading-primary font-weight-normal">
My Dashboard
</h2>
<h2 class="h3 mb-sm">
<strong>Account Information</strong>
</h2>
<div class="row">
<div class="col-sm-12">
<div class="panel-box">
<div class="panel-box-title">
<h3>Contact Information</h3>
<%= link_to 'Edit', edit_user_registration_path, class: 'panel-box-edit' %>
</div>
<div class="panel-box-content">
<p><%= @user.first_name %> <%= @user.last_name %></p>
<p><%= @user.email %></p>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3 col-md-pull-9">
<%= render 'shared/account_sidebar' %>
</div>
</div>
</div>
\ No newline at end of file
...@@ -8,4 +8,8 @@ Rails.application.routes.draw do ...@@ -8,4 +8,8 @@ Rails.application.routes.draw do
resources :cart, only: :index, controller: 'carts' resources :cart, only: :index, controller: 'carts'
delete '/cart/remove', to: 'carts#destroy', as: 'remove_cart' delete '/cart/remove', to: 'carts#destroy', as: 'remove_cart'
devise_for :users devise_for :users
scope '/users' do
get '/', to: 'users#show', as: 'user_profile'
get '/products', to: 'users#products', as: 'user_products'
end
end end
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