feat: add cart page, cart drawer, and shared cart infrastructure
- Cart context with pure functions for add/remove/update/hydrate - Price formatting via ex_money (replaces all float division) - CartHook on_mount with attach_hook for shared event handlers (open/close drawer, remove item, PubSub sync) - Accessible cart drawer with focus trap, scroll lock, aria-live - Cart page with increment/decrement quantity controls - Preview mode cart drawer support in theme editor - Cart persistence to session via JS hook + API endpoint - 19 tests covering all Cart pure functions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
|> assign(:header_image, header_image)
|
||||
|> assign(:customise_open, false)
|
||||
|> assign(:sidebar_collapsed, false)
|
||||
|> assign(:cart_drawer_open, false)
|
||||
|> allow_upload(:logo_upload,
|
||||
accept: ~w(.png .jpg .jpeg .webp .svg),
|
||||
max_entries: 1,
|
||||
@@ -287,6 +288,16 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
{:noreply, assign(socket, :sidebar_collapsed, !socket.assigns.sidebar_collapsed)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("open_cart_drawer", _params, socket) do
|
||||
{:noreply, assign(socket, :cart_drawer_open, true)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("close_cart_drawer", _params, socket) do
|
||||
{:noreply, assign(socket, :cart_drawer_open, false)}
|
||||
end
|
||||
|
||||
@impl true
|
||||
def handle_event("noop", _params, socket) do
|
||||
{:noreply, socket}
|
||||
@@ -303,6 +314,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
attr :theme_settings, :map, required: true
|
||||
attr :logo_image, :any, required: true
|
||||
attr :header_image, :any, required: true
|
||||
attr :cart_drawer_open, :boolean, default: false
|
||||
|
||||
defp preview_page(%{page: :home} = assigns) do
|
||||
~H"""
|
||||
@@ -315,6 +327,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
cart_items={PreviewData.cart_drawer_items()}
|
||||
cart_count={2}
|
||||
cart_subtotal="£72.00"
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
/>
|
||||
"""
|
||||
end
|
||||
@@ -330,6 +343,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
cart_items={PreviewData.cart_drawer_items()}
|
||||
cart_count={2}
|
||||
cart_subtotal="£72.00"
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
/>
|
||||
"""
|
||||
end
|
||||
@@ -379,6 +393,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
cart_items={PreviewData.cart_drawer_items()}
|
||||
cart_count={2}
|
||||
cart_subtotal="£72.00"
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
option_types={@option_types}
|
||||
selected_options={@selected_options}
|
||||
available_options={@available_options}
|
||||
@@ -409,6 +424,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
cart_items={PreviewData.cart_drawer_items()}
|
||||
cart_count={2}
|
||||
cart_subtotal="£72.00"
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
/>
|
||||
"""
|
||||
end
|
||||
@@ -423,6 +439,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
cart_items={PreviewData.cart_drawer_items()}
|
||||
cart_count={2}
|
||||
cart_subtotal="£72.00"
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
/>
|
||||
"""
|
||||
end
|
||||
@@ -437,6 +454,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
cart_items={PreviewData.cart_drawer_items()}
|
||||
cart_count={2}
|
||||
cart_subtotal="£72.00"
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
/>
|
||||
"""
|
||||
end
|
||||
@@ -455,6 +473,7 @@ defmodule SimpleshopThemeWeb.ThemeLive.Index do
|
||||
cart_items={PreviewData.cart_drawer_items()}
|
||||
cart_count={2}
|
||||
cart_subtotal="£72.00"
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
/>
|
||||
"""
|
||||
end
|
||||
|
||||
@@ -1164,6 +1164,7 @@
|
||||
theme_settings={@theme_settings}
|
||||
logo_image={@logo_image}
|
||||
header_image={@header_image}
|
||||
cart_drawer_open={@cart_drawer_open}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user