Packages

phoenix_kit

1.7.63
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib modules shop web helpers.ex
Raw

lib/modules/shop/web/helpers.ex

defmodule PhoenixKit.Modules.Shop.Web.Helpers do
@moduledoc """
Shared helper functions for Shop public LiveViews.
Centralizes utility functions that were duplicated across shop_catalog,
catalog_category, catalog_product, cart_page, checkout_page, and checkout_complete.
"""
alias PhoenixKit.Modules.Billing.Currency
alias PhoenixKit.Modules.Languages
alias PhoenixKit.Modules.Languages.DialectMapper
alias PhoenixKit.Modules.Shop.Translations
alias PhoenixKit.Modules.Storage
alias PhoenixKit.Modules.Storage.URLSigner
alias PhoenixKit.Utils.Routes
# ---------------------------------------------------------------------------
# Price formatting
# ---------------------------------------------------------------------------
@doc "Format a price value with currency. Returns \"-\" for nil price."
def format_price(nil, _currency), do: "-"
def format_price(price, %Currency{} = currency) do
Currency.format_amount(price, currency)
end
def format_price(price, nil) do
"$#{Decimal.round(price, 2)}"
end
# ---------------------------------------------------------------------------
# Current user
# ---------------------------------------------------------------------------
@doc "Extract current user from socket assigns scope."
def get_current_user(socket) do
case socket.assigns[:phoenix_kit_current_scope] do
%{user: %{uuid: _} = user} -> user
_ -> nil
end
end
# ---------------------------------------------------------------------------
# Language helpers
# ---------------------------------------------------------------------------
@doc """
Determine language from URL params.
Uses locale param if present, otherwise falls back to Translations.default_language/0.
Used by catalog and category pages (non-product pages).
"""
def get_language_from_params_or_default(%{"locale" => locale}) when is_binary(locale) do
DialectMapper.resolve_dialect(locale, nil)
end
def get_language_from_params_or_default(_params) do
Translations.default_language()
end
@doc """
Find the best enabled language that has a slug for this entity.
Prefers the default language, then checks other enabled languages.
Returns nil if no valid language found.
"""
def best_redirect_language(slug_map) when slug_map == %{}, do: nil
def best_redirect_language(slug_map) do
enabled = Languages.get_enabled_languages()
default_first = Enum.sort_by(enabled, fn l -> if l.is_default, do: 0, else: 1 end)
Enum.find_value(default_first, fn lang ->
code = lang.code
base = DialectMapper.extract_base(code)
if Map.has_key?(slug_map, code) or Map.has_key?(slug_map, base), do: code
end)
end
@doc """
Build a localized URL path, adding language prefix for non-default languages.
Delegates to Routes.path which handles default vs non-default consistently.
"""
def build_lang_url(path, lang) do
base = DialectMapper.extract_base(lang)
Routes.path(path, locale: base)
end
# ---------------------------------------------------------------------------
# Pagination helpers
# ---------------------------------------------------------------------------
@doc "Parse page param with validation. Returns 1 for invalid/missing values."
def parse_page(nil), do: 1
def parse_page(""), do: 1
def parse_page(page) when is_binary(page) do
case Integer.parse(page) do
{p, ""} when p > 0 -> p
_ -> 1
end
end
def parse_page(page) when is_integer(page) and page > 0, do: page
def parse_page(_), do: 1
# ---------------------------------------------------------------------------
# Image helpers (for catalog list pages - uses featured_image_uuid)
# ---------------------------------------------------------------------------
@doc """
Get the first image URL for a product.
Handles Storage-based images (new format with featured_image_uuid or image_uuids)
and legacy URL-based images (Shopify imports).
Returns nil if no image is available.
"""
def first_image(%{featured_image_uuid: id}) when is_binary(id) do
get_storage_image_url(id, "small")
end
def first_image(%{image_uuids: [id | _]}) when is_binary(id) do
get_storage_image_url(id, "small")
end
# Legacy URL-based images (Shopify imports)
def first_image(%{images: [%{"src" => src} | _]}), do: src
def first_image(%{images: [first | _]}) when is_binary(first), do: first
def first_image(_), do: nil
@doc """
Get signed URL for a Storage image file.
Returns nil if file or variant not found (unlike product detail page
which returns a placeholder). Falls back to original variant if
requested variant is not available.
"""
def get_storage_image_url(file_uuid, variant) do
case Storage.get_file(file_uuid) do
%{uuid: uuid} ->
case Storage.get_file_instance_by_name(uuid, variant) do
nil ->
case Storage.get_file_instance_by_name(uuid, "original") do
nil -> nil
_instance -> URLSigner.signed_url(file_uuid, "original")
end
_instance ->
URLSigner.signed_url(file_uuid, variant)
end
nil ->
nil
end
end
# ---------------------------------------------------------------------------
# UI helpers
# ---------------------------------------------------------------------------
@doc """
Convert a key string to human-readable format.
Example: "material_type" -> "Material Type"
"""
def humanize_key(key) when is_binary(key) do
key
|> String.replace("_", " ")
|> String.split(" ")
|> Enum.map_join(" ", &String.capitalize/1)
end
def humanize_key(key), do: to_string(key)
# ---------------------------------------------------------------------------
# Billing profile helpers
# ---------------------------------------------------------------------------
@doc "Format display name for a billing profile."
def profile_display_name(%{type: "company"} = profile) do
profile.company_name || "#{profile.first_name} #{profile.last_name}"
end
def profile_display_name(profile) do
"#{profile.first_name} #{profile.last_name}"
end
@doc "Format address for a billing profile."
def profile_address(profile) do
[profile.address_line1, profile.city, profile.postal_code, profile.country]
|> Enum.filter(& &1)
|> Enum.join(", ")
end
end