|
26 | 26 | </select> |
27 | 27 | </div> |
28 | 28 | <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;"> |
30 | 30 | </div> |
31 | 31 | <div class="filter-actions"> |
32 | 32 | <button type="submit" class="btn btn-sm btn-secondary">Go</button> |
|
45 | 45 | {% if sponsorships %} |
46 | 46 | <form method="post" action="{% url 'manage_bulk_action' %}" id="bulk-action-form"> |
47 | 47 | {% csrf_token %} |
48 | | - <!-- Bulk action bar (compact, aligned) --> |
| 48 | + <!-- Bulk action bar --> |
49 | 49 | <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;"> |
51 | 51 | <option value="">Bulk action...</option> |
52 | 52 | <option value="export_csv">Export CSV</option> |
53 | 53 | <option value="export_assets">Export Assets ZIP</option> |
54 | 54 | <option value="send_notification">Send Notification</option> |
55 | 55 | </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> |
58 | 58 | </div> |
59 | 59 |
|
60 | 60 | <table class="manage-table"> |
|
75 | 75 | </thead> |
76 | 76 | <tbody> |
77 | 77 | {% 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 %}"> |
79 | 79 | <td style="text-align:center;"> |
80 | 80 | <input type="checkbox" name="selected_ids" value="{{ sp.pk }}" class="row-select"> |
81 | 81 | </td> |
|
176 | 176 | } |
177 | 177 | return true; |
178 | 178 | } |
| 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 “' + q.replace(/</g, '<') + '”</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 “' + q.replace(/</g, '<') + '”</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 | +})(); |
179 | 223 | </script> |
180 | 224 | {% endblock %} |
181 | 225 |
|
|
0 commit comments