add url slug resolution to shop routing

Shop.Page resolves custom URLs to correct page types:
- resolve_custom_slug/2 detects system pages with custom URLs
- Dynamic prefix resolution for /:prefix/:id routes
- Updates live_action when slug resolves to different type

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-04-01 00:36:05 +01:00
parent e9649218fb
commit c115f08cb8
2 changed files with 112 additions and 18 deletions

View File

@@ -12,7 +12,7 @@ defmodule BerrypodWeb.Shop.Pages.CustomPage do
{:noreply, socket}
end
def handle_params(%{"slug" => slug}, _uri, socket) do
def handle_params(%{"slug" => slug} = params, uri, socket) do
page = Pages.get_page(slug)
cond do
@@ -27,33 +27,67 @@ defmodule BerrypodWeb.Shop.Pages.CustomPage do
raise BerrypodWeb.NotFoundError
true ->
extra = Pages.load_block_data(page.blocks, socket.assigns)
base = BerrypodWeb.Endpoint.url()
socket =
socket
|> assign(:page_title, page.title)
|> assign(:page, page)
|> maybe_assign_meta(page, base)
|> assign(extra)
{:noreply, socket}
handle_page(page_to_map(page), params, uri, socket)
end
end
defp handle_page(page, _params, _uri, socket) do
extra = Pages.load_block_data(page.blocks, socket.assigns)
base = BerrypodWeb.Endpoint.url()
socket =
socket
|> assign(:page_title, page.title)
|> assign(:page, page)
|> maybe_assign_meta(page, base)
|> assign(extra)
{:noreply, socket}
end
# Convert Page struct to map for consistent handling
defp page_to_map(%Berrypod.Pages.Page{} = page) do
%{
id: page.id,
slug: page.slug,
title: page.title,
blocks: page.blocks,
type: page.type,
published: page.published,
meta_description: page.meta_description,
url_slug: page.url_slug,
show_in_nav: page.show_in_nav,
nav_label: page.nav_label,
nav_position: page.nav_position
}
end
defp page_to_map(page) when is_map(page), do: page
def handle_event(_event, _params, _socket), do: :cont
defp record_broken_url(path) do
prior_hits = Berrypod.Analytics.count_pageviews_for_path(path)
Berrypod.Redirects.record_broken_url(path, prior_hits)
# Skip static asset paths - these are expected 404s
unless static_path?(path) do
prior_hits = Berrypod.Analytics.count_pageviews_for_path(path)
Berrypod.Redirects.record_broken_url(path, prior_hits)
if prior_hits > 0 do
Berrypod.Redirects.attempt_auto_resolve(path)
if prior_hits > 0 do
Berrypod.Redirects.attempt_auto_resolve(path)
end
end
rescue
_ -> :ok
end
defp static_path?(path) do
String.starts_with?(path, "/assets/") or
String.starts_with?(path, "/images/") or
String.starts_with?(path, "/image_cache/") or
String.starts_with?(path, "/mockups/") or
String.starts_with?(path, "/favicon")
end
defp maybe_assign_meta(socket, page, base) do
socket
|> assign(:og_url, base <> "/#{page.slug}")