salix-front/src/components/ui/VnSearchbar.vue

184 lines
4.1 KiB
Vue

<script setup>
import { onMounted, ref, watch } from 'vue';
import { useQuasar } from 'quasar';
import { useArrayData } from 'composables/useArrayData';
import VnInput from 'src/components/common/VnInput.vue';
import { useI18n } from 'vue-i18n';
import { useStateStore } from 'src/stores/useStateStore';
const quasar = useQuasar();
const { t } = useI18n();
const state = useStateStore();
const props = defineProps({
dataKey: {
type: String,
required: true,
},
label: {
type: String,
default: 'Search',
},
info: {
type: String,
default: '',
},
redirect: {
type: Boolean,
default: true,
},
url: {
type: String,
default: '',
},
filter: {
type: Object,
default: null,
},
where: {
type: Object,
default: null,
},
order: {
type: String,
default: '',
},
limit: {
type: Number,
default: 20,
},
userParams: {
type: Object,
default: null,
},
staticParams: {
type: Array,
default: () => [],
},
exprBuilder: {
type: Function,
default: null,
},
customRouteRedirectName: {
type: String,
default: '',
},
whereFilter: {
type: Function,
default: undefined,
},
});
const searchText = ref();
let arrayDataProps = { ...props };
if (props.redirect)
arrayDataProps = {
...props,
...{
navigate: {
customRouteRedirectName: props.customRouteRedirectName,
searchText: searchText.value,
},
},
};
let arrayData = useArrayData(props.dataKey, arrayDataProps);
let store = arrayData.store;
watch(
() => props.dataKey,
(val) => {
arrayData = useArrayData(val, { ...props });
store = arrayData.store;
}
);
onMounted(() => {
const params = store.userParams;
if (params && params.search) {
searchText.value = params.search;
}
});
async function search() {
const staticParams = Object.entries(store.userParams);
arrayData.reset(['skip', 'page']);
const filter = {
params: {
...Object.fromEntries(staticParams),
search: searchText.value,
},
...{ filter: props.filter },
};
if (props.whereFilter) {
filter.filter = {
where: props.whereFilter(searchText.value),
};
delete filter.params.search;
}
await arrayData.applyFilter(filter);
}
</script>
<template>
<Teleport to="#searchbar" v-if="state.isHeaderMounted()">
<QForm @submit="search" id="searchbarForm">
<VnInput
id="searchbar"
v-model.trim="searchText"
:placeholder="t(props.label)"
dense
standout
autofocus
data-cy="vnSearchBar"
>
<template #prepend>
<QIcon
v-if="!quasar.platform.is.mobile"
class="cursor-pointer"
name="search"
@click="search"
/>
</template>
<template #append>
<QIcon
v-if="props.info && $q.screen.gt.xs"
name="info"
class="cursor-info"
>
<QTooltip>{{ t(props.info) }}</QTooltip>
</QIcon>
</template>
</VnInput>
</QForm>
</Teleport>
</template>
<style lang="scss" scoped>
@media screen and (min-width: $breakpoint-sm-max) {
.q-field {
width: 450px;
}
}
.q-field {
transition: width 0.36s;
}
</style>
<style lang="scss">
.cursor-info {
cursor: help;
}
#searchbar {
.q-field--standout.q-field--highlighted .q-field__control {
background-color: white;
color: black;
.q-field__native,
.q-icon {
color: black !important;
}
}
}
</style>