integrate R module and add url editor ui
Replaces hardcoded paths with R module throughout: - Shop components: layout nav, cart, product links - Controllers: cart, checkout, contact, seo, order lookup - Shop pages: collection, product, search, checkout success, etc. - Site context: nav item url resolution Admin URL management: - Settings page: prefix editor with validation feedback - Page renderer: url_editor component for page URLs - CSS for url editor styling Test updates for cache isolation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,6 +4,7 @@ defmodule BerrypodWeb.Admin.ProductShow do
|
||||
alias Berrypod.Products
|
||||
alias Berrypod.Products.{Product, ProductImage, ProductVariant}
|
||||
alias Berrypod.Cart
|
||||
alias BerrypodWeb.R
|
||||
|
||||
@impl true
|
||||
def mount(%{"id" => id}, _session, socket) do
|
||||
@@ -109,7 +110,7 @@ defmodule BerrypodWeb.Admin.ProductShow do
|
||||
<.icon name="hero-arrow-top-right-on-square-mini" class="size-4" />
|
||||
</.external_link>
|
||||
<.link
|
||||
navigate={~p"/products/#{@product.slug}"}
|
||||
navigate={R.product(@product.slug)}
|
||||
class="admin-btn admin-btn-ghost admin-btn-sm"
|
||||
>
|
||||
View on shop <.icon name="hero-arrow-top-right-on-square-mini" class="size-4" />
|
||||
|
||||
@@ -18,7 +18,15 @@ defmodule BerrypodWeb.Admin.Settings do
|
||||
|> assign(:from_address_status, :idle)
|
||||
|> assign(:signing_secret_status, :idle)
|
||||
|> assign_stripe_state()
|
||||
|> assign_products_state()}
|
||||
|> assign_products_state()
|
||||
|> assign_url_prefixes()}
|
||||
end
|
||||
|
||||
defp assign_url_prefixes(socket) do
|
||||
socket
|
||||
|> assign(:products_prefix, Settings.get_url_prefix(:products))
|
||||
|> assign(:collections_prefix, Settings.get_url_prefix(:collections))
|
||||
|> assign(:prefix_status, :idle)
|
||||
end
|
||||
|
||||
# -- Stripe assigns --
|
||||
@@ -117,6 +125,51 @@ defmodule BerrypodWeb.Admin.Settings do
|
||||
end
|
||||
end
|
||||
|
||||
# -- Events: URL prefixes --
|
||||
|
||||
def handle_event("change_prefix", _params, socket) do
|
||||
{:noreply, assign(socket, :prefix_status, :idle)}
|
||||
end
|
||||
|
||||
def handle_event("save_prefixes", %{"prefixes" => params}, socket) do
|
||||
products_prefix = params["products"] || ""
|
||||
collections_prefix = params["collections"] || ""
|
||||
|
||||
errors = []
|
||||
|
||||
# Update products prefix if changed
|
||||
errors =
|
||||
if products_prefix != socket.assigns.products_prefix do
|
||||
case Settings.update_url_prefix(:products, products_prefix) do
|
||||
{:ok, _} -> errors
|
||||
{:error, reason} -> [{:products, reason} | errors]
|
||||
end
|
||||
else
|
||||
errors
|
||||
end
|
||||
|
||||
# Update collections prefix if changed
|
||||
errors =
|
||||
if collections_prefix != socket.assigns.collections_prefix do
|
||||
case Settings.update_url_prefix(:collections, collections_prefix) do
|
||||
{:ok, _} -> errors
|
||||
{:error, reason} -> [{:collections, reason} | errors]
|
||||
end
|
||||
else
|
||||
errors
|
||||
end
|
||||
|
||||
if errors == [] do
|
||||
{:noreply,
|
||||
socket
|
||||
|> assign_url_prefixes()
|
||||
|> assign(:prefix_status, :saved)}
|
||||
else
|
||||
error_message = format_prefix_errors(errors)
|
||||
{:noreply, put_flash(socket, :error, error_message)}
|
||||
end
|
||||
end
|
||||
|
||||
# -- Events: Stripe --
|
||||
|
||||
def handle_event("connect_stripe", %{"stripe" => %{"api_key" => api_key}}, socket) do
|
||||
@@ -388,6 +441,67 @@ defmodule BerrypodWeb.Admin.Settings do
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<%!-- URL prefixes --%>
|
||||
<section class="admin-section">
|
||||
<h2 class="admin-section-title">URL prefixes</h2>
|
||||
<p class="admin-section-desc">
|
||||
Customise the URL structure for products and collections.
|
||||
Old URLs will automatically redirect to the new ones.
|
||||
</p>
|
||||
<div class="admin-section-body">
|
||||
<form
|
||||
phx-change="change_prefix"
|
||||
phx-submit="save_prefixes"
|
||||
class="admin-stack"
|
||||
>
|
||||
<div class="admin-row admin-row-lg">
|
||||
<label class="admin-label admin-label-inline" for="prefix-products">
|
||||
Products
|
||||
</label>
|
||||
<div class="admin-row admin-row-sm">
|
||||
<span class="admin-text-secondary">/</span>
|
||||
<.input
|
||||
name="prefixes[products]"
|
||||
id="prefix-products"
|
||||
value={@products_prefix}
|
||||
placeholder="products"
|
||||
pattern="[a-z0-9-]+"
|
||||
/>
|
||||
<span class="admin-text-secondary">/</span>
|
||||
<span class="admin-text-tertiary">product-slug</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="admin-row admin-row-lg">
|
||||
<label class="admin-label admin-label-inline" for="prefix-collections">
|
||||
Collections
|
||||
</label>
|
||||
<div class="admin-row admin-row-sm">
|
||||
<span class="admin-text-secondary">/</span>
|
||||
<.input
|
||||
name="prefixes[collections]"
|
||||
id="prefix-collections"
|
||||
value={@collections_prefix}
|
||||
placeholder="collections"
|
||||
pattern="[a-z0-9-]+"
|
||||
/>
|
||||
<span class="admin-text-secondary">/</span>
|
||||
<span class="admin-text-tertiary">collection-slug</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="admin-help-text">
|
||||
Use only lowercase letters, numbers, and hyphens.
|
||||
</p>
|
||||
|
||||
<div class="admin-form-actions-sm">
|
||||
<.button phx-disable-with="Saving...">Save</.button>
|
||||
<.inline_feedback status={@prefix_status} />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
@@ -639,4 +753,20 @@ defmodule BerrypodWeb.Admin.Settings do
|
||||
true -> "#{div(diff, 86400)} days ago"
|
||||
end
|
||||
end
|
||||
|
||||
defp format_prefix_errors(errors) do
|
||||
Enum.map_join(errors, "; ", fn {field, reason} ->
|
||||
field_name = if field == :products, do: "Products", else: "Collections"
|
||||
|
||||
message =
|
||||
case reason do
|
||||
:empty_prefix -> "can't be blank"
|
||||
:invalid_format -> "must contain only letters, numbers, and hyphens"
|
||||
:reserved_prefix -> "is reserved"
|
||||
_ -> "is invalid"
|
||||
end
|
||||
|
||||
"#{field_name} prefix #{message}"
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user