Files
MySMSAPio/app/views/admin/dashboard/index.html.erb
2025-10-22 17:22:17 +08:00

231 lines
12 KiB
Plaintext

<div class="space-y-8">
<!-- Page header -->
<div class="border-b border-gray-200 pb-5">
<h1 class="text-3xl font-bold leading-tight tracking-tight text-gray-900">Dashboard</h1>
<p class="mt-2 text-sm text-gray-600">Welcome back! Here's what's happening with your SMS gateway today.</p>
</div>
<!-- Stats grid -->
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
<!-- Gateways stat -->
<div class="relative overflow-hidden rounded-xl bg-white px-4 py-5 shadow-sm ring-1 ring-gray-900/5 sm:px-6">
<dt>
<div class="absolute rounded-lg bg-blue-500 p-3">
<i class="fas fa-mobile-alt text-xl text-white"></i>
</div>
<p class="ml-16 truncate text-sm font-medium text-gray-500">Gateways</p>
</dt>
<dd class="ml-16 flex items-baseline">
<p class="text-3xl font-semibold text-gray-900"><%= @stats[:total_gateways] %></p>
<p class="ml-2 flex items-baseline text-sm font-semibold text-green-600">
<%= @stats[:online_gateways] %> online
</p>
</dd>
</div>
<!-- API Keys stat -->
<div class="relative overflow-hidden rounded-xl bg-white px-4 py-5 shadow-sm ring-1 ring-gray-900/5 sm:px-6">
<dt>
<div class="absolute rounded-lg bg-green-500 p-3">
<i class="fas fa-key text-xl text-white"></i>
</div>
<p class="ml-16 truncate text-sm font-medium text-gray-500">API Keys</p>
</dt>
<dd class="ml-16 flex items-baseline">
<p class="text-3xl font-semibold text-gray-900"><%= @stats[:active_api_keys] %></p>
<p class="ml-2 flex items-baseline text-sm text-gray-600">
of <%= @stats[:total_api_keys] %> total
</p>
</dd>
</div>
<!-- Messages Today stat -->
<div class="relative overflow-hidden rounded-xl bg-white px-4 py-5 shadow-sm ring-1 ring-gray-900/5 sm:px-6">
<dt>
<div class="absolute rounded-lg bg-yellow-500 p-3">
<i class="fas fa-paper-plane text-xl text-white"></i>
</div>
<p class="ml-16 truncate text-sm font-medium text-gray-500">Messages Today</p>
</dt>
<dd class="ml-16 flex items-baseline">
<p class="text-3xl font-semibold text-gray-900"><%= @stats[:messages_today] %></p>
</dd>
<div class="ml-16 mt-1 flex items-center gap-3 text-xs">
<span class="inline-flex items-center gap-1 text-green-600">
<i class="fas fa-arrow-up"></i> <%= @stats[:messages_sent_today] %> sent
</span>
<span class="inline-flex items-center gap-1 text-blue-600">
<i class="fas fa-arrow-down"></i> <%= @stats[:messages_received_today] %> received
</span>
</div>
</div>
<!-- Failed Messages stat -->
<div class="relative overflow-hidden rounded-xl bg-white px-4 py-5 shadow-sm ring-1 ring-gray-900/5 sm:px-6">
<dt>
<div class="absolute rounded-lg bg-red-500 p-3">
<i class="fas fa-exclamation-triangle text-xl text-white"></i>
</div>
<p class="ml-16 truncate text-sm font-medium text-gray-500">Failed Today</p>
</dt>
<dd class="ml-16 flex items-baseline">
<p class="text-3xl font-semibold text-gray-900"><%= @stats[:failed_messages_today] %></p>
<p class="ml-2 flex items-baseline text-sm text-gray-600">
<%= @stats[:pending_messages] %> pending
</p>
</dd>
</div>
</div>
<!-- Recent Messages -->
<div class="rounded-xl bg-white shadow-sm ring-1 ring-gray-900/5">
<div class="px-4 py-5 sm:px-6 border-b border-gray-200">
<h3 class="text-lg font-semibold leading-6 text-gray-900">Recent Messages</h3>
<p class="mt-1 text-sm text-gray-500">Latest SMS activity across all gateways</p>
</div>
<div class="overflow-hidden">
<% if @recent_messages.any? %>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Message ID</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Phone Number</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Direction</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Status</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Gateway</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Created</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<% @recent_messages.each do |msg| %>
<tr class="hover:bg-gray-50 transition-colors">
<td class="whitespace-nowrap px-6 py-4 text-sm">
<code class="rounded bg-gray-100 px-2 py-1 text-xs font-mono text-gray-800"><%= msg.message_id[0..15] %>...</code>
</td>
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-900"><%= msg.phone_number %></td>
<td class="whitespace-nowrap px-6 py-4 text-sm">
<% if msg.direction == "outbound" %>
<span class="inline-flex items-center gap-1 rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10">
<i class="fas fa-arrow-up"></i> Outbound
</span>
<% else %>
<span class="inline-flex items-center gap-1 rounded-full bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-700/10">
<i class="fas fa-arrow-down"></i> Inbound
</span>
<% end %>
</td>
<td class="whitespace-nowrap px-6 py-4 text-sm">
<% case msg.status %>
<% when "delivered" %>
<span class="inline-flex rounded-full bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-700/10">Delivered</span>
<% when "sent" %>
<span class="inline-flex rounded-full bg-blue-50 px-2 py-1 text-xs font-medium text-blue-700 ring-1 ring-inset ring-blue-700/10">Sent</span>
<% when "failed" %>
<span class="inline-flex rounded-full bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-red-700/10">Failed</span>
<% when "pending" %>
<span class="inline-flex rounded-full bg-yellow-50 px-2 py-1 text-xs font-medium text-yellow-700 ring-1 ring-inset ring-yellow-700/10">Pending</span>
<% else %>
<span class="inline-flex rounded-full bg-gray-50 px-2 py-1 text-xs font-medium text-gray-700 ring-1 ring-inset ring-gray-700/10"><%= msg.status.titleize %></span>
<% end %>
</td>
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500"><%= msg.gateway&.name || "-" %></td>
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500"><%= time_ago_in_words(msg.created_at) %> ago</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div class="border-t border-gray-200 px-6 py-4">
<%= link_to admin_logs_path, class: "inline-flex items-center gap-2 text-sm font-semibold text-blue-600 hover:text-blue-500" do %>
View all logs
<i class="fas fa-arrow-right"></i>
<% end %>
</div>
<% else %>
<div class="px-6 py-14 text-center">
<i class="fas fa-inbox text-4xl text-gray-300"></i>
<p class="mt-4 text-sm text-gray-500">No messages yet</p>
</div>
<% end %>
</div>
</div>
<!-- Gateway Status -->
<div class="rounded-xl bg-white shadow-sm ring-1 ring-gray-900/5">
<div class="px-4 py-5 sm:px-6 border-b border-gray-200">
<h3 class="text-lg font-semibold leading-6 text-gray-900">Gateway Status</h3>
<p class="mt-1 text-sm text-gray-500">Active gateway devices and their performance</p>
</div>
<div class="overflow-hidden">
<% if @recent_gateways.any? %>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Name</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Device ID</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Status</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Messages Today</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium uppercase tracking-wide text-gray-500">Last Heartbeat</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200 bg-white">
<% @recent_gateways.each do |gateway| %>
<tr class="hover:bg-gray-50 transition-colors">
<td class="whitespace-nowrap px-6 py-4">
<%= link_to gateway.name, admin_gateway_path(gateway), class: "text-sm font-medium text-blue-600 hover:text-blue-500" %>
</td>
<td class="whitespace-nowrap px-6 py-4 text-sm">
<code class="rounded bg-gray-100 px-2 py-1 text-xs font-mono text-gray-800"><%= gateway.device_id %></code>
</td>
<td class="whitespace-nowrap px-6 py-4 text-sm">
<% if gateway.status == "online" %>
<span class="inline-flex items-center gap-1.5 rounded-full bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-inset ring-green-700/10">
<span class="h-1.5 w-1.5 rounded-full bg-green-500"></span>
Online
</span>
<% else %>
<span class="inline-flex items-center gap-1.5 rounded-full bg-red-50 px-2 py-1 text-xs font-medium text-red-700 ring-1 ring-inset ring-red-700/10">
<span class="h-1.5 w-1.5 rounded-full bg-red-500"></span>
Offline
</span>
<% end %>
</td>
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500">
<span class="inline-flex items-center gap-1 text-green-600">
<i class="fas fa-arrow-up text-xs"></i> <%= gateway.messages_sent_today %>
</span>
<span class="mx-1 text-gray-300">|</span>
<span class="inline-flex items-center gap-1 text-blue-600">
<i class="fas fa-arrow-down text-xs"></i> <%= gateway.messages_received_today %>
</span>
</td>
<td class="whitespace-nowrap px-6 py-4 text-sm text-gray-500">
<% if gateway.last_heartbeat_at %>
<%= time_ago_in_words(gateway.last_heartbeat_at) %> ago
<% else %>
Never
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<div class="border-t border-gray-200 px-6 py-4">
<%= link_to admin_gateways_path, class: "inline-flex items-center gap-2 text-sm font-semibold text-blue-600 hover:text-blue-500" do %>
View all gateways
<i class="fas fa-arrow-right"></i>
<% end %>
</div>
<% else %>
<div class="px-6 py-14 text-center">
<i class="fas fa-mobile-alt text-4xl text-gray-300"></i>
<p class="mt-4 text-sm text-gray-500">No gateways registered yet</p>
</div>
<% end %>
</div>
</div>
</div>