improve cart recovery: product links in email, persistent session cookie
All checks were successful
deploy / deploy (push) Successful in 3m32s

- add product_id to order_items (migration + schema + create_order)
- cart recovery email now includes a direct product link per item
- extend session cookie max_age to 7 days so carts survive browser restarts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-24 13:12:41 +00:00
parent 2f4cd81f98
commit 61887b9d5b
7 changed files with 69 additions and 14 deletions

View File

@@ -98,6 +98,7 @@ defmodule Berrypod.Orders do
%{
order_id: order.id,
variant_id: item.variant_id,
product_id: item[:product_id],
product_name: item.name,
variant_title: item.variant,
quantity: item.quantity,

View File

@@ -7,6 +7,7 @@ defmodule Berrypod.Orders.OrderItem do
schema "order_items" do
field :variant_id, :string
field :product_id, :string
field :product_name, :string
field :variant_title, :string
field :quantity, :integer
@@ -19,7 +20,15 @@ defmodule Berrypod.Orders.OrderItem do
def changeset(item, attrs) do
item
|> cast(attrs, [:variant_id, :product_name, :variant_title, :quantity, :unit_price, :order_id])
|> cast(attrs, [
:variant_id,
:product_id,
:product_name,
:variant_title,
:quantity,
:unit_price,
:order_id
])
|> validate_required([:variant_id, :product_name, :quantity, :unit_price])
|> validate_number(:quantity, greater_than: 0)
|> validate_number(:unit_price, greater_than_or_equal_to: 0)

View File

@@ -100,6 +100,7 @@ defmodule Berrypod.Orders.OrderNotifier do
def deliver_cart_recovery(cart, order, unsubscribe_url) do
from_address = Berrypod.Settings.get_setting("email_from_address", "contact@example.com")
subject = "You left something behind"
base_url = BerrypodWeb.Endpoint.url()
body = """
==============================
@@ -107,11 +108,9 @@ defmodule Berrypod.Orders.OrderNotifier do
You recently started a checkout but didn't complete it.
Your cart had:
#{format_items(order.items)}
#{format_cart_items(order.items, base_url)}
Total: #{Cart.format_price(cart.cart_total)}
If you'd like to complete your order, head to our shop and add these items again.
We're only sending this once.
Don't want to hear from us? Unsubscribe: #{unsubscribe_url}
@@ -169,6 +168,22 @@ defmodule Berrypod.Orders.OrderNotifier do
defp format_items(_), do: ""
defp format_cart_items(items, base_url) when is_list(items) do
items
|> Enum.map_join("\n", fn item ->
price = Cart.format_price(item.unit_price * item.quantity)
line = " #{item.quantity}x #{item.product_name} (#{item.variant_title}) - #{price}"
if item.product_id do
line <> "\n #{base_url}/products/#{item.product_id}"
else
line
end
end)
end
defp format_cart_items(_, _), do: ""
defp format_shipping_address(address) when is_map(address) and map_size(address) > 0 do
lines =
[

View File

@@ -8,7 +8,8 @@ defmodule BerrypodWeb.Endpoint do
store: :cookie,
key: "_berrypod_key",
signing_salt: "JNwRcD7y",
same_site: "Lax"
same_site: "Lax",
max_age: 604_800
]
socket "/live", Phoenix.LiveView.Socket,