<div class="bg-white rounded-md border border-zinc-200 shadow-[0_1px_4px_rgba(0,0,0,0.04)] overflow-hidden"
data-page-ids="[{% for row in rows %}"{{ row.id }}"{% if not loop.last %},{% endif %}{% endfor %}]">
<div class="overflow-x-auto">
<table class="w-full text-left border-collapse">
<thead>
<tr class="border-b border-zinc-200 bg-zinc-50/50">
{% if can_delete or can_edit %}
<th class="py-3 px-4 w-10">
<input type="checkbox"
class="w-4 h-4 rounded border-zinc-300 text-black focus:ring-black"
:checked="allIds.length > 0 && allIds.every(id => selected.includes(id))"
:indeterminate="allIds.some(id => selected.includes(id)) && !allIds.every(id => selected.includes(id))"
@change="$event.target.checked
? selected = [...new Set([...selected, ...allIds])]
: selected = selected.filter(id => !allIds.includes(id))" />
</th>
{% endif %}
{% for col in columns %}
<th class="py-3 px-4 text-[11px] font-bold uppercase tracking-wider text-zinc-500">
<a class="hover:text-zinc-900 transition-colors flex items-center gap-1 cursor-pointer"
hx-get="/admin/{{ entity_name }}/?order_by={{ col }}&order_dir={% if order_by == col and order_dir == 'asc' %}desc{% else %}asc{% endif %}"
hx-target="#list-table"
hx-include="[data-filter-input], [name='search']">
{{ col }}
{% if order_by == col %}
{% if order_dir == "asc" %}<i class="fa-solid fa-arrow-up text-[10px]"></i>
{% else %}<i class="fa-solid fa-arrow-down text-[10px]"></i>{% endif %}
{% endif %}
</a>
</th>
{% endfor %}
{% if can_edit or can_delete %}<th class="py-3 px-4 text-[11px] font-bold uppercase tracking-wider text-zinc-500 text-right">Actions</th>{% endif %}
</tr>
</thead>
<tbody class="divide-y divide-zinc-100">
{% for row in rows %}
<tr class="hover:bg-zinc-50/60 transition-colors group">
{% if can_delete or can_edit %}
<td class="py-3 px-4">
<input type="checkbox" name="selected_ids" value="{{ row.id }}"
class="w-4 h-4 rounded border-zinc-300 text-black focus:ring-black"
x-model="selected" />
</td>
{% endif %}
{% for col in columns %}
<td class="py-3 px-4 text-sm text-zinc-700">
{% if loop.index == 1 and can_edit %}
<a href="/admin/{{ entity_name }}/{{ row.id }}/" class="font-medium text-zinc-900 hover:underline">
{% if column_types[col] == "Image" %}
{% if row.data[col] %}<img src="{{ row.data[col] }}" class="h-10 w-auto rounded object-cover" alt="{{ row.data[col] | basename }}">{% endif %}
{% elif column_types[col] == "File" %}
{{ row.data[col] | basename }}
{% else %}
{{ row.data[col] }}
{% endif %}
</a>
{% elif column_types[col] == "Image" %}
{% if row.data[col] %}<img src="{{ row.data[col] }}" class="h-10 w-auto rounded object-cover" alt="{{ row.data[col] | basename }}">{% endif %}
{% elif column_types[col] == "File" %}
{{ row.data[col] | basename }}
{% else %}
{{ row.data[col] }}
{% endif %}
</td>
{% endfor %}
{% if can_edit or can_delete %}
<td class="py-3 px-4 text-right">
<div class="flex items-center justify-end gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
{% if can_edit %}
<a href="/admin/{{ entity_name }}/{{ row.id }}/"
class="p-1.5 text-zinc-400 hover:text-zinc-900 transition-colors rounded">
<i class="fa-solid fa-pen text-xs"></i>
</a>
{% endif %}
{% if can_delete %}
<button
hx-delete="/admin/{{ entity_name }}/{{ row.id }}/delete"
hx-confirm="Delete this record?"
hx-target="closest tr"
hx-swap="outerHTML"
class="p-1.5 text-zinc-400 hover:text-red-600 transition-colors rounded">
<i class="fa-solid fa-trash text-xs"></i>
</button>
{% endif %}
</div>
</td>
{% endif %}
</tr>
{% endfor %}
{% if rows | length == 0 %}
<tr>
<td colspan="99" class="py-12 text-center text-sm text-zinc-400">
<i class="fa-solid fa-inbox text-zinc-300 text-2xl mb-2 block"></i>
No records found.
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<div class="px-6 py-3 flex items-center justify-between border-t border-zinc-100 bg-zinc-50/30">
<p class="text-xs text-zinc-500 font-medium">Page {{ page }} of {{ total_pages }}</p>
<div class="flex items-center gap-1">
{% if page > 1 %}
<button hx-get="/admin/{{ entity_name }}/?page={{ page - 1 }}"
hx-target="#list-table"
hx-include="[data-filter-input], [name='search']"
class="flex items-center justify-center w-7 h-7 rounded text-xs font-semibold text-zinc-500 hover:text-zinc-900 hover:bg-zinc-100 transition-colors">
<i class="fa-solid fa-chevron-left text-[10px]"></i>
</button>
{% endif %}
{% for p in range(1, total_pages + 1) %}
{% if p == page %}
<span class="flex items-center justify-center w-7 h-7 rounded bg-black text-white text-xs font-semibold">{{ p }}</span>
{% elif p == 1 or p == total_pages or (p >= page - 2 and p <= page + 2) %}
<button hx-get="/admin/{{ entity_name }}/?page={{ p }}"
hx-target="#list-table"
hx-include="[data-filter-input], [name='search']"
class="flex items-center justify-center w-7 h-7 rounded text-xs font-semibold text-zinc-500 hover:text-zinc-900 hover:bg-zinc-100 transition-colors">
{{ p }}
</button>
{% elif p == page - 3 or p == page + 3 %}
<span class="flex items-center justify-center w-7 h-7 text-xs text-zinc-400">…</span>
{% endif %}
{% endfor %}
{% if page < total_pages %}
<button hx-get="/admin/{{ entity_name }}/?page={{ page + 1 }}"
hx-target="#list-table"
hx-include="[data-filter-input], [name='search']"
class="flex items-center justify-center w-7 h-7 rounded text-xs font-semibold text-zinc-500 hover:text-zinc-900 hover:bg-zinc-100 transition-colors">
<i class="fa-solid fa-chevron-right text-[10px]"></i>
</button>
{% endif %}
</div>
</div>
</div>