Home, Content (about/delivery/privacy/terms), Contact, and ErrorHTML now render through the generic PageRenderer instead of hardcoded templates. Block wrapper divs enable CSS grid targeting. Featured products block supports layout/card_variant/columns settings for different page contexts. Contact page uses CSS grid on data-block-type attributes for two-column layout. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
218 lines
6.1 KiB
Elixir
218 lines
6.1 KiB
Elixir
defmodule Berrypod.Pages.Defaults do
|
|
@moduledoc """
|
|
Default block definitions for all pages.
|
|
|
|
These match the current static templates exactly. When a page has never
|
|
been customised, `Pages.get_page/1` returns these defaults. First edit
|
|
saves to the DB and overrides them.
|
|
"""
|
|
|
|
@doc "Returns the default page definition for the given slug."
|
|
def for_slug(slug), do: %{slug: slug, title: title(slug), blocks: blocks(slug)}
|
|
|
|
@doc "Returns default definitions for all pages."
|
|
def all do
|
|
Berrypod.Pages.Page.valid_slugs()
|
|
|> Enum.map(&for_slug/1)
|
|
end
|
|
|
|
# ── Page titles ─────────────────────────────────────────────────
|
|
|
|
defp title("home"), do: "Home page"
|
|
defp title("about"), do: "About"
|
|
defp title("delivery"), do: "Delivery"
|
|
defp title("privacy"), do: "Privacy policy"
|
|
defp title("terms"), do: "Terms & conditions"
|
|
defp title("contact"), do: "Contact"
|
|
defp title("collection"), do: "Collection"
|
|
defp title("pdp"), do: "Product page"
|
|
defp title("cart"), do: "Cart"
|
|
defp title("search"), do: "Search"
|
|
defp title("checkout_success"), do: "Checkout success"
|
|
defp title("orders"), do: "Orders"
|
|
defp title("order_detail"), do: "Order detail"
|
|
defp title("error"), do: "Error"
|
|
|
|
# ── Block lists ─────────────────────────────────────────────────
|
|
|
|
defp blocks("home") do
|
|
[
|
|
block("hero", %{
|
|
"title" => "Original designs, printed on demand",
|
|
"description" =>
|
|
"Welcome to the Berrypod demo store. This is where your hero text goes \u2013 something short and punchy about what makes your shop worth a browse.",
|
|
"cta_text" => "Shop the collection",
|
|
"cta_href" => "/collections/all",
|
|
"variant" => "default"
|
|
}),
|
|
block("category_nav"),
|
|
block("featured_products", %{
|
|
"title" => "Featured products",
|
|
"product_count" => 8
|
|
}),
|
|
block("image_text", %{
|
|
"title" => "Made with passion, printed with care",
|
|
"description" =>
|
|
"This is an example content section. Use it to share your story, highlight what makes your products special, or link to your about page.",
|
|
"image_url" => "/mockups/mountain-sunrise-print-3-800.webp",
|
|
"link_text" => "Learn more about the studio \u2192",
|
|
"link_href" => "/about"
|
|
})
|
|
]
|
|
end
|
|
|
|
defp blocks("about") do
|
|
[
|
|
block("hero", %{
|
|
"title" => "About the studio",
|
|
"description" => "Your story goes here \u2013 this is sample content for the demo shop",
|
|
"variant" => "sunken"
|
|
}),
|
|
block("content_body", %{
|
|
"image_src" => "/mockups/night-sky-blanket-3",
|
|
"image_alt" => "Night sky blanket draped over a chair"
|
|
})
|
|
]
|
|
end
|
|
|
|
defp blocks("delivery") do
|
|
[
|
|
block("hero", %{
|
|
"title" => "Delivery & returns",
|
|
"description" => "Everything you need to know about shipping and returns",
|
|
"variant" => "page"
|
|
}),
|
|
block("content_body")
|
|
]
|
|
end
|
|
|
|
defp blocks("privacy") do
|
|
[
|
|
block("hero", %{
|
|
"title" => "Privacy policy",
|
|
"description" => "How we handle your personal information",
|
|
"variant" => "page"
|
|
}),
|
|
block("content_body")
|
|
]
|
|
end
|
|
|
|
defp blocks("terms") do
|
|
[
|
|
block("hero", %{
|
|
"title" => "Terms of service",
|
|
"description" => "The legal bits",
|
|
"variant" => "page"
|
|
}),
|
|
block("content_body")
|
|
]
|
|
end
|
|
|
|
defp blocks("contact") do
|
|
[
|
|
block("hero", %{
|
|
"title" => "Get in touch",
|
|
"description" =>
|
|
"Sample contact page for the demo store. Add your own message here \u2013 something friendly about how customers can reach you.",
|
|
"variant" => "page"
|
|
}),
|
|
block("contact_form", %{"email" => "hello@example.com"}),
|
|
block("order_tracking_card"),
|
|
block("info_card", %{
|
|
"title" => "Handy to know",
|
|
"items" => [
|
|
%{"label" => "Printing", "value" => "Example: 2-5 business days"},
|
|
%{"label" => "Delivery", "value" => "Example: 3-7 business days after printing"},
|
|
%{"label" => "Issues", "value" => "Example: Reprints for any defects"}
|
|
]
|
|
}),
|
|
block("newsletter_card"),
|
|
block("social_links_card")
|
|
]
|
|
end
|
|
|
|
defp blocks("collection") do
|
|
[
|
|
block("collection_header"),
|
|
block("filter_bar"),
|
|
block("product_grid")
|
|
]
|
|
end
|
|
|
|
defp blocks("pdp") do
|
|
[
|
|
block("breadcrumb"),
|
|
block("product_hero"),
|
|
block("trust_badges"),
|
|
block("product_details"),
|
|
block("reviews_section"),
|
|
block("related_products")
|
|
]
|
|
end
|
|
|
|
defp blocks("cart") do
|
|
[
|
|
block("cart_items"),
|
|
block("order_summary")
|
|
]
|
|
end
|
|
|
|
defp blocks("search") do
|
|
[
|
|
block("search_results")
|
|
]
|
|
end
|
|
|
|
defp blocks("checkout_success") do
|
|
[
|
|
block("checkout_result")
|
|
]
|
|
end
|
|
|
|
defp blocks("orders") do
|
|
[
|
|
block("order_card")
|
|
]
|
|
end
|
|
|
|
defp blocks("order_detail") do
|
|
[
|
|
block("order_detail_card")
|
|
]
|
|
end
|
|
|
|
defp blocks("error") do
|
|
[
|
|
block("hero", %{
|
|
"variant" => "error",
|
|
"cta_text" => "Go to Homepage",
|
|
"cta_href" => "/",
|
|
"secondary_cta_text" => "Browse Products",
|
|
"secondary_cta_href" => "/collections/all"
|
|
}),
|
|
block("featured_products", %{
|
|
"title" => "Featured products",
|
|
"product_count" => 4,
|
|
"layout" => "grid",
|
|
"card_variant" => "minimal",
|
|
"columns" => "fixed-4"
|
|
})
|
|
]
|
|
end
|
|
|
|
# ── Helpers ─────────────────────────────────────────────────────
|
|
|
|
defp block(type, settings \\ %{}) do
|
|
%{
|
|
"id" => generate_block_id(),
|
|
"type" => type,
|
|
"settings" => settings
|
|
}
|
|
end
|
|
|
|
@doc "Generates a unique block ID."
|
|
def generate_block_id do
|
|
"blk_" <> (:crypto.strong_rand_bytes(8) |> Base.url_encode64(padding: false))
|
|
end
|
|
end
|