All modules, configs, paths, and references updated. 836 tests pass, zero warnings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
72 lines
2.1 KiB
Elixir
72 lines
2.1 KiB
Elixir
defmodule Berrypod.Products.ProductImage do
|
|
@moduledoc """
|
|
Schema for product images.
|
|
|
|
Images are ordered by position and belong to a single product.
|
|
"""
|
|
|
|
use Ecto.Schema
|
|
import Ecto.Changeset
|
|
|
|
@primary_key {:id, :binary_id, autogenerate: true}
|
|
@foreign_key_type :binary_id
|
|
|
|
schema "product_images" do
|
|
field :src, :string
|
|
field :position, :integer, default: 0
|
|
field :alt, :string
|
|
field :color, :string
|
|
field :image_id, :binary_id
|
|
|
|
belongs_to :product, Berrypod.Products.Product
|
|
belongs_to :image, Berrypod.Media.Image, define_field: false
|
|
|
|
timestamps(type: :utc_datetime)
|
|
end
|
|
|
|
@doc """
|
|
Changeset for creating or updating a product image.
|
|
"""
|
|
def changeset(product_image, attrs) do
|
|
product_image
|
|
|> cast(attrs, [:product_id, :src, :position, :alt, :color, :image_id])
|
|
|> validate_required([:product_id, :src])
|
|
|> foreign_key_constraint(:product_id)
|
|
|> foreign_key_constraint(:image_id)
|
|
end
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Display helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
@doc """
|
|
Returns the URL for a product image variant at the given width.
|
|
Prefers local image_id (static file), falls back to CDN src.
|
|
Handles mockup URL patterns that need size suffixes.
|
|
"""
|
|
def url(image, width \\ 800)
|
|
|
|
def url(%{image_id: id}, width) when not is_nil(id),
|
|
do: "/image_cache/#{id}-#{width}.webp"
|
|
|
|
def url(%{src: "/mockups/" <> _ = src}, width), do: "#{src}-#{width}.webp"
|
|
def url(%{src: src}, _width) when is_binary(src), do: src
|
|
def url(_, _), do: nil
|
|
|
|
@doc """
|
|
Returns the URL for the pre-generated 200px thumbnail.
|
|
Used for small previews (admin lists, cart items).
|
|
"""
|
|
def thumbnail_url(%{image_id: id}) when not is_nil(id),
|
|
do: "/image_cache/#{id}-thumb.jpg"
|
|
|
|
def thumbnail_url(%{src: src}) when is_binary(src), do: src
|
|
def thumbnail_url(_), do: nil
|
|
|
|
@doc """
|
|
Returns the source width from the linked Media.Image, if preloaded.
|
|
"""
|
|
def source_width(%{image: %{source_width: w}}) when not is_nil(w), do: w
|
|
def source_width(_), do: nil
|
|
end
|