prevent checkout with unavailable product variants
- Include is_available flag in hydrated cart items - Show unavailable message on cart items and product page - Block add-to-cart for unavailable variants - Redirect back to cart with error if checkout has unavailable items Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
09f55dfe67
commit
a6e5db73c0
@ -781,6 +781,15 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ── Unavailable message ── */
|
||||
|
||||
.variant-unavailable-msg {
|
||||
color: var(--t-sale-color);
|
||||
font-size: var(--t-text-small);
|
||||
font-weight: 500;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* ── Add to cart ── */
|
||||
|
||||
.atc-wrap {
|
||||
@ -1709,6 +1718,13 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.cart-item-unavailable {
|
||||
font-size: var(--t-text-caption);
|
||||
color: var(--t-sale-color);
|
||||
font-weight: 500;
|
||||
margin: 0.25rem 0 0;
|
||||
}
|
||||
|
||||
.cart-item-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@ -132,7 +132,8 @@ defmodule Berrypod.Cart do
|
||||
variant: format_variant_options(variant.options),
|
||||
price: variant.price,
|
||||
quantity: quantity,
|
||||
image: variant_image_url(variant.product)
|
||||
image: variant_image_url(variant.product),
|
||||
is_available: variant.is_available
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
||||
@ -212,6 +212,10 @@ defmodule BerrypodWeb.ShopComponents.Cart do
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<p :if={Map.get(@item, :is_available) == false} class="cart-item-unavailable">
|
||||
This item is currently unavailable
|
||||
</p>
|
||||
|
||||
<div class="cart-item-actions">
|
||||
<%= if @show_quantity_controls do %>
|
||||
<form
|
||||
|
||||
@ -16,11 +16,18 @@ defmodule BerrypodWeb.CheckoutController do
|
||||
cart_items = Cart.get_from_session(get_session(conn))
|
||||
hydrated = Cart.hydrate(cart_items)
|
||||
|
||||
if hydrated == [] do
|
||||
cond do
|
||||
hydrated == [] ->
|
||||
conn
|
||||
|> put_flash(:error, "Your basket is empty")
|
||||
|> redirect(to: ~p"/cart")
|
||||
else
|
||||
|
||||
Enum.any?(hydrated, &(&1.is_available == false)) ->
|
||||
conn
|
||||
|> put_flash(:error, "Some items in your basket are no longer available")
|
||||
|> redirect(to: ~p"/cart")
|
||||
|
||||
true ->
|
||||
track_checkout_start(conn)
|
||||
create_checkout(conn, hydrated)
|
||||
end
|
||||
|
||||
@ -90,7 +90,7 @@ defmodule BerrypodWeb.Shop.Pages.Product do
|
||||
def handle_event("add_to_cart", _params, socket) do
|
||||
variant = socket.assigns.selected_variant
|
||||
|
||||
if variant do
|
||||
if variant && variant.is_available do
|
||||
cart = Cart.add_item(socket.assigns.raw_cart, variant.id, socket.assigns.quantity)
|
||||
|
||||
if socket.assigns[:analytics_visitor_hash] do
|
||||
|
||||
@ -553,7 +553,18 @@ defmodule BerrypodWeb.PageRenderer do
|
||||
</div>
|
||||
|
||||
<.quantity_selector quantity={assigns[:quantity] || 1} in_stock={@product.in_stock} />
|
||||
<.add_to_cart_button mode={@mode} />
|
||||
|
||||
<p
|
||||
:if={assigns[:selected_variant] && !assigns[:selected_variant].is_available}
|
||||
class="variant-unavailable-msg"
|
||||
>
|
||||
This option is currently unavailable
|
||||
</p>
|
||||
|
||||
<.add_to_cart_button
|
||||
mode={@mode}
|
||||
disabled={assigns[:selected_variant] && !assigns[:selected_variant].is_available}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user