rework admin conviction menu

This commit is contained in:
Echo
2025-06-26 13:05:40 -04:00
parent cfae3443cb
commit b9a2649545
3 changed files with 166 additions and 143 deletions

View File

@@ -15,7 +15,7 @@ function debounce(func, wait) {
}
export default class extends Controller {
static targets = ["searchInput", "searchResults", "selectedUsersContainer", "userIdsInput", "dateInput"]
static targets = ["searchInput", "searchResults", "selectedUsersContainer", "userIdsInput", "dateInput", "searchIcon", "searchSpinner"]
static values = {
currentUserJson: Object,
@@ -76,36 +76,39 @@ export default class extends Controller {
if (query.length < 2) {
this.searchResultsTarget.innerHTML = "";
this.searchResultsTarget.classList.remove('active');
this.hideSpinner();
return;
}
this.showSpinner();
const request = new FetchRequest('get', `${this.searchUrlValue}?query=${encodeURIComponent(query)}`, { responseKind: 'json' })
const response = await request.perform()
this.hideSpinner();
if (response.ok) {
const users = await response.json;
console.log(`Found ${users.length} users in search results`);
this.renderSearchResults(users);
} else {
this.searchResultsTarget.innerHTML = "<li class='px-4 py-2 text-red-400 text-sm'>Error searching users</li>";
this.searchResultsTarget.innerHTML = "<div class='px-4 py-2 text-red-400 text-sm'>Error searching users</div>";
this.searchResultsTarget.classList.add('active');
}
}
renderSearchResults(users) {
if (users.length === 0) {
this.searchResultsTarget.innerHTML = "<li class='px-4 py-2 text-gray-400 text-sm'>No users found</li>";
this.searchResultsTarget.innerHTML = "<div class='px-4 py-2 text-gray-400 text-sm'>No users found</div>";
} else {
this.searchResultsTarget.innerHTML = users.map(user => `
<li class="px-4 py-2 hover:bg-gray-700 cursor-pointer text-white text-sm flex items-center transition-colors"
<div class="mx-2 my-1 px-3 py-2 hover:bg-darkless cursor-pointer text-white text-sm flex items-center transition-colors rounded-lg border border-transparent hover:border-gray-600"
data-action="click->${this.identifier}#selectUser"
data-${this.identifier}-user-id-value="${user.id}"
data-${this.identifier}-user-display-name-value="${this.escapeHTML(user.display_name)}"
data-${this.identifier}-user-avatar-url-value="${user.avatar_url || ''}">
<img src="${user.avatar_url || 'https://via.placeholder.com/20'}" alt="${this.escapeHTML(user.display_name)}" class="w-5 h-5 rounded-full mr-3">
<span>${this.escapeHTML(user.display_name)}</span>
<span class="ml-auto text-xs text-gray-400">#${user.id}</span>
</li>
<span class="ml-auto text-xs text-gray-400 bg-gray-700 px-2 py-1 rounded-full">#${user.id}</span>
</div>
`).join("");
}
// Make sure the result list is shown
@@ -277,9 +280,65 @@ export default class extends Controller {
}
}
handleKeydown(event) {
async handleKeydown(event) {
if (event.key === "Escape") {
this.clearSearch();
} else if (event.key === "Enter") {
event.preventDefault();
await this.handle();
}
}
async handle() {
const query = this.searchInputTarget.value.trim();
if (/^\d+$/.test(query)) {
this.showSpinner();
try {
const request = new FetchRequest('get', `${this.searchUrlValue}?query=${encodeURIComponent(query)}&limit=1`, { responseKind: 'json' })
const response = await request.perform()
if (response.ok) {
const users = await response.json;
if (users.length > 0) {
const user = users[0];
if (!this.selectedUsers.has(parseInt(user.id, 10))) {
this.addUserToSelection(user, false);
this.updateHiddenInput();
this.updateDateLinks();
}
this.clearSearch();
this.hideSpinner();
return;
}
}
} catch (error) {
console.error(error);
}
this.hideSpinner();
}
if (query.length >= 2) {
this.showSpinner();
try {
const request = new FetchRequest('get', `${this.searchUrlValue}?query=${encodeURIComponent(query)}&limit=1`, { responseKind: 'json' })
const response = await request.perform()
if (response.ok) {
const users = await response.json;
if (users.length > 0) {
const user = users[0];
if (!this.selectedUsers.has(parseInt(user.id, 10))) {
this.addUserToSelection(user, false);
this.updateHiddenInput();
this.updateDateLinks();
}
this.clearSearch();
}
}
} catch (error) {
console.error(error);
}
this.hideSpinner();
}
}
@@ -298,6 +357,16 @@ export default class extends Controller {
}, 200);
}
showSpinner() {
if (this.hasSearchIconTarget) this.searchIconTarget.classList.add('hidden');
if (this.hasSearchSpinnerTarget) this.searchSpinnerTarget.classList.remove('hidden');
}
hideSpinner() {
if (this.hasSearchSpinnerTarget) this.searchSpinnerTarget.classList.add('hidden');
if (this.hasSearchIconTarget) this.searchIconTarget.classList.remove('hidden');
}
escapeHTML(str) {
if (str === null || str === undefined) return '';
return str.toString().replace(/[&<>"']/g, function (match) {