From b3d1019cd48186f07934d0c8d1b17f34132baeba Mon Sep 17 00:00:00 2001 From: jamey Date: Wed, 11 Feb 2026 00:15:04 +0000 Subject: [PATCH] add quantity controls to cart drawer via shared CartHook Move increment/decrement handlers from Cart LiveView into CartHook so they work from any page's drawer. Enable show_quantity_controls on the drawer's cart_item_row. Scope cart tests to #main-content to avoid duplicate button matches. Co-Authored-By: Claude Opus 4.6 --- PROGRESS.md | 2 +- lib/simpleshop_theme_web/cart_hook.ex | 30 +++++++++++++++++-- .../components/shop_components/cart.ex | 2 +- .../live/shop_live/cart.ex | 27 ----------------- .../live/shop_live/cart_test.exs | 4 +-- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/PROGRESS.md b/PROGRESS.md index 0a011ab..61167a5 100644 --- a/PROGRESS.md +++ b/PROGRESS.md @@ -48,7 +48,7 @@ Issues found during hands-on testing of the deployed prod site on mobile and des - [ ] Real product variants need testing and refinement with live data ### Cart -- [ ] Should be able to change quantity in the cart drawer (currently only on cart page?) +- [x] Should be able to change quantity in the cart drawer (currently only on cart page?) - [ ] Cart drawer button → "view basket" feels redundant — streamline the flow ### Navigation & links diff --git a/lib/simpleshop_theme_web/cart_hook.ex b/lib/simpleshop_theme_web/cart_hook.ex index 895a8b9..a5770f2 100644 --- a/lib/simpleshop_theme_web/cart_hook.ex +++ b/lib/simpleshop_theme_web/cart_hook.ex @@ -8,10 +8,11 @@ defmodule SimpleshopThemeWeb.CartHook do Handles these events so individual LiveViews don't have to: - `open_cart_drawer` / `close_cart_drawer` - toggle drawer visibility - `remove_item` - remove item from cart + - `increment` / `decrement` - change item quantity - `{:cart_updated, cart}` info - cross-tab cart sync via PubSub - LiveViews with custom cart logic (add_to_cart, increment, decrement) - can call `update_cart_assigns/2` and `broadcast_and_update/2` directly. + LiveViews with custom cart logic (e.g. add_to_cart) can call + `update_cart_assigns/2` and `broadcast_and_update/2` directly. """ import Phoenix.Component, only: [assign: 3] @@ -64,6 +65,31 @@ defmodule SimpleshopThemeWeb.CartHook do {:halt, socket} end + defp handle_cart_event("increment", %{"id" => variant_id}, socket) do + cart = Cart.add_item(socket.assigns.raw_cart, variant_id, 1) + new_qty = Cart.get_quantity(cart, variant_id) + + socket = + socket + |> broadcast_and_update(cart) + |> assign(:cart_status, "Quantity updated to #{new_qty}") + + {:halt, socket} + end + + defp handle_cart_event("decrement", %{"id" => variant_id}, socket) do + current = Cart.get_quantity(socket.assigns.raw_cart, variant_id) + cart = Cart.update_quantity(socket.assigns.raw_cart, variant_id, current - 1) + new_qty = Cart.get_quantity(cart, variant_id) + + socket = + socket + |> broadcast_and_update(cart) + |> assign(:cart_status, "Quantity updated to #{new_qty}") + + {:halt, socket} + end + defp handle_cart_event(_event, _params, socket), do: {:cont, socket} # Shared info handlers diff --git a/lib/simpleshop_theme_web/components/shop_components/cart.ex b/lib/simpleshop_theme_web/components/shop_components/cart.ex index 738e0da..58138b4 100644 --- a/lib/simpleshop_theme_web/components/shop_components/cart.ex +++ b/lib/simpleshop_theme_web/components/shop_components/cart.ex @@ -105,7 +105,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Cart do diff --git a/lib/simpleshop_theme_web/live/shop_live/cart.ex b/lib/simpleshop_theme_web/live/shop_live/cart.ex index 3585820..77e53ef 100644 --- a/lib/simpleshop_theme_web/live/shop_live/cart.ex +++ b/lib/simpleshop_theme_web/live/shop_live/cart.ex @@ -8,33 +8,6 @@ defmodule SimpleshopThemeWeb.ShopLive.Cart do {:ok, assign(socket, :page_title, "Cart")} end - @impl true - def handle_event("increment", %{"id" => variant_id}, socket) do - cart = Cart.add_item(socket.assigns.raw_cart, variant_id, 1) - new_qty = Cart.get_quantity(cart, variant_id) - - socket = - socket - |> SimpleshopThemeWeb.CartHook.broadcast_and_update(cart) - |> assign(:cart_status, "Quantity updated to #{new_qty}") - - {:noreply, socket} - end - - @impl true - def handle_event("decrement", %{"id" => variant_id}, socket) do - current = Cart.get_quantity(socket.assigns.raw_cart, variant_id) - cart = Cart.update_quantity(socket.assigns.raw_cart, variant_id, current - 1) - new_qty = Cart.get_quantity(cart, variant_id) - - socket = - socket - |> SimpleshopThemeWeb.CartHook.broadcast_and_update(cart) - |> assign(:cart_status, "Quantity updated to #{new_qty}") - - {:noreply, socket} - end - @impl true def render(assigns) do assigns = assign(assigns, :cart_page_subtotal, Cart.calculate_subtotal(assigns.cart_items)) diff --git a/test/simpleshop_theme_web/live/shop_live/cart_test.exs b/test/simpleshop_theme_web/live/shop_live/cart_test.exs index d432af2..bfb02e2 100644 --- a/test/simpleshop_theme_web/live/shop_live/cart_test.exs +++ b/test/simpleshop_theme_web/live/shop_live/cart_test.exs @@ -68,7 +68,7 @@ defmodule SimpleshopThemeWeb.ShopLive.CartTest do html = view - |> element("button[aria-label='Increase quantity of #{product.title}']") + |> element("#main-content button[aria-label='Increase quantity of #{product.title}']") |> render_click() assert html =~ "Quantity updated to 2" @@ -83,7 +83,7 @@ defmodule SimpleshopThemeWeb.ShopLive.CartTest do html = view - |> element("button[aria-label='Decrease quantity of #{product.title}']") + |> element("#main-content button[aria-label='Decrease quantity of #{product.title}']") |> render_click() assert html =~ "Your basket is empty"