Skip to content

Commit

Permalink
Marketplace: Cart Total Updates as Products are Added and Removed (#927)
Browse files Browse the repository at this point in the history
* Marketplace: Cart can Total Price

Co-Authored-By: Ana Ulin <[email protected]>

* Marketplace: Adding and Removing Products updates Cart's Total

Co-authored-by: Ana Ulin <[email protected]>

Co-authored-by: Ana Ulin <[email protected]>
  • Loading branch information
zspencer and anaulin authored Nov 10, 2022
1 parent 2c44d95 commit e4cb538
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 30 deletions.
8 changes: 7 additions & 1 deletion app/furniture/marketplace/cart.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@ class Cart < ApplicationRecord

belongs_to :marketplace
delegate :space, :room, to: :marketplace
has_many :cart_products
has_many :cart_products, dependent: :destroy
has_many :products, through: :cart_products

def self.model_name
@_model_name ||= ActiveModel::Name.new(self, ::Marketplace)
end

def price_total
cart_products.sum do |cart_product|
cart_product.product.price * cart_product.quantity
end
end
end
end
18 changes: 15 additions & 3 deletions app/furniture/marketplace/cart_products_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ def create
end

format.turbo_stream do
render turbo_stream: turbo_stream.replace("cart-product-#{cart_product.product_id}", cart_product)
render turbo_stream: [
turbo_stream.replace("cart-product-#{cart_product.product_id}", cart_product),
turbo_stream.replace("cart-footer-#{cart.id}",
partial: "marketplace/carts/footer", locals: {cart: cart}),
]
end
end
end
Expand All @@ -41,7 +45,11 @@ def update
redirect_to [marketplace.space, marketplace.room]
end
format.turbo_stream do
render turbo_stream: turbo_stream.replace("cart-product-#{cart_product.product_id}", cart_product)
render turbo_stream: [
turbo_stream.replace("cart-product-#{cart_product.product_id}", cart_product),
turbo_stream.replace("cart-footer-#{cart.id}",
partial: "marketplace/carts/footer", locals: {cart: cart}),
]
end
end
end
Expand All @@ -63,7 +71,11 @@ def destroy
end

format.turbo_stream do
render turbo_stream: turbo_stream.replace("cart-product-#{cart_product.product_id}", cart.cart_products.new(product: cart_product.product))
render turbo_stream: [
turbo_stream.replace("cart-product-#{cart_product.product_id}", cart.cart_products.new(product: cart_product.product)),
turbo_stream.replace("cart-footer-#{cart.id}",
partial: "marketplace/carts/footer", locals: {cart: cart})
]
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions app/furniture/marketplace/carts/_cart.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<div class="-mx-4 mt-8 overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:-mx-6 md:mx-0 md:rounded-lg">
<table class="min-w-full divide-y divide-gray-300 table-fixed">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
<%= Marketplace::Product.human_attribute_name(:name) %>
</th>
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">
<%= Marketplace::Product.human_attribute_name(:description) %>
</th>
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:table-cell">
<%= Marketplace::Product.human_attribute_name(:price) %>
</th>
<th scope="col" class="w-48">&nbsp;</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<%- cart.marketplace.products.each do |product| %>
<%= render cart.cart_products.find_or_initialize_by(product: product) %>
<%- end %>
</tbody>
<%= render "marketplace/carts/footer", cart: cart %>
</table>
</div>
9 changes: 9 additions & 0 deletions app/furniture/marketplace/carts/_footer.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<tfoot id="cart-footer-<%= cart.id%>" class="bg-gray-50">
<tr>
<td></td>
<th scope="row" class="text-right px-1 py-3.5">Total: </th>
<td class="text-left px-3 py-3.5 font-bold">
<%= humanized_money_with_symbol(cart.price_total) %>
</td>
</tr>
</tfoot
28 changes: 4 additions & 24 deletions app/furniture/marketplace/marketplaces/_marketplace.html.erb
Original file line number Diff line number Diff line change
@@ -1,28 +1,8 @@

<div class="-mx-4 mt-8 overflow-hidden shadow ring-1 ring-black ring-opacity-5 sm:-mx-6 md:mx-0 md:rounded-lg">
<table class="min-w-full divide-y divide-gray-300 table-fixed">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
<%= Marketplace::Product.human_attribute_name(:name) %>
</th>
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">
<%= Marketplace::Product.human_attribute_name(:description) %>
</th>
<th scope="col" class="hidden px-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:table-cell">
<%= Marketplace::Product.human_attribute_name(:price) %>
</th>
<th scope="col" class="w-48">&nbsp;</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<%- cart = marketplace.carts.find_or_create_by(id: session[:current_cart] ||= SecureRandom.uuid) %>
<%- marketplace.products.each do |product| %>
<%= render cart.cart_products.find_or_initialize_by(product: product) %>
<%- end %>
</tbody>
</table>
</div>
<%- cart = marketplace.carts.find_or_create_by(id: session[:current_cart] ||= SecureRandom.uuid) %>

<%= render cart %>

<div class="m-2 text-center">
<%- if policy(marketplace.products.new).create? %>
<%= link_to t('.manage_products'), marketplace.location(:products) %>
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/money.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
#
# set to BigDecimal::ROUND_HALF_EVEN by default
#
# config.rounding_mode = BigDecimal::ROUND_HALF_UP
config.rounding_mode = BigDecimal::ROUND_HALF_EVEN

# Set default money format globally.
# Default value is nil meaning "ignore this option".
Expand Down
17 changes: 16 additions & 1 deletion spec/furniture/marketplace/cart_spec.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,24 @@
require "rails_helper"

RSpec.describe Marketplace::Cart, type: :model do
it { is_expected.to have_many(:cart_products) }
it { is_expected.to have_many(:cart_products).dependent(:destroy) }

it { is_expected.to have_many(:products).through(:cart_products) }

it { is_expected.to belong_to(:marketplace).class_name("Marketplace::Marketplace") }

describe "#price_total" do
subject(:price_total) { cart.price_total }

let(:cart) { create(:marketplace_cart) }
let(:product_a) { create(:marketplace_product, marketplace: cart.marketplace) }
let(:product_b) { create(:marketplace_product, marketplace: cart.marketplace) }

before do
cart.cart_products.create!(product: product_a, quantity: 1)
cart.cart_products.create!(product: product_b, quantity: 2)
end

it { is_expected.to eql(product_a.price + product_b.price + product_b.price) }
end
end

0 comments on commit e4cb538

Please sign in to comment.