Packages
phoenix_kit
1.7.65
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/modules/emails/web/settings.html.heex
<PhoenixKitWeb.Components.LayoutWrapper.app_layout
flash={@flash}
phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]}
page_title="{@project_title} Emails"
current_path={@current_path}
project_title={@project_title}
>
<div class="container flex flex-col mx-auto px-4 py-6">
<.admin_page_header
back={PhoenixKit.Utils.Routes.path("/admin/settings")}
title="Emails Settings"
subtitle="Configure emails behavior and data retention"
/>
<%!-- Main Content --%>
<div class="max-w-4xl mx-auto space-y-8">
<%!-- Status Card --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">
<.icon name="hero-cog-6-tooth" class="w-6 h-6" /> Status
</h2>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text text-lg">
<span class="font-semibold">Enable Emails</span>
<div class="text-sm text-base-content/70 mt-1">
Track email delivery, opens, clicks, and other events
</div>
</span>
<input
type="checkbox"
class="toggle toggle-primary"
checked={@email_enabled}
phx-click="toggle_emails"
/>
</label>
</div>
</div>
</div>
<%= if @email_enabled do %>
<%!-- Sender Configuration Card --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">
<.icon name="hero-envelope" class="w-6 h-6" /> Sender Configuration
</h2>
<form phx-submit="save_sender_settings">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<%!-- From Email --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">From Email</span>
</label>
<input
name="sender[from_email]"
type="email"
placeholder="noreply@example.com"
value={@sender_settings.from_email}
class="input input-bordered focus:input-primary"
required
/>
<label class="label">
<span class="label-text-alt">
Email address used as sender for all outgoing emails
</span>
</label>
</div>
<%!-- From Name --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">From Name</span>
</label>
<input
name="sender[from_name]"
type="text"
placeholder="My Application"
value={@sender_settings.from_name}
class="input input-bordered focus:input-primary"
required
/>
<label class="label">
<span class="label-text-alt">Sender name displayed to recipients</span>
</label>
</div>
</div>
<%!-- Save Button --%>
<div class="card-actions justify-end">
<button
type="submit"
class={[
"btn btn-primary",
if(@saving_sender, do: "loading", else: "")
]}
disabled={@saving_sender}
>
<%= if @saving_sender do %>
Saving...
<% else %>
<.icon name="hero-check" class="w-4 h-4 mr-2" /> Save Sender Settings
<% end %>
</button>
</div>
</form>
</div>
</div>
<%!-- Options Card --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">
<.icon name="hero-adjustments-horizontal" class="w-6 h-6" /> Options
</h2>
<%!-- Save Email Bodies --%>
<div class="form-control mb-4">
<label class="label cursor-pointer">
<span class="label-text text-lg">
<span class="font-semibold">Save Email Bodies</span>
<div class="text-sm text-base-content/70 mt-1">
Store the full content of sent emails for debugging and analysis
</div>
</span>
<input
type="checkbox"
class="toggle toggle-secondary"
checked={@email_save_body}
phx-click="toggle_email_save_body"
/>
</label>
</div>
<div class="divider"></div>
<%!-- Save Email Headers --%>
<div class="form-control mb-4">
<label class="label cursor-pointer">
<span class="label-text text-lg">
<span class="font-semibold">Save Email Headers</span>
<div class="text-sm text-base-content/70 mt-1">
Store email headers for debugging and analysis (increases storage usage)
</div>
</span>
<input
type="checkbox"
class="toggle toggle-secondary"
checked={@email_save_headers}
phx-click="toggle_email_save_headers"
/>
</label>
</div>
<div class="divider"></div>
<%!-- AWS SES Events --%>
<div class="form-control mb-4">
<label class="label cursor-pointer">
<span class="label-text text-lg">
<span class="font-semibold">AWS SES Events Options</span>
<div class="text-sm text-base-content/70 mt-1">
Track delivery, bounce, and complaint events from Amazon SES
</div>
</span>
<input
type="checkbox"
class="toggle toggle-accent"
checked={@email_ses_events}
phx-click="toggle_email_ses_events"
/>
</label>
</div>
<div class="divider"></div>
<%!-- Sampling Rate --%>
<div class="form-control">
<label class="label">
<span class="label-text text-lg font-semibold">Emails Sampling Rate</span>
</label>
<div class="input-group">
<input
name="sampling_rate"
type="number"
placeholder="Enter sampling rate"
class="input input-bordered w-full max-w-xs"
value={@email_sampling_rate}
min="0"
max="100"
phx-blur="update_email_sampling_rate"
/>
<span class="bg-base-200 px-4 py-3 text-sm">%</span>
</div>
<label class="label">
<span class="label-text-alt text-base-content/70">
Percentage of emails to fully track for analytics (0-100%)
</span>
</label>
</div>
</div>
</div>
<%!-- Data Retention Card --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">
<.icon name="hero-archive-box" class="w-6 h-6" /> Data Retention
</h2>
<div class="form-control">
<label class="label">
<span class="label-text text-lg font-semibold">Email Retention Period</span>
</label>
<div class="flex gap-2 items-start">
<div class="input-group flex-1">
<input
name="retention_days"
type="number"
placeholder="Enter retention days"
class="input input-bordered w-full max-w-xs"
value={@email_retention_days}
min="1"
max="365"
phx-blur="update_email_retention"
/>
<span class="bg-base-200 px-4 py-3 text-sm">days</span>
</div>
<button
type="button"
phx-click="run_cleanup_now"
class={[
"btn btn-warning btn-sm",
if(assigns[:running_cleanup], do: "loading", else: "")
]}
disabled={assigns[:running_cleanup]}
>
<%= if assigns[:running_cleanup] do %>
Running...
<% else %>
<.icon name="hero-trash" class="w-4 h-4 mr-1" /> Run Cleanup Now
<% end %>
</button>
</div>
<label class="label">
<span class="label-text-alt text-base-content/70">
How long to keep emails data before automatic cleanup (1-365 days)
</span>
</label>
</div>
<div class="divider"></div>
<%= if @email_save_body do %>
<%!-- Compress Body After Days --%>
<div class="form-control">
<label class="label">
<span class="label-text text-lg font-semibold">
Compress Email Bodies After
</span>
<span class="label-text-alt text-base-content/70">
Auto-saves when you click outside the input field
</span>
</label>
<div class="flex gap-2 items-start">
<div class="input-group flex-1">
<input
name="compress_days"
type="number"
placeholder="Enter compression days"
class={[
"input input-bordered w-full max-w-xs",
"transition-colors duration-200",
"focus:input-primary",
if(assigns[:updating_compress_days],
do: "input-warning loading",
else: ""
)
]}
value={@email_compress_body}
min="7"
max="365"
phx-blur="update_compress_days"
phx-focus="set_compress_days_focused"
phx-keydown="set_compress_days_changed"
/>
<span class="bg-base-200 px-4 py-3 text-sm">days</span>
</div>
<button
type="button"
phx-click="run_compression_now"
class={[
"btn btn-info btn-sm",
if(assigns[:running_compression], do: "loading", else: "")
]}
disabled={assigns[:running_compression]}
>
<%= if assigns[:running_compression] do %>
Compressing...
<% else %>
<.icon name="hero-archive-box-arrow-down" class="w-4 h-4 mr-1" />
Compress Now
<% end %>
</button>
</div>
<label class="label">
<span class="label-text-alt text-base-content/70">
<span class="flex items-center gap-1">
<.icon name="hero-information-circle" class="w-3 h-3" />
Compress old email bodies to save storage space (7-365 days).
Changes are saved automatically.
</span>
</span>
</label>
</div>
<div class="divider"></div>
<% end %>
<%!-- S3 Archival Toggle --%>
<div class="form-control mb-4">
<label class="label cursor-pointer">
<span class="label-text text-lg">
<span class="font-semibold">Enable S3 Archival</span>
<div class="text-sm text-base-content/70 mt-1">
Move old email data to AWS S3 for long-term cold storage
</div>
</span>
<input
type="checkbox"
class="toggle toggle-warning"
checked={@email_archive_to_s3}
phx-click="toggle_s3_archival"
/>
</label>
</div>
<%= if @email_archive_to_s3 do %>
<%!-- S3 Archival Action Button --%>
<div class="form-control mt-2">
<div class="flex gap-2 items-start">
<div class="flex-1">
<span class="text-sm text-base-content/70">
Manually trigger S3 archival for emails older than retention period
</span>
</div>
<button
type="button"
phx-click="run_s3_archival_now"
class={[
"btn btn-warning btn-sm",
if(assigns[:running_archival], do: "loading", else: "")
]}
disabled={assigns[:running_archival]}
>
<%= if assigns[:running_archival] do %>
Archiving...
<% else %>
<.icon name="hero-cloud-arrow-up" class="w-4 h-4 mr-1" /> Archive to S3 Now
<% end %>
</button>
</div>
</div>
<% end %>
<div class="alert alert-warning mt-4">
<.icon name="hero-exclamation-triangle" class="w-5 h-5" />
<div>
<h3 class="font-bold">Data Privacy Notice</h3>
<p class="text-sm mt-1">
Email data will be automatically deleted after the retention period expires.
This helps maintain privacy compliance and reduces storage requirements.
</p>
</div>
</div>
</div>
</div>
<%!-- AWS Configuration Card --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">
<.icon name="hero-cog-6-tooth" class="w-6 h-6" /> AWS Configuration
</h2>
<%!-- AWS Setup Guide (daisyUI collapse) --%>
<div class="collapse collapse-arrow bg-base-200 mb-6">
<input type="checkbox" class="peer" />
<div class="collapse-title text-sm font-medium">
<span class="flex items-center gap-2">
<.icon name="hero-book-open" class="w-5 h-5" /> AWS Setup Guide
</span>
</div>
<div class="collapse-content text-sm space-y-4">
<%!-- Step 1: Create IAM User --%>
<div class="bg-base-100 border border-base-300 rounded-lg p-4">
<h4 class="font-semibold mb-2 text-base-content">1. Create IAM User</h4>
<ol class="list-decimal list-inside space-y-2 text-base-content/80">
<li>
Visit
<a
href="https://console.aws.amazon.com/iam/"
target="_blank"
class="link link-primary"
>
AWS IAM Console
</a>
</li>
<li>Create new user with programmatic access</li>
<li>
Attach policies: <strong>SES</strong>, <strong>SQS</strong>, <strong>SNS</strong>,
<strong>STS:GetCallerIdentity</strong>
</li>
<li>Save Access Key ID and Secret Access Key</li>
</ol>
</div>
<%!-- Step 2: Configure Credentials --%>
<div class="bg-base-100 border border-base-300 rounded-lg p-4">
<h4 class="font-semibold mb-2 text-base-content">2. Configure Credentials</h4>
<ol class="list-decimal list-inside space-y-2 text-base-content/80">
<li>
Enter Access Key ID (20 characters, e.g., <code>AKIAIOSFODNN7EXAMPLE</code>)
</li>
<li>Enter Secret Access Key</li>
<li>Enter AWS Region manually (e.g., eu-north-1)</li>
<li>Click <strong>"Verify Credentials"</strong> to test connectivity</li>
<li>
<em>Optional:</em>
Click <strong>"Load regions"</strong>
to see all available regions
</li>
</ol>
</div>
<%!-- Step 3: Setup Infrastructure --%>
<div class="bg-base-100 border border-base-300 rounded-lg p-4">
<h4 class="font-semibold mb-2 text-base-content">
3. Setup Infrastructure
</h4>
<ol class="list-decimal list-inside space-y-2 text-base-content/80">
<li>
Click <strong>"Setup AWS Infrastructure"</strong>
to create SNS/SQS resources
</li>
<li>Wait for setup completion (typically 30-60 seconds)</li>
<li>
All created resources will be automatically filled in the form below
</li>
<li>
Click <strong>"Save AWS Settings"</strong>
one more time to persist everything
</li>
</ol>
</div>
<%!-- Step 4: Verify Email --%>
<div class="bg-base-100 border border-base-300 rounded-lg p-4">
<h4 class="font-semibold mb-2 text-base-content">
4. Verify Email/Domain in SES
</h4>
<ol class="list-decimal list-inside space-y-2 text-base-content/80">
<li>
Go to
<a
href="https://console.aws.amazon.com/ses/"
target="_blank"
class="link link-primary"
>
AWS SES Console
</a>
</li>
<li>Verify your sender email address or domain</li>
<li>Request production access (if needed to exit sandbox mode)</li>
</ol>
</div>
<%!-- Required Permissions --%>
<div class="bg-base-200 border border-base-300 rounded-lg p-3 text-xs">
<div class="flex items-start gap-2">
<.icon
name="hero-information-circle"
class="h-4 w-4 text-info shrink-0 mt-0.5"
/>
<div class="text-base-content/80">
<strong class="text-base-content">Required IAM Permissions:</strong>
<ul class="list-disc list-inside mt-1 space-y-1">
<li><code>sqs:*</code> - Simple Queue Service</li>
<li><code>sns:*</code> - Simple Notification Service</li>
<li><code>ses:*</code> - Simple Email Service</li>
<li><code>sts:GetCallerIdentity</code> - Credential verification</li>
</ul>
</div>
</div>
</div>
<%!-- Full Documentation Link --%>
<div class="bg-base-200 border border-base-300 rounded-lg p-3 text-xs">
<div class="flex items-start gap-2">
<.icon
name="hero-book-open"
class="h-4 w-4 text-success shrink-0 mt-0.5"
/>
<div class="text-base-content/80">
<strong class="text-base-content">Need more help?</strong>
<p class="mt-1">
See <code>guides/aws_email_setup.md</code>
for comprehensive documentation including security best practices, cost optimization, and troubleshooting.
</p>
</div>
</div>
</div>
</div>
</div>
<%!-- Credentials Verification Section --%>
<.aws_credentials_verify
access_key_id={@aws_settings.access_key_id}
secret_access_key={@aws_settings.secret_access_key}
region={@aws_settings.region}
verifying={@verifying_credentials}
verified={@credential_verification_status}
message={@credential_verification_message}
permissions={@aws_permissions}
phx_click="verify_aws_credentials"
disabled={@saving or @setting_up_aws}
/>
<form phx-submit="save_aws_settings">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<%!-- AWS Access Key ID --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">AWS Access Key ID</span>
</label>
<input
name="aws_settings[access_key_id]"
type="text"
placeholder="AKIAIOSFODNN7EXAMPLE"
value={@aws_settings.access_key_id}
class="input input-bordered focus:input-primary"
/>
<label class="label">
<span class="label-text-alt text-sm text-base-content/70">
Example: AKIAIOSFODNN7EXAMPLE (20 characters)
</span>
</label>
</div>
<%!-- AWS Secret Access Key --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">AWS Secret Access Key</span>
</label>
<input
name="aws_settings[secret_access_key]"
type="password"
placeholder="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
value={@aws_settings.secret_access_key}
class="input input-bordered focus:input-primary"
/>
<label class="label">
<span class="label-text-alt text-sm text-base-content/70">
Example: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
</span>
</label>
</div>
<%!-- AWS Region --%>
<div class="form-control md:col-span-2">
<div class="flex gap-2">
<.aws_region_select
id="aws-region-select"
name="aws_settings[region]"
value={@aws_settings.region}
regions={@available_regions}
regions_loaded={@regions_loaded}
selected_region={@selected_region}
verifying={@verifying_credentials}
verified={@credential_verification_status}
phx_change="select_region"
class="flex-1"
/>
<%!-- Button to load/refresh regions --%>
<button
type="button"
phx-click="fetch_available_regions"
disabled={
@verifying_credentials or String.trim(@aws_settings.access_key_id) == "" or
String.trim(@aws_settings.secret_access_key) == ""
}
class="btn btn-outline btn-sm h-fit"
title={
if @regions_loaded,
do: "Refresh regions list",
else: "Load available regions"
}
>
<%= if @verifying_credentials do %>
<span class="loading loading-spinner loading-xs"></span>
<% else %>
<.icon name="hero-arrow-path" class="w-4 h-4" />
<% end %>
</button>
</div>
<%!-- Helper text is now in the component itself --%>
</div>
</div>
<%= if @email_ses_events do %>
<%!-- Advanced AWS Settings (collapse) --%>
<div class="collapse collapse-arrow bg-base-200 mt-4">
<input type="checkbox" />
<div class="collapse-title text-sm font-medium">
<span class="flex items-center gap-2">
<.icon name="hero-cog-6-tooth" class="w-5 h-5" /> Advanced AWS Settings
</span>
</div>
<div class="collapse-content text-sm space-y-4">
<p class="text-base-content/70 mb-4">
These settings are automatically configured when you run "Setup AWS Infrastructure".
Manual changes may break the integration.
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<%!-- SES Configuration Set --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">SES Configuration Set</span>
</label>
<input
name="aws_settings[ses_configuration_set]"
type="text"
placeholder="phoenixkit-emails"
value={@aws_settings.ses_configuration_set}
class="input input-bordered focus:input-primary"
/>
<label class="label">
<span class="label-text-alt">SES configuration set name</span>
</label>
</div>
<%!-- SNS Topic ARN --%>
<div class="form-control md:col-span-2">
<label class="label">
<span class="label-text font-medium">SNS Topic ARN</span>
</label>
<input
name="aws_settings[sns_topic_arn]"
type="text"
placeholder="arn:aws:sns:eu-north-1:123456789012:email-events"
value={@aws_settings.sns_topic_arn}
class="input input-bordered focus:input-primary"
/>
<label class="label">
<span class="label-text-alt">SNS topic for email events</span>
</label>
</div>
<%!-- SQS Queue URL --%>
<div class="form-control md:col-span-2">
<label class="label">
<span class="label-text font-medium">SQS Queue URL</span>
</label>
<input
name="aws_settings[sqs_queue_url]"
type="url"
placeholder="https://sqs.eu-north-1.amazonaws.com/123456789012/email-events"
value={@aws_settings.sqs_queue_url}
class="input input-bordered focus:input-primary"
/>
<label class="label">
<span class="label-text-alt">Main queue for email events</span>
</label>
</div>
<%!-- SQS Queue ARN --%>
<div class="form-control md:col-span-1">
<label class="label">
<span class="label-text font-medium">SQS Queue ARN</span>
</label>
<input
name="aws_settings[sqs_queue_arn]"
type="text"
placeholder="arn:aws:sqs:eu-north-1:123456789012:email-events"
value={@aws_settings.sqs_queue_arn}
class="input input-bordered focus:input-primary"
/>
<label class="label">
<span class="label-text-alt">SQS queue ARN for permissions</span>
</label>
</div>
<%!-- SQS DLQ URL --%>
<div class="form-control md:col-span-1">
<label class="label">
<span class="label-text font-medium">SQS Dead Letter Queue URL</span>
</label>
<input
name="aws_settings[sqs_dlq_url]"
type="url"
placeholder="https://sqs.eu-north-1.amazonaws.com/123456789012/email-events-dlq"
value={@aws_settings.sqs_dlq_url}
class="input input-bordered focus:input-primary"
/>
<label class="label">
<span class="label-text-alt">
Dead letter queue for failed messages
</span>
</label>
</div>
</div>
</div>
</div>
<%!-- SQS Worker Settings (collapse) --%>
<div class="collapse collapse-arrow bg-base-200 mt-4">
<input type="checkbox" />
<div class="collapse-title text-sm font-medium">
<span class="flex items-center gap-2">
<.icon name="hero-cog-6-tooth" class="w-5 h-5" /> SQS Worker Settings
</span>
</div>
<div class="collapse-content text-sm space-y-4">
<%!-- Enable SQS Polling --%>
<div class="form-control">
<label class="label cursor-pointer">
<span class="label-text text-lg">
<span class="font-semibold">Enable SQS Polling</span>
<div class="text-sm text-base-content/70 mt-1">
Automatically poll SQS queue for email events in background
</div>
</span>
<input
type="checkbox"
class="toggle toggle-info"
checked={@sqs_polling_enabled}
phx-click="toggle_sqs_polling"
/>
</label>
</div>
<%!-- SQS Polling Interval --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">SQS Polling Interval</span>
</label>
<div class="input-group">
<input
name="aws_settings[sqs_polling_interval_ms]"
type="number"
placeholder="5000"
value={@aws_settings.sqs_polling_interval_ms}
class="input input-bordered focus:input-primary w-full max-w-xs"
min="1000"
max="60000"
/>
<span class="bg-base-200 px-4 py-3 text-sm">ms</span>
</div>
<label class="label">
<span class="label-text-alt">
How often to check for SQS messages (1-60 seconds)
</span>
</label>
</div>
<%= if @sqs_polling_enabled do %>
<%!-- SQS Max Messages Per Poll --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Max Messages Per Poll</span>
</label>
<div class="input-group">
<input
name="max_messages"
type="number"
placeholder="Enter max messages"
class="input input-bordered w-full max-w-xs"
value={@sqs_max_messages_per_poll}
min="1"
max="10"
phx-blur="update_max_messages"
/>
<span class="bg-base-200 px-4 py-3 text-sm">messages</span>
</div>
<label class="label">
<span class="label-text-alt text-base-content/70">
Maximum number of messages to process in each polling cycle (1-10)
</span>
</label>
</div>
<%!-- SQS Visibility Timeout --%>
<div class="form-control">
<label class="label">
<span class="label-text font-medium">Visibility Timeout</span>
</label>
<div class="input-group">
<input
name="timeout"
type="number"
placeholder="Enter timeout"
class="input input-bordered w-full max-w-xs"
value={@sqs_visibility_timeout}
min="30"
max="43200"
phx-blur="update_visibility_timeout"
/>
<span class="bg-base-200 px-4 py-3 text-sm">seconds</span>
</div>
<label class="label">
<span class="label-text-alt text-base-content/70">
How long messages remain invisible after being received (30-43200 seconds)
</span>
</label>
</div>
<% end %>
<%!-- Performance Optimization Tips --%>
<div class="p-4 bg-blue-50 border border-blue-200 rounded-md">
<h4 class="font-semibold text-blue-900 mb-2 flex items-center gap-2">
<.icon name="hero-light-bulb" class="w-4 h-4" /> Performance Tips
</h4>
<ul class="text-sm text-blue-800 space-y-1">
<li>• Use longer polling intervals (5-10 seconds) to reduce API calls</li>
<li>• Set visibility timeout to match processing time</li>
<li>• Monitor queue depth and adjust max messages accordingly</li>
<li>• Enable compression to reduce storage requirements</li>
</ul>
</div>
</div>
</div>
<% end %>
<%!-- Warning for credentials changes --%>
<%= if String.trim(@aws_settings.access_key_id) != "" or String.trim(@aws_settings.secret_access_key) != "" do %>
<div class="alert alert-warning mb-4">
<.icon name="hero-exclamation-triangle" class="w-5 h-5" />
<div>
<h3 class="font-bold">Configuration Changes Detected</h3>
<p class="text-sm mt-1">
You've modified your AWS credentials. Click "Save AWS Settings" first, then use "Setup AWS Infrastructure" to create the required resources.
</p>
</div>
</div>
<% end %>
<%!-- Action Buttons --%>
<div class="flex flex-col sm:flex-row gap-4 mt-6">
<div class="flex-1">
<button
type="submit"
class={[
"btn btn-primary w-full sm:w-auto",
if(@saving, do: "loading", else: "")
]}
disabled={@saving or @verifying_credentials}
>
<%= if @saving do %>
Saving...
<% else %>
<.icon name="hero-check" class="w-4 h-4 mr-2" /> Save AWS Settings
<% end %>
</button>
</div>
<div class="flex-1">
<button
type="button"
phx-click="setup_aws_infrastructure"
class={[
"btn btn-accent w-full sm:w-auto",
if(@setting_up_aws, do: "loading", else: "")
]}
disabled={
@setting_up_aws or @saving or String.trim(@aws_settings.access_key_id) == "" or
String.trim(@aws_settings.secret_access_key) == ""
}
>
<%= if @setting_up_aws do %>
Setting up...
<% else %>
<.icon name="hero-cog-6-tooth" class="w-4 h-4 mr-2" />
Setup AWS Infrastructure
<% end %>
</button>
</div>
</div>
</form>
</div>
</div>
<%!-- Current Configuration Summary --%>
<div class="alert alert-info">
<.icon name="hero-information-circle" class="w-5 h-5" />
<div>
<h3 class="font-bold">Current Configuration</h3>
<div class="text-sm mt-1">
<p>Status: <span class="font-semibold">Enabled</span></p>
<p>
Save email bodies:
<span class="font-semibold">
{if @email_save_body, do: "Yes", else: "No"}
</span>
</p>
<p>
AWS SES events:
<span class="font-semibold">
{if @email_ses_events, do: "Yes", else: "No"}
</span>
</p>
<p>
Retention period: <span class="font-semibold">{@email_retention_days} days</span>
</p>
<p>
Sampling rate: <span class="font-semibold">{@email_sampling_rate}%</span>
</p>
<p>
SQS polling:
<span class="font-semibold">
{if @sqs_polling_enabled, do: "Enabled", else: "Disabled"}
</span>
</p>
</div>
</div>
</div>
<% else %>
<%!-- Disabled State Information --%>
<div class="alert alert-warning">
<.icon name="hero-exclamation-triangle" class="w-5 h-5" />
<div>
<h3 class="font-bold">Emails Disabled</h3>
<p class="text-sm mt-1">
Enable the emails above to access configuration options and start managing email delivery events.
</p>
</div>
</div>
<%!-- Benefits Card when Disabled --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-2xl mb-4">
<.icon name="hero-light-bulb" class="w-6 h-6" /> Emails Benefits
</h2>
<div class="space-y-3">
<div class="flex items-start gap-3">
<.icon name="hero-check-circle" class="w-5 h-5 text-success mt-0.5" />
<div>
<h3 class="font-semibold">Delivery Monitoring</h3>
<p class="text-sm text-base-content/70">
Track successful email deliveries and identify issues
</p>
</div>
</div>
<div class="flex items-start gap-3">
<.icon name="hero-check-circle" class="w-5 h-5 text-success mt-0.5" />
<div>
<h3 class="font-semibold">Engagement Analytics</h3>
<p class="text-sm text-base-content/70">
Monitor email opens, clicks, and user engagement
</p>
</div>
</div>
<div class="flex items-start gap-3">
<.icon name="hero-check-circle" class="w-5 h-5 text-success mt-0.5" />
<div>
<h3 class="font-semibold">Debugging Support</h3>
<p class="text-sm text-base-content/70">
Store email content for troubleshooting delivery issues
</p>
</div>
</div>
<div class="flex items-start gap-3">
<.icon name="hero-check-circle" class="w-5 h-5 text-success mt-0.5" />
<div>
<h3 class="font-semibold">AWS SES Integration</h3>
<p class="text-sm text-base-content/70">
Automatic webhook handling for bounce and complaint events
</p>
</div>
</div>
</div>
</div>
</div>
<% end %>
</div>
</div>
</PhoenixKitWeb.Components.LayoutWrapper.app_layout>