filter Printify options to enabled variants and order by hero colour

Printify's API returns all blueprint option values (e.g. 21 colours)
even when only a few are enabled as variants. This caused the PDP to
show phantom colour swatches with no images or purchasable variants.

Now filter_options_by_variants strips option values to only those with
enabled variants, ordered by first appearance so the hero/default
colour leads the swatch list.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey 2026-02-16 00:29:20 +00:00
parent 4e19d4c4a9
commit 0fe48baaa8

View File

@ -338,6 +338,7 @@ defmodule SimpleshopTheme.Providers.Printify do
options = raw["options"] || [] options = raw["options"] || []
raw_variants = raw["variants"] || [] raw_variants = raw["variants"] || []
color_lookup = build_image_color_lookup(raw_variants, options) color_lookup = build_image_color_lookup(raw_variants, options)
filtered_options = filter_options_by_variants(options, raw_variants)
%{ %{
provider_product_id: to_string(raw["id"]), provider_product_id: to_string(raw["id"]),
@ -350,7 +351,7 @@ defmodule SimpleshopTheme.Providers.Printify do
blueprint_id: raw["blueprint_id"], blueprint_id: raw["blueprint_id"],
print_provider_id: raw["print_provider_id"], print_provider_id: raw["print_provider_id"],
tags: raw["tags"] || [], tags: raw["tags"] || [],
options: options, options: filtered_options,
raw: raw raw: raw
} }
} }
@ -382,6 +383,59 @@ defmodule SimpleshopTheme.Providers.Printify do
end) end)
end end
# Filter blueprint options to only include values present in enabled variants,
# ordered to match variant ordering (so the default variant's colour comes first).
defp filter_options_by_variants(options, raw_variants) do
enabled_order = enabled_option_value_order(options, raw_variants)
Enum.map(options, fn opt ->
name = opt["name"]
case Map.get(enabled_order, name) do
nil ->
opt
ordered_values ->
values_by_title = Map.new(opt["values"] || [], fn v -> {v["title"], v} end)
sorted =
ordered_values
|> Enum.map(&Map.get(values_by_title, &1))
|> Enum.reject(&is_nil/1)
Map.put(opt, "values", sorted)
end
end)
end
# Returns %{"Colors" => ["Dark Heather", "Navy", ...], "Sizes" => ["S", "2XL"]}
# preserving first-seen order from enabled variants.
defp enabled_option_value_order(options, raw_variants) do
option_names = Enum.map(options, & &1["name"])
raw_variants
|> Enum.filter(& &1["is_enabled"])
|> Enum.reduce(%{}, fn var, acc ->
parts = String.split(var["title"] || "", " / ")
option_names
|> Enum.with_index()
|> Enum.reduce(acc, fn {name, idx}, inner_acc ->
case Enum.at(parts, idx) do
nil ->
inner_acc
val ->
existing = Map.get(inner_acc, name, [])
if val in existing,
do: inner_acc,
else: Map.put(inner_acc, name, existing ++ [val])
end
end)
end)
end
defp build_image_color_lookup(raw_variants, options) do defp build_image_color_lookup(raw_variants, options) do
option_names = Enum.map(options, & &1["name"]) option_names = Enum.map(options, & &1["name"])
color_index = Enum.find_index(option_names, &(&1 in ["Colors", "Color"])) color_index = Enum.find_index(option_names, &(&1 in ["Colors", "Color"]))