Packages

phoenix_kit

1.7.13
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
phoenix_kit lib phoenix_kit_web live users roles.html.heex
Raw

lib/phoenix_kit_web/live/users/roles.html.heex

<PhoenixKitWeb.Components.LayoutWrapper.app_layout
flash={@flash}
phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]}
page_title="Role Management"
current_path={@url_path}
project_title={@project_title}
current_locale={@current_locale}
>
<div class="container 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")}
class="btn btn-outline btn-primary btn-sm absolute left-0 top-0 -mb-12"
>
<.icon name="hero-arrow-left" class="w-4 h-4" /> Back to Dashboard
</.link>
<%!-- Title Section --%>
<div class="text-center">
<h1 class="text-4xl font-bold text-base-content mb-3">Role Management</h1>
<p class="text-lg text-base-content">Create and manage user roles</p>
</div>
</header>
<%!-- Action Button --%>
<div class="flex justify-center mb-6">
<button
phx-click="show_create_form"
class="btn btn-primary btn-lg"
>
<.icon name="hero-plus" class="w-5 h-5 mr-2" /> Create New Role
</button>
</div>
<%!-- Role Edit Form Modals --%>
<%= if @show_create_form do %>
<div class="modal modal-open">
<div class="modal-box max-w-2xl">
<h3 class="font-bold text-xl mb-4">
Create New Role
</h3>
<form
phx-submit="create_role"
class="space-y-4"
>
<div class="form-control">
<.input
field={@create_role_form[:name]}
label="Role Name *"
placeholder="Enter role name (e.g., Manager, Editor)"
maxlength="50"
required
/>
<p class="label mt-1">
Must be unique, 1-50 characters.
</p>
</div>
<div class="form-control">
<.textarea
field={@create_role_form[:description]}
label="Description"
placeholder="Describe what this role can do (optional)"
maxlength="500"
/>
<p class="label mt-1">
Optional, up to 500 characters.
</p>
</div>
<div class="modal-action">
<button type="button" phx-click="hide_form" class="btn btn-outline">
Cancel
</button>
<button type="submit" class="btn btn-primary">
Create Role
</button>
</div>
</form>
</div>
</div>
<% end %>
<%!-- Role Edit Form Modal --%>
<%= if @show_edit_form do %>
<div class="modal modal-open">
<div class="modal-box max-w-2xl">
<h3 class="font-bold text-xl mb-4">
Edit Role
</h3>
<form
phx-submit="update_role"
class="space-y-4"
>
<div class="form-control">
<.input
field={@edit_role_form[:name]}
label="Role Name *"
placeholder="Enter role name (e.g., Manager, Editor)"
maxlength="50"
required
/>
<p class="label mt-1">
Must be unique, 1-50 characters.
</p>
</div>
<div class="form-control">
<.textarea
field={@edit_role_form[:description]}
label="Description"
placeholder="Describe what this role can do (optional)"
maxlength="500"
/>
<p class="label mt-1">
Optional, up to 500 characters.
</p>
</div>
<div class="modal-action">
<button type="button" phx-click="hide_form" class="btn btn-outline">
Cancel
</button>
<button type="submit" class="btn btn-primary">
Update Role
</button>
</div>
</form>
</div>
</div>
<% end %>
<%!-- Roles List --%>
<div class="bg-base-100">
<%= if length(@roles) > 0 do %>
<.table_default variant="zebra">
<.table_default_header>
<.table_default_row>
<.table_default_header_cell>Role</.table_default_header_cell>
<.table_default_header_cell>Type</.table_default_header_cell>
<.table_default_header_cell>Description</.table_default_header_cell>
<.table_default_header_cell>Users</.table_default_header_cell>
<.table_default_header_cell>Actions</.table_default_header_cell>
</.table_default_row>
</.table_default_header>
<.table_default_body>
<%= for role <- @roles do %>
<.table_default_row>
<.table_default_cell>
<div class="flex items-center gap-2">
<.role_badge role={role} />
</div>
</.table_default_cell>
<.table_default_cell>
<%= if role.is_system_role do %>
<span class="badge badge-outline badge-sm">System Role</span>
<% else %>
<span class="badge badge-success badge-sm">Custom Role</span>
<% end %>
</.table_default_cell>
<.table_default_cell class="max-w-xs">
<div class="text-sm">
<%= if role.description do %>
{role.description}
<% else %>
<span class="text-base-content/50 italic">No description</span>
<% end %>
</div>
</.table_default_cell>
<.table_default_cell>
<div class="flex items-center gap-2">
<.users_count role={role} stats={@role_stats} />
<span class="text-sm text-base-content/70">users</span>
</div>
</.table_default_cell>
<.table_default_cell>
<div class="flex flex-wrap gap-1">
<%= if !role.is_system_role do %>
<%!-- Edit Button --%>
<button
class="btn btn-xs btn-outline btn-primary"
phx-click="show_edit_role"
phx-value-role_id={role.id}
>
<.icon name="hero-pencil" class="h-3 w-3 mr-1" /> Edit
</button>
<%!-- Delete Button --%>
<button
class="btn btn-xs btn-outline btn-error"
phx-click="request_delete_role"
phx-value-role_id={role.id}
phx-value-role_name={role.name}
>
<.icon name="hero-trash" class="h-3 w-3 mr-1" /> Delete
</button>
<% else %>
<span class="text-xs text-base-content/50">Protected</span>
<% end %>
</div>
</.table_default_cell>
</.table_default_row>
<% end %>
</.table_default_body>
</.table_default>
<% else %>
<%!-- Empty state --%>
<div class="text-center py-12">
<.icon name="hero-shield-check" class="h-16 w-16 mx-auto text-base-content/40 mb-4" />
<h3 class="text-lg font-medium text-base-content mb-2">
No roles found
</h3>
<p class="text-base-content/70 mb-4">
Start by creating your first custom role.
</p>
<button
phx-click="show_create_form"
class="btn btn-primary"
>
Create First Role
</button>
</div>
<% end %>
</div>
<%!-- Role Statistics --%>
<div class="mt-8">
<h3 class="text-lg font-semibold text-base-content mb-6">Role Statistics</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<%!-- System Roles Count --%>
<PhoenixKitWeb.Components.Core.StatCard.stat_card
compact={true}
rounded="xl"
value={Enum.count(@roles, & &1.is_system_role)}
title="System Roles"
subtitle="Protected core roles"
>
<:icon>
<.icon name="hero-lock-closed" class="w-5 h-5" />
</:icon>
</PhoenixKitWeb.Components.Core.StatCard.stat_card>
<%!-- Custom Roles Count --%>
<PhoenixKitWeb.Components.Core.StatCard.stat_card
compact={true}
rounded="xl"
value={Enum.count(@roles, &(!&1.is_system_role))}
title="Custom Roles"
subtitle="User-defined roles"
>
<:icon>
<.icon name="hero-cog-6-tooth" class="w-5 h-5" />
</:icon>
</PhoenixKitWeb.Components.Core.StatCard.stat_card>
<%!-- Total Roles Count --%>
<PhoenixKitWeb.Components.Core.StatCard.stat_card
compact={true}
rounded="xl"
value={length(@roles)}
title="Total Roles"
subtitle="All available roles"
>
<:icon>
<.icon name="hero-chart-bar" class="w-5 h-5" />
</:icon>
</PhoenixKitWeb.Components.Core.StatCard.stat_card>
</div>
</div>
<%!-- Confirmation Modal --%>
<%= if assigns[:delete_confirmation] && @delete_confirmation.show do %>
<div class="modal modal-open">
<div class="modal-box">
<h3 class="font-bold text-lg">Delete Role Confirmation</h3>
<p class="py-4">
Are you sure you want to delete the role <strong>{@delete_confirmation.role_name}</strong>?
This action cannot be undone.
</p>
<div class="modal-action">
<button class="btn btn-ghost" phx-click="cancel_delete">
Cancel
</button>
<button
class="btn btn-error"
phx-click="confirm_delete_role"
phx-value-role_id={@delete_confirmation.role_id}
>
Delete Role
</button>
</div>
</div>
</div>
<% end %>
</div>
</PhoenixKitWeb.Components.LayoutWrapper.app_layout>