Skip to content

Commit f3dab4b

Browse files
committed
add live search
1 parent 67cb4cc commit f3dab4b

1 file changed

Lines changed: 50 additions & 6 deletions

File tree

apps/sponsors/templates/sponsors/manage/sponsorship_list.html

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
</select>
2727
</div>
2828
<div class="filter-field">
29-
<input type="text" name="search" placeholder="Search..." value="{{ filter_search }}" style="width:140px;">
29+
<input type="text" name="search" id="live-search" placeholder="Search..." value="{{ filter_search }}" autocomplete="off" style="width:140px;">
3030
</div>
3131
<div class="filter-actions">
3232
<button type="submit" class="btn btn-sm btn-secondary">Go</button>
@@ -45,16 +45,16 @@
4545
{% if sponsorships %}
4646
<form method="post" action="{% url 'manage_bulk_action' %}" id="bulk-action-form">
4747
{% csrf_token %}
48-
<!-- Bulk action bar (compact, aligned) -->
48+
<!-- Bulk action bar -->
4949
<div style="display:flex;align-items:center;gap:6px;margin-bottom:6px;">
50-
<select name="action" style="height:24px;padding:0 6px;font-size:11px;border:1px solid #ccc;border-radius:3px;box-sizing:border-box;">
50+
<select name="action" style="height:28px;padding:0 8px;font-size:12px;border:1px solid #ccc;border-radius:3px;box-sizing:border-box;">
5151
<option value="">Bulk action...</option>
5252
<option value="export_csv">Export CSV</option>
5353
<option value="export_assets">Export Assets ZIP</option>
5454
<option value="send_notification">Send Notification</option>
5555
</select>
56-
<button type="submit" style="height:24px;padding:0 8px;font-size:11px;font-weight:600;border:1px solid #ccc;border-radius:3px;background:#f0f0f0;color:#333;cursor:pointer;box-sizing:border-box;font-family:inherit;" onclick="return validateBulkAction();">Apply</button>
57-
<span id="bulk-count" style="font-size:11px;color:#999;">0 selected</span>
56+
<button type="submit" style="height:28px;padding:0 10px;font-size:12px;font-weight:600;border:1px solid #ccc;border-radius:3px;background:#f0f0f0;color:#333;cursor:pointer;box-sizing:border-box;font-family:inherit;" onclick="return validateBulkAction();">Apply</button>
57+
<span style="font-size:11px;color:#999;" id="bulk-count">0 selected</span>
5858
</div>
5959

6060
<table class="manage-table">
@@ -75,7 +75,7 @@
7575
</thead>
7676
<tbody>
7777
{% for sp in sponsorships %}
78-
<tr>
78+
<tr class="sp-row" data-search="{% if sp.sponsor %}{{ sp.sponsor.name|lower }}{% endif %} {% if sp.package %}{{ sp.package.name|lower }}{% endif %} {{ sp.status|lower }} {{ sp.year|default:'' }} {% if sp.sponsorship_fee %}{{ sp.sponsorship_fee|floatformat:"0" }}{% endif %}">
7979
<td style="text-align:center;">
8080
<input type="checkbox" name="selected_ids" value="{{ sp.pk }}" class="row-select">
8181
</td>
@@ -176,6 +176,50 @@
176176
}
177177
return true;
178178
}
179+
180+
// Live search filtering
181+
(function() {
182+
var input = document.getElementById('live-search');
183+
if (!input) return;
184+
var rows = document.querySelectorAll('tr.sp-row');
185+
var debounceTimer;
186+
187+
input.addEventListener('input', function() {
188+
clearTimeout(debounceTimer);
189+
debounceTimer = setTimeout(function() {
190+
var q = input.value.toLowerCase().trim();
191+
var visible = 0;
192+
for (var i = 0; i < rows.length; i++) {
193+
var haystack = rows[i].getAttribute('data-search') || '';
194+
var match = !q || haystack.indexOf(q) !== -1;
195+
rows[i].style.display = match ? '' : 'none';
196+
if (match) visible++;
197+
}
198+
// Update empty state
199+
var emptyRow = document.getElementById('live-search-empty');
200+
if (visible === 0 && q) {
201+
if (!emptyRow) {
202+
emptyRow = document.createElement('tr');
203+
emptyRow.id = 'live-search-empty';
204+
emptyRow.innerHTML = '<td colspan="9" style="text-align:center;padding:20px;color:#999;">No sponsorships match &ldquo;' + q.replace(/</g, '&lt;') + '&rdquo;</td>';
205+
rows[0].parentNode.appendChild(emptyRow);
206+
} else {
207+
emptyRow.innerHTML = '<td colspan="9" style="text-align:center;padding:20px;color:#999;">No sponsorships match &ldquo;' + q.replace(/</g, '&lt;') + '&rdquo;</td>';
208+
emptyRow.style.display = '';
209+
}
210+
} else if (emptyRow) {
211+
emptyRow.style.display = 'none';
212+
}
213+
}, 100);
214+
});
215+
216+
// Prevent form submit on Enter in search field — just filter live
217+
input.addEventListener('keydown', function(e) {
218+
if (e.key === 'Enter') {
219+
e.preventDefault();
220+
}
221+
});
222+
})();
179223
</script>
180224
{% endblock %}
181225

0 commit comments

Comments
 (0)