add per-colour product images and gallery colour filtering
Tag product images with their colour during sync (both Printful and Printify providers). Printify images are cherry-picked: hero colour keeps all angles, other colours keep front + back only. Printful MockupEnricher now generates mockups per colour from the color_variant_map. PDP gallery filters by the selected colour, falling back to all images when the selected colour has none. Fix option name mismatch (Printify "Colors" vs variant "Color") by singularizing in Product.option_types. Generator creates multi-colour apparel products so mock data matches real sync behaviour. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -66,7 +66,8 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
category: "Apparel",
|
||||
artwork_url: unsplash_download_url("EhvMzMRO4_o"),
|
||||
product_type: :tshirt,
|
||||
price: 2999
|
||||
price: 2999,
|
||||
colors: ["Black", "White", "Sport Grey", "Forest Green"]
|
||||
},
|
||||
%{
|
||||
name: "Forest Light Hoodie",
|
||||
@@ -74,7 +75,8 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
category: "Apparel",
|
||||
artwork_url: unsplash_download_url("FwVkxITt8Bg"),
|
||||
product_type: :hoodie,
|
||||
price: 4499
|
||||
price: 4499,
|
||||
colors: ["Dark Heather", "Navy", "Forest Green", "Sand"]
|
||||
},
|
||||
%{
|
||||
name: "Wildflower Meadow Tote Bag",
|
||||
@@ -275,6 +277,10 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
|
||||
@doc """
|
||||
Create a product with the uploaded artwork.
|
||||
|
||||
When the product definition includes a `colors` list, enables one variant
|
||||
per colour (picking a middle size for each). Printify generates mockup
|
||||
images for every enabled colour automatically.
|
||||
"""
|
||||
def create_product(
|
||||
shop_id,
|
||||
@@ -286,17 +292,17 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
print_provider_id,
|
||||
variants
|
||||
) do
|
||||
# Get the first variant for simplicity (typically a standard size/color)
|
||||
variant = hd(variants)
|
||||
variant_id = variant["id"]
|
||||
selected_variants = select_variants(variants, product_def)
|
||||
|
||||
# Get placeholder info
|
||||
IO.puts(" Enabling #{length(selected_variants)} variant(s)")
|
||||
|
||||
# Use the first selected variant for placeholder/scale calculations
|
||||
variant = hd(selected_variants)
|
||||
placeholders = variant["placeholders"] || []
|
||||
|
||||
front_placeholder =
|
||||
Enum.find(placeholders, fn p -> p["position"] == "front" end) || hd(placeholders)
|
||||
|
||||
# Extract placeholder dimensions and calculate cover scale
|
||||
placeholder_width = front_placeholder["width"]
|
||||
placeholder_height = front_placeholder["height"]
|
||||
|
||||
@@ -307,32 +313,25 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
" Scale calculation: artwork #{image_width}x#{image_height}, placeholder #{placeholder_width}x#{placeholder_height} -> scale #{Float.round(scale, 3)}"
|
||||
)
|
||||
|
||||
variant_ids = Enum.map(selected_variants, & &1["id"])
|
||||
|
||||
product_data = %{
|
||||
title: product_def.name,
|
||||
description: "#{product_def.name} - Nature-inspired design from Wildprint Studio",
|
||||
blueprint_id: blueprint_id,
|
||||
print_provider_id: print_provider_id,
|
||||
variants: [
|
||||
%{
|
||||
id: variant_id,
|
||||
price: product_def.price,
|
||||
is_enabled: true
|
||||
}
|
||||
],
|
||||
variants:
|
||||
Enum.map(selected_variants, fn v ->
|
||||
%{id: v["id"], price: product_def.price, is_enabled: true}
|
||||
end),
|
||||
print_areas: [
|
||||
%{
|
||||
variant_ids: [variant_id],
|
||||
variant_ids: variant_ids,
|
||||
placeholders: [
|
||||
%{
|
||||
position: front_placeholder["position"] || "front",
|
||||
images: [
|
||||
%{
|
||||
id: image_id,
|
||||
x: 0.5,
|
||||
y: 0.5,
|
||||
scale: scale,
|
||||
angle: 0
|
||||
}
|
||||
%{id: image_id, x: 0.5, y: 0.5, scale: scale, angle: 0}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -343,6 +342,33 @@ defmodule SimpleshopTheme.Mockups.Generator do
|
||||
Client.create_product(shop_id, product_data)
|
||||
end
|
||||
|
||||
# Pick one variant per requested colour (middle size), or fall back to hd.
|
||||
defp select_variants(variants, %{colors: colors}) when is_list(colors) and colors != [] do
|
||||
# Group variants by the colour portion of their title ("Dark Heather / L" → "Dark Heather")
|
||||
by_color =
|
||||
Enum.group_by(variants, fn v ->
|
||||
v["title"] |> to_string() |> String.split(" / ") |> hd() |> String.trim()
|
||||
end)
|
||||
|
||||
selected =
|
||||
Enum.flat_map(colors, fn color ->
|
||||
case Map.get(by_color, color) do
|
||||
nil ->
|
||||
IO.puts(" Warning: colour #{inspect(color)} not found in blueprint variants")
|
||||
[]
|
||||
|
||||
color_variants ->
|
||||
# Pick the middle variant (typically a medium size)
|
||||
mid = div(length(color_variants), 2)
|
||||
[Enum.at(color_variants, mid)]
|
||||
end
|
||||
end)
|
||||
|
||||
if selected == [], do: [hd(variants)], else: selected
|
||||
end
|
||||
|
||||
defp select_variants(variants, _product_def), do: [hd(variants)]
|
||||
|
||||
@doc """
|
||||
Extract mockup image URLs from a created product.
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user