68 lines
1.5 KiB
TypeScript
68 lines
1.5 KiB
TypeScript
import { useSearch } from '@composables/search';
|
|
import { useDebounceFn } from '@vueuse/core';
|
|
|
|
export function useSearchUI() {
|
|
const query = ref('');
|
|
const isSearchActive = ref<boolean>(false);
|
|
const { search, loading, searchResults } = useSearch();
|
|
|
|
const filteredSearchResults = computed(() => {
|
|
if (!searchResults.value) return {};
|
|
|
|
return Object.entries(searchResults.value).reduce<Record<string>>((acc, [category, blocks]) => {
|
|
if (Array.isArray(blocks) && blocks.length > 0) {
|
|
acc[category] = blocks;
|
|
}
|
|
return acc;
|
|
}, {});
|
|
});
|
|
|
|
const hasResults = computed(() => {
|
|
if (!searchResults.value) return false;
|
|
|
|
return Object.values(searchResults.value).some((blocks) => Array.isArray(blocks) && blocks.length > 0);
|
|
});
|
|
|
|
function getBlockTitle(category: string) {
|
|
return category.charAt(0).toUpperCase() + category.slice(1);
|
|
}
|
|
|
|
function clearSearch() {
|
|
query.value = '';
|
|
searchResults.value = null;
|
|
}
|
|
|
|
function toggleSearch(value: boolean) {
|
|
isSearchActive.value = value !== undefined ? value : !isSearchActive.value;
|
|
}
|
|
|
|
const debouncedSearch = useDebounceFn(async () => {
|
|
if (query.value) {
|
|
await search(query.value);
|
|
} else {
|
|
searchResults.value = null;
|
|
}
|
|
}, 750);
|
|
|
|
watch(
|
|
() => query.value,
|
|
async () => {
|
|
await debouncedSearch();
|
|
},
|
|
{
|
|
immediate: false,
|
|
},
|
|
);
|
|
|
|
return {
|
|
query,
|
|
isSearchActive,
|
|
loading,
|
|
searchResults,
|
|
filteredSearchResults,
|
|
hasResults,
|
|
getBlockTitle,
|
|
clearSearch,
|
|
toggleSearch,
|
|
};
|
|
}
|