fix: add missing th_sortable macro for sortable table headers
The subscription templates were importing th_sortable but the macro didn't exist. Added the macro to tables.html with: - Clickable header with sort indicator arrows - Alpine.js integration for sorting state - Visual feedback for current sort column and direction Also removed unused empty_state import from subscription-tiers.html. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
{% extends "admin/base.html" %}
|
||||
{% from 'shared/macros/alerts.html' import alert_dynamic, error_state %}
|
||||
{% from 'shared/macros/headers.html' import page_header_refresh %}
|
||||
{% from 'shared/macros/tables.html' import table_wrapper, table_header_custom, th_sortable, empty_state %}
|
||||
{% from 'shared/macros/tables.html' import table_wrapper, table_header_custom, th_sortable %}
|
||||
{% from 'shared/macros/modals.html' import modal_confirm %}
|
||||
|
||||
{% block title %}Subscription Tiers{% endblock %}
|
||||
|
||||
@@ -69,6 +69,65 @@
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{#
|
||||
Sortable Table Header Cell (th_sortable)
|
||||
========================================
|
||||
Renders a single sortable table header cell for use inside table_header_custom.
|
||||
|
||||
Parameters:
|
||||
- key: The data key/column name for sorting
|
||||
- label: Display label for the column
|
||||
- sort_func: Alpine.js function name to call on click (default: 'sortBy')
|
||||
- sort_order_var: Alpine.js variable for current sort order (default: 'sortOrder')
|
||||
|
||||
Usage:
|
||||
{% call table_header_custom() %}
|
||||
{{ th_sortable('name', 'Name', 'sortBy', 'sortOrder') }}
|
||||
{{ th_sortable('created_at', 'Created', 'sortBy', 'sortOrder') }}
|
||||
<th class="px-4 py-3">Actions</th>
|
||||
{% endcall %}
|
||||
|
||||
Required Alpine.js:
|
||||
sortBy: '',
|
||||
sortOrder: 'asc',
|
||||
handleSort(key) {
|
||||
if (this.sortBy === key) {
|
||||
this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
|
||||
} else {
|
||||
this.sortBy = key;
|
||||
this.sortOrder = 'asc';
|
||||
}
|
||||
this.loadData();
|
||||
}
|
||||
#}
|
||||
{% macro th_sortable(key, label, sort_func='sortBy', sort_order_var='sortOrder') %}
|
||||
<th class="px-4 py-3">
|
||||
<button
|
||||
@click="{{ sort_func }} = '{{ key }}'; {{ sort_order_var }} = {{ sort_func }} === '{{ key }}' && {{ sort_order_var }} === 'asc' ? 'desc' : 'asc'; loadData()"
|
||||
class="flex items-center space-x-1 hover:text-gray-700 dark:hover:text-gray-200 transition-colors group"
|
||||
>
|
||||
<span>{{ label }}</span>
|
||||
<span class="flex flex-col">
|
||||
<svg
|
||||
class="w-3 h-3 -mb-1 transition-colors"
|
||||
:class="{{ sort_func }} === '{{ key }}' && {{ sort_order_var }} === 'asc' ? 'text-purple-600 dark:text-purple-400' : 'text-gray-300 dark:text-gray-600 group-hover:text-gray-400'"
|
||||
fill="currentColor" viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M5 12l5-5 5 5H5z"/>
|
||||
</svg>
|
||||
<svg
|
||||
class="w-3 h-3 -mt-1 transition-colors"
|
||||
:class="{{ sort_func }} === '{{ key }}' && {{ sort_order_var }} === 'desc' ? 'text-purple-600 dark:text-purple-400' : 'text-gray-300 dark:text-gray-600 group-hover:text-gray-400'"
|
||||
fill="currentColor" viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M15 8l-5 5-5-5h10z"/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</th>
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{#
|
||||
Sortable Table Header
|
||||
=====================
|
||||
|
||||
Reference in New Issue
Block a user