add no-JS progressive enhancement for all shop flows
All checks were successful
deploy / deploy (push) Successful in 1m23s
All checks were successful
deploy / deploy (push) Successful in 1m23s
Every key shop flow now works via plain HTML forms when JS is unavailable. LiveView progressively enhances when JS connects. - PDP: form wraps variant/qty/add-to-cart with action="/cart/add" - Cart page: qty +/- and remove use form POST fallbacks - Cart/search header icons are now links with phx-click enhancement - Collection sort form has GET action + noscript submit button - New /search page with form-based search for no-JS users - CartController gains add/remove/update_item POST actions - CartHook gains update_quantity_form and remove_item_form handlers - Fix flaky analytics tests caused by event table pollution Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
defmodule BerrypodWeb.CartController do
|
||||
@moduledoc """
|
||||
API controller for cart session persistence.
|
||||
Cart controller handling both JSON API persistence and HTML form fallbacks.
|
||||
|
||||
LiveView cannot write to session directly, so cart updates are persisted
|
||||
via this API endpoint called from a JS hook after each cart modification.
|
||||
The JSON `update/2` action is called by a JS hook after each LiveView cart
|
||||
change. The HTML actions (`add/2`, `remove/2`, `update_item/2`) provide
|
||||
no-JS fallbacks via plain form POST + redirect.
|
||||
"""
|
||||
|
||||
use BerrypodWeb, :controller
|
||||
@@ -11,9 +12,7 @@ defmodule BerrypodWeb.CartController do
|
||||
alias Berrypod.Cart
|
||||
|
||||
@doc """
|
||||
Updates the cart in session.
|
||||
|
||||
Expects JSON body with `items` as a list of [variant_id, quantity] arrays.
|
||||
Updates the cart in session (JSON API for JS hook).
|
||||
"""
|
||||
def update(conn, %{"items" => items}) when is_list(items) do
|
||||
cart_items = Cart.deserialize(items)
|
||||
@@ -28,4 +27,69 @@ defmodule BerrypodWeb.CartController do
|
||||
|> put_status(:bad_request)
|
||||
|> json(%{error: "Invalid cart data"})
|
||||
end
|
||||
|
||||
@doc """
|
||||
Adds an item to cart via form POST (no-JS fallback).
|
||||
"""
|
||||
def add(conn, %{"variant_id" => variant_id, "quantity" => qty_str}) do
|
||||
quantity = parse_quantity(qty_str)
|
||||
cart = Cart.get_from_session(get_session(conn))
|
||||
cart = Cart.add_item(cart, variant_id, quantity)
|
||||
|
||||
conn
|
||||
|> Cart.put_in_session(cart)
|
||||
|> put_flash(:info, "Added to basket")
|
||||
|> redirect(to: ~p"/cart")
|
||||
end
|
||||
|
||||
def add(conn, _params) do
|
||||
conn
|
||||
|> put_flash(:error, "Could not add item to basket")
|
||||
|> redirect(to: ~p"/cart")
|
||||
end
|
||||
|
||||
@doc """
|
||||
Removes an item from cart via form POST (no-JS fallback).
|
||||
"""
|
||||
def remove(conn, %{"variant_id" => variant_id}) do
|
||||
cart = Cart.get_from_session(get_session(conn))
|
||||
cart = Cart.remove_item(cart, variant_id)
|
||||
|
||||
conn
|
||||
|> Cart.put_in_session(cart)
|
||||
|> put_flash(:info, "Removed from basket")
|
||||
|> redirect(to: ~p"/cart")
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates item quantity via form POST (no-JS fallback).
|
||||
"""
|
||||
def update_item(conn, %{"variant_id" => variant_id, "quantity" => qty_str}) do
|
||||
quantity = parse_update_quantity(qty_str)
|
||||
cart = Cart.get_from_session(get_session(conn))
|
||||
cart = Cart.update_quantity(cart, variant_id, quantity)
|
||||
|
||||
conn
|
||||
|> Cart.put_in_session(cart)
|
||||
|> redirect(to: ~p"/cart")
|
||||
end
|
||||
|
||||
defp parse_quantity(str) when is_binary(str) do
|
||||
case Integer.parse(str) do
|
||||
{qty, _} when qty > 0 -> qty
|
||||
_ -> 1
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_quantity(_), do: 1
|
||||
|
||||
# Allows 0 and negative values so Cart.update_quantity can remove items
|
||||
defp parse_update_quantity(str) when is_binary(str) do
|
||||
case Integer.parse(str) do
|
||||
{qty, _} -> qty
|
||||
:error -> 1
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_update_quantity(_), do: 1
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user