Packages

phoenix_kit

1.2.10
1.7.211 1.7.210 1.7.209 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 live_sessions_live.html.heex
Raw

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

<PhoenixKitWeb.Components.LayoutWrapper.app_layout
flash={@flash}
phoenix_kit_current_scope={assigns[:phoenix_kit_current_scope]}
page_title="Live Sessions - {@project_title} Admin"
current_path={@current_path}
project_title={@project_title}
>
<div class="container mx-auto px-4 py-8">
<%!-- Header with Live Indicator --%>
<div class="mb-8">
<div class="flex items-center justify-between">
<div class="flex items-center gap-4">
<h1 class="text-3xl font-bold text-base-content">
Live Sessions
</h1>
<%!-- Live Indicator --%>
<div class="flex items-center gap-2 px-3 py-1 bg-success/10 text-success rounded-full">
<div class="w-2 h-2 bg-success rounded-full animate-pulse"></div>
<span class="text-xs font-medium">LIVE</span>
</div>
</div>
<%!-- Controls --%>
<div class="flex items-center gap-2">
<%!-- Auto-refresh toggle --%>
<button
phx-click="toggle_auto_refresh"
class={[
"btn btn-sm",
if(@auto_refresh, do: "btn-success", else: "btn-outline")
]}
>
<%= if @auto_refresh do %>
<PhoenixKitWeb.Components.Core.Icons.icon_auto_refresh_on /> Auto-refresh ON
<% else %>
<PhoenixKitWeb.Components.Core.Icons.icon_auto_refresh_off /> Auto-refresh OFF
<% end %>
</button>
<%!-- Manual refresh --%>
<button
phx-click="refresh_now"
class="btn btn-sm btn-outline"
>
<PhoenixKitWeb.Components.Core.Icons.icon_refresh /> Refresh
</button>
</div>
</div>
<p class="text-base-content/70 mt-2">
Real-time monitoring of all active sessions with live updates.
Last updated: {Calendar.strftime(@last_updated, "%H:%M:%S")}
</p>
</div>
<%!-- Statistics Cards --%>
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
<%!-- Total Sessions --%>
<div class="card bg-gradient-to-br from-blue-500 to-blue-600 text-white shadow-xl">
<div class="card-body p-4">
<div class="flex items-center justify-between">
<div>
<div class="text-2xl font-bold">
{@presence_stats.total_sessions}
</div>
<div class="text-blue-100 text-sm">Total Sessions</div>
</div>
<div class="p-2 bg-white/20 rounded-lg">
<PhoenixKitWeb.Components.Core.Icons.icon_user_profile />
</div>
</div>
</div>
</div>
<%!-- Anonymous Sessions --%>
<div class="card bg-gradient-to-br from-orange-500 to-orange-600 text-white shadow-xl">
<div class="card-body p-4">
<div class="flex items-center justify-between">
<div>
<div class="text-2xl font-bold">
{@presence_stats.anonymous_sessions}
</div>
<div class="text-orange-100 text-sm">Anonymous</div>
</div>
<div class="p-2 bg-white/20 rounded-lg">
<PhoenixKitWeb.Components.Core.Icons.icon_user_simple />
</div>
</div>
</div>
</div>
<%!-- Authenticated Sessions --%>
<div class="card bg-gradient-to-br from-green-500 to-green-600 text-white shadow-xl">
<div class="card-body p-4">
<div class="flex items-center justify-between">
<div>
<div class="text-2xl font-bold">
{@presence_stats.authenticated_sessions}
</div>
<div class="text-green-100 text-sm">Authenticated</div>
</div>
<div class="p-2 bg-white/20 rounded-lg">
<PhoenixKitWeb.Components.Core.Icons.icon_shield />
</div>
</div>
</div>
</div>
<%!-- Unique Visitors --%>
<div class="card bg-gradient-to-br from-purple-500 to-purple-600 text-white shadow-xl">
<div class="card-body p-4">
<div class="flex items-center justify-between">
<div>
<div class="text-2xl font-bold">
{@presence_stats.unique_anonymous_visitors}
</div>
<div class="text-purple-100 text-sm">Unique Visitors</div>
</div>
<div class="p-2 bg-white/20 rounded-lg">
<PhoenixKitWeb.Components.Core.Icons.icon_eye class="w-6 h-6" />
</div>
</div>
</div>
</div>
</div>
<%!-- Filters and Search --%>
<div class="card bg-base-100 shadow-xl mb-6">
<div class="card-body p-4">
<div class="flex flex-col md:flex-row gap-4 items-center justify-between">
<%!-- Search --%>
<div class="flex-1 max-w-md">
<form phx-submit="search" phx-change="search" class="form-control">
<div class="input-group">
<input
type="text"
name="search"
value={@search_query}
placeholder="Search by IP, User-Agent, email..."
class="input input-bordered flex-1"
/>
<button type="submit" class="btn btn-square">
<PhoenixKitWeb.Components.Core.Icons.icon_search />
</button>
</div>
</form>
</div>
<%!-- Filter Tabs --%>
<div class="tabs tabs-boxed">
<button
phx-click="filter_by"
phx-value-type="all"
class={["tab", if(@filter_type == "all", do: "tab-active", else: "")]}
>
All ({@total_sessions})
</button>
<button
phx-click="filter_by"
phx-value-type="anonymous"
class={["tab", if(@filter_type == "anonymous", do: "tab-active", else: "")]}
>
Anonymous ({@presence_stats.anonymous_sessions})
</button>
<button
phx-click="filter_by"
phx-value-type="authenticated"
class={["tab", if(@filter_type == "authenticated", do: "tab-active", else: "")]}
>
Authenticated ({@presence_stats.authenticated_sessions})
</button>
</div>
</div>
</div>
</div>
<%!-- Sessions Table --%>
<div class="card bg-base-100 shadow-xl">
<div class="card-body p-0">
<div class="overflow-x-auto">
<table class="table table-zebra">
<thead>
<tr>
<th>
<button
phx-click="sort_by"
phx-value-field="type"
class="flex items-center gap-1 hover:text-primary"
>
Type
<%= if @sort_by == :type do %>
<%= if @sort_order == :asc do %>
<PhoenixKitWeb.Components.Core.Icons.icon_sort_asc />
<% else %>
<PhoenixKitWeb.Components.Core.Icons.icon_sort_desc />
<% end %>
<% end %>
</button>
</th>
<th>User/Session</th>
<th>IP Address</th>
<th>Current Page</th>
<th>
<button
phx-click="sort_by"
phx-value-field="connected_at"
class="flex items-center gap-1 hover:text-primary"
>
Connected
<%= if @sort_by == :connected_at do %>
<%= if @sort_order == :asc do %>
<PhoenixKitWeb.Components.Core.Icons.icon_sort_asc />
<% else %>
<PhoenixKitWeb.Components.Core.Icons.icon_sort_desc />
<% end %>
<% end %>
</button>
</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<%= for session <- @sessions do %>
<tr>
<td>
<div class="flex items-center gap-2">
<%= if session.type == :authenticated do %>
<div class="badge badge-success badge-sm">
<PhoenixKitWeb.Components.Core.Icons.icon_shield class="w-3 h-3 mr-1" />
Auth
</div>
<% else %>
<div class="badge badge-warning badge-sm">
<PhoenixKitWeb.Components.Core.Icons.icon_user_simple class="w-3 h-3 mr-1" />
Anon
</div>
<% end %>
</div>
</td>
<td>
<%= if session.type == :authenticated do %>
<div class="flex items-center gap-2">
<div class="w-8 h-8 bg-success rounded-full flex items-center justify-center text-success-content text-xs font-bold">
{String.first(session.user_email || "?") |> String.upcase()}
</div>
<div>
<div class="font-medium text-sm">
{session.user_email}
</div>
<div class="text-xs text-base-content/70">
ID: {session.user_id}
</div>
</div>
</div>
<% else %>
<div class="flex items-center gap-2">
<div class="w-8 h-8 bg-warning rounded-full flex items-center justify-center text-warning-content text-xs font-bold">
?
</div>
<div>
<div class="font-medium text-sm">
Anonymous User
</div>
<div class="text-xs text-base-content/70 font-mono">
{session.session_id}
</div>
</div>
</div>
<% end %>
</td>
<td>
<code class="text-xs bg-base-200 px-2 py-1 rounded">
{session.ip_address || "Unknown"}
</code>
</td>
<td>
<%= if session.current_page do %>
<code class="text-xs bg-base-200 px-2 py-1 rounded">
{session.current_page}
</code>
<% else %>
<span class="text-base-content/50"></span>
<% end %>
</td>
<td>
<div class="text-xs">
{format_time_ago(session.connected_at)}
</div>
</td>
<td>
<div class="flex items-center gap-1">
<div class="w-2 h-2 bg-success rounded-full animate-pulse"></div>
<span class="text-xs text-success">Active</span>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= if Enum.empty?(@sessions) do %>
<div class="text-center py-12">
<div class="text-base-content/50 mb-4">
<PhoenixKitWeb.Components.Core.Icons.icon_empty_inbox />
</div>
<h3 class="text-lg font-medium text-base-content mb-2">No active sessions</h3>
<p class="text-base-content/70">
There are currently no active sessions to display.
</p>
</div>
<% end %>
</div>
</div>
</div>
<%!-- Pagination --%>
<%= if @total_pages > 1 do %>
<div class="flex justify-center mt-6">
<div class="btn-group">
<%= for page_num <- 1..@total_pages do %>
<button
phx-click="goto_page"
phx-value-page={page_num}
class={[
"btn btn-sm",
if(page_num == @page, do: "btn-active", else: "")
]}
>
{page_num}
</button>
<% end %>
</div>
</div>
<% end %>
</div>
</PhoenixKitWeb.Components.LayoutWrapper.app_layout>