defmodule DaProductAppWeb.DashboardLive do
use DaProductAppWeb, :live_view
import Logger
alias DaProductApp.Users
alias DaProductApp.TerminalManagement
# on_mount DaProductAppWeb.Live.SetCurrentPage
def mount(_params, session, socket) do
user_token = session["user_token"]
user = user_token && Users.get_user_by_session_token(user_token)
current_user = user || nil
Logger.debug("Socket Assigns: #{inspect(socket.assigns)}", []) # Correct usage
#current_user = Map.get(session, "current_user", nil)
stats = TerminalManagement.get_dashboard_statistics()
online_rate = TerminalManagement.get_device_online_rate()
terminals = TerminalManagement.list_terminals_with_latest_status()
chart_data = TerminalManagement.get_chart_data("today")
# Phase 3.1: Add real-time monitoring data
monitoring_data = TerminalManagement.get_realtime_monitoring_data()
# Subscribe to real-time updates
if connected?(socket) do
TerminalManagement.subscribe_to_device_updates()
# Set up periodic updates every 30 seconds
Process.send_after(self(), :update_monitoring_data, 30_000)
end
socket =
socket
|> assign(:current_user, current_user)
|> assign(:show_sidebar, true) # Enable sidebar for dashboard
|> assign(:page_title, "Dashboard") # Set the page title
|> assign(:current_page, :dashboard) # Set the current page for sidebar highlighting
|> assign(:stats, stats)
|> assign(:online_rate, online_rate)
|> assign(:terminals, terminals)
|> assign(:selected_terminal, nil)
|> assign(:terminal_logs, [])
|> assign(:show_panel, false)
|> assign(:chart_data, chart_data)
|> assign(:selected_period, "today")
# Phase 3.1: Real-time monitoring assigns
|> assign(:monitoring_data, monitoring_data)
|> assign(:device_health, monitoring_data.device_health)
|> assign(:connection_status, monitoring_data.connection_status)
|> assign(:performance_metrics, monitoring_data.performance_metrics)
|> assign(:alert_summary, monitoring_data.alert_summary)
|> assign(:show_monitoring_details, false)
{:ok, socket}
end
def render(assigns) do
~H"""
Real-time Device Monitoring
Live updates every 30 seconds • Last updated: <%= Calendar.strftime(@monitoring_data.last_updated, "%H:%M:%S") %>
<%= @device_health.total %>
Total Devices
<%= @device_health.healthy %>
Healthy
<%= if @alert_summary.total_alerts > 0 do %>
<%= @alert_summary.total_alerts %>
Alerts
<% end %>
<%= @device_health.healthy %>
Healthy Devices
Last 5 minutes
<%= @device_health.warning %>
Warning
5-30 minutes ago
<%= @device_health.critical %>
Critical
30-60 minutes ago
<%= @device_health.offline %>
Offline
Over 1 hour ago
Success Rate
<%= Float.round(@performance_metrics.parameter_push_success_rate, 1) %>%
Parameter Operations
Avg Response
<%= @performance_metrics.avg_response_time_ms %>ms
Last Hour
Uptime
<%= @performance_metrics.uptime_percentage %>%
Last Hour
Connections
<%= @connection_status.current_connections %>
Per Minute
Total Devices
<%= @stats.total_devices %>
Registered devices
New Devices
<%= @stats.new_devices_today %>
Added today
Activated
<%= @stats.activated_devices %>
Active today
Upgrades
<%= @stats.upgrades_today %>
Completed today
App Downloads
<%= @stats.app_downloads_today %>
Downloaded today
■ OTA updates
■ total number of APP downloads
The device is online Rate
<%= @online_rate.online_rate %>%
<%= @online_rate.online_devices %> stand
"""
end
def handle_event("set_chart_range", %{"range" => range}, socket) do
chart_data = TerminalManagement.get_chart_data(range)
stats = TerminalManagement.get_dashboard_statistics(range)
{:noreply, assign(socket, :chart_data, chart_data) |> assign(:selected_period, range) |> assign(:stats, stats)}
end
def handle_event("refresh_update_statistics", _params, socket) do
# Refresh all statistics and chart data based on the currently selected period
stats = TerminalManagement.get_dashboard_statistics(socket.assigns.selected_period)
chart_data = TerminalManagement.get_chart_data(socket.assigns.selected_period)
online_rate = TerminalManagement.get_device_online_rate()
socket =
socket
|> assign(:stats, stats)
|> assign(:chart_data, chart_data)
|> assign(:online_rate, online_rate)
|> put_flash(:info, "Statistics updated successfully")
{:noreply, socket}
end
# Navigation event handlers for dashboard cards
def handle_event("navigate_to_devices", _params, socket) do
{:noreply, push_navigate(socket, to: ~p"/terminals")}
end
def handle_event("navigate_to_new_devices", _params, socket) do
# Navigate to terminals page with today's filter
{:noreply, push_navigate(socket, to: ~p"/terminals?filter=today")}
end
def handle_event("navigate_to_activated_devices", _params, socket) do
# Navigate to terminals page with active filter
{:noreply, push_navigate(socket, to: ~p"/terminals?status=online")}
end
def handle_event("navigate_to_upgrades", _params, socket) do
# Navigate to app upgrade status page
{:noreply, push_navigate(socket, to: ~p"/appupgrade/status")}
end
def handle_event("navigate_to_app_downloads", _params, socket) do
# Navigate to app packages page
{:noreply, push_navigate(socket, to: ~p"/apppackage")}
end
# Phase 3.1: Real-time monitoring event handlers
def handle_event("refresh_monitoring", _params, socket) do
monitoring_data = TerminalManagement.get_realtime_monitoring_data()
socket =
socket
|> assign(:monitoring_data, monitoring_data)
|> assign(:device_health, monitoring_data.device_health)
|> assign(:connection_status, monitoring_data.connection_status)
|> assign(:performance_metrics, monitoring_data.performance_metrics)
|> assign(:alert_summary, monitoring_data.alert_summary)
{:noreply, socket}
end
def handle_event("toggle_monitoring_details", _params, socket) do
{:noreply, assign(socket, :show_monitoring_details, !socket.assigns.show_monitoring_details)}
end
# Handle real-time PubSub messages
def handle_info({:device_update, device_data}, socket) do
# Update specific device in the terminals list
updated_terminals = update_terminal_in_list(socket.assigns.terminals, device_data)
{:noreply, assign(socket, :terminals, updated_terminals)}
end
def handle_info({:monitoring_update, monitoring_data}, socket) do
socket =
socket
|> assign(:monitoring_data, monitoring_data)
|> assign(:device_health, monitoring_data.device_health)
|> assign(:connection_status, monitoring_data.connection_status)
|> assign(:performance_metrics, monitoring_data.performance_metrics)
|> assign(:alert_summary, monitoring_data.alert_summary)
{:noreply, socket}
end
# Periodic updates
def handle_info(:update_monitoring_data, socket) do
monitoring_data = TerminalManagement.get_realtime_monitoring_data()
socket =
socket
|> assign(:monitoring_data, monitoring_data)
|> assign(:device_health, monitoring_data.device_health)
|> assign(:connection_status, monitoring_data.connection_status)
|> assign(:performance_metrics, monitoring_data.performance_metrics)
|> assign(:alert_summary, monitoring_data.alert_summary)
# Schedule next update
Process.send_after(self(), :update_monitoring_data, 30_000)
{:noreply, socket}
end
# Helper function to update terminal in list
defp update_terminal_in_list(terminals, device_data) do
Enum.map(terminals, fn terminal ->
if terminal.serial_number == device_data.serial_number do
Map.merge(terminal, device_data)
else
terminal
end
end)
end
# Helper function to get period description for UI labels
defp period_description("today"), do: "today"
defp period_description("week"), do: "this week"
defp period_description("month"), do: "this month"
end