rename project from SimpleshopTheme to Berrypod

All modules, configs, paths, and references updated.
836 tests pass, zero warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-18 21:23:15 +00:00
parent c65e777832
commit 9528700862
300 changed files with 23932 additions and 1349 deletions

View File

@@ -1,6 +1,6 @@
defmodule SimpleshopTheme do
defmodule Berrypod do
@moduledoc """
SimpleshopTheme keeps the contexts that define your domain
Berrypod keeps the contexts that define your domain
and business logic.
Contexts are also responsible for managing your data, regardless

View File

@@ -1,12 +1,12 @@
defmodule SimpleshopTheme.Accounts do
defmodule Berrypod.Accounts do
@moduledoc """
The Accounts context.
"""
import Ecto.Query, warn: false
alias SimpleshopTheme.Repo
alias Berrypod.Repo
alias SimpleshopTheme.Accounts.{User, UserToken, UserNotifier}
alias Berrypod.Accounts.{User, UserToken, UserNotifier}
## Database getters
@@ -63,7 +63,7 @@ defmodule SimpleshopTheme.Accounts do
@doc """
Returns whether an admin user exists.
SimpleShop is single-tenant any user in the database is the admin.
Berrypod is single-tenant any user in the database is the admin.
"""
def has_admin? do
Repo.exists?(User)
@@ -108,7 +108,7 @@ defmodule SimpleshopTheme.Accounts do
@doc """
Returns an `%Ecto.Changeset{}` for changing the user email.
See `SimpleshopTheme.Accounts.User.email_changeset/3` for a list of supported options.
See `Berrypod.Accounts.User.email_changeset/3` for a list of supported options.
## Examples
@@ -144,7 +144,7 @@ defmodule SimpleshopTheme.Accounts do
@doc """
Returns an `%Ecto.Changeset{}` for changing the user password.
See `SimpleshopTheme.Accounts.User.password_changeset/3` for a list of supported options.
See `Berrypod.Accounts.User.password_changeset/3` for a list of supported options.
## Examples

View File

@@ -1,8 +1,8 @@
defmodule SimpleshopTheme.Accounts.Scope do
defmodule Berrypod.Accounts.Scope do
@moduledoc """
Defines the scope of the caller to be used throughout the app.
The `SimpleshopTheme.Accounts.Scope` allows public interfaces to receive
The `Berrypod.Accounts.Scope` allows public interfaces to receive
information about the caller, such as if the call is initiated from an
end-user, and if so, which user. Additionally, such a scope can carry fields
such as "super user" or other privileges for use as authorization, or to
@@ -16,7 +16,7 @@ defmodule SimpleshopTheme.Accounts.Scope do
growing application requirements.
"""
alias SimpleshopTheme.Accounts.User
alias Berrypod.Accounts.User
defstruct user: nil

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Accounts.User do
defmodule Berrypod.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
@@ -42,7 +42,7 @@ defmodule SimpleshopTheme.Accounts.User do
if Keyword.get(opts, :validate_unique, true) do
changeset
|> unsafe_validate_unique(:email, SimpleshopTheme.Repo)
|> unsafe_validate_unique(:email, Berrypod.Repo)
|> unique_constraint(:email)
|> validate_email_changed()
else
@@ -122,7 +122,7 @@ defmodule SimpleshopTheme.Accounts.User do
If there is no user or the user doesn't have a password, we call
`Bcrypt.no_user_verify/0` to avoid timing attacks.
"""
def valid_password?(%SimpleshopTheme.Accounts.User{hashed_password: hashed_password}, password)
def valid_password?(%Berrypod.Accounts.User{hashed_password: hashed_password}, password)
when is_binary(hashed_password) and byte_size(password) > 0 do
Bcrypt.verify_pass(password, hashed_password)
end

View File

@@ -1,15 +1,15 @@
defmodule SimpleshopTheme.Accounts.UserNotifier do
defmodule Berrypod.Accounts.UserNotifier do
import Swoosh.Email
alias SimpleshopTheme.Mailer
alias SimpleshopTheme.Accounts.User
alias Berrypod.Mailer
alias Berrypod.Accounts.User
# Delivers the email using the application mailer.
defp deliver(recipient, subject, body) do
email =
new()
|> to(recipient)
|> from({"SimpleshopTheme", "contact@example.com"})
|> from({"Berrypod", "contact@example.com"})
|> subject(subject)
|> text_body(body)

View File

@@ -1,7 +1,7 @@
defmodule SimpleshopTheme.Accounts.UserToken do
defmodule Berrypod.Accounts.UserToken do
use Ecto.Schema
import Ecto.Query
alias SimpleshopTheme.Accounts.UserToken
alias Berrypod.Accounts.UserToken
@hash_algorithm :sha256
@rand_size 32
@@ -19,7 +19,7 @@ defmodule SimpleshopTheme.Accounts.UserToken do
field :context, :string
field :sent_to, :string
field :authenticated_at, :utc_datetime
belongs_to :user, SimpleshopTheme.Accounts.User
belongs_to :user, Berrypod.Accounts.User
timestamps(type: :utc_datetime, updated_at: false)
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Application do
defmodule Berrypod.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
@moduledoc false
@@ -8,29 +8,29 @@ defmodule SimpleshopTheme.Application do
@impl true
def start(_type, _args) do
children = [
SimpleshopThemeWeb.Telemetry,
SimpleshopTheme.Repo,
BerrypodWeb.Telemetry,
Berrypod.Repo,
{Ecto.Migrator,
repos: Application.fetch_env!(:simpleshop_theme, :ecto_repos), skip: skip_migrations?()},
repos: Application.fetch_env!(:berrypod, :ecto_repos), skip: skip_migrations?()},
# Seed default theme settings if none exist (first boot)
Supervisor.child_spec({Task, &SimpleshopTheme.Release.seed_defaults/0}, id: :seed_defaults),
Supervisor.child_spec({Task, &Berrypod.Release.seed_defaults/0}, id: :seed_defaults),
# Load encrypted secrets from DB into Application env
{Task, &SimpleshopTheme.Secrets.load_all/0},
{DNSCluster, query: Application.get_env(:simpleshop_theme, :dns_cluster_query) || :ignore},
{Phoenix.PubSub, name: SimpleshopTheme.PubSub},
{Task, &Berrypod.Secrets.load_all/0},
{DNSCluster, query: Application.get_env(:berrypod, :dns_cluster_query) || :ignore},
{Phoenix.PubSub, name: Berrypod.PubSub},
# Background job processing
{Oban, Application.fetch_env!(:simpleshop_theme, Oban)},
{Oban, Application.fetch_env!(:berrypod, Oban)},
# Image variant cache - ensures all variants exist on startup
SimpleshopTheme.Images.VariantCache,
Berrypod.Images.VariantCache,
# Start to serve requests
SimpleshopThemeWeb.Endpoint,
BerrypodWeb.Endpoint,
# Theme CSS cache - must start after Endpoint for static_path/1 to work
SimpleshopTheme.Theme.CSSCache
Berrypod.Theme.CSSCache
]
# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: SimpleshopTheme.Supervisor]
opts = [strategy: :one_for_one, name: Berrypod.Supervisor]
Supervisor.start_link(children, opts)
end
@@ -38,7 +38,7 @@ defmodule SimpleshopTheme.Application do
# whenever the application is updated.
@impl true
def config_change(changed, _new, removed) do
SimpleshopThemeWeb.Endpoint.config_change(changed, removed)
BerrypodWeb.Endpoint.config_change(changed, removed)
:ok
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Cart do
defmodule Berrypod.Cart do
@moduledoc """
The Cart context.
@@ -7,8 +7,8 @@ defmodule SimpleshopTheme.Cart do
Items are hydrated with full product/variant data when needed for display.
"""
alias SimpleshopTheme.Products
alias SimpleshopTheme.Products.ProductImage
alias Berrypod.Products
alias Berrypod.Products.ProductImage
@session_key "cart"

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Cldr do
defmodule Berrypod.Cldr do
@moduledoc """
CLDR backend for internationalization and currency formatting.

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Clients.Printful do
defmodule Berrypod.Clients.Printful do
@moduledoc """
HTTP client for the Printful API.

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Clients.Printify do
defmodule Berrypod.Clients.Printify do
@moduledoc """
HTTP client for the Printify API.

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.ExchangeRate do
defmodule Berrypod.ExchangeRate do
@moduledoc """
Fetches and caches exchange rates for shipping cost conversion.
@@ -7,7 +7,7 @@ defmodule SimpleshopTheme.ExchangeRate do
they survive restarts without an API call.
"""
alias SimpleshopTheme.Settings
alias Berrypod.Settings
require Logger

View File

@@ -1,11 +1,11 @@
defmodule SimpleshopTheme.Images.OptimizeWorker do
defmodule Berrypod.Images.OptimizeWorker do
@moduledoc """
Oban worker for processing image variants in the background.
Handles both database images and filesystem mockups.
"""
use Oban.Worker, queue: :images, max_attempts: 3
alias SimpleshopTheme.Images.Optimizer
alias Berrypod.Images.Optimizer
@impl Oban.Worker
def perform(%Oban.Job{args: %{"type" => "mockup", "source_path" => source_path}}) do

View File

@@ -1,12 +1,12 @@
defmodule SimpleshopTheme.Images.Optimizer do
defmodule Berrypod.Images.Optimizer do
@moduledoc """
Generates optimized image variants. Only creates sizes source dimensions.
"""
require Logger
alias SimpleshopTheme.Repo
alias SimpleshopTheme.Media.Image, as: ImageSchema
alias Berrypod.Repo
alias Berrypod.Media.Image, as: ImageSchema
@all_widths [400, 800, 1200]
@pregenerated_formats [:avif, :webp, :jpg]
@@ -15,8 +15,8 @@ defmodule SimpleshopTheme.Images.Optimizer do
@storage_quality 90
def cache_dir do
Application.get_env(:simpleshop_theme, :image_cache_dir) ||
Application.app_dir(:simpleshop_theme, "priv/static/image_cache")
Application.get_env(:berrypod, :image_cache_dir) ||
Application.app_dir(:berrypod, "priv/static/image_cache")
end
def all_widths, do: @all_widths

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Images.VariantCache do
defmodule Berrypod.Images.VariantCache do
@moduledoc """
Ensures all image variants exist on startup.
@@ -12,14 +12,14 @@ defmodule SimpleshopTheme.Images.VariantCache do
use GenServer
require Logger
alias SimpleshopTheme.Repo
alias SimpleshopTheme.Media.Image, as: ImageSchema
alias SimpleshopTheme.Images.{Optimizer, OptimizeWorker}
alias SimpleshopTheme.Products
alias SimpleshopTheme.Sync.ImageDownloadWorker
alias Berrypod.Repo
alias Berrypod.Media.Image, as: ImageSchema
alias Berrypod.Images.{Optimizer, OptimizeWorker}
alias Berrypod.Products
alias Berrypod.Sync.ImageDownloadWorker
import Ecto.Query
defp mockup_dir, do: Application.app_dir(:simpleshop_theme, "priv/static/mockups")
defp mockup_dir, do: Application.app_dir(:berrypod, "priv/static/mockups")
def start_link(opts) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)

3
lib/berrypod/mailer.ex Normal file
View File

@@ -0,0 +1,3 @@
defmodule Berrypod.Mailer do
use Swoosh.Mailer, otp_app: :berrypod
end

View File

@@ -1,13 +1,13 @@
defmodule SimpleshopTheme.Media do
defmodule Berrypod.Media do
@moduledoc """
The Media context for managing images and file uploads.
"""
import Ecto.Query, warn: false
alias SimpleshopTheme.Repo
alias SimpleshopTheme.Media.Image, as: ImageSchema
alias SimpleshopTheme.Images.Optimizer
alias SimpleshopTheme.Images.OptimizeWorker
alias Berrypod.Repo
alias Berrypod.Media.Image, as: ImageSchema
alias Berrypod.Images.Optimizer
alias Berrypod.Images.OptimizeWorker
@doc """
Uploads an image and stores it in the database.

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Media.Image do
defmodule Berrypod.Media.Image do
use Ecto.Schema
import Ecto.Changeset

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Media.SVGRecolorer do
defmodule Berrypod.Media.SVGRecolorer do
@moduledoc """
Recolors SVG images by replacing fill and stroke colors with a target color.

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Mockups.Generator do
defmodule Berrypod.Mockups.Generator do
@moduledoc """
Generates product mockups using the Printify API.
@@ -11,7 +11,7 @@ defmodule SimpleshopTheme.Mockups.Generator do
6. Optionally cleaning up created products
"""
alias SimpleshopTheme.Clients.Printify, as: Client
alias Berrypod.Clients.Printify, as: Client
@output_dir "priv/static/mockups"
@@ -382,7 +382,7 @@ defmodule SimpleshopTheme.Mockups.Generator do
Sources are saved for regeneration on startup via VariantCache.
"""
def download_mockups(product_slug, mockup_urls) do
alias SimpleshopTheme.Images.Optimizer
alias Berrypod.Images.Optimizer
File.mkdir_p!(@output_dir)

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Mockups.PrintfulGenerator do
defmodule Berrypod.Mockups.PrintfulGenerator do
@moduledoc """
Generates product mockups and/or creates demo products using the Printful API.
@@ -11,9 +11,9 @@ defmodule SimpleshopTheme.Mockups.PrintfulGenerator do
v1 store products API. These can later be synced into the shop.
"""
alias SimpleshopTheme.Clients.Printful, as: Client
alias SimpleshopTheme.Images.Optimizer
alias SimpleshopTheme.Mockups.Generator
alias Berrypod.Clients.Printful, as: Client
alias Berrypod.Images.Optimizer
alias Berrypod.Mockups.Generator
@output_dir "priv/static/mockups"
@poll_interval_ms 2_000

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Orders do
defmodule Berrypod.Orders do
@moduledoc """
The Orders context.
@@ -8,10 +8,10 @@ defmodule SimpleshopTheme.Orders do
"""
import Ecto.Query
alias SimpleshopTheme.Repo
alias SimpleshopTheme.Orders.{Order, OrderItem, OrderNotifier}
alias SimpleshopTheme.Products
alias SimpleshopTheme.Providers.Provider
alias Berrypod.Repo
alias Berrypod.Orders.{Order, OrderItem, OrderNotifier}
alias Berrypod.Products
alias Berrypod.Providers.Provider
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Orders.FulfilmentStatusWorker do
defmodule Berrypod.Orders.FulfilmentStatusWorker do
@moduledoc """
Oban Cron worker that polls the fulfilment provider for status updates.
@@ -9,7 +9,7 @@ defmodule SimpleshopTheme.Orders.FulfilmentStatusWorker do
use Oban.Worker, queue: :sync, max_attempts: 1
alias SimpleshopTheme.Orders
alias Berrypod.Orders
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Orders.Order do
defmodule Berrypod.Orders.Order do
use Ecto.Schema
import Ecto.Changeset
@@ -34,7 +34,7 @@ defmodule SimpleshopTheme.Orders.Order do
field :shipped_at, :utc_datetime
field :delivered_at, :utc_datetime
has_many :items, SimpleshopTheme.Orders.OrderItem
has_many :items, Berrypod.Orders.OrderItem
timestamps(type: :utc_datetime)
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Orders.OrderItem do
defmodule Berrypod.Orders.OrderItem do
use Ecto.Schema
import Ecto.Changeset
@@ -12,7 +12,7 @@ defmodule SimpleshopTheme.Orders.OrderItem do
field :quantity, :integer
field :unit_price, :integer
belongs_to :order, SimpleshopTheme.Orders.Order
belongs_to :order, Berrypod.Orders.Order
timestamps(type: :utc_datetime)
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Orders.OrderNotifier do
defmodule Berrypod.Orders.OrderNotifier do
@moduledoc """
Sends transactional emails for orders.
@@ -7,8 +7,8 @@ defmodule SimpleshopTheme.Orders.OrderNotifier do
import Swoosh.Email
alias SimpleshopTheme.Cart
alias SimpleshopTheme.Mailer
alias Berrypod.Cart
alias Berrypod.Mailer
require Logger
@@ -73,7 +73,7 @@ defmodule SimpleshopTheme.Orders.OrderNotifier do
email =
new()
|> to(recipient)
|> from({"SimpleshopTheme", "contact@example.com"})
|> from({"Berrypod", "contact@example.com"})
|> subject(subject)
|> text_body(body)

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Orders.OrderSubmissionWorker do
defmodule Berrypod.Orders.OrderSubmissionWorker do
@moduledoc """
Oban worker for submitting paid orders to the fulfilment provider.
@@ -9,7 +9,7 @@ defmodule SimpleshopTheme.Orders.OrderSubmissionWorker do
use Oban.Worker, queue: :checkout, max_attempts: 3
alias SimpleshopTheme.Orders
alias Berrypod.Orders
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Products do
defmodule Berrypod.Products do
@moduledoc """
The Products context.
@@ -7,8 +7,8 @@ defmodule SimpleshopTheme.Products do
"""
import Ecto.Query
alias SimpleshopTheme.Repo
alias SimpleshopTheme.Products.{ProviderConnection, Product, ProductImage, ProductVariant}
alias Berrypod.Repo
alias Berrypod.Products.{ProviderConnection, Product, ProductImage, ProductVariant}
# =============================================================================
# Provider Connections
@@ -105,7 +105,7 @@ defmodule SimpleshopTheme.Products do
Returns `{:ok, job}` or `{:error, changeset}`.
"""
def enqueue_sync(%ProviderConnection{} = conn) do
SimpleshopTheme.Sync.ProductSyncWorker.enqueue(conn.id)
Berrypod.Sync.ProductSyncWorker.enqueue(conn.id)
end
# =============================================================================
@@ -669,7 +669,7 @@ defmodule SimpleshopTheme.Products do
defp cleanup_orphaned_images([]), do: :ok
defp cleanup_orphaned_images(image_ids) do
alias SimpleshopTheme.Media.Image, as: ImageSchema
alias Berrypod.Media.Image, as: ImageSchema
from(i in ImageSchema, where: i.id in ^image_ids)
|> Repo.delete_all()

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Products.Product do
defmodule Berrypod.Products.Product do
@moduledoc """
Schema for products synced from POD providers.
@@ -31,9 +31,9 @@ defmodule SimpleshopTheme.Products.Product do
field :in_stock, :boolean, default: true
field :on_sale, :boolean, default: false
belongs_to :provider_connection, SimpleshopTheme.Products.ProviderConnection
has_many :images, SimpleshopTheme.Products.ProductImage
has_many :variants, SimpleshopTheme.Products.ProductVariant
belongs_to :provider_connection, Berrypod.Products.ProviderConnection
has_many :images, Berrypod.Products.ProductImage
has_many :variants, Berrypod.Products.ProductVariant
timestamps(type: :utc_datetime)
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Products.ProductImage do
defmodule Berrypod.Products.ProductImage do
@moduledoc """
Schema for product images.
@@ -18,8 +18,8 @@ defmodule SimpleshopTheme.Products.ProductImage do
field :color, :string
field :image_id, :binary_id
belongs_to :product, SimpleshopTheme.Products.Product
belongs_to :image, SimpleshopTheme.Media.Image, define_field: false
belongs_to :product, Berrypod.Products.Product
belongs_to :image, Berrypod.Media.Image, define_field: false
timestamps(type: :utc_datetime)
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Products.ProductVariant do
defmodule Berrypod.Products.ProductVariant do
@moduledoc """
Schema for product variants.
@@ -34,7 +34,7 @@ defmodule SimpleshopTheme.Products.ProductVariant do
field :is_enabled, :boolean, default: true
field :is_available, :boolean, default: true
belongs_to :product, SimpleshopTheme.Products.Product
belongs_to :product, Berrypod.Products.Product
timestamps(type: :utc_datetime)
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Products.ProviderConnection do
defmodule Berrypod.Products.ProviderConnection do
@moduledoc """
Schema for POD provider connections.
@@ -9,7 +9,7 @@ defmodule SimpleshopTheme.Products.ProviderConnection do
use Ecto.Schema
import Ecto.Changeset
alias SimpleshopTheme.Vault
alias Berrypod.Vault
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
@@ -29,7 +29,7 @@ defmodule SimpleshopTheme.Products.ProviderConnection do
# Virtual field for setting API key
field :api_key, :string, virtual: true
has_many :products, SimpleshopTheme.Products.Product
has_many :products, Berrypod.Products.Product
timestamps(type: :utc_datetime)
end

View File

@@ -1,10 +1,10 @@
defmodule SimpleshopTheme.Providers do
defmodule Berrypod.Providers do
@moduledoc """
Convenience functions for working with POD providers.
"""
alias SimpleshopTheme.Products.ProviderConnection
alias SimpleshopTheme.Providers.Provider
alias Berrypod.Products.ProviderConnection
alias Berrypod.Providers.Provider
@doc """
Tests a provider connection.

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Providers.Printful do
defmodule Berrypod.Providers.Printful do
@moduledoc """
Printful provider implementation.
@@ -6,10 +6,10 @@ defmodule SimpleshopTheme.Providers.Printful do
Uses v2 API endpoints where available, v1 for sync products.
"""
@behaviour SimpleshopTheme.Providers.Provider
@behaviour Berrypod.Providers.Provider
alias SimpleshopTheme.Clients.Printful, as: Client
alias SimpleshopTheme.Products.ProviderConnection
alias Berrypod.Clients.Printful, as: Client
alias Berrypod.Products.ProviderConnection
require Logger

View File

@@ -1,14 +1,14 @@
defmodule SimpleshopTheme.Providers.Printify do
defmodule Berrypod.Providers.Printify do
@moduledoc """
Printify provider implementation.
Handles product sync and order submission for Printify.
"""
@behaviour SimpleshopTheme.Providers.Provider
@behaviour Berrypod.Providers.Provider
alias SimpleshopTheme.Clients.Printify, as: Client
alias SimpleshopTheme.Products.ProviderConnection
alias Berrypod.Clients.Printify, as: Client
alias Berrypod.Products.ProviderConnection
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Providers.Provider do
defmodule Berrypod.Providers.Provider do
@moduledoc """
Behaviour for POD provider integrations.
@@ -21,7 +21,7 @@ defmodule SimpleshopTheme.Providers.Provider do
- Images are maps with keys: `src`, `position`, `alt`
"""
alias SimpleshopTheme.Products.ProviderConnection
alias Berrypod.Products.ProviderConnection
@doc """
Returns the provider type identifier (e.g., "printify", "gelato").
@@ -79,7 +79,7 @@ defmodule SimpleshopTheme.Providers.Provider do
overrides via Mox. Falls back to hardcoded dispatch.
"""
def for_type(type) do
case Application.get_env(:simpleshop_theme, :provider_modules, %{}) do
case Application.get_env(:berrypod, :provider_modules, %{}) do
modules when is_map(modules) ->
case Map.get(modules, type) do
nil -> default_for_type(type)
@@ -91,10 +91,10 @@ defmodule SimpleshopTheme.Providers.Provider do
end
end
defp default_for_type("printify"), do: {:ok, SimpleshopTheme.Providers.Printify}
defp default_for_type("printify"), do: {:ok, Berrypod.Providers.Printify}
defp default_for_type("gelato"), do: {:error, :not_implemented}
defp default_for_type("prodigi"), do: {:error, :not_implemented}
defp default_for_type("printful"), do: {:ok, SimpleshopTheme.Providers.Printful}
defp default_for_type("printful"), do: {:ok, Berrypod.Providers.Printful}
defp default_for_type(type), do: {:error, {:unknown_provider, type}}
@doc """

View File

@@ -1,12 +1,12 @@
defmodule SimpleshopTheme.Release do
defmodule Berrypod.Release do
@moduledoc """
Release tasks that can be run via `bin/migrate` or `bin/simpleshop_theme eval`.
Release tasks that can be run via `bin/migrate` or `bin/berrypod eval`.
Migrations run automatically on startup (see Application), so this is mainly
useful as a standalone tool for debugging or manual recovery.
"""
@app :simpleshop_theme
@app :berrypod
def migrate do
load_app()
@@ -23,7 +23,7 @@ defmodule SimpleshopTheme.Release do
(when the settings table is empty). Safe to call repeatedly.
"""
def seed_defaults do
alias SimpleshopTheme.Settings
alias Berrypod.Settings
case Settings.get_setting("theme_settings") do
nil ->

5
lib/berrypod/repo.ex Normal file
View File

@@ -0,0 +1,5 @@
defmodule Berrypod.Repo do
use Ecto.Repo,
otp_app: :berrypod,
adapter: Ecto.Adapters.SQLite3
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Search do
defmodule Berrypod.Search do
@moduledoc """
Full-text product search backed by SQLite FTS5.
@@ -8,8 +8,8 @@ defmodule SimpleshopTheme.Search do
import Ecto.Query
alias SimpleshopTheme.Products.Product
alias SimpleshopTheme.Repo
alias Berrypod.Products.Product
alias Berrypod.Repo
@listing_preloads [images: :image]

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Secrets do
defmodule Berrypod.Secrets do
@moduledoc """
Loads encrypted secrets from the database into Application env at runtime.
@@ -9,7 +9,7 @@ defmodule SimpleshopTheme.Secrets do
The only external dependency is `SECRET_KEY_BASE` (used to derive encryption keys).
"""
alias SimpleshopTheme.Settings
alias Berrypod.Settings
require Logger

View File

@@ -1,12 +1,12 @@
defmodule SimpleshopTheme.Settings do
defmodule Berrypod.Settings do
@moduledoc """
The Settings context for managing site-wide configuration.
"""
import Ecto.Query, warn: false
alias SimpleshopTheme.Repo
alias SimpleshopTheme.Settings.{Setting, ThemeSettings}
alias SimpleshopTheme.Vault
alias Berrypod.Repo
alias Berrypod.Settings.{Setting, ThemeSettings}
alias Berrypod.Vault
@doc """
Gets a setting by key with an optional default value.
@@ -86,7 +86,7 @@ defmodule SimpleshopTheme.Settings do
put_setting("theme_settings", json, "json")
# Invalidate and rewarm CSS cache
alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator}
alias Berrypod.Theme.{CSSCache, CSSGenerator}
CSSCache.invalidate()
css = CSSGenerator.generate(settings)
CSSCache.put(css)
@@ -107,7 +107,7 @@ defmodule SimpleshopTheme.Settings do
"""
def apply_preset(preset_name) when is_atom(preset_name) do
preset = SimpleshopTheme.Theme.Presets.get(preset_name)
preset = Berrypod.Theme.Presets.get(preset_name)
if preset do
update_theme_settings(preset)

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Settings.Setting do
defmodule Berrypod.Settings.Setting do
use Ecto.Schema
import Ecto.Changeset

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Settings.ThemeSettings do
defmodule Berrypod.Settings.ThemeSettings do
use Ecto.Schema
import Ecto.Changeset

View File

@@ -1,9 +1,9 @@
defmodule SimpleshopTheme.Setup do
defmodule Berrypod.Setup do
@moduledoc """
Aggregates setup status checks for the admin setup flow.
"""
alias SimpleshopTheme.{Accounts, Products, Settings}
alias Berrypod.{Accounts, Products, Settings}
@doc """
Returns a map describing the current setup status.

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Shipping do
defmodule Berrypod.Shipping do
@moduledoc """
The Shipping context.
@@ -7,11 +7,11 @@ defmodule SimpleshopTheme.Shipping do
"""
import Ecto.Query
alias SimpleshopTheme.ExchangeRate
alias SimpleshopTheme.Repo
alias SimpleshopTheme.Shipping.ShippingRate
alias SimpleshopTheme.Products
alias SimpleshopTheme.Settings
alias Berrypod.ExchangeRate
alias Berrypod.Repo
alias Berrypod.Shipping.ShippingRate
alias Berrypod.Products
alias Berrypod.Settings
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Shipping.ShippingRate do
defmodule Berrypod.Shipping.ShippingRate do
use Ecto.Schema
import Ecto.Changeset
@@ -14,7 +14,7 @@ defmodule SimpleshopTheme.Shipping.ShippingRate do
field :currency, :string, default: "USD"
field :handling_time_days, :integer
belongs_to :provider_connection, SimpleshopTheme.Products.ProviderConnection
belongs_to :provider_connection, Berrypod.Products.ProviderConnection
timestamps(type: :utc_datetime)
end

View File

@@ -1,11 +1,11 @@
defmodule SimpleshopTheme.Stripe.Setup do
defmodule Berrypod.Stripe.Setup do
@moduledoc """
Handles Stripe account setup: key verification, automatic webhook
endpoint creation, and teardown.
"""
alias SimpleshopTheme.Settings
alias SimpleshopTheme.Secrets
alias Berrypod.Settings
alias Berrypod.Secrets
require Logger
@@ -75,14 +75,14 @@ defmodule SimpleshopTheme.Stripe.Setup do
Returns the webhook URL for this app.
"""
def webhook_url do
"#{SimpleshopThemeWeb.Endpoint.url()}/webhooks/stripe"
"#{BerrypodWeb.Endpoint.url()}/webhooks/stripe"
end
@doc """
Returns true if the app is running on localhost (Stripe can't reach it).
"""
def localhost? do
url = SimpleshopThemeWeb.Endpoint.url()
url = BerrypodWeb.Endpoint.url()
uri = URI.parse(url)
uri.host in ["localhost", "127.0.0.1", "0.0.0.0", "::1"]
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Sync.ImageDownloadWorker do
defmodule Berrypod.Sync.ImageDownloadWorker do
@moduledoc """
Oban worker for downloading product images from external URLs.
@@ -17,8 +17,8 @@ defmodule SimpleshopTheme.Sync.ImageDownloadWorker do
use Oban.Worker, queue: :images, max_attempts: 3
alias SimpleshopTheme.Products
alias SimpleshopTheme.Media
alias Berrypod.Products
alias Berrypod.Media
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Sync.MockupEnricher do
defmodule Berrypod.Sync.MockupEnricher do
@moduledoc """
Oban worker that enriches Printful products with extra mockup angle images.
@@ -16,10 +16,10 @@ defmodule SimpleshopTheme.Sync.MockupEnricher do
use Oban.Worker, queue: :images, max_attempts: 5
alias SimpleshopTheme.Clients.Printful, as: Client
alias SimpleshopTheme.Products
alias SimpleshopTheme.Products.ProviderConnection
alias SimpleshopTheme.Sync.ImageDownloadWorker
alias Berrypod.Clients.Printful, as: Client
alias Berrypod.Products
alias Berrypod.Products.ProviderConnection
alias Berrypod.Sync.ImageDownloadWorker
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Sync.ProductSyncWorker do
defmodule Berrypod.Sync.ProductSyncWorker do
@moduledoc """
Oban worker for syncing products from POD providers.
@@ -17,11 +17,11 @@ defmodule SimpleshopTheme.Sync.ProductSyncWorker do
use Oban.Worker, queue: :sync, max_attempts: 3
alias SimpleshopTheme.Products
alias SimpleshopTheme.Products.ProviderConnection
alias SimpleshopTheme.Providers.Provider
alias SimpleshopTheme.Sync.ImageDownloadWorker
alias SimpleshopTheme.Sync.MockupEnricher
alias Berrypod.Products
alias Berrypod.Products.ProviderConnection
alias Berrypod.Providers.Provider
alias Berrypod.Sync.ImageDownloadWorker
alias Berrypod.Sync.MockupEnricher
require Logger
@@ -110,7 +110,7 @@ defmodule SimpleshopTheme.Sync.ProductSyncWorker do
broadcast_sync(conn.id, {:sync_status, "completed", product_count})
# Rebuild search index after successful sync
SimpleshopTheme.Search.rebuild_index()
Berrypod.Search.rebuild_index()
:ok
else
@@ -165,7 +165,7 @@ defmodule SimpleshopTheme.Sync.ProductSyncWorker do
end
defp broadcast_sync(conn_id, message) do
Phoenix.PubSub.broadcast(SimpleshopTheme.PubSub, "sync:#{conn_id}", message)
Phoenix.PubSub.broadcast(Berrypod.PubSub, "sync:#{conn_id}", message)
end
defp sync_product_associations(product, product_data) do
@@ -214,11 +214,11 @@ defmodule SimpleshopTheme.Sync.ProductSyncWorker do
defp sync_shipping_rates(conn, provider, products) do
if function_exported?(provider, :fetch_shipping_rates, 2) do
# Fetch live exchange rates so shipping costs are stored in GBP
{:ok, exchange_rates} = SimpleshopTheme.ExchangeRate.fetch_and_cache()
{:ok, exchange_rates} = Berrypod.ExchangeRate.fetch_and_cache()
case provider.fetch_shipping_rates(conn, products) do
{:ok, rates} when rates != [] ->
SimpleshopTheme.Shipping.upsert_rates(conn.id, rates, exchange_rates)
Berrypod.Shipping.upsert_rates(conn.id, rates, exchange_rates)
{:ok, []} ->
Logger.info("No shipping rates returned for #{conn.provider_type}")

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Sync.ScheduledSyncWorker do
defmodule Berrypod.Sync.ScheduledSyncWorker do
@moduledoc """
Oban cron worker for periodic product + shipping rate sync.
@@ -9,7 +9,7 @@ defmodule SimpleshopTheme.Sync.ScheduledSyncWorker do
use Oban.Worker, queue: :sync, max_attempts: 1
alias SimpleshopTheme.Products
alias Berrypod.Products
require Logger

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Theme.CSSCache do
defmodule Berrypod.Theme.CSSCache do
@moduledoc """
GenServer that maintains an ETS table for caching generated theme CSS.
@@ -80,13 +80,13 @@ defmodule SimpleshopTheme.Theme.CSSCache do
"""
def warm do
alias SimpleshopTheme.Settings
alias SimpleshopTheme.Theme.CSSGenerator
alias Berrypod.Settings
alias Berrypod.Theme.CSSGenerator
settings = Settings.get_theme_settings()
# Use endpoint's static_path for digested URLs in production
path_resolver = &SimpleshopThemeWeb.Endpoint.static_path/1
path_resolver = &BerrypodWeb.Endpoint.static_path/1
css = CSSGenerator.generate(settings, path_resolver)
put(css)

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Theme.CSSGenerator do
defmodule Berrypod.Theme.CSSGenerator do
@moduledoc """
Generates CSS custom properties (Layer 2: Theme Tokens) from theme settings.
@@ -10,8 +10,8 @@ defmodule SimpleshopTheme.Theme.CSSGenerator do
The theme editor still uses those selectors for live preview switching.
"""
alias SimpleshopTheme.Settings.ThemeSettings
alias SimpleshopTheme.Theme.Fonts
alias Berrypod.Settings.ThemeSettings
alias Berrypod.Theme.Fonts
@doc """
Generates CSS for theme settings.
@@ -23,7 +23,7 @@ defmodule SimpleshopTheme.Theme.CSSGenerator do
Also includes @font-face declarations for the fonts used by the typography preset.
Accepts an optional path_resolver function for digested font paths.
In production, pass `&SimpleshopThemeWeb.Endpoint.static_path/1`.
In production, pass `&BerrypodWeb.Endpoint.static_path/1`.
"""
def generate(%ThemeSettings{} = settings, path_resolver \\ fn path -> path end) do
"""

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Theme.Fonts do
defmodule Berrypod.Theme.Fonts do
@moduledoc """
Centralized font configuration for the theme system.
@@ -116,7 +116,7 @@ defmodule SimpleshopTheme.Theme.Fonts do
Only includes the fonts needed for that preset.
Accepts an optional path_resolver function to transform font URLs.
In production, pass `&SimpleshopThemeWeb.Endpoint.static_path/1` for digested paths.
In production, pass `&BerrypodWeb.Endpoint.static_path/1` for digested paths.
"""
def generate_font_faces(typography, path_resolver \\ &default_path_resolver/1) do
%{heading: heading_key, body: body_key} = fonts_for_typography(typography)
@@ -188,7 +188,7 @@ defmodule SimpleshopTheme.Theme.Fonts do
Returns a list of maps with href, as, type, and crossorigin attributes.
Accepts an optional path_resolver function for digested paths.
In production, pass `&SimpleshopThemeWeb.Endpoint.static_path/1`.
In production, pass `&BerrypodWeb.Endpoint.static_path/1`.
"""
def preload_links(typography, path_resolver \\ &default_path_resolver/1) do
typography

View File

@@ -1,6 +1,6 @@
defmodule SimpleshopTheme.Theme.Presets do
defmodule Berrypod.Theme.Presets do
@moduledoc """
Defines the 8 curated theme presets for SimpleShop.
Defines the 8 curated theme presets for Berrypod.
"""
@presets %{

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Theme.PreviewData do
defmodule Berrypod.Theme.PreviewData do
@moduledoc """
Provides preview data for theme customization.
@@ -6,7 +6,7 @@ defmodule SimpleshopTheme.Theme.PreviewData do
This allows users to preview themes before adding products to their shop.
"""
alias SimpleshopTheme.Products
alias Berrypod.Products
@doc """
Returns products for preview.
@@ -105,7 +105,7 @@ defmodule SimpleshopTheme.Theme.PreviewData do
%{
type: :lead,
text:
"This is a sample about page for your SimpleShop store. You're reading it as Robin, a fictional nature photographer but this is where your own story goes."
"This is a sample about page for your Berrypod store. You're reading it as Robin, a fictional nature photographer but this is where your own story goes."
},
%{
type: :paragraph,

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopTheme.Vault do
defmodule Berrypod.Vault do
@moduledoc """
Handles encryption and decryption of sensitive data.
@@ -6,7 +6,7 @@ defmodule SimpleshopTheme.Vault do
Keys are derived from the application's secret_key_base.
"""
@aad "SimpleshopTheme.Vault"
@aad "Berrypod.Vault"
@doc """
Encrypts a string value.
@@ -87,7 +87,7 @@ defmodule SimpleshopTheme.Vault do
end
defp get_secret_key_base do
case Application.get_env(:simpleshop_theme, SimpleshopThemeWeb.Endpoint)[:secret_key_base] do
case Application.get_env(:berrypod, BerrypodWeb.Endpoint)[:secret_key_base] do
nil ->
raise """
Secret key base is not configured.

View File

@@ -1,13 +1,13 @@
defmodule SimpleshopTheme.Webhooks do
defmodule Berrypod.Webhooks do
@moduledoc """
Handles incoming webhook events from POD providers.
"""
alias SimpleshopTheme.Orders
alias SimpleshopTheme.Orders.OrderNotifier
alias SimpleshopTheme.Products
alias SimpleshopTheme.Sync.ProductSyncWorker
alias SimpleshopTheme.Webhooks.ProductDeleteWorker
alias Berrypod.Orders
alias Berrypod.Orders.OrderNotifier
alias Berrypod.Products
alias Berrypod.Sync.ProductSyncWorker
alias Berrypod.Webhooks.ProductDeleteWorker
require Logger

View File

@@ -1,11 +1,11 @@
defmodule SimpleshopTheme.Webhooks.ProductDeleteWorker do
defmodule Berrypod.Webhooks.ProductDeleteWorker do
@moduledoc """
Oban worker for deleting products removed from POD providers.
"""
use Oban.Worker, queue: :sync, max_attempts: 3
alias SimpleshopTheme.Products
alias Berrypod.Products
require Logger

View File

@@ -1,12 +1,12 @@
defmodule SimpleshopThemeWeb do
defmodule BerrypodWeb do
@moduledoc """
The entrypoint for defining your web interface, such
as controllers, components, channels, and so on.
This can be used in your application as:
use SimpleshopThemeWeb, :controller
use SimpleshopThemeWeb, :html
use BerrypodWeb, :controller
use BerrypodWeb, :html
The definitions below will be executed for every controller,
component, etc, so keep them short and clean, focused
@@ -41,7 +41,7 @@ defmodule SimpleshopThemeWeb do
quote do
use Phoenix.Controller, formats: [:html, :json]
use Gettext, backend: SimpleshopThemeWeb.Gettext
use Gettext, backend: BerrypodWeb.Gettext
import Plug.Conn
@@ -81,18 +81,18 @@ defmodule SimpleshopThemeWeb do
defp html_helpers do
quote do
# Translation
use Gettext, backend: SimpleshopThemeWeb.Gettext
use Gettext, backend: BerrypodWeb.Gettext
# HTML escaping functionality
import Phoenix.HTML
# Core UI components
import SimpleshopThemeWeb.CoreComponents
import BerrypodWeb.CoreComponents
# Shop UI components
use SimpleshopThemeWeb.ShopComponents
use BerrypodWeb.ShopComponents
# Common modules used in templates
alias Phoenix.LiveView.JS
alias SimpleshopThemeWeb.Layouts
alias BerrypodWeb.Layouts
# Routes generation with the ~p sigil
unquote(verified_routes())
@@ -102,9 +102,9 @@ defmodule SimpleshopThemeWeb do
def verified_routes do
quote do
use Phoenix.VerifiedRoutes,
endpoint: SimpleshopThemeWeb.Endpoint,
router: SimpleshopThemeWeb.Router,
statics: SimpleshopThemeWeb.static_paths()
endpoint: BerrypodWeb.Endpoint,
router: BerrypodWeb.Router,
statics: BerrypodWeb.static_paths()
end
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.AdminLayoutHook do
defmodule BerrypodWeb.AdminLayoutHook do
@moduledoc """
LiveView on_mount hook that assigns the current path for admin sidebar navigation.
"""

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.CartHook do
defmodule BerrypodWeb.CartHook do
@moduledoc """
LiveView on_mount hook for cart state and shared event handling.
@@ -19,8 +19,8 @@ defmodule SimpleshopThemeWeb.CartHook do
import Phoenix.Component, only: [assign: 3]
import Phoenix.LiveView, only: [attach_hook: 4, connected?: 1, push_event: 3]
alias SimpleshopTheme.Cart
alias SimpleshopTheme.Shipping
alias Berrypod.Cart
alias Berrypod.Shipping
def on_mount(:mount_cart, _params, session, socket) do
cart_items = Cart.get_from_session(session)
@@ -41,7 +41,7 @@ defmodule SimpleshopThemeWeb.CartHook do
if connected?(socket) do
csrf_token = Map.get(session, "_csrf_token", "default")
topic = "cart:#{csrf_token}"
Phoenix.PubSub.subscribe(SimpleshopTheme.PubSub, topic)
Phoenix.PubSub.subscribe(Berrypod.PubSub, topic)
assign(socket, :cart_topic, topic)
else
assign(socket, :cart_topic, nil)
@@ -152,7 +152,7 @@ defmodule SimpleshopThemeWeb.CartHook do
def broadcast_and_update(socket, cart) do
if socket.assigns.cart_topic do
Phoenix.PubSub.broadcast_from(
SimpleshopTheme.PubSub,
Berrypod.PubSub,
self(),
socket.assigns.cart_topic,
{:cart_updated, cart}

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.CoreComponents do
defmodule BerrypodWeb.CoreComponents do
@moduledoc """
Provides core UI components.
@@ -18,7 +18,7 @@ defmodule SimpleshopThemeWeb.CoreComponents do
"""
use Phoenix.Component
use Gettext, backend: SimpleshopThemeWeb.Gettext
use Gettext, backend: BerrypodWeb.Gettext
alias Phoenix.LiveView.JS
@@ -448,9 +448,9 @@ defmodule SimpleshopThemeWeb.CoreComponents do
# with our gettext backend as first argument. Translations are
# available in the errors.po file (as we use the "errors" domain).
if count = opts[:count] do
Gettext.dngettext(SimpleshopThemeWeb.Gettext, "errors", msg, msg, count, opts)
Gettext.dngettext(BerrypodWeb.Gettext, "errors", msg, msg, count, opts)
else
Gettext.dgettext(SimpleshopThemeWeb.Gettext, "errors", msg, opts)
Gettext.dgettext(BerrypodWeb.Gettext, "errors", msg, opts)
end
end

View File

@@ -1,9 +1,9 @@
defmodule SimpleshopThemeWeb.Layouts do
defmodule BerrypodWeb.Layouts do
@moduledoc """
This module holds layouts and related functionality
used by your application.
"""
use SimpleshopThemeWeb, :html
use BerrypodWeb, :html
# Embed all files in layouts/* within this module.
# The default root.html.heex file contains the HTML

View File

@@ -12,7 +12,7 @@
>
<.icon name="hero-bars-3" class="size-5" />
</label>
<span class="admin-topbar-title">SimpleShop</span>
<span class="admin-topbar-title">Berrypod</span>
<.link href={~p"/"} class="admin-btn admin-btn-ghost admin-btn-sm">
<.icon name="hero-arrow-top-right-on-square-mini" class="size-4" /> Shop
</.link>
@@ -33,7 +33,7 @@
<%!-- sidebar header --%>
<div class="p-4 border-b border-base-300">
<.link navigate={~p"/admin"} class="text-lg font-bold tracking-tight">
SimpleShop
Berrypod
</.link>
<p class="text-xs text-base-content/60 mt-0.5 truncate">
{@current_scope.user.email}

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title default="Admin" suffix=" · SimpleShop">
<.live_title default="Admin" suffix=" · Berrypod">
{assigns[:page_title]}
</.live_title>
<!-- Pre-declare layer order so shop reset < Tailwind base regardless of load order -->

View File

@@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title default="SimpleshopTheme" suffix=" · Phoenix Framework">
<.live_title default="Berrypod" suffix=" · Phoenix Framework">
{assigns[:page_title]}
</.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/css/admin.css"} />

View File

@@ -13,9 +13,9 @@
/>
<.live_title>{assigns[:page_title] || @theme_settings.site_name}</.live_title>
<!-- Preload critical fonts for the current typography preset -->
<%= for preload <- SimpleshopTheme.Theme.Fonts.preload_links(
<%= for preload <- Berrypod.Theme.Fonts.preload_links(
@theme_settings.typography,
&SimpleshopThemeWeb.Endpoint.static_path/1
&BerrypodWeb.Endpoint.static_path/1
) do %>
<link rel="preload" href={preload.href} as="font" type="font/woff2" crossorigin />
<% end %>

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.PageTemplates do
defmodule BerrypodWeb.PageTemplates do
@moduledoc """
Shared page templates used by both the public shop and theme preview.
@@ -15,7 +15,7 @@ defmodule SimpleshopThemeWeb.PageTemplates do
- `cart_count` - Number of items in cart
"""
use Phoenix.Component
use SimpleshopThemeWeb.ShopComponents
use BerrypodWeb.ShopComponents
embed_templates "page_templates/*"
end

View File

@@ -52,7 +52,7 @@
</p>
</div>
<span class="checkout-item-price">
{SimpleshopTheme.Cart.format_price(item.unit_price * item.quantity)}
{Berrypod.Cart.format_price(item.unit_price * item.quantity)}
</span>
</li>
<% end %>
@@ -62,7 +62,7 @@
<div class="checkout-total">
<span class="checkout-total-label">Total</span>
<span class="checkout-total-amount">
{SimpleshopTheme.Cart.format_price(@order.total)}
{Berrypod.Cart.format_price(@order.total)}
</span>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<main id="main-content">
<.hero_section
title="Original designs, printed on demand"
description="Welcome to the SimpleShop demo store. This is where your hero text goes something short and punchy about what makes your shop worth a browse."
description="Welcome to the Berrypod demo store. This is where your hero text goes something short and punchy about what makes your shop worth a browse."
cta_text="Shop the collection"
cta_page="collection"
cta_href="/collections/all"

View File

@@ -52,7 +52,7 @@
<.reviews_section
:if={@theme_settings.pdp_reviews}
reviews={SimpleshopTheme.Theme.PreviewData.reviews()}
reviews={Berrypod.Theme.PreviewData.reviews()}
average_rating={5}
total_count={24}
/>

View File

@@ -1,8 +1,8 @@
defmodule SimpleshopThemeWeb.ShopComponents do
defmodule BerrypodWeb.ShopComponents do
@moduledoc """
Facade module for shop/storefront UI components.
`use SimpleshopThemeWeb.ShopComponents` imports all sub-modules:
`use BerrypodWeb.ShopComponents` imports all sub-modules:
- `Base` themed inputs, buttons, cards
- `Layout` header, footer, mobile nav, shop_layout wrapper
@@ -13,11 +13,11 @@ defmodule SimpleshopThemeWeb.ShopComponents do
defmacro __using__(_opts \\ []) do
quote do
import SimpleshopThemeWeb.ShopComponents.Base
import SimpleshopThemeWeb.ShopComponents.Cart
import SimpleshopThemeWeb.ShopComponents.Content
import SimpleshopThemeWeb.ShopComponents.Layout
import SimpleshopThemeWeb.ShopComponents.Product
import BerrypodWeb.ShopComponents.Base
import BerrypodWeb.ShopComponents.Cart
import BerrypodWeb.ShopComponents.Content
import BerrypodWeb.ShopComponents.Layout
import BerrypodWeb.ShopComponents.Product
end
end
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.ShopComponents.Base do
defmodule BerrypodWeb.ShopComponents.Base do
use Phoenix.Component
@doc """

View File

@@ -1,11 +1,11 @@
defmodule SimpleshopThemeWeb.ShopComponents.Cart do
defmodule BerrypodWeb.ShopComponents.Cart do
@moduledoc false
use Phoenix.Component
import SimpleshopThemeWeb.ShopComponents.Base
import BerrypodWeb.ShopComponents.Base
alias SimpleshopTheme.Products.{Product, ProductImage}
alias Berrypod.Products.{Product, ProductImage}
defp close_cart_drawer_js do
Phoenix.LiveView.JS.push("close_cart_drawer")
@@ -248,7 +248,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Cart do
<div class="cart-item-price-col">
<p class="cart-item-price" data-size={if @size == :compact, do: "compact"}>
{SimpleshopTheme.Cart.format_price(@item.price * @item.quantity)}
{Berrypod.Cart.format_price(@item.price * @item.quantity)}
</p>
</div>
</div>
@@ -370,7 +370,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Cart do
<div class="cart-page-item-price-col">
<p class="cart-page-item-price">
{SimpleshopTheme.Cart.format_price(@item.product.cheapest_price * @item.quantity)}
{Berrypod.Cart.format_price(@item.product.cheapest_price * @item.quantity)}
</p>
</div>
</.shop_card>
@@ -406,11 +406,11 @@ defmodule SimpleshopThemeWeb.ShopComponents.Cart do
</select>
</form>
<% else %>
<span>{SimpleshopTheme.Shipping.country_name(@country_code)}</span>
<span>{Berrypod.Shipping.country_name(@country_code)}</span>
<% end %>
</span>
<%= if @shipping_estimate do %>
<span>{SimpleshopTheme.Cart.format_price(@shipping_estimate)}</span>
<span>{Berrypod.Cart.format_price(@shipping_estimate)}</span>
<% else %>
<span>Calculated at checkout</span>
<% end %>
@@ -453,7 +453,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Cart do
<div class="order-summary-line">
<span>Subtotal</span>
<span>
{SimpleshopTheme.Cart.format_price(@subtotal)}
{Berrypod.Cart.format_price(@subtotal)}
</span>
</div>
<.delivery_line
@@ -468,7 +468,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Cart do
{if @shipping_estimate, do: "Estimated total", else: "Subtotal"}
</span>
<span>
{SimpleshopTheme.Cart.format_price(@estimated_total)}
{Berrypod.Cart.format_price(@estimated_total)}
</span>
</div>
</div>

View File

@@ -1,9 +1,9 @@
defmodule SimpleshopThemeWeb.ShopComponents.Content do
defmodule BerrypodWeb.ShopComponents.Content do
@moduledoc false
use Phoenix.Component
import SimpleshopThemeWeb.ShopComponents.Base
import BerrypodWeb.ShopComponents.Base
@default_social_links [
%{platform: :instagram, url: "https://instagram.com", label: "Instagram"},
@@ -966,7 +966,7 @@ defmodule SimpleshopThemeWeb.ShopComponents.Content do
attr :priority, :boolean, default: false
def responsive_image(assigns) do
alias SimpleshopTheme.Images.Optimizer
alias Berrypod.Images.Optimizer
# Compute available widths from source dimensions (no upscaling)
available = Optimizer.applicable_widths(assigns.source_width)

View File

@@ -1,8 +1,8 @@
defmodule SimpleshopThemeWeb.ShopComponents.Layout do
defmodule BerrypodWeb.ShopComponents.Layout do
use Phoenix.Component
import SimpleshopThemeWeb.ShopComponents.Cart
import SimpleshopThemeWeb.ShopComponents.Content
import BerrypodWeb.ShopComponents.Cart
import BerrypodWeb.ShopComponents.Content
@doc """
Renders the announcement bar.
@@ -350,8 +350,8 @@ defmodule SimpleshopThemeWeb.ShopComponents.Layout do
attr :search_open, :boolean, default: false
def search_modal(assigns) do
alias SimpleshopTheme.Cart
alias SimpleshopTheme.Products.{Product, ProductImage}
alias Berrypod.Cart
alias Berrypod.Products.{Product, ProductImage}
assigns =
assign(

View File

@@ -1,10 +1,10 @@
defmodule SimpleshopThemeWeb.ShopComponents.Product do
defmodule BerrypodWeb.ShopComponents.Product do
use Phoenix.Component
import SimpleshopThemeWeb.ShopComponents.Base
import SimpleshopThemeWeb.ShopComponents.Content, only: [responsive_image: 1]
import BerrypodWeb.ShopComponents.Base
import BerrypodWeb.ShopComponents.Content, only: [responsive_image: 1]
alias SimpleshopTheme.Products.{Product, ProductImage}
alias Berrypod.Products.{Product, ProductImage}
@doc """
Renders a product card with configurable variants.
@@ -298,14 +298,14 @@ defmodule SimpleshopThemeWeb.ShopComponents.Product do
<div>
<%= if @product.on_sale do %>
<span class="product-price--sale">
{SimpleshopTheme.Cart.format_price(@product.cheapest_price)}
{Berrypod.Cart.format_price(@product.cheapest_price)}
</span>
<span class="product-price--compare">
{SimpleshopTheme.Cart.format_price(@product.compare_at_price)}
{Berrypod.Cart.format_price(@product.compare_at_price)}
</span>
<% else %>
<span class="product-price--regular">
{SimpleshopTheme.Cart.format_price(@product.cheapest_price)}
{Berrypod.Cart.format_price(@product.cheapest_price)}
</span>
<% end %>
</div>
@@ -313,18 +313,18 @@ defmodule SimpleshopThemeWeb.ShopComponents.Product do
<p class="product-price--secondary">
<%= if @product.on_sale do %>
<span class="product-price--compare">
{SimpleshopTheme.Cart.format_price(@product.compare_at_price)}
{Berrypod.Cart.format_price(@product.compare_at_price)}
</span>
<% end %>
{SimpleshopTheme.Cart.format_price(@product.cheapest_price)}
{Berrypod.Cart.format_price(@product.cheapest_price)}
</p>
<% :compact -> %>
<p class="product-price--regular">
{SimpleshopTheme.Cart.format_price(@product.cheapest_price)}
{Berrypod.Cart.format_price(@product.cheapest_price)}
</p>
<% :minimal -> %>
<p class="product-price--secondary">
{SimpleshopTheme.Cart.format_price(@product.cheapest_price)}
{Berrypod.Cart.format_price(@product.cheapest_price)}
</p>
<% end %>
"""
@@ -1294,17 +1294,17 @@ defmodule SimpleshopThemeWeb.ShopComponents.Product do
<div class="pdp-price-row">
<%= if @product.on_sale do %>
<span class="product-price--sale">
{SimpleshopTheme.Cart.format_price(@price)}
{Berrypod.Cart.format_price(@price)}
</span>
<span class="product-price--compare">
{SimpleshopTheme.Cart.format_price(@product.compare_at_price)}
{Berrypod.Cart.format_price(@product.compare_at_price)}
</span>
<span class="sale-badge">
SAVE {round((@product.compare_at_price - @price) / @product.compare_at_price * 100)}%
</span>
<% else %>
<span class="product-price--regular">
{SimpleshopTheme.Cart.format_price(@price)}
{Berrypod.Cart.format_price(@price)}
</span>
<% end %>
</div>

View File

@@ -0,0 +1,7 @@
defmodule BerrypodWeb.AdminController do
use BerrypodWeb, :controller
def index(conn, _params) do
redirect(conn, to: ~p"/admin/orders")
end
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.CartController do
defmodule BerrypodWeb.CartController do
@moduledoc """
API controller for cart session persistence.
@@ -6,9 +6,9 @@ defmodule SimpleshopThemeWeb.CartController do
via this API endpoint called from a JS hook after each cart modification.
"""
use SimpleshopThemeWeb, :controller
use BerrypodWeb, :controller
alias SimpleshopTheme.Cart
alias Berrypod.Cart
@doc """
Updates the cart in session.

View File

@@ -1,9 +1,9 @@
defmodule SimpleshopThemeWeb.CheckoutController do
use SimpleshopThemeWeb, :controller
defmodule BerrypodWeb.CheckoutController do
use BerrypodWeb, :controller
alias SimpleshopTheme.Cart
alias SimpleshopTheme.Orders
alias SimpleshopTheme.Shipping
alias Berrypod.Cart
alias Berrypod.Orders
alias Berrypod.Shipping
require Logger
@@ -53,7 +53,7 @@ defmodule SimpleshopThemeWeb.CheckoutController do
}
end)
base_url = SimpleshopThemeWeb.Endpoint.url()
base_url = BerrypodWeb.Endpoint.url()
params =
%{

View File

@@ -1,16 +1,16 @@
defmodule SimpleshopThemeWeb.ErrorHTML do
defmodule BerrypodWeb.ErrorHTML do
@moduledoc """
This module is invoked by your endpoint in case of errors on HTML requests.
See config/config.exs.
"""
use SimpleshopThemeWeb, :html
use BerrypodWeb, :html
alias SimpleshopTheme.Settings
alias SimpleshopTheme.Settings.ThemeSettings
alias SimpleshopTheme.Media
alias SimpleshopTheme.Products
alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator}
alias Berrypod.Settings
alias Berrypod.Settings.ThemeSettings
alias Berrypod.Media
alias Berrypod.Products
alias Berrypod.Theme.{CSSCache, CSSGenerator}
def render("404.html", assigns) do
render_error_page(
@@ -84,7 +84,7 @@ defmodule SimpleshopThemeWeb.ErrorHTML do
data-layout={@theme_settings.layout_width}
data-shadow={@theme_settings.card_shadow}
>
<SimpleshopThemeWeb.PageTemplates.error
<BerrypodWeb.PageTemplates.error
theme_settings={@theme_settings}
logo_image={@logo_image}
header_image={@header_image}

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.ErrorJSON do
defmodule BerrypodWeb.ErrorJSON do
@moduledoc """
This module is invoked by your endpoint in case of errors on JSON requests.

View File

@@ -1,20 +1,20 @@
defmodule SimpleshopThemeWeb.ErrorPreviewController do
defmodule BerrypodWeb.ErrorPreviewController do
@moduledoc """
Development-only controller for previewing error pages.
"""
use SimpleshopThemeWeb, :controller
use BerrypodWeb, :controller
def not_found(conn, _params) do
conn
|> put_status(:not_found)
|> put_view(SimpleshopThemeWeb.ErrorHTML)
|> put_view(BerrypodWeb.ErrorHTML)
|> render("404.html")
end
def server_error(conn, _params) do
conn
|> put_status(:internal_server_error)
|> put_view(SimpleshopThemeWeb.ErrorHTML)
|> put_view(BerrypodWeb.ErrorHTML)
|> render("500.html")
end
end

View File

@@ -0,0 +1,7 @@
defmodule BerrypodWeb.HealthController do
use BerrypodWeb, :controller
def show(conn, _params) do
json(conn, %{status: "ok"})
end
end

View File

@@ -1,8 +1,8 @@
defmodule SimpleshopThemeWeb.ImageController do
use SimpleshopThemeWeb, :controller
defmodule BerrypodWeb.ImageController do
use BerrypodWeb, :controller
alias SimpleshopTheme.Media
alias SimpleshopTheme.Media.SVGRecolorer
alias Berrypod.Media
alias Berrypod.Media.SVGRecolorer
@doc """
Serves an SVG image recolored with the specified color.

View File

@@ -0,0 +1,7 @@
defmodule BerrypodWeb.PageController do
use BerrypodWeb, :controller
def home(conn, _params) do
render(conn, :home)
end
end

View File

@@ -1,10 +1,10 @@
defmodule SimpleshopThemeWeb.PageHTML do
defmodule BerrypodWeb.PageHTML do
@moduledoc """
This module contains pages rendered by PageController.
See the `page_html` directory for all templates available.
"""
use SimpleshopThemeWeb, :html
use BerrypodWeb, :html
embed_templates "page_html/*"
end

View File

@@ -1,8 +1,8 @@
defmodule SimpleshopThemeWeb.StripeWebhookController do
use SimpleshopThemeWeb, :controller
defmodule BerrypodWeb.StripeWebhookController do
use BerrypodWeb, :controller
alias SimpleshopTheme.Orders
alias SimpleshopTheme.Orders.{OrderNotifier, OrderSubmissionWorker}
alias Berrypod.Orders
alias Berrypod.Orders.{OrderNotifier, OrderSubmissionWorker}
require Logger
@@ -64,7 +64,7 @@ defmodule SimpleshopThemeWeb.StripeWebhookController do
# Broadcast to success page via PubSub
Phoenix.PubSub.broadcast(
SimpleshopTheme.PubSub,
Berrypod.PubSub,
"order:#{order.id}:status",
{:order_paid, order}
)

View File

@@ -1,8 +1,8 @@
defmodule SimpleshopThemeWeb.UserSessionController do
use SimpleshopThemeWeb, :controller
defmodule BerrypodWeb.UserSessionController do
use BerrypodWeb, :controller
alias SimpleshopTheme.Accounts
alias SimpleshopThemeWeb.UserAuth
alias Berrypod.Accounts
alias BerrypodWeb.UserAuth
def create(conn, %{"_action" => "confirmed"} = params) do
create(conn, params, "User confirmed successfully.")

View File

@@ -1,7 +1,7 @@
defmodule SimpleshopThemeWeb.WebhookController do
use SimpleshopThemeWeb, :controller
defmodule BerrypodWeb.WebhookController do
use BerrypodWeb, :controller
alias SimpleshopTheme.Webhooks
alias Berrypod.Webhooks
require Logger

View File

@@ -1,12 +1,12 @@
defmodule SimpleshopThemeWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :simpleshop_theme
defmodule BerrypodWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :berrypod
# The session will be stored in the cookie and signed,
# this means its contents can be read but not tampered with.
# Set :encryption_salt if you would also like to encrypt it.
@session_options [
store: :cookie,
key: "_simpleshop_theme_key",
key: "_berrypod_key",
signing_salt: "JNwRcD7y",
same_site: "Lax"
]
@@ -22,11 +22,11 @@ defmodule SimpleshopThemeWeb.Endpoint do
# In dev, we omit the option to get the Plug.Static default ("public").
plug Plug.Static,
at: "/",
from: :simpleshop_theme,
from: :berrypod,
gzip: true,
only: SimpleshopThemeWeb.static_paths(),
only: BerrypodWeb.static_paths(),
cache_control_for_etags:
if(Application.compile_env(:simpleshop_theme, :env) == :prod,
if(Application.compile_env(:berrypod, :env) == :prod,
do: "public, max-age=31536000, immutable",
else: "public"
)
@@ -41,7 +41,7 @@ defmodule SimpleshopThemeWeb.Endpoint do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader
plug Phoenix.CodeReloader
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :simpleshop_theme
plug Phoenix.Ecto.CheckRepoStatus, otp_app: :berrypod
end
plug Phoenix.LiveDashboard.RequestLogger,
@@ -54,11 +54,11 @@ defmodule SimpleshopThemeWeb.Endpoint do
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
body_reader: {SimpleshopThemeWeb.Plugs.CacheRawBody, :read_body, []},
body_reader: {BerrypodWeb.Plugs.CacheRawBody, :read_body, []},
json_decoder: Phoenix.json_library()
plug Plug.MethodOverride
plug Plug.Head
plug Plug.Session, @session_options
plug SimpleshopThemeWeb.Router
plug BerrypodWeb.Router
end

View File

@@ -1,4 +1,4 @@
defmodule SimpleshopThemeWeb.Gettext do
defmodule BerrypodWeb.Gettext do
@moduledoc """
A module providing Internationalization with a gettext-based API.
@@ -6,7 +6,7 @@ defmodule SimpleshopThemeWeb.Gettext do
that you can use in your application. To use this Gettext backend module,
call `use Gettext` and pass it as an option:
use Gettext, backend: SimpleshopThemeWeb.Gettext
use Gettext, backend: BerrypodWeb.Gettext
# Simple translation
gettext("Here is the string to translate")
@@ -21,5 +21,5 @@ defmodule SimpleshopThemeWeb.Gettext do
See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
"""
use Gettext.Backend, otp_app: :simpleshop_theme
use Gettext.Backend, otp_app: :berrypod
end

Some files were not shown because too many files have changed in this diff Show More