add admin products list and detail pages
Read-mostly admin views for synced products: filterable/sortable list with inline visibility toggle, and detail page with images grid, variants table, storefront controls form, and provider edit links. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -225,6 +225,7 @@ defmodule SimpleshopTheme.Products do
|
||||
defp maybe_filter_on_sale(query, _), do: query
|
||||
|
||||
defp maybe_filter_in_stock(query, true), do: where(query, [p], p.in_stock == true)
|
||||
defp maybe_filter_in_stock(query, false), do: where(query, [p], p.in_stock == false)
|
||||
defp maybe_filter_in_stock(query, _), do: query
|
||||
|
||||
defp apply_sort(query, "price_asc"), do: order_by(query, [p], asc: p.cheapest_price)
|
||||
@@ -264,6 +265,42 @@ defmodule SimpleshopTheme.Products do
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns products for the admin list page with sorting, stock filtering,
|
||||
and full preloads for display.
|
||||
|
||||
## Options
|
||||
|
||||
* `:visible` - filter by visibility (boolean)
|
||||
* `:status` - filter by status (string)
|
||||
* `:category` - filter by category (string)
|
||||
* `:provider_connection_id` - filter by provider connection
|
||||
* `:in_stock` - filter by stock status (boolean)
|
||||
* `:sort` - sort order (string)
|
||||
|
||||
"""
|
||||
def list_products_admin(opts \\ []) do
|
||||
Product
|
||||
|> apply_product_filters(opts)
|
||||
|> maybe_filter_in_stock(opts[:in_stock])
|
||||
|> apply_sort(opts[:sort])
|
||||
|> preload([:provider_connection, images: :image, variants: []])
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns distinct category names from all products (including hidden/draft).
|
||||
"""
|
||||
def list_all_categories do
|
||||
from(p in Product,
|
||||
where: not is_nil(p.category),
|
||||
select: p.category,
|
||||
distinct: true,
|
||||
order_by: p.category
|
||||
)
|
||||
|> Repo.all()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single product by ID.
|
||||
"""
|
||||
@@ -310,6 +347,22 @@ defmodule SimpleshopTheme.Products do
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates storefront-only fields (visibility and category).
|
||||
"""
|
||||
def update_storefront(%Product{} = product, attrs) do
|
||||
product
|
||||
|> Product.storefront_changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Toggles a product's visibility.
|
||||
"""
|
||||
def toggle_visibility(%Product{} = product) do
|
||||
update_storefront(product, %{visible: !product.visible})
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a product.
|
||||
"""
|
||||
|
||||
@@ -67,6 +67,14 @@ defmodule SimpleshopTheme.Products.Product do
|
||||
|> unique_constraint([:provider_connection_id, :provider_product_id])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Changeset for admin storefront controls (visibility and category only).
|
||||
"""
|
||||
def storefront_changeset(product, attrs) do
|
||||
product
|
||||
|> cast(attrs, [:visible, :category])
|
||||
end
|
||||
|
||||
@doc """
|
||||
Changeset for recomputing denormalized fields from variants.
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user