You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.9 KiB
JavaScript
82 lines
2.9 KiB
JavaScript
import Alpine from 'alpinejs'
|
|
import Fuse from 'fuse.js'
|
|
|
|
const SHOW_MORE_INCREMENT = 15
|
|
const FUSE_OPTIONS = {
|
|
includeScore: true,
|
|
keys: [
|
|
'nome',
|
|
'cognome',
|
|
'tags',
|
|
{ name: 'nomeCompleto', getFn: user => `${user.nome} ${user.cognome}` },
|
|
],
|
|
}
|
|
|
|
const SORT_MODES = {
|
|
chronological: () => 0,
|
|
name: (a, b) => (a.nome < b.nome ? -1 : 1),
|
|
surname: (a, b) => (a.cognome < b.cognome ? -1 : 1),
|
|
}
|
|
|
|
function getSortedUserList(original, mode) {
|
|
return [...original].sort(SORT_MODES[mode])
|
|
}
|
|
|
|
Alpine.data('utenti', () => ({
|
|
searchField: '', // two-way binding for the search input field
|
|
sortMode: 'chronological', // two-way binding for the sorting mode
|
|
fetchedUsers: [], // hold complete user list
|
|
sortedUserBuffer: [], // Yet another buffer of the user list for the sort mode
|
|
fuse: new Fuse([], FUSE_OPTIONS), // current fuse instance, used to filter the list above
|
|
searchResultsBuffer: [], // stores the full current search
|
|
searchResults: [], // list to renderer on screen with a subset of the whole search results buffer
|
|
async init() {
|
|
// Get user list from server
|
|
const response = await fetch('/api/utenti')
|
|
this.fetchedUsers = await response.json()
|
|
|
|
// This will call the function "showMore()" when the user is near the end of the list
|
|
new IntersectionObserver(entries => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
console.log('Near the bottom of the page')
|
|
this.showMore()
|
|
}
|
|
})
|
|
}).observe(this.$refs.spinner)
|
|
|
|
// Initialize with an empty query
|
|
this.updateSortMode()
|
|
this.updateSearch()
|
|
},
|
|
showMore() {
|
|
// setTimeout(() => {
|
|
// Updates the final "searchResults" list with more items from the previous buffer
|
|
const newCount = this.searchResults.length + SHOW_MORE_INCREMENT
|
|
this.searchResults = this.searchResultsBuffer.slice(0, newCount)
|
|
// }, 250) // For fun
|
|
},
|
|
setResults(list) {
|
|
this.searchResultsBuffer = list.filter(
|
|
entry => entry.score === undefined || entry.score <= 0.25
|
|
)
|
|
this.searchResults = this.searchResultsBuffer.slice(0, SHOW_MORE_INCREMENT)
|
|
},
|
|
updateSortMode() {
|
|
this.sortedUserBuffer = getSortedUserList(this.fetchedUsers, this.sortMode)
|
|
this.fuse.setCollection(this.sortedUserBuffer)
|
|
this.updateSearch()
|
|
},
|
|
updateSearch() {
|
|
console.time('search')
|
|
if (this.searchField.trim().length === 0) {
|
|
// Reset the result list
|
|
this.setResults(this.sortedUserBuffer.map(user => ({ item: user })))
|
|
} else {
|
|
// Update the result list with the new results
|
|
this.setResults(this.fuse.search(this.searchField))
|
|
}
|
|
console.timeEnd('search')
|
|
},
|
|
}))
|