From e6d4fce6564603226634217ccdf94396a4b0d01d Mon Sep 17 00:00:00 2001 From: jamey Date: Sun, 8 Feb 2026 11:59:33 +0000 Subject: [PATCH] refactor: extract ThemeHook to eliminate mount duplication on_mount hook assigns theme_settings, generated_css, logo_image, header_image, and mode for all public shop LiveViews. Removes ~70 lines of identical boilerplate and 18 unused aliases across 7 LiveViews. Co-Authored-By: Claude Opus 4.6 --- .../live/shop_live/cart.ex | 30 +-------------- .../live/shop_live/checkout_success.ex | 29 +------------- .../live/shop_live/collection.ex | 25 +----------- .../live/shop_live/contact.ex | 31 +-------------- .../live/shop_live/content.ex | 24 +----------- .../live/shop_live/home.ex | 25 +----------- .../live/shop_live/product_show.ex | 25 +----------- lib/simpleshop_theme_web/router.ex | 5 ++- lib/simpleshop_theme_web/theme_hook.ex | 38 +++++++++++++++++++ 9 files changed, 50 insertions(+), 182 deletions(-) create mode 100644 lib/simpleshop_theme_web/theme_hook.ex diff --git a/lib/simpleshop_theme_web/live/shop_live/cart.ex b/lib/simpleshop_theme_web/live/shop_live/cart.ex index 337e974..3585820 100644 --- a/lib/simpleshop_theme_web/live/shop_live/cart.ex +++ b/lib/simpleshop_theme_web/live/shop_live/cart.ex @@ -2,38 +2,10 @@ defmodule SimpleshopThemeWeb.ShopLive.Cart do use SimpleshopThemeWeb, :live_view alias SimpleshopTheme.Cart - alias SimpleshopTheme.Settings - alias SimpleshopTheme.Media - alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator} @impl true def mount(_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 - - logo_image = Media.get_logo() - header_image = Media.get_header() - - socket = - socket - |> assign(:page_title, "Cart") - |> assign(:theme_settings, theme_settings) - |> assign(:generated_css, generated_css) - |> assign(:logo_image, logo_image) - |> assign(:header_image, header_image) - |> assign(:mode, :shop) - - {:ok, socket} + {:ok, assign(socket, :page_title, "Cart")} end @impl true diff --git a/lib/simpleshop_theme_web/live/shop_live/checkout_success.ex b/lib/simpleshop_theme_web/live/shop_live/checkout_success.ex index 5dff297..8b18c44 100644 --- a/lib/simpleshop_theme_web/live/shop_live/checkout_success.ex +++ b/lib/simpleshop_theme_web/live/shop_live/checkout_success.ex @@ -1,27 +1,10 @@ defmodule SimpleshopThemeWeb.ShopLive.CheckoutSuccess do use SimpleshopThemeWeb, :live_view - alias SimpleshopTheme.{Orders, Settings, Media} - alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator} + alias SimpleshopTheme.Orders @impl true def mount(%{"session_id" => session_id}, _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 - - logo_image = Media.get_logo() - header_image = Media.get_header() - order = Orders.get_order_by_stripe_session(session_id) # Subscribe to order status updates (webhook may arrive after redirect) @@ -32,10 +15,7 @@ defmodule SimpleshopThemeWeb.ShopLive.CheckoutSuccess do # Clear the cart after successful checkout socket = if order && connected?(socket) do - empty_cart = [] - - socket - |> SimpleshopThemeWeb.CartHook.broadcast_and_update(empty_cart) + SimpleshopThemeWeb.CartHook.broadcast_and_update(socket, []) else socket end @@ -43,11 +23,6 @@ defmodule SimpleshopThemeWeb.ShopLive.CheckoutSuccess do socket = socket |> assign(:page_title, "Order confirmed") - |> assign(:theme_settings, theme_settings) - |> assign(:generated_css, generated_css) - |> assign(:logo_image, logo_image) - |> assign(:header_image, header_image) - |> assign(:mode, :shop) |> assign(:order, order) {:ok, socket} diff --git a/lib/simpleshop_theme_web/live/shop_live/collection.ex b/lib/simpleshop_theme_web/live/shop_live/collection.ex index 2372613..26567c0 100644 --- a/lib/simpleshop_theme_web/live/shop_live/collection.ex +++ b/lib/simpleshop_theme_web/live/shop_live/collection.ex @@ -1,9 +1,7 @@ defmodule SimpleshopThemeWeb.ShopLive.Collection do use SimpleshopThemeWeb, :live_view - alias SimpleshopTheme.Settings - alias SimpleshopTheme.Media - alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator, PreviewData} + alias SimpleshopTheme.Theme.PreviewData @sort_options [ {"featured", "Featured"}, @@ -16,29 +14,8 @@ defmodule SimpleshopThemeWeb.ShopLive.Collection do @impl true def mount(_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 - - logo_image = Media.get_logo() - header_image = Media.get_header() - socket = socket - |> assign(:theme_settings, theme_settings) - |> assign(:generated_css, generated_css) - |> assign(:logo_image, logo_image) - |> assign(:header_image, header_image) - |> assign(:mode, :shop) |> assign(:categories, PreviewData.categories()) |> assign(:sort_options, @sort_options) |> assign(:current_sort, "featured") diff --git a/lib/simpleshop_theme_web/live/shop_live/contact.ex b/lib/simpleshop_theme_web/live/shop_live/contact.ex index 07c9183..b150ce9 100644 --- a/lib/simpleshop_theme_web/live/shop_live/contact.ex +++ b/lib/simpleshop_theme_web/live/shop_live/contact.ex @@ -1,38 +1,9 @@ defmodule SimpleshopThemeWeb.ShopLive.Contact do use SimpleshopThemeWeb, :live_view - alias SimpleshopTheme.Settings - alias SimpleshopTheme.Media - alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator} - @impl true def mount(_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 - - logo_image = Media.get_logo() - header_image = Media.get_header() - - socket = - socket - |> assign(:page_title, "Contact") - |> assign(:theme_settings, theme_settings) - |> assign(:generated_css, generated_css) - |> assign(:logo_image, logo_image) - |> assign(:header_image, header_image) - |> assign(:mode, :shop) - - {:ok, socket} + {:ok, assign(socket, :page_title, "Contact")} end @impl true diff --git a/lib/simpleshop_theme_web/live/shop_live/content.ex b/lib/simpleshop_theme_web/live/shop_live/content.ex index 65e71ea..2e7b19a 100644 --- a/lib/simpleshop_theme_web/live/shop_live/content.ex +++ b/lib/simpleshop_theme_web/live/shop_live/content.ex @@ -1,32 +1,10 @@ defmodule SimpleshopThemeWeb.ShopLive.Content do use SimpleshopThemeWeb, :live_view - alias SimpleshopTheme.{Settings, Media} - alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator, PreviewData} + alias SimpleshopTheme.Theme.PreviewData @impl true def mount(_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(:mode, :shop) - {:ok, socket} end diff --git a/lib/simpleshop_theme_web/live/shop_live/home.ex b/lib/simpleshop_theme_web/live/shop_live/home.ex index 793eb58..972f6af 100644 --- a/lib/simpleshop_theme_web/live/shop_live/home.ex +++ b/lib/simpleshop_theme_web/live/shop_live/home.ex @@ -1,28 +1,10 @@ defmodule SimpleshopThemeWeb.ShopLive.Home do use SimpleshopThemeWeb, :live_view - alias SimpleshopTheme.Settings - alias SimpleshopTheme.Media - alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator, PreviewData} + alias SimpleshopTheme.Theme.PreviewData @impl true def mount(_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 - - logo_image = Media.get_logo() - header_image = Media.get_header() - preview_data = %{ products: PreviewData.products(), categories: PreviewData.categories() @@ -31,12 +13,7 @@ defmodule SimpleshopThemeWeb.ShopLive.Home do socket = socket |> assign(:page_title, "Home") - |> assign(:theme_settings, theme_settings) - |> assign(:generated_css, generated_css) - |> assign(:logo_image, logo_image) - |> assign(:header_image, header_image) |> assign(:preview_data, preview_data) - |> assign(:mode, :shop) {:ok, socket} end diff --git a/lib/simpleshop_theme_web/live/shop_live/product_show.ex b/lib/simpleshop_theme_web/live/shop_live/product_show.ex index 0962eb4..5c0f075 100644 --- a/lib/simpleshop_theme_web/live/shop_live/product_show.ex +++ b/lib/simpleshop_theme_web/live/shop_live/product_show.ex @@ -2,28 +2,10 @@ defmodule SimpleshopThemeWeb.ShopLive.ProductShow do use SimpleshopThemeWeb, :live_view alias SimpleshopTheme.Cart - alias SimpleshopTheme.Settings - alias SimpleshopTheme.Media - alias SimpleshopTheme.Theme.{CSSCache, CSSGenerator, PreviewData} + alias SimpleshopTheme.Theme.PreviewData @impl true def mount(%{"id" => id}, _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 - - logo_image = Media.get_logo() - header_image = Media.get_header() - products = PreviewData.products() # Find product by slug or ID (real products use slugs, mock data uses string IDs) @@ -53,15 +35,10 @@ defmodule SimpleshopThemeWeb.ShopLive.ProductShow do socket = socket |> assign(:page_title, product.name) - |> assign(:theme_settings, theme_settings) - |> assign(:generated_css, generated_css) - |> assign(:logo_image, logo_image) - |> assign(:header_image, header_image) |> assign(:product, product) |> assign(:gallery_images, gallery_images) |> assign(:related_products, related_products) |> assign(:quantity, 1) - |> assign(:mode, :shop) |> assign(:option_types, option_types) |> assign(:variants, variants) |> assign(:selected_options, selected_options) diff --git a/lib/simpleshop_theme_web/router.ex b/lib/simpleshop_theme_web/router.ex index 7640b2b..bb3d890 100644 --- a/lib/simpleshop_theme_web/router.ex +++ b/lib/simpleshop_theme_web/router.ex @@ -32,7 +32,10 @@ defmodule SimpleshopThemeWeb.Router do live_session :public_shop, layout: {SimpleshopThemeWeb.Layouts, :shop}, - on_mount: [{SimpleshopThemeWeb.CartHook, :mount_cart}] do + on_mount: [ + {SimpleshopThemeWeb.ThemeHook, :mount_theme}, + {SimpleshopThemeWeb.CartHook, :mount_cart} + ] do live "/", ShopLive.Home, :index live "/about", ShopLive.Content, :about live "/delivery", ShopLive.Content, :delivery diff --git a/lib/simpleshop_theme_web/theme_hook.ex b/lib/simpleshop_theme_web/theme_hook.ex new file mode 100644 index 0000000..2ac9d1b --- /dev/null +++ b/lib/simpleshop_theme_web/theme_hook.ex @@ -0,0 +1,38 @@ +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. + """ + + import Phoenix.Component, only: [assign: 3] + + alias SimpleshopTheme.{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(:mode, :shop) + + {:cont, socket} + end +end