add newsletter and email campaigns
Subscribers with double opt-in confirmation, campaign composer with draft/scheduled/sent lifecycle, admin dashboard with overview stats, CSV export, and shop signup form wired into page builder blocks. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -286,16 +286,18 @@ defmodule BerrypodWeb.ShopComponents.Content do
|
||||
|
||||
## Attributes
|
||||
|
||||
* `title` - Optional. Card heading. Defaults to "Stay in touch".
|
||||
* `title` - Optional. Card heading. Defaults to "Newsletter".
|
||||
* `description` - Optional. Card description.
|
||||
* `button_text` - Optional. Button text. Defaults to "Subscribe".
|
||||
* `variant` - Optional. Either `:card` (default, with border/background) or `:inline` (no card styling, for embedding in footer).
|
||||
* `newsletter_state` - Optional. `:idle | :submitted | :error | :disabled`. Defaults to `:idle`.
|
||||
* `newsletter_enabled` - Optional. Whether signups are active. Defaults to `true`.
|
||||
|
||||
## Examples
|
||||
|
||||
<.newsletter_card />
|
||||
<.newsletter_card title="Studio news" description="Get updates on new products." />
|
||||
<.newsletter_card variant={:inline} />
|
||||
<.newsletter_card variant={:inline} newsletter_state={@newsletter_state} />
|
||||
"""
|
||||
attr :title, :string, default: "Newsletter"
|
||||
|
||||
@@ -304,6 +306,30 @@ defmodule BerrypodWeb.ShopComponents.Content do
|
||||
|
||||
attr :button_text, :string, default: "Subscribe"
|
||||
attr :variant, :atom, default: :card
|
||||
attr :newsletter_state, :atom, default: :idle
|
||||
attr :newsletter_enabled, :boolean, default: true
|
||||
|
||||
def newsletter_card(%{newsletter_state: :submitted, variant: :inline} = assigns) do
|
||||
~H"""
|
||||
<div>
|
||||
<h3 class="newsletter-heading">{@title}</h3>
|
||||
<p class="card-text card-text--spaced">
|
||||
Check your inbox to confirm your subscription.
|
||||
</p>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
||||
def newsletter_card(%{newsletter_state: :submitted} = assigns) do
|
||||
~H"""
|
||||
<.shop_card class="card-section">
|
||||
<h3 class="card-heading">{@title}</h3>
|
||||
<p class="card-text card-text--spaced">
|
||||
Check your inbox to confirm your subscription.
|
||||
</p>
|
||||
</.shop_card>
|
||||
"""
|
||||
end
|
||||
|
||||
def newsletter_card(%{variant: :inline} = assigns) do
|
||||
~H"""
|
||||
@@ -314,10 +340,27 @@ defmodule BerrypodWeb.ShopComponents.Content do
|
||||
<p class="card-text card-text--spaced">
|
||||
{@description}
|
||||
</p>
|
||||
<form class="card-inline-form" onsubmit="return false">
|
||||
<.shop_input type="email" placeholder="your@email.com" class="email-input" />
|
||||
<.shop_button type="submit">{@button_text}</.shop_button>
|
||||
</form>
|
||||
<%= if @newsletter_enabled do %>
|
||||
<form
|
||||
action="/newsletter/subscribe"
|
||||
method="post"
|
||||
phx-submit="newsletter_subscribe"
|
||||
class="card-inline-form"
|
||||
>
|
||||
<input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
|
||||
<.shop_input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="your@email.com"
|
||||
class="email-input"
|
||||
required
|
||||
/>
|
||||
<.shop_button type="submit">{@button_text}</.shop_button>
|
||||
</form>
|
||||
<p :if={@newsletter_state == :error} class="card-text newsletter-error">
|
||||
Something went wrong. Please try again.
|
||||
</p>
|
||||
<% end %>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
@@ -329,10 +372,27 @@ defmodule BerrypodWeb.ShopComponents.Content do
|
||||
<p class="card-text card-text--spaced">
|
||||
{@description}
|
||||
</p>
|
||||
<form class="card-inline-form" onsubmit="return false">
|
||||
<.shop_input type="email" placeholder="your@email.com" class="email-input" />
|
||||
<.shop_button type="submit">{@button_text}</.shop_button>
|
||||
</form>
|
||||
<%= if @newsletter_enabled do %>
|
||||
<form
|
||||
action="/newsletter/subscribe"
|
||||
method="post"
|
||||
phx-submit="newsletter_subscribe"
|
||||
class="card-inline-form"
|
||||
>
|
||||
<input type="hidden" name="_csrf_token" value={Phoenix.Controller.get_csrf_token()} />
|
||||
<.shop_input
|
||||
type="email"
|
||||
name="email"
|
||||
placeholder="your@email.com"
|
||||
class="email-input"
|
||||
required
|
||||
/>
|
||||
<.shop_button type="submit">{@button_text}</.shop_button>
|
||||
</form>
|
||||
<p :if={@newsletter_state == :error} class="card-text newsletter-error">
|
||||
Something went wrong. Please try again.
|
||||
</p>
|
||||
<% end %>
|
||||
</.shop_card>
|
||||
"""
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user