ldc-legaulois/resources/ts/fo/components/MeilisearchModelsComponent.vue

200 lines
5.8 KiB
Vue

<template>
<div class="search-component row">
<!-- INPUT -->
<div class="col-12 col-md-6 mb-5 mx-auto text-center">
<div class="input-group mx-auto">
<div class="form-floating">
<input
id="search-input"
ref="searchInput"
class="form-control fs-5 border-dark border-1 border-end-0 f-bourton-base shadow-none rounded-start-2"
type="text"
name="search"
:value="searchValue"
@keydown="executeSearchFromKey($event)"
:placeholder="__('Rechercher...')"
>
<label for="search-input">{{ __('Rechercher...') }}</label>
</div>
<button
class="btn btn-outline-dark shadow-none border-end-0"
id="btn-search-empty"
type="button"
@click="resetSearch()"
:title="__('Effacer la recherche')"
:aria-label="__('Effacer le contenu la barre de recherche')"
>
<i class="fa-solid fa-xmark" />
</button>
<button
class="btn btn-outline-dark shadow-none rounded-end-2"
type="button"
@click="setSearch()"
:title="__('Lancer la recherche')"
:aria-label="__('Lancer la recherche')"
>
<i class="fa-solid fa-magnifying-glass" />
</button>
</div>
</div>
<!-- RESULTS -->
<template v-if="elements.length">
<template
v-for="(element, elementKey) in elements"
:key="elementKey"
>
<div class="col-12 mb-5">
<MeilisearchPaginateViewsComponent
:identifier="elementKey"
:search="searchInput?.value"
:route-url="routeUrl"
:trans-name="element.name"
:class-name="element.class"
:default-models="element.models"
@reset-search="resetSearch"
/>
</div>
</template>
</template>
</div>
</template>
<script lang="ts" setup>
import { __ } from "@modules/trans";
import type { SwiperContainer } from "swiper/element";
import { computed, nextTick, onMounted, ref, useAttrs } from "vue";
import axios from "~/axios";
import parseLaravelErrorMessages from "../../modules/parseLaravelErrorMessages";
import MeilisearchPaginateViewsComponent from "./MeilisearchPaginateViewsComponent.vue";
defineOptions({
name: "MeilisearchModelsComponent"
});
// * ATTRIBUTES
const attrs = useAttrs();
// * REFS
const searchInput = ref<HTMLInputElement|null>(null);
// * DATA
const elements = ref<Array<{name: string, class: string, models: LaravelPaginator}>>([]);
const searchValue = ref<string|null>(null);
const routeUrl = ref<string>("");
const loading = ref<boolean>(false);
// * COMPUTED
const isUsedWithProps = computed<boolean>(() => attrs.json === undefined);
// * LIFECYCLE
onMounted(() => {
const json = String(attrs.json ?? "{}"),
data = JSON.parse(json);
if (!isUsedWithProps.value) {
elements.value = data.elements;
searchValue.value = data.searchValue;
routeUrl.value = data.routeUrl;
}
});
// * METHODS
/**
* Reset all filters activated.
* @return void
*/
function resetSearch(): void {
searchInput.value!.value = "";
searchValue.value = "";
setSearch();
history.replaceState("Object", "", "/recherche");
}
/**
* Execute the search when the enter key is down.
* @return void
*/
function executeSearchFromKey(event: KeyboardEvent): void {
if (event.key === "Enter") {
setSearch();
}
}
/**
* Get models by activated filters.
* @return void
*/
function setSearch(): void {
if (!routeUrl.value) {
throw new Error(`Route ${routeUrl.value} doesn't exist`);
}
searchValue.value = String(searchInput.value?.value);
loading.value = true;
window.axios
.post(routeUrl.value, {
"texte": searchValue.value,
"models": elements.value.map((element) => { return element.class; }),
"page": 1,
})
.then((response) => {
elements.value.forEach((element, index) => {
// Erase existing results by the new.
element.models = response.data[index];
// Update sliders in children components.
const swiperContainer = document.querySelector(`.swiper-search-${index}`) as SwiperContainer|null;
swiperContainer?.swiper.slideTo(0);
nextTick(() => {
swiperContainer?.swiper.update();
});
});
history.replaceState("Object", "", "/recherche" + ((searchValue.value?.length) ? "?texte=" + searchValue.value : ""));
}).then(() => {
loading.value = false;
document.getElementById("search-input")?.scrollIntoView();
})
.catch(ajaxErrorHandler);
}
/**
* Return error message after the ajax call.
* @param e any
* @return void
*/
function ajaxErrorHandler(e: unknown): void {
let message = __("Une erreur est survenue");
if (axios.isAxiosError<LaravelValidationErrorResponse>(e)) {
if (e.response) {
if (e.response.status === 422) {
message = parseLaravelErrorMessages.methods.parseValidationErrors(
e.response?.data?.errors ?? {}
) || message;
if (window.vueDebug) {
console.warn(e.response.data.errors);
}
} else if (e.response.status === 419) {
console.log(__("Votre session a expiré, la page va être rechargée"));
setTimeout(() => window.location.reload(), 2000);
} else if (e.response.status === 403) {
console.log(__("Vous n'êtes pas autorisé a effectuer cette action"));
setTimeout(() => window.location.reload(), 2000);
} else {
if (window.vueDebug) {
console.error(e);
}
}
} else if (e.request) {
console.error("Aucune réponse reçue :", e.request);
} else {
console.error("Erreur de configuration de la requête :", e.message);
}
}
console.log(message);
}
</script>
<style lang="scss">
#search-input {
scroll-margin-top: 8rem;
}
</style>