simpleshop_theme/lib/simpleshop_theme/settings/theme_settings.ex
jamey 336b2bb81d chore: apply mix format to codebase
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 14:24:58 +00:00

124 lines
4.3 KiB
Elixir

defmodule SimpleshopTheme.Settings.ThemeSettings do
use Ecto.Schema
import Ecto.Changeset
@derive Jason.Encoder
@primary_key false
embedded_schema do
# Core theme tokens
field :mood, :string, default: "neutral"
field :typography, :string, default: "clean"
field :shape, :string, default: "soft"
field :density, :string, default: "balanced"
field :grid_columns, :string, default: "4"
field :header_layout, :string, default: "standard"
field :accent_color, :string, default: "#f97316"
# Branding
field :site_name, :string, default: "Store Name"
field :site_description, :string, default: "Discover unique products and original designs."
field :logo_mode, :string, default: "text-only"
field :logo_image_id, :binary_id
field :logo_size, :integer, default: 36
field :logo_recolor, :boolean, default: false
field :logo_color, :string, default: "#171717"
# Header Background
field :header_background_enabled, :boolean, default: false
field :header_image_id, :binary_id
field :header_zoom, :integer, default: 100
field :header_position_x, :integer, default: 50
field :header_position_y, :integer, default: 50
# Advanced customization
field :secondary_accent_color, :string, default: "#ea580c"
field :sale_color, :string, default: "#dc2626"
field :font_size, :string, default: "medium"
field :heading_weight, :string, default: "bold"
field :layout_width, :string, default: "wide"
field :button_style, :string, default: "filled"
field :card_shadow, :string, default: "none"
field :product_text_align, :string, default: "left"
field :image_aspect_ratio, :string, default: "square"
# Feature toggles
field :announcement_bar, :boolean, default: true
field :sticky_header, :boolean, default: false
field :hover_image, :boolean, default: true
field :show_prices, :boolean, default: true
field :pdp_trust_badges, :boolean, default: true
field :pdp_reviews, :boolean, default: true
field :pdp_related_products, :boolean, default: true
end
@doc false
def changeset(settings, attrs) do
settings
|> cast(attrs, [
:mood,
:typography,
:shape,
:density,
:grid_columns,
:header_layout,
:accent_color,
:site_name,
:site_description,
:logo_mode,
:logo_image_id,
:logo_size,
:logo_recolor,
:logo_color,
:header_background_enabled,
:header_image_id,
:header_zoom,
:header_position_x,
:header_position_y,
:secondary_accent_color,
:sale_color,
:font_size,
:heading_weight,
:layout_width,
:button_style,
:card_shadow,
:product_text_align,
:image_aspect_ratio,
:announcement_bar,
:sticky_header,
:hover_image,
:show_prices,
:pdp_trust_badges,
:pdp_reviews,
:pdp_related_products
])
|> validate_required([:mood, :typography, :shape, :density])
|> validate_inclusion(:mood, ~w(neutral warm cool dark))
|> validate_inclusion(
:typography,
~w(clean editorial modern classic friendly minimal impulse)
)
|> validate_inclusion(:shape, ~w(sharp soft round pill))
|> validate_inclusion(:density, ~w(spacious balanced compact))
|> validate_inclusion(:grid_columns, ~w(2 3 4))
|> validate_inclusion(:header_layout, ~w(standard centered left))
|> validate_inclusion(:logo_mode, ~w(text-only logo-text logo-only))
|> validate_number(:logo_size, greater_than_or_equal_to: 24, less_than_or_equal_to: 120)
|> validate_number(:header_zoom, greater_than_or_equal_to: 100, less_than_or_equal_to: 200)
|> validate_number(:header_position_x,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 100
)
|> validate_number(:header_position_y,
greater_than_or_equal_to: 0,
less_than_or_equal_to: 100
)
|> validate_inclusion(:layout_width, ~w(contained wide full))
|> validate_inclusion(:card_shadow, ~w(none sm md lg))
|> validate_inclusion(:font_size, ~w(small medium large))
|> validate_inclusion(:heading_weight, ~w(regular medium bold))
|> validate_inclusion(:button_style, ~w(filled outline soft))
|> validate_inclusion(:product_text_align, ~w(left center))
|> validate_inclusion(:image_aspect_ratio, ~w(square portrait landscape))
end
end