aprs.me/lib/aprsme_web/live/packets_live/index.html.heex
Graham McIntire 4de48294c6
Remove DaisyUI, migrate to pure Tailwind CSS with TailwindUI patterns
Replace all DaisyUI component classes with pure Tailwind CSS utility
classes following TailwindUI conventions. Use dark: variants for dark
mode instead of DaisyUI's data-theme semantic color system.

- Remove DaisyUI plugin and theme vendor files
- Configure Tailwind v4 custom dark variant for data-theme attribute
- Migrate all components: cards, tables, badges, buttons, forms,
  navigation, dropdowns, modals, alerts, star ratings, spinners
- Update all auth pages (login, register, settings, password reset,
  confirmation) to TailwindUI card layout
- Update content pages (about, API docs, status, packets, bad packets,
  info, weather) to TailwindUI patterns
- Replace opacity-based text styling with semantic gray colors
- Update test assertions to match new class names
2026-02-19 10:07:50 -06:00

164 lines
7 KiB
Text

<div class="container mx-auto max-w-7xl py-8">
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
<div class="px-6 py-6">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-700">
<thead>
<tr>
<th>{gettext("Sender")}</th>
<th>{gettext("SSID")}</th>
<th>{gettext("Base Callsign")}</th>
<th>{gettext("Data Type")}</th>
<th>{gettext("Symbol")}</th>
<th>{gettext("Path")}</th>
<th>{gettext("Latitude")}</th>
<th>{gettext("Longitude")}</th>
<th>{gettext("Device")}</th>
</tr>
</thead>
<tbody>
<%= for packet <- @packets do %>
<tr>
<td>
<.link
navigate={~p"/packets/#{Map.get(packet, :base_callsign, Map.get(packet, "base_callsign", ""))}"}
class="font-semibold text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
>
{Map.get(packet, :sender, Map.get(packet, "sender", ""))}
</.link>
</td>
<td>
<span class="text-sm">
{Map.get(packet, :ssid, Map.get(packet, "ssid", ""))}
</span>
</td>
<td>
<.link
navigate={~p"/packets/#{Map.get(packet, :base_callsign, Map.get(packet, "base_callsign", ""))}"}
class="font-semibold text-indigo-600 hover:text-indigo-500 dark:text-indigo-400 dark:hover:text-indigo-300"
>
{Map.get(packet, :base_callsign, Map.get(packet, "base_callsign", ""))}
</.link>
</td>
<td>
<span class="inline-flex items-center rounded-md bg-indigo-100 px-2 py-1 text-xs font-medium text-indigo-700 dark:bg-indigo-400/10 dark:text-indigo-400">
{Map.get(packet, :data_type, Map.get(packet, "data_type", ""))}
</span>
</td>
<td>
<span class="text-xs font-mono">
<% data = Map.get(packet, :data_extended) || %{}
raw_table =
Map.get(data, :symbol_table_id) || Map.get(data, "symbol_table_id") || "/"
table = if raw_table in ["/", "\\", "]"], do: raw_table, else: "/"
code = Map.get(data, :symbol_code) || Map.get(data, "symbol_code") || ">" %>
{table}{code}
</span>
</td>
<td>
<span class="text-xs font-mono text-gray-500 dark:text-gray-400">
{Map.get(packet, :path, Map.get(packet, "path", ""))}
</span>
</td>
<td>
<span class="text-xs font-mono">
<% lat =
Map.get(packet, :lat) ||
if(
Map.has_key?(packet, :location) and not is_nil(packet.location) and
function_exported?(Aprsme.Packet, :lat, 1),
do: Aprsme.Packet.lat(packet),
else: nil
) ||
case Map.get(packet, :data_extended) do
%{} = data_ext ->
case Map.get(data_ext, :latitude) || Map.get(data_ext, "latitude") do
{:ok, value} -> value
value -> value
end
_ ->
nil
end %>
<%= if not is_nil(lat) do %>
<%= if is_float(lat) do %>
{:io_lib.format("~.6f", [lat]) |> List.to_string()}
<% else %>
<%= if is_binary(lat) do %>
{Regex.replace(~r/(\d+\.\d{1,6})\d*/, lat, "\\1")}
<% else %>
{lat}
<% end %>
<% end %>
<% else %>
""
<% end %>
</span>
</td>
<td>
<span class="text-xs font-mono">
<% lon =
Map.get(packet, :lon) ||
if(
Map.has_key?(packet, :location) and not is_nil(packet.location) and
function_exported?(Aprsme.Packet, :lon, 1),
do: Aprsme.Packet.lon(packet),
else: nil
) ||
case Map.get(packet, :data_extended) do
%{} = data_ext ->
case Map.get(data_ext, :longitude) || Map.get(data_ext, "longitude") do
{:ok, value} -> value
value -> value
end
_ ->
nil
end %>
<%= if not is_nil(lon) do %>
<%= if is_float(lon) do %>
{:io_lib.format("~.6f", [lon]) |> List.to_string()}
<% else %>
<%= if is_binary(lon) do %>
{Regex.replace(~r/(\d+\.\d{1,6})\d*/, lon, "\\1")}
<% else %>
{lon}
<% end %>
<% end %>
<% else %>
""
<% end %>
</span>
</td>
<td>
<span class="text-xs font-mono">
{Map.get(packet, :device_identifier, Map.get(packet, "device_identifier", ""))}
</span>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
</div>
<%= if length(@packets) == 0 do %>
<div class="text-center py-12">
<div class="flex justify-center mb-4">
<svg class="w-16 h-16 text-gray-400 dark:text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4"
/>
</svg>
</div>
<h3 class="text-lg font-medium mb-2">{gettext("No packets")}</h3>
<p class="text-gray-500 dark:text-gray-400">{gettext("Packets will appear here as they are received.")}</p>
</div>
<% end %>
</div>