Replace PreviewData indirection in all shop LiveViews with direct Products context queries. Home, collection, product detail and error pages now query the database. Categories loaded once in ThemeHook. Cart hydration no longer falls back to mock data. PreviewData kept only for the theme editor. Search modal gains keyboard navigation (arrow keys, Enter, Escape), Cmd+K/Ctrl+K shortcut, full ARIA combobox pattern, LiveView navigate links, and 150ms debounce. SearchModal JS hook manages selection state and highlight. search.ex gets transaction safety on reindex and a public remove_product/1. 10 new integration tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
64 lines
1.8 KiB
Elixir
64 lines
1.8 KiB
Elixir
defmodule SimpleshopThemeWeb.ThemeHook do
|
|
@moduledoc """
|
|
LiveView on_mount hook for theme settings, CSS, and media assigns.
|
|
|
|
Mounted in the public_shop live_session alongside CartHook.
|
|
Eliminates the identical theme-loading boilerplate from every shop LiveView.
|
|
|
|
## Actions
|
|
|
|
- `:mount_theme` — loads theme settings, CSS, and media assigns
|
|
- `:require_site_live` — redirects unauthenticated visitors to /coming-soon
|
|
when the shop is not live
|
|
"""
|
|
|
|
import Phoenix.Component, only: [assign: 3]
|
|
|
|
alias SimpleshopTheme.{Products, Settings, Media}
|
|
alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator}
|
|
|
|
def on_mount(:mount_theme, _params, _session, socket) do
|
|
theme_settings = Settings.get_theme_settings()
|
|
|
|
generated_css =
|
|
case CSSCache.get() do
|
|
{:ok, css} ->
|
|
css
|
|
|
|
:miss ->
|
|
css = CSSGenerator.generate(theme_settings)
|
|
CSSCache.put(css)
|
|
css
|
|
end
|
|
|
|
socket =
|
|
socket
|
|
|> assign(:theme_settings, theme_settings)
|
|
|> assign(:generated_css, generated_css)
|
|
|> assign(:logo_image, Media.get_logo())
|
|
|> assign(:header_image, Media.get_header())
|
|
|> assign(:categories, Products.list_categories())
|
|
|> assign(:mode, :shop)
|
|
|
|
{:cont, socket}
|
|
end
|
|
|
|
def on_mount(:require_site_live, _params, _session, socket) do
|
|
cond do
|
|
Settings.site_live?() ->
|
|
{:cont, socket}
|
|
|
|
# mount_current_scope runs first, so current_scope is already validated
|
|
socket.assigns[:current_scope] && socket.assigns.current_scope.user ->
|
|
{:cont, socket}
|
|
|
|
not SimpleshopTheme.Accounts.has_admin?() ->
|
|
# Fresh install — send to registration
|
|
{:halt, Phoenix.LiveView.redirect(socket, to: "/users/register")}
|
|
|
|
true ->
|
|
{:halt, Phoenix.LiveView.redirect(socket, to: "/coming-soon")}
|
|
end
|
|
end
|
|
end
|