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
103 lines
4 KiB
Text
103 lines
4 KiB
Text
<div class="container mx-auto px-4 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="flex items-center justify-between mb-4">
|
|
<span class="text-sm text-gray-500 dark:text-gray-400">
|
|
{gettext("Auto-refreshes every 5 seconds")}
|
|
</span>
|
|
<%= if @loading do %>
|
|
<span class="flex items-center gap-2 text-sm text-indigo-600 dark:text-indigo-400">
|
|
<svg
|
|
class="animate-spin h-4 w-4"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4" />
|
|
<path
|
|
class="opacity-75"
|
|
fill="currentColor"
|
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
/>
|
|
</svg>
|
|
{gettext("Updating...")}
|
|
</span>
|
|
<% end %>
|
|
</div>
|
|
|
|
<div class="overflow-x-auto">
|
|
<table class="min-w-full divide-y divide-gray-300 dark:divide-gray-700">
|
|
<thead>
|
|
<tr>
|
|
<th>{gettext("Attempted At")}</th>
|
|
<th>{gettext("Error Type")}</th>
|
|
<th>{gettext("Error Message")}</th>
|
|
<th>{gettext("Raw Packet")}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<%= for bad_packet <- @bad_packets do %>
|
|
<tr>
|
|
<td>
|
|
<span class="text-sm">
|
|
{Calendar.strftime(
|
|
bad_packet.attempted_at || bad_packet.inserted_at,
|
|
"%Y-%m-%d %H:%M:%S UTC"
|
|
)}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="inline-flex items-center rounded-md bg-red-100 px-2 py-1 text-xs font-medium text-red-700 dark:bg-red-400/10 dark:text-red-400">
|
|
{bad_packet.error_type || gettext("Unknown")}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="text-sm text-red-600 dark:text-red-400 font-mono">
|
|
{bad_packet.error_message || gettext("No error message")}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<div class="max-w-md">
|
|
<div class="text-xs font-mono text-gray-600 dark:text-gray-300 break-all">
|
|
<%= if is_binary(bad_packet.raw_packet) do %>
|
|
{Aprsme.EncodingUtils.sanitize_string(bad_packet.raw_packet)}
|
|
<% else %>
|
|
{bad_packet.raw_packet}
|
|
<% end %>
|
|
</div>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<% end %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<%= if length(@bad_packets) == 0 do %>
|
|
<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 mt-8">
|
|
<div class="px-6 py-8 text-center">
|
|
<div class="flex justify-center mb-4">
|
|
<div class="w-16 h-16 bg-green-100 dark:bg-green-500/20 rounded-full flex items-center justify-center">
|
|
<svg
|
|
class="w-8 h-8 text-green-600 dark:text-green-400"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
<h3 class="text-lg font-semibold">{gettext("No bad packets")}</h3>
|
|
<p class="text-gray-500 dark:text-gray-400">{gettext("All packets are parsing successfully!")}</p>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|