defmodule SimpleshopThemeWeb.Admin.Dashboard do use SimpleshopThemeWeb, :live_view alias SimpleshopTheme.{Cart, Orders, Setup} @impl true def mount(_params, _session, socket) do status = Setup.setup_status() status_counts = Orders.count_orders_by_status() paid_count = Map.get(status_counts, "paid", 0) recent_orders = Orders.list_orders(status: "paid") |> Enum.take(5) {:ok, socket |> assign(:page_title, "Dashboard") |> assign(:setup, status) |> assign(:paid_count, paid_count) |> assign(:revenue, Orders.total_revenue()) |> assign(:recent_orders, recent_orders)} end @impl true def render(assigns) do ~H""" <.header> Dashboard <%!-- Setup checklist (when not fully set up) --%> <.setup_checklist :if={!@setup.site_live} setup={@setup} /> <%!-- Stats --%>
<.stat_card label="Orders" value={@paid_count} icon="hero-shopping-bag" href={~p"/admin/orders"} /> <.stat_card label="Revenue" value={format_revenue(@revenue)} icon="hero-banknotes" href={~p"/admin/orders"} /> <.stat_card label="Products" value={@setup.product_count} icon="hero-cube" href={~p"/admin/settings"} />
<%!-- Recent orders --%>

Recent orders

<.link navigate={~p"/admin/orders"} class="text-sm text-zinc-500 hover:text-zinc-700"> View all →
<%= if @recent_orders == [] do %>
<.icon name="hero-inbox" class="size-10 mx-auto mb-3 text-zinc-300" />

No orders yet

Orders will appear here once customers check out.

<% else %>
Order Date Customer Total Fulfilment
{order.order_number} {format_date(order.inserted_at)} {order.customer_email || "—"} {Cart.format_price(order.total)} <.fulfilment_pill status={order.fulfilment_status} />
<% end %>
""" end # -- Function components -- attr :setup, :map, required: true defp setup_checklist(assigns) do steps = [ %{done: assigns.setup.admin_created, label: "Create admin account", href: nil}, %{ done: assigns.setup.printify_connected, label: "Connect to Printify", href: ~p"/admin/providers/new" }, %{done: assigns.setup.products_synced, label: "Sync products", href: nil}, %{done: assigns.setup.stripe_connected, label: "Connect Stripe", href: ~p"/admin/settings"}, %{done: assigns.setup.site_live, label: "Go live", href: ~p"/admin/settings"} ] done_count = Enum.count(steps, & &1.done) assigns = assign(assigns, steps: steps, done_count: done_count, total: length(steps)) ~H"""

Setup progress

{@done_count}/{@total}
""" end attr :label, :string, required: true attr :value, :any, required: true attr :icon, :string, required: true attr :href, :string, required: true defp stat_card(assigns) do ~H""" <.link navigate={@href} class="rounded-lg border border-zinc-200 p-4 hover:border-zinc-300 transition-colors" >
<.icon name={@icon} class="size-5 text-zinc-600" />

{@value}

{@label}

""" end defp fulfilment_pill(assigns) do {color, label} = case assigns.status do "unfulfilled" -> {"bg-zinc-100 text-zinc-600", "unfulfilled"} "submitted" -> {"bg-blue-50 text-blue-700", "submitted"} "processing" -> {"bg-amber-50 text-amber-700", "processing"} "shipped" -> {"bg-purple-50 text-purple-700", "shipped"} "delivered" -> {"bg-green-50 text-green-700", "delivered"} "failed" -> {"bg-red-50 text-red-700", "failed"} _ -> {"bg-zinc-100 text-zinc-600", assigns.status || "—"} end assigns = assign(assigns, color: color, label: label) ~H""" {@label} """ end defp format_revenue(amount_pence) when is_integer(amount_pence) do Cart.format_price(amount_pence) end defp format_revenue(_), do: "£0.00" defp format_date(datetime) do Calendar.strftime(datetime, "%d %b %Y") end end