fix privacy policy niggles and add last-updated date to legal pages
All checks were successful
deploy / deploy (push) Successful in 1m19s

- Capitalise lead sentence regardless of shop_name value
- Add stripe.com/privacy URL when mentioning Stripe in payment section
- Remove mention of logout from session cookie description
- Make third-party sharing text provider-agnostic (no longer names Printify etc.)
- Add :updated_at block to privacy, delivery, and terms pages showing when
  content last changed — auto-tracked via content hash, so the date advances
  automatically whenever relevant settings change

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey 2026-02-24 14:33:01 +00:00
parent 933f685b63
commit 781ebc8cd8
3 changed files with 71 additions and 9 deletions

View File

@ -2043,10 +2043,16 @@
.rich-text-lead { .rich-text-lead {
font-size: var(--t-text-large); font-size: var(--t-text-large);
margin-bottom: 1rem; margin-bottom: 0.5rem;
color: var(--t-text-primary); color: var(--t-text-primary);
} }
.rich-text-updated-at {
font-size: var(--t-text-small);
color: var(--t-text-secondary);
margin-bottom: 2rem;
}
.rich-text-paragraph { .rich-text-paragraph {
margin-bottom: 1rem; margin-bottom: 1rem;
color: var(--t-text-secondary); color: var(--t-text-secondary);

View File

@ -26,6 +26,12 @@ defmodule Berrypod.LegalPages do
newsletter). newsletter).
""" """
def privacy_content do def privacy_content do
blocks = privacy_blocks()
date = track_and_get_date("privacy", blocks)
insert_version(blocks, date)
end
defp privacy_blocks do
shop_name = Settings.get_setting("shop_name", "this shop") shop_name = Settings.get_setting("shop_name", "this shop")
contact_email = Settings.get_setting("contact_email") contact_email = Settings.get_setting("contact_email")
shop_country = Settings.get_setting("shop_country", "GB") shop_country = Settings.get_setting("shop_country", "GB")
@ -38,6 +44,7 @@ defmodule Berrypod.LegalPages do
type: :lead, type: :lead,
text: text:
"#{shop_name} takes your privacy seriously. This policy explains what personal data we collect and how we use it, #{jurisdiction(shop_country)}." "#{shop_name} takes your privacy seriously. This policy explains what personal data we collect and how we use it, #{jurisdiction(shop_country)}."
|> capitalise()
}, },
%{type: :heading, text: "What we collect"}, %{type: :heading, text: "What we collect"},
%{ %{
@ -49,7 +56,7 @@ defmodule Berrypod.LegalPages do
%{ %{
type: :paragraph, type: :paragraph,
text: text:
"Payment is processed by Stripe. We never see or store your card number or payment details — these go directly to Stripe and are subject to their privacy policy." "Payment is processed by Stripe (stripe.com/privacy). We never see or store your card number or payment details — these go directly to Stripe and are subject to their privacy policy."
}, },
%{type: :heading, text: "Analytics"}, %{type: :heading, text: "Analytics"},
%{ %{
@ -61,7 +68,7 @@ defmodule Berrypod.LegalPages do
%{ %{
type: :list, type: :list,
items: [ items: [
"_berrypod_session — keeps your shopping cart and login session active. Expires after 7 days or when you log out. Strictly necessary; no consent required.", "_berrypod_session — keeps your shopping cart and login session active. Stored for up to 7 days. Strictly necessary; no consent required.",
"country_code — remembers your shipping country preference. Stored for 1 year. Strictly necessary for showing correct shipping rates; no consent required." "country_code — remembers your shipping country preference. Stored for 1 year. Strictly necessary for showing correct shipping rates; no consent required."
] ]
}, },
@ -114,6 +121,12 @@ defmodule Berrypod.LegalPages do
Returns policy cites the correct UK legal exemptions for POD. Returns policy cites the correct UK legal exemptions for POD.
""" """
def delivery_content do def delivery_content do
blocks = delivery_blocks()
date = track_and_get_date("delivery", blocks)
insert_version(blocks, date)
end
defp delivery_blocks do
providers = connected_providers() providers = connected_providers()
countries = Shipping.list_available_countries_with_names() countries = Shipping.list_available_countries_with_names()
contact_email = Settings.get_setting("contact_email") contact_email = Settings.get_setting("contact_email")
@ -154,6 +167,12 @@ defmodule Berrypod.LegalPages do
when the vat_enabled setting is true. when the vat_enabled setting is true.
""" """
def terms_content do def terms_content do
blocks = terms_blocks()
date = track_and_get_date("terms", blocks)
insert_version(blocks, date)
end
defp terms_blocks do
shop_name = Settings.get_setting("shop_name", "this shop") shop_name = Settings.get_setting("shop_name", "this shop")
shop_country = Settings.get_setting("shop_country", "GB") shop_country = Settings.get_setting("shop_country", "GB")
vat_enabled = Settings.get_setting("vat_enabled", false) vat_enabled = Settings.get_setting("vat_enabled", false)
@ -363,14 +382,12 @@ defmodule Berrypod.LegalPages do
"To fulfil your order, we share your name and shipping address with our print-on-demand provider. Payment details are handled by Stripe. Both process data in accordance with their own privacy policies." "To fulfil your order, we share your name and shipping address with our print-on-demand provider. Payment details are handled by Stripe. Both process data in accordance with their own privacy policies."
end end
defp provider_sharing_text([name]) do defp provider_sharing_text([_]) do
"To fulfil your order, we share your name and shipping address with #{name}. Payment details are handled by Stripe. Both process data in accordance with their own privacy policies." "To fulfil your order, we share your name and shipping address with our print-on-demand provider. Payment details are handled by Stripe. Both process data in accordance with their own privacy policies."
end end
defp provider_sharing_text(names) do defp provider_sharing_text(_names) do
joined = Enum.join(names, " and ") "To fulfil your order, we share your name and shipping address with our print-on-demand providers. Payment details are handled by Stripe. All process data in accordance with their own privacy policies."
"To fulfil your order, we share your name and shipping address with #{joined}. Payment details are handled by Stripe. All process data in accordance with their own privacy policies."
end end
defp contact_text(nil), defp contact_text(nil),
@ -394,4 +411,35 @@ defmodule Berrypod.LegalPages do
defp legal_disclaimer do defp legal_disclaimer do
"This page was generated from this shop's configuration. It's a good starting point — review it and take independent legal advice if you're unsure about anything." "This page was generated from this shop's configuration. It's a good starting point — review it and take independent legal advice if you're unsure about anything."
end end
# Inserts an :updated_at block immediately after the first :lead block.
defp insert_version([%{type: :lead} = lead | rest], date) do
[lead, %{type: :updated_at, date: date} | rest]
end
defp insert_version(blocks, _date), do: blocks
# Stores a hash of the content blocks in settings. When the hash changes
# (i.e. relevant settings changed), records today as the new updated date.
defp track_and_get_date(page_key, blocks) do
hash = :erlang.phash2(blocks) |> Integer.to_string()
hash_key = "#{page_key}_policy_hash"
date_key = "#{page_key}_policy_updated_at"
if hash != Settings.get_setting(hash_key) do
today = format_date(Date.utc_today())
Settings.put_setting(hash_key, hash)
Settings.put_setting(date_key, today)
today
else
Settings.get_setting(date_key, format_date(Date.utc_today()))
end
end
defp format_date(%Date{} = date) do
"#{date.day} #{Calendar.strftime(date, "%B")} #{date.year}"
end
defp capitalise(<<first::utf8, rest::binary>>), do: String.upcase(<<first::utf8>>) <> rest
defp capitalise(""), do: ""
end end

View File

@ -926,6 +926,14 @@ defmodule BerrypodWeb.ShopComponents.Content do
""" """
end end
defp rich_text_block(%{block: %{type: :updated_at}} = assigns) do
~H"""
<p class="rich-text-updated-at">
Last updated: {@block.date}
</p>
"""
end
defp rich_text_block(%{block: %{type: :paragraph}} = assigns) do defp rich_text_block(%{block: %{type: :paragraph}} = assigns) do
~H""" ~H"""
<p class="rich-text-paragraph"> <p class="rich-text-paragraph">