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') }, }))