ldc-supportweb/resources/ts/bo/components/SearchBelongsToDropdownComponent.vue
2023-10-12 15:56:11 +02:00

260 lines
6.5 KiB
Vue

<template>
<div>
<Transition name="fade">
<p
v-if="intMessage"
class="message"
>
{{ intMessage }}
</p>
</Transition>
<VueSelect
:id="intName"
ref="select"
:loading="intLoading"
v-model="intModelRelated"
:clearable="false"
:label="intLabel"
:options="intData"
@search="search"
:filterable="true"
:disabled="intReadonly || intDisabled"
:searchable="true"
:placeholder="intPlaceholder"
>
<template #list-footer>
<li class="pagination">
<button
@click="
$event.preventDefault();
intPage -= 1;
"
:disabled="!intHasPrevPage"
class="btn btn-sm btn-primary mt-2 mb-2 ms-2 me-2"
>
{{ __("Précédent") }}
</button>
<button
@click="
$event.preventDefault();
intPage += 1;
"
:disabled="!intHasNextPage"
class="btn btn-sm btn-primary mt-2 mb-2"
>
{{ __("Suivant") }}
</button>
</li>
</template>
</VueSelect>
<input
type="hidden"
v-model="intModelRelated.value"
:name="intName"
>
</div>
</template>
<script lang="ts">
import type { PropType } from "vue";
import { defineComponent } from "vue";
import VueSelect from "vue-select";
import route from "./../../modules/route";
import trans from "./../../modules/trans";
export default defineComponent({
components: {
VueSelect,
},
mixins: [route, trans],
props: {
label: {
type: String,
default: "",
},
name: {
type: String,
default: "",
},
targetmodel: {
type: String,
default: "",
},
routename: {
type: String,
default: "",
},
modelrelated: {
type: Object as PropType<VselectOption>,
default: null
},
modelselected: {
type: Object as PropType<VselectOption>,
default: null
},
readonly: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
default: "",
},
helper: {
type: String,
default: "",
},
required: {
type: Boolean,
default: true,
},
searchlabel: {
type: String,
default: "name",
}
},
data(): {
intName: string;
intRouteName: string;
intTargetModel: string;
intPlaceholder: string;
intDisabled: boolean;
intReadonly: boolean;
intModelRelated: VselectOption;
intLoading: boolean;
intSearchText: string;
intData: LaravelModelList;
intPage: number;
intPerPage: number;
intHasNextPage: boolean;
intHasPrevPage: boolean;
intMessage: string | null;
intLabel: string;
} {
return {
intName: "",
intRouteName: "",
intTargetModel: "",
intPlaceholder: "",
intDisabled: false,
intReadonly: false,
intModelRelated: {
id: 0,
name: "",
value: 0,
},
intLoading: false,
intSearchText: "",
intData: [],
intPage: 1,
intPerPage: 12,
intHasNextPage: true,
intHasPrevPage: false,
intMessage: null,
intLabel: "name",
};
},
mounted() {
const json = String(this.$attrs.json ?? "{}"),
data = JSON.parse(json);
this.intName = (this.name) ? this.name : data.name;
this.intRouteName = (this.routename) ? this.routename : data.routeName;
this.intTargetModel = (this.targetmodel) ? this.targetmodel : data.targetModel;
this.intPlaceholder = (this.placeholder) ? this.placeholder : data.placeholder;
this.intDisabled = (this.disabled) ? this.disabled : !!data.disabled;
this.intReadonly = (this.readonly) ? this.readonly : !!data.readonly;
if ((this.modelselected && this.modelselected.value !== null) || data.modelSelected) {
this.intModelRelated = (this.modelselected) ? this.modelselected : data.modelSelected;
} else if ((this.modelrelated && this.modelrelated.value !== null) || data.modelRelated) {
this.intModelRelated = (this.modelrelated) ? this.modelrelated : data.modelRelated;
} else {
this.intModelRelated = {
id: 0,
name: "",
value: 0,
};
}
this.intLabel = (this.searchlabel) ? this.searchlabel : data.searchlabel ?? "name";
this.search(false);
},
watch: {
intPage() {
if (this.intPage < 1) {
this.intPage = 1;
}
if (this.intPage > 1) {
this.intHasPrevPage = true;
} else {
this.intHasPrevPage = false;
}
this.search();
},
intData() {
if (this.intData.length == this.intPerPage) {
this.intHasNextPage = true;
} else {
this.intHasNextPage = false;
}
},
},
methods: {
search(search: false | null | string = null): void {
if (search !== false && search !== null) {
this.intSearchText = search;
}
let init = search === false ? true : false,
routeUrl = this.route(this.intRouteName);
if (!routeUrl) {
throw new Error("undefined route " + this.intRouteName);
}
if (this.intPage) {
routeUrl += "?targetModel=" + this.intTargetModel + "&page=" + this.intPage;
}
if (this.intSearchText) {
routeUrl += "&search=" + this.intSearchText;
}
this.intLoading = true;
window.axios
.get(routeUrl)
.then((response) => {
this.intData = response.data.data as LaravelModelList;
if (init && this.intData.length && this.intModelRelated.value === null) {
this.intModelRelated = this.intData[0] as VselectOption;
}
})
.catch((e) => {
this.intMessage =
"Erreur lors de l'opération, merci d'actualiser la page.";
if (e.response?.status === 422) {
const errors = e.response?.data?.errors;
if (errors instanceof String) {
this.intMessage = errors as string;
}
if (errors instanceof Object) {
this.intMessage = Object.values(errors).reduce(function (
previous,
current
) {
return String(previous) + String(current);
}) as string;
}
console.warn(errors);
}
})
.then(() => {
this.intLoading = false;
});
},
},
});
</script>
<style lang="scss">
@import "vue-select/dist/vue-select.css";
:root {
--vs-dropdown-max-height: 15rem;
}
</style>