Files
archy/packages/app/src/composables/useFederatedSearch.ts
T

108 lines
2.3 KiB
TypeScript
Raw Normal View History

import { ref, watch } from 'vue'
import { mockFilms } from '@/mocks/films'
import { mockSongs } from '@/mocks/songs'
import { mockPodcasts } from '@/mocks/podcasts'
export interface SearchResult {
type: 'film' | 'song' | 'podcast'
title: string
subtitle: string
id: string
data: unknown
}
const query = ref('')
const results = ref<SearchResult[]>([])
const isSearching = ref(false)
let debounceTimer: ReturnType<typeof setTimeout> | null = null
function searchLibrary(q: string): SearchResult[] {
const lower = q.toLowerCase()
const matched: SearchResult[] = []
for (const film of mockFilms) {
if (
film.title.toLowerCase().includes(lower) ||
film.director.toLowerCase().includes(lower) ||
film.genres.some(g => g.toLowerCase().includes(lower))
) {
matched.push({
type: 'film',
title: film.title,
subtitle: `${film.year} · ${film.director}`,
id: film.id,
data: film,
})
}
}
for (const song of mockSongs) {
if (
song.title.toLowerCase().includes(lower) ||
song.artist.toLowerCase().includes(lower) ||
(song.album ?? '').toLowerCase().includes(lower)
) {
matched.push({
type: 'song',
title: song.title,
subtitle: song.artist,
id: song.id,
data: song,
})
}
}
for (const podcast of mockPodcasts) {
if (
podcast.title.toLowerCase().includes(lower) ||
(podcast.host ?? '').toLowerCase().includes(lower)
) {
matched.push({
type: 'podcast',
title: podcast.title,
subtitle: podcast.host ?? 'Unknown',
id: podcast.id,
data: podcast,
})
}
}
return matched.slice(0, 20)
}
export function useFederatedSearch() {
function search(q: string) {
query.value = q
}
function clear() {
query.value = ''
results.value = []
isSearching.value = false
}
watch(query, (q) => {
if (debounceTimer) clearTimeout(debounceTimer)
if (!q.trim()) {
results.value = []
isSearching.value = false
return
}
isSearching.value = true
debounceTimer = setTimeout(() => {
results.value = searchLibrary(q.trim())
isSearching.value = false
}, 150)
})
return {
query,
results,
isSearching,
search,
clear,
}
}