Packages
phoenix_kit
1.2.10
1.7.208
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/phoenix_kit_web/live/settings_live.html.heex
<PhoenixKitWeb.Components.LayoutWrapper.app_layout
flash={@flash}
phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]}
page_title="{@project_title} Settings"
current_path={@url_path}
project_title={@project_title}
>
<div class="container flex flex-col mx-auto px-4 py-6">
<%!-- Header Section --%>
<header class="w-full relative mb-6">
<%!-- Back Button (Left aligned) --%>
<.link
navigate={PhoenixKit.Utils.Routes.path("/admin/dashboard")}
class="btn btn-outline btn-primary btn-sm absolute left-0 top-0 -mb-12"
>
<PhoenixKitWeb.Components.Core.Icons.icon_arrow_left /> Back to Dashboard
</.link>
<%!-- Title Section --%>
<div class="text-center">
<h1 class="text-4xl font-bold text-base-content mb-3">System Settings</h1>
<p class="text-lg text-base-content">Configure system preferences and options</p>
</div>
</header>
<%!-- Settings Form --%>
<div class="max-w-2xl mx-auto">
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title text-xl mb-6">System Configuration</h2>
<.form
:let={_form}
for={@changeset}
id="settings_form"
phx-submit="save_settings"
phx-change="validate_settings"
class="space-y-6"
>
<%!-- Project Title Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">Project Title</span>
<span class="label-text-alt text-sm text-base-content/60">
Application name display
</span>
</label>
<input
name="settings[project_title]"
type="text"
value={@settings["project_title"]}
class="input input-bordered w-full focus:input-primary"
placeholder="Enter project title"
phx-debounce="500"
/>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["project_title"] != @saved_settings["project_title"] do %>
<span class="text-warning">
Selected: {@settings["project_title"]}
</span>
<span class="text-base-content/40">
| Saved: {@saved_settings["project_title"]}
</span>
<% else %>
Saved: {@settings["project_title"]}
<% end %>
</span>
</div>
</div>
<%!-- Site Address URL Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">Site Address (URL)</span>
</label>
<input
name="settings[site_url]"
type="url"
value={@settings["site_url"]}
class="input input-bordered w-full focus:input-primary"
placeholder="https://site.com"
phx-debounce="500"
/>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["site_url"] != @saved_settings["site_url"] do %>
<span class="text-warning">
Selected: {if @settings["site_url"] != "",
do: @settings["site_url"],
else: "(empty)"}
</span>
<span class="text-base-content/40">
| Saved: {if @saved_settings["site_url"] != "",
do: @saved_settings["site_url"],
else: "(empty)"}
</span>
<% else %>
Saved: {if @settings["site_url"] != "",
do: @settings["site_url"],
else: "(empty)"}
<% end %>
</span>
</div>
</div>
<%!-- Registration Control Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">Registration Settings</span>
</label>
<div class="flex items-center gap-3 mb-3">
<input
name="settings[allow_registration]"
type="hidden"
value="false"
/>
<input
name="settings[allow_registration]"
type="checkbox"
value="true"
checked={@settings["allow_registration"] == "true"}
class="checkbox checkbox-primary"
/>
<span class="label-text">Anyone can register</span>
</div>
<div class="flex items-center gap-3">
<input
name="settings[track_registration_geolocation]"
type="hidden"
value="false"
/>
<input
name="settings[track_registration_geolocation]"
type="checkbox"
value="true"
checked={@settings["track_registration_geolocation"] == "true"}
class="checkbox checkbox-primary"
/>
<span class="label-text">Track user registration location</span>
</div>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["allow_registration"] != @saved_settings["allow_registration"] or @settings["track_registration_geolocation"] != @saved_settings["track_registration_geolocation"] do %>
<span class="text-warning">
Registration: {if @settings["allow_registration"] == "true", do: "Enabled", else: "Disabled"} |
Geolocation: {if @settings["track_registration_geolocation"] == "true", do: "Enabled", else: "Disabled"}
</span>
<span class="text-base-content/40">
| Saved: {if @saved_settings["allow_registration"] == "true", do: "Enabled", else: "Disabled"} |
{if @saved_settings["track_registration_geolocation"] == "true", do: "Enabled", else: "Disabled"}
</span>
<% else %>
Registration: {if @settings["allow_registration"] == "true", do: "Enabled", else: "Disabled"} |
Geolocation: {if @settings["track_registration_geolocation"] == "true", do: "Enabled", else: "Disabled"}
<% end %>
</span>
</div>
<%!-- Privacy Notice for Geolocation --%>
<%= if @settings["track_registration_geolocation"] == "true" do %>
<div class="alert alert-info text-sm mt-2">
<PhoenixKitWeb.Components.Core.Icons.icon_info class="stroke-current shrink-0 h-5 w-5" />
<div>
<div class="font-semibold">
Privacy Notice: IP Geolocation Tracking
</div>
<div class="text-xs">
When enabled, registration IP addresses and approximate location data (country, region, city) will be collected for analytics.
Uses free APIs: IP-API.com (45 requests/minute) with ipapi.co (1000 requests/day) fallback. Defaults to OFF for privacy.
</div>
</div>
</div>
<% end %>
</div>
<%!-- New User Default Role Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">New User Default Role</span>
<span class="label-text-alt text-sm text-base-content/60">
Role assigned to new user registrations
</span>
</label>
<select
name="settings[new_user_default_role]"
class="select select-bordered w-full focus:select-primary"
>
<%= for {label, value} <- @setting_options["new_user_default_role"] do %>
<option value={value} selected={value == @settings["new_user_default_role"]}>
{label}
</option>
<% end %>
</select>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["new_user_default_role"] != @saved_settings["new_user_default_role"] do %>
<span class="text-warning">
Selected: {get_option_label(
@settings["new_user_default_role"],
@setting_options["new_user_default_role"]
)}
</span>
<span class="text-base-content/40">
| Saved: {get_option_label(
@saved_settings["new_user_default_role"],
@setting_options["new_user_default_role"]
)}
</span>
<% else %>
Saved: {get_option_label(
@settings["new_user_default_role"],
@setting_options["new_user_default_role"]
)}
<% end %>
</span>
</div>
<%!-- Security Warning for Admin Role --%>
<%= if @settings["new_user_default_role"] == "Admin" do %>
<div class="alert alert-warning text-sm mt-2">
<PhoenixKitWeb.Components.Core.Icons.icon_warning class="stroke-current shrink-0 h-5 w-5" />
<div>
<div class="font-semibold">
Security Notice: Medium Risk
</div>
<div class="text-xs">
All new users will receive administrative privileges and access to the admin panel.
Consider "User" for most installations to maintain security.
</div>
</div>
</div>
<% end %>
</div>
<%!-- Week Start Day Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">Week Start On</span>
<span class="label-text-alt text-sm text-base-content/60">
First day of the week
</span>
</label>
<select
name="settings[week_start_day]"
class="select select-bordered w-full focus:select-primary"
>
<%= for {label, value} <- @setting_options["week_start_day"] do %>
<option value={value} selected={value == @settings["week_start_day"]}>
{label}
</option>
<% end %>
</select>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["week_start_day"] != @saved_settings["week_start_day"] do %>
<span class="text-warning">
Selected: {get_option_label(
@settings["week_start_day"],
@setting_options["week_start_day"]
)}
</span>
<span class="text-base-content/40">
| Saved: {get_option_label(
@saved_settings["week_start_day"],
@setting_options["week_start_day"]
)}
</span>
<% else %>
Saved: {get_option_label(
@settings["week_start_day"],
@setting_options["week_start_day"]
)}
<% end %>
</span>
</div>
</div>
<%!-- Time Zone Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">Time Zone</span>
<span class="label-text-alt text-sm text-base-content/60">
System default timezone
</span>
</label>
<select
name="settings[time_zone]"
class="select select-bordered w-full focus:select-primary"
>
<%= for {label, value} <- @setting_options["time_zone"] do %>
<option value={value} selected={value == @settings["time_zone"]}>
{label}
</option>
<% end %>
</select>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["time_zone"] != @saved_settings["time_zone"] do %>
<span class="text-warning">
Selected: {get_timezone_label(@settings["time_zone"], @setting_options)}
</span>
<span class="text-base-content/40">
| Saved: {get_timezone_label(@saved_settings["time_zone"], @setting_options)}
</span>
<% else %>
Saved: {get_timezone_label(@settings["time_zone"], @setting_options)}
<% end %>
</span>
</div>
</div>
<%!-- Date Format Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">Date Format</span>
<span class="label-text-alt text-sm text-base-content/60">
How dates are displayed
</span>
</label>
<select
name="settings[date_format]"
class="select select-bordered w-full focus:select-primary"
>
<%= for {label, value} <- @setting_options["date_format"] do %>
<option value={value} selected={value == @settings["date_format"]}>
{label}
</option>
<% end %>
</select>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["date_format"] != @saved_settings["date_format"] do %>
<span class="text-warning">
Selected: {get_option_label(
@settings["date_format"],
@setting_options["date_format"]
)}
</span>
<span class="text-base-content/40">
| Saved: {get_option_label(
@saved_settings["date_format"],
@setting_options["date_format"]
)}
</span>
<% else %>
Saved: {get_option_label(
@settings["date_format"],
@setting_options["date_format"]
)}
<% end %>
</span>
</div>
</div>
<%!-- Time Format Setting --%>
<div class="form-control w-full">
<label class="label">
<span class="label-text text-base font-medium">Time Format</span>
<span class="label-text-alt text-sm text-base-content/60">
How times are displayed
</span>
</label>
<select
name="settings[time_format]"
class="select select-bordered w-full focus:select-primary"
>
<%= for {label, value} <- @setting_options["time_format"] do %>
<option value={value} selected={value == @settings["time_format"]}>
{label}
</option>
<% end %>
</select>
<div class="label">
<span class="label-text-alt text-xs text-base-content/50">
<%= if @settings["time_format"] != @saved_settings["time_format"] do %>
<span class="text-warning">
Selected: {get_option_label(
@settings["time_format"],
@setting_options["time_format"]
)}
</span>
<span class="text-base-content/40">
| Saved: {get_option_label(
@saved_settings["time_format"],
@setting_options["time_format"]
)}
</span>
<% else %>
Saved: {get_option_label(
@settings["time_format"],
@setting_options["time_format"]
)}
<% end %>
</span>
</div>
</div>
<%!-- Action Buttons --%>
<div class="flex gap-3 pt-4">
<button
type="submit"
class={[
"btn btn-primary flex-1",
if(@saving, do: "loading", else: "")
]}
disabled={@saving}
>
<%= if @saving do %>
Saving...
<% else %>
Save All Settings
<% end %>
</button>
<button
type="button"
class="btn btn-outline"
phx-click="reset_to_defaults"
>
<PhoenixKitWeb.Components.Core.Icons.icon_refresh class="w-4 h-4 mr-2" /> Reset
</button>
</div>
</.form>
<%!-- Information Panel --%>
<div class="divider">Information</div>
<div class="bg-base-200 rounded-lg p-4 mt-6">
<div class="flex items-start gap-3">
<div class="text-2xl">💡</div>
<div class="flex-1">
<h3 class="font-semibold text-base-content mb-2">About System Settings</h3>
<ul class="text-sm text-base-content/70 space-y-1">
<li>• Make changes to dropdowns and click "Save All Settings" to apply</li>
<li>• Changes show "Selected" vs "Saved" values until you click Save</li>
<li>
• New user default role determines privileges for new registrations (first user always becomes Owner)
</li>
<li>
• Week start day controls which day begins the week (useful for calendar features)
</li>
<li>• Time zone affects date/time display throughout the system</li>
<li>
• Date formats control how dates appear (e.g. Users dashboard "Registered" field)
</li>
<li>• Time formats control 12-hour vs 24-hour time display</li>
<li>• Settings are applied system-wide and use Timex for robust formatting</li>
<li>• Currently supports 6 date formats including "September 2, 2025" style</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</PhoenixKitWeb.Components.LayoutWrapper.app_layout>