defmodule PhoenixKit.Modules.Shop.Web.CheckoutComplete do @moduledoc """ Order confirmation page after successful checkout. """ use PhoenixKitWeb, :live_view alias PhoenixKit.Modules.Billing alias PhoenixKit.Modules.Shop alias PhoenixKit.Modules.Shop.Web.Components.ShopLayouts import PhoenixKit.Modules.Shop.Web.Helpers, only: [format_price: 2, profile_display_name: 1, profile_address: 1, get_current_user: 1] alias PhoenixKit.Users.Auth alias PhoenixKit.Utils.Routes @impl true def mount(%{"uuid" => uuid}, _session, socket) do user = get_current_user(socket) case Billing.get_order_by_uuid(uuid) do nil -> {:ok, redirect_with_error(socket, "Order not found")} order -> handle_order_access(socket, order, user) end end defp handle_order_access(socket, order, user) do if has_order_access?(order, user) do {:ok, setup_order_assigns(socket, order)} else {:ok, redirect_with_error(socket, "You don't have access to this order")} end end defp has_order_access?(order, user) do cond do # No user_uuid on order - legacy guest order is_nil(order.user_uuid) -> true # Logged-in user owns the order not is_nil(user) and order.user_uuid == user.uuid -> true # Guest checkout - order belongs to unconfirmed user (allow access to confirmation page) guest_user_order?(order) -> true true -> false end end # Check if order belongs to an unconfirmed guest user defp guest_user_order?(%{user_uuid: nil}), do: false defp guest_user_order?(%{user_uuid: user_uuid}) do case Auth.get_user(user_uuid) do %{confirmed_at: nil} -> true _ -> false end end defp setup_order_assigns(socket, order) do currency = Shop.get_default_currency() billing_profile = get_billing_profile(order) {is_guest_order, order_email} = check_guest_order(order) # Check if user is authenticated authenticated = not is_nil(socket.assigns[:phoenix_kit_current_user]) socket |> assign(:page_title, "Order Confirmed") |> assign(:order, order) |> assign(:currency, currency) |> assign(:billing_profile, billing_profile) |> assign(:is_guest_order, is_guest_order) |> assign(:order_email, order_email) |> assign(:authenticated, authenticated) end defp get_billing_profile(%{billing_profile_uuid: nil}), do: nil defp get_billing_profile(%{billing_profile_uuid: uuid}), do: Billing.get_billing_profile(uuid) defp check_guest_order(%{user_uuid: nil} = order) do email = get_in(order.billing_snapshot, ["email"]) {not is_nil(email), email} end defp check_guest_order(%{user_uuid: user_uuid}) do case Auth.get_user(user_uuid) do %{confirmed_at: nil, email: email} -> {true, email} _ -> {false, nil} end end defp redirect_with_error(socket, message) do socket |> put_flash(:error, message) |> push_navigate(to: Routes.path("/shop")) end @impl true def render(assigns) do ~H"""
<%!-- Success Header --%>
<.icon name="hero-check-circle" class="w-12 h-12 text-success" />

Order Confirmed!

Thank you for your order. We've received your order and will process it shortly.

<%!-- Guest Order Email Confirmation Reminder --%> <%= if @is_guest_order do %>
<.icon name="hero-envelope" class="w-8 h-8 text-info flex-shrink-0" />

Check your inbox

We've sent a confirmation email to {@order_email}.

  1. Open the email titled "Confirm your account"
  2. Click the confirmation link inside
  3. Your account will be activated and you can track your order

Don't see it? Check your spam or junk folder. The email may take a minute to arrive.

<% end %> <%!-- Order Number --%>
Order Number
{@order.order_number}
<%= unless @is_guest_order do %>
A confirmation email will be sent to your email address.
<% end %>
<%!-- Order Details --%>

Order Details

<%!-- Billing Info --%> <%= if @billing_profile do %>

Billing Information

{profile_display_name(@billing_profile)}
{profile_address(@billing_profile)}
<%= if @billing_profile.email do %>
{@billing_profile.email}
<% end %>
<% else %> <%!-- Guest order - show billing snapshot --%> <%= if @order.billing_snapshot && map_size(@order.billing_snapshot) > 0 do %>

Billing Information

{@order.billing_snapshot["first_name"]} {@order.billing_snapshot["last_name"]}
{[ @order.billing_snapshot["address_line1"], @order.billing_snapshot["city"], @order.billing_snapshot["postal_code"], @order.billing_snapshot["country"] ] |> Enum.filter(&(&1 && &1 != "")) |> Enum.join(", ")}
<%= if @order.billing_snapshot["email"] do %>
{@order.billing_snapshot["email"]}
<% end %>
<% end %> <% end %> <%!-- Items --%>

Items

<%= for item <- @order.line_items || [] do %>
{item["name"]} <%= if item["type"] != "shipping" do %> × {item["quantity"]} <% end %>
{format_price_string(item["total"])}
<% end %>
<%!-- Totals --%>
Subtotal {format_price(@order.subtotal, @currency)}
<%= if @order.tax_amount && Decimal.compare(@order.tax_amount, Decimal.new("0")) == :gt do %>
Tax {format_price(@order.tax_amount, @currency)}
<% end %> <%= if @order.discount_amount && Decimal.compare(@order.discount_amount, Decimal.new("0")) == :gt do %>
Discount -{format_price(@order.discount_amount, @currency)}
<% end %>
Total {format_price(@order.total, @currency)}
<%!-- Status --%>

Order Status

Your order is being processed

{@order.status}
<%!-- Actions --%>
<.link navigate={Routes.path("/shop")} class="btn btn-primary"> <.icon name="hero-shopping-bag" class="w-5 h-5 mr-2" /> Continue Shopping <%= if @authenticated do %> <.link navigate={Routes.path("/dashboard/orders")} class="btn btn-outline"> <.icon name="hero-clipboard-document-list" class="w-5 h-5 mr-2" /> My Orders <% end %>
""" end # Helpers defp format_price_string(nil), do: "-" defp format_price_string(amount) when is_binary(amount), do: "$#{amount}" defp format_price_string(amount), do: "$#{amount}" end