consolidate shop pages into unified LiveView for editor state persistence
All checks were successful
deploy / deploy (push) Successful in 1m27s

Replace individual shop LiveViews with a single Shop.Page that dispatches
to page modules based on live_action. This enables patch navigation between
pages, preserving socket state (including editor state) across transitions.

Changes:
- Add Shop.Page unified LiveView with handle_params dispatch
- Extract page logic into Shop.Pages.* modules (Home, Product, Collection, etc.)
- Update router to use Shop.Page with live_action for all shop routes
- Change navigate= to patch= in shop component links
- Add maybe_sync_editing_blocks to reload editor state when page changes
- Track editor_page_slug to detect cross-page navigation while editing
- Fix picture element height when hover image disabled
- Extract ThemeEditor components for shared use

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-03-09 14:47:50 +00:00
parent ae0a149ecd
commit bb5d220079
29 changed files with 1410 additions and 1037 deletions

View File

@@ -31,6 +31,7 @@ defmodule BerrypodWeb.PageEditorHook do
# Page editing state
|> assign(:editing, false)
|> assign(:editing_blocks, nil)
|> assign(:editor_page_slug, nil)
|> assign(:editor_dirty, false)
|> assign(:editor_at_defaults, true)
|> assign(:editor_history, [])
@@ -67,13 +68,81 @@ defmodule BerrypodWeb.PageEditorHook do
{:cont, socket}
end
# ── handle_params: track current path ────────────────────────────
# ── handle_params: track current path and restore editor state ────
defp handle_editor_params(_params, uri, socket) do
defp handle_editor_params(params, uri, socket) do
parsed = URI.parse(uri)
# Store the current path for reference (e.g. the Done button)
{:cont, assign(socket, :editor_current_path, parsed.path)}
socket =
socket
|> assign(:editor_current_path, parsed.path)
|> maybe_restore_editor_state(params)
{:cont, socket}
end
# Restore editor state from URL params on navigation
# Only activates state if not already in the requested state (avoids loops)
defp maybe_restore_editor_state(socket, params) do
if socket.assigns.is_admin do
requested_tab = params["edit"]
current_tab = socket.assigns.editor_active_tab
current_state = socket.assigns.editor_sheet_state
# If already in the correct state, don't re-apply
already_correct? =
current_state == :open && requested_tab &&
String.to_existing_atom(requested_tab) == current_tab
if already_correct? do
socket
else
case requested_tab do
"theme" ->
socket
|> assign(:editor_sheet_state, :open)
|> assign(:editor_active_tab, :theme)
|> maybe_enter_theme_mode()
"page" ->
socket
|> assign(:editor_sheet_state, :open)
|> assign(:editor_active_tab, :page)
|> maybe_enter_page_mode()
"settings" ->
socket
|> assign(:editor_sheet_state, :open)
|> assign(:editor_active_tab, :settings)
|> maybe_enter_theme_mode()
_ ->
socket
end
end
else
socket
end
end
defp maybe_enter_theme_mode(socket) do
if socket.assigns.theme_editing do
socket
else
load_theme_state(socket)
end
end
defp maybe_enter_page_mode(socket) do
if socket.assigns.editing do
socket
else
if socket.assigns[:page] do
enter_edit_mode(socket)
else
socket
end
end
end
# ── handle_info ─────────────────────────────────────────────────
@@ -703,6 +772,7 @@ defmodule BerrypodWeb.PageEditorHook do
socket
|> assign(:editing, true)
|> assign(:editing_blocks, page.blocks)
|> assign(:editor_page_slug, page.slug)
|> assign(:editor_dirty, false)
|> assign(:editor_at_defaults, at_defaults)
|> assign(:editor_history, [])
@@ -725,6 +795,7 @@ defmodule BerrypodWeb.PageEditorHook do
socket
|> assign(:editing, false)
|> assign(:editing_blocks, nil)
|> assign(:editor_page_slug, nil)
|> assign(:editor_dirty, false)
|> assign(:editor_history, [])
|> assign(:editor_future, [])