defmodule PhoenixKit.Modules.Shop.Web.Components.ShopCards do @moduledoc """ Reusable product display components for the shop storefront. Provides product card and pagination components shared between the main catalog page and category pages. """ use Phoenix.Component import PhoenixKitWeb.Components.Core.Icon, only: [icon: 1] alias PhoenixKit.Modules.Shop alias PhoenixKit.Modules.Shop.Translations alias PhoenixKit.Modules.Shop.Web.Components.FilterHelpers alias PhoenixKit.Modules.Shop.Web.Helpers @doc """ Renders a product card with image, title, price, and optional category badge. """ attr :product, :map, required: true attr :currency, :any, required: true attr :language, :string, default: "en" attr :filter_qs, :string, default: "" attr :show_category, :boolean, default: false def product_card(assigns) do assigns = assigns |> assign(:product_title, Translations.get(assigns.product, :title, assigns.language)) |> assign(:product_url, Shop.product_url(assigns.product, assigns.language)) |> assign(:product_image_url, Helpers.first_image(assigns.product)) |> assign( :category_name, if(assigns.show_category && assigns.product.category, do: Translations.get(assigns.product.category, :name, assigns.language), else: nil ) ) ~H""" <.link navigate={@product_url <> @filter_qs} class="card bg-base-100 shadow-md hover:shadow-xl transition-all hover:-translate-y-1" >
<%= if @product_image_url do %> {@product_title} <% else %>
<.icon name="hero-cube" class="w-16 h-16 opacity-30" />
<% end %>

{@product_title}

{Helpers.format_price(@product.price, @currency)} <%= if @product.compare_at_price && Decimal.compare(@product.compare_at_price, @product.price) == :gt do %> {Helpers.format_price(@product.compare_at_price, @currency)} <% end %>
<%= if @category_name do %>
{@category_name}
<% end %>
""" end @doc """ Renders a "load more" button + page links for product grids. """ attr :page, :integer, required: true attr :total_pages, :integer, required: true attr :total_products, :integer, required: true attr :per_page, :integer, required: true attr :base_path, :string, required: true attr :active_filters, :map, default: %{} attr :enabled_filters, :list, default: [] def shop_pagination(assigns) do remaining = assigns.total_products - assigns.page * assigns.per_page assigns = assigns |> assign(:remaining, max(0, remaining)) |> assign(:has_more, assigns.page < assigns.total_pages) ~H""" <%= if @total_pages > 1 do %>
<%!-- Load More Button --%> <%= if @has_more do %>
<% end %> <%!-- Page Links for SEO and direct access --%> <%!-- Status text --%>

Showing {min(@page * @per_page, @total_products)} of {@total_products} products

<% end %> """ end end