Search spelling suggestions across every list

This commit is contained in:
2026-08-21 11:15:06 -04:00
parent fdf3c51cb0
commit 04107ff8ab
18 changed files with 1005 additions and 82 deletions

View File

@@ -42,6 +42,7 @@
<div v-else-if="results.length === 0" class="no-results">
No results found for "{{ query }}"
<SearchSuggestion :suggestion="suggestion" @pick="applySuggestion" />
</div>
<div v-else class="results-list">
@@ -94,12 +95,14 @@
import { ref, computed, onMounted, watch, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { searchApi, knowledgebaseApi } from '../api'
import SearchSuggestion from '../components/SearchSuggestion.vue'
const route = useRoute()
const router = useRouter()
const loading = ref(false)
const results = ref([])
const suggestion = ref(null)
const query = ref('')
const searchInput = ref('')
const activeFilter = ref('all')
@@ -175,6 +178,7 @@ const filteredResults = computed(() => {
async function search(q) {
if (!q || q.length < 2) {
results.value = []
suggestion.value = null
return
}
@@ -184,6 +188,10 @@ async function search(q) {
try {
const response = await searchApi.search(q)
const data = response.data.data
// The global endpoint carries the suggestion with the results, so no second
// call is needed here. A list page that has no such key uses the
// useSearchSuggestion composable against /search/suggest instead.
suggestion.value = data?.suggestion || null
// Handle ServiceNOW redirect
if (data?.redirect?.type === 'servicenow') {
@@ -212,6 +220,14 @@ async function search(q) {
}
}
// Take the offered spelling: put it in the box and search it, so the person
// sees what was searched rather than results for a word they did not type.
function applySuggestion(word) {
searchInput.value = word
suggestion.value = null
performSearch()
}
function performSearch() {
const term = searchInput.value.trim()
if (!term) return

View File

@@ -55,6 +55,7 @@
<tr v-if="vendors.length === 0">
<td colspan="5" style="text-align: center; color: var(--text-light);">
No vendors found
<SearchSuggestion :suggestion="suggestion" @pick="applySuggestion" />
</td>
</tr>
</tbody>
@@ -189,11 +190,21 @@ import PaginationBar from '../../components/PaginationBar.vue'
import { useToast } from '../../composables/toast'
import { apiError } from '../../utils/apiError'
import { useListQuery } from '@/composables/listQuery'
import SearchSuggestion from '@/components/SearchSuggestion.vue'
const toast = useToast()
const vendors = ref([])
const loading = ref(true)
const { page, search, setPage, setSearch } = useListQuery({ onChange: loadVendors })
const { page, search, setPage, setSearch, suggestion, reportCount } = useListQuery({ onChange: loadVendors })
// Take the offered spelling. setSearch only syncs the URL and the watcher
// that reloads is suppressed because search.value already holds the new
// term, so load directly.
function applySuggestion(word) {
search.value = word
setSearch(word)
loadVendors()
}
const totalPages = ref(1)
const perPage = ref(20)
@@ -232,6 +243,7 @@ async function loadVendors() {
const response = await vendorsApi.list(params)
vendors.value = response.data.data || []
reportCount(vendors.value.length)
totalPages.value = response.data.meta?.pagination?.totalpages || response.data.meta?.pagination?.total_pages || 1
} catch (err) {
console.error('Error loading vendors:', err)