Forked from
websites / monnaie-libre-fr
1262 commits behind the upstream repository.
-
Emmanuel Salomon authoredEmmanuel Salomon authored
SearchContainer.vue 5.56 KiB
<template>
<div class="container">
<slot name="header">
<PageHeader v-if="title" :document="{ title }" />
</slot>
<div class="md:flex justify-between mb-8">
<div class="w-full">
<div class="md:flex">
<TInputIcon
v-model="query"
type="search"
:placeholder="searchPlaceholder || $t('search')"
input-class="rounded-full"
icon="search"
icon-class="text-2xl text-blue-100 dark:text-gray-600"
class="flex-1"
has-focus
/>
<slot name="search" />
</div>
<slot name="items" :items="computedResults">
<section v-if="computedResults.length" class="mt-8">
<transition-group name="list">
<nuxt-link
v-for="(item, index) of computedResults"
:id="
(index === 0 ||
computedResults[index - 1].firstLetter !==
item.firstLetter) &&
item.firstLetter
"
:key="item.path"
:to="item.path.replace(/^\/pages\//, '/')"
class="block cursor-pointer dark-hover:bg-gray-700 hover:bg-gray-100 mb-2 p-2 rounded-lg transition-colors"
>
<slot name="item" :item="item">
<h1 class="text-xl" v-html="item.title" />
<div
class="font-light text-gray-600 dark:text-gray-400"
v-html="item.description"
/>
</slot>
</nuxt-link>
</transition-group>
</section>
</slot>
<SearchNoResult v-if="query.length && hasNoResult">
<slot name="noResult" :query="query">
<ul class="list-disc list-inside mt-3">
<li>
<nuxt-link
:to="`/recherche?q=${query}`"
class="hover:underline"
>
{{ $t('noResult.searchWholeSite', { query }) }}
</nuxt-link>
</li>
<li>
<a
:href="`https://forum.monnaie-libre.fr/search?q=${query}`"
class="hover:underline"
target="_blank"
rel="noopener noreferrer"
>
{{ $t('noResult.searchOnForum', { query }) }}
</a>
</li>
</ul>
</slot>
</SearchNoResult>
</div>
<aside class="sticky h-full top-24 ml-12 bottom-12">
<slot
name="sidebar"
:query="query"
:computedResults="computedResults"
/>
</aside>
</div>
<slot name="footer" :query="query" :computedResults="computedResults" />
</div>
</template>
<script>
import { debounce, highlight } from '~/libs/helpers'
export default {
name: 'SearchContainer',
props: {
results: {
type: Array,
required: true,
},
title: {
type: String,
default: null,
},
searchPlaceholder: {
type: String,
default: null,
},
searchFunction: {
type: Function,
required: true,
},
getQueryUrl: {
type: Function,
default(q) {
return new URLSearchParams({
q,
})
},
},
},
data() {
return {
query: '',
searchResults: [],
hasNoResult: false,
}
},
computed: {
computedResults() {
return this.searchResults.map((item) => ({
...item,
firstLetter: item.title.replace(/^<mark>/, '')[0].toUpperCase(), // ! remove <mark> if title start by highlighten query
}))
},
},
watch: {
query: debounce(function () {
this.search()
}, 500),
},
mounted() {
this.searchResults = this.results
this.query = this.$route.query.q || ''
},
methods: {
async search(force) {
const query = this.query.trim()
if (query.length || force) {
const results = await this.searchFunction(this.query)
if (results.length) {
this.hasNoResult = false
this.searchResults = highlight(this.query, results)
} else {
this.hasNoResult = true
this.searchResults = []
}
} else {
this.searchResults = this.results
this.hasNoResult = false
}
// Replace url with query string
const queryUrl = this.getQueryUrl(query).toString()
history.replaceState(
{},
null,
this.$route.path + (queryUrl.length ? `?${queryUrl}` : '')
)
},
},
}
// @ManUtopiK: Test avec composition-api
// import {
// defineComponent,
// ref,
// useContext,
// useAsync,
// useFetch,
// onBeforeMount,
// watch,
// } from '@nuxtjs/composition-api'
// export default defineComponent({
// name: 'FaqPage',
// setup() {
// const { route, query, $content } = useContext()
// const query = ref(query.value.q)
// const results = useAsync(() => $content('faq').fetch())
// const documentFAQ = useAsync(() => $content('ui/faq').fetch())
// onBeforeMount(async () => {
// results.value = await $content('faq').search(query.value).fetch()
// })
// watch(query, async (val) => {
// val = val.trim()
// results.value = await $content('faq').search(val).fetch()
// const queryPath = val.length ? `?s=${encodeURIComponent(val)}` : ''
// history.pushState({}, null, route.value.path + queryPath)
// })
// console.log(documentFAQ.value)
// return { query, results, documentFAQ }
// },
// })
</script>