|
|
|
@ -1,11 +1,11 @@
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import { defineComponent, PropType } from "vue"
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
|
import { defineComponent, PropType, ref, watch } from "vue"
|
|
|
|
|
import { GET } from "../api";
|
|
|
|
|
import { useBudgetsStore } from "../stores/budget";
|
|
|
|
|
|
|
|
|
|
export interface Suggestion {
|
|
|
|
|
ID : string
|
|
|
|
|
Name : string
|
|
|
|
|
ID: string
|
|
|
|
|
Name: string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface Data {
|
|
|
|
@ -14,88 +14,88 @@ interface Data {
|
|
|
|
|
Suggestions: Suggestion[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default defineComponent({
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
Selected: undefined,
|
|
|
|
|
SearchQuery: this.modelValue || "",
|
|
|
|
|
Suggestions: new Array<Suggestion>(),
|
|
|
|
|
} as Data
|
|
|
|
|
},
|
|
|
|
|
props: {
|
|
|
|
|
modelValue: Object as PropType<Suggestion>,
|
|
|
|
|
type: String
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
SearchQuery() {
|
|
|
|
|
this.load(this.$data.SearchQuery);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
saveTransaction(e : MouseEvent) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
},
|
|
|
|
|
load(text : String) {
|
|
|
|
|
this.$emit('update:modelValue', {ID: null, Name: text});
|
|
|
|
|
if (text == ""){
|
|
|
|
|
this.$data.Suggestions = [];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const budgetStore = useBudgetsStore();
|
|
|
|
|
GET("/budget/" + budgetStore.CurrentBudgetID + "/autocomplete/" + this.type + "?s=" + text)
|
|
|
|
|
.then(x=>x.json())
|
|
|
|
|
.then(x => {
|
|
|
|
|
let suggestions = x || [];
|
|
|
|
|
if(suggestions.length > 10){
|
|
|
|
|
suggestions = suggestions.slice(0, 10);
|
|
|
|
|
}
|
|
|
|
|
this.$data.Suggestions = suggestions;
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
keypress(e : KeyboardEvent) {
|
|
|
|
|
console.log(e.key);
|
|
|
|
|
if(e.key == "Enter") {
|
|
|
|
|
const selected = this.$data.Suggestions[0];
|
|
|
|
|
this.selectElement(selected);
|
|
|
|
|
const el = (<HTMLInputElement>e.target);
|
|
|
|
|
const inputElements = Array.from(el.ownerDocument.querySelectorAll('input:not([disabled]):not([readonly])'));
|
|
|
|
|
const currentIndex = inputElements.indexOf(el);
|
|
|
|
|
const nextElement = inputElements[currentIndex < inputElements.length - 1 ? currentIndex + 1 : 0];
|
|
|
|
|
(<HTMLInputElement>nextElement).focus();
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
modelValue: Suggestion,
|
|
|
|
|
type: String
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
selectElement(element : Suggestion) {
|
|
|
|
|
this.$data.Selected = element;
|
|
|
|
|
this.$data.Suggestions = [];
|
|
|
|
|
this.$emit('update:modelValue', element);
|
|
|
|
|
},
|
|
|
|
|
select(e : MouseEvent) {
|
|
|
|
|
const target = (<HTMLInputElement>e.target);
|
|
|
|
|
const valueAttribute = target.attributes.getNamedItem("value");
|
|
|
|
|
let selectedID = "";
|
|
|
|
|
if(valueAttribute != null)
|
|
|
|
|
selectedID = valueAttribute.value;
|
|
|
|
|
const selected = this.$data.Suggestions.filter(x => x.ID == selectedID)[0];
|
|
|
|
|
this.selectElement(selected);
|
|
|
|
|
},
|
|
|
|
|
clear() {
|
|
|
|
|
this.$data.Selected = undefined;
|
|
|
|
|
this.$emit('update:modelValue', {ID: null, Name: this.$data.SearchQuery});
|
|
|
|
|
}
|
|
|
|
|
const Selected = ref<Suggestion | undefined>(props.modelValue || undefined);
|
|
|
|
|
const SearchQuery = ref(props.modelValue?.Name || "");
|
|
|
|
|
const Suggestions = ref<Array<Suggestion>>([]);
|
|
|
|
|
const emit = defineEmits(["update:modelValue"]);
|
|
|
|
|
watch(SearchQuery, () => {
|
|
|
|
|
load(SearchQuery.value);
|
|
|
|
|
});
|
|
|
|
|
function saveTransaction(e: MouseEvent) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
};
|
|
|
|
|
function load(text: String) {
|
|
|
|
|
emit('update:modelValue', { ID: null, Name: text });
|
|
|
|
|
if (text == "") {
|
|
|
|
|
Suggestions.value = [];
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const budgetStore = useBudgetsStore();
|
|
|
|
|
GET("/budget/" + budgetStore.CurrentBudgetID + "/autocomplete/" + props.type + "?s=" + text)
|
|
|
|
|
.then(x => x.json())
|
|
|
|
|
.then(x => {
|
|
|
|
|
let suggestions = x || [];
|
|
|
|
|
if (suggestions.length > 10) {
|
|
|
|
|
suggestions = suggestions.slice(0, 10);
|
|
|
|
|
}
|
|
|
|
|
Suggestions.value = suggestions;
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
function keypress(e: KeyboardEvent) {
|
|
|
|
|
console.log(e.key);
|
|
|
|
|
if (e.key == "Enter") {
|
|
|
|
|
const selected = Suggestions.value[0];
|
|
|
|
|
selectElement(selected);
|
|
|
|
|
const el = (<HTMLInputElement>e.target);
|
|
|
|
|
const inputElements = Array.from(el.ownerDocument.querySelectorAll('input:not([disabled]):not([readonly])'));
|
|
|
|
|
const currentIndex = inputElements.indexOf(el);
|
|
|
|
|
const nextElement = inputElements[currentIndex < inputElements.length - 1 ? currentIndex + 1 : 0];
|
|
|
|
|
(<HTMLInputElement>nextElement).focus();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
function selectElement(element: Suggestion) {
|
|
|
|
|
Selected.value = element;
|
|
|
|
|
Suggestions.value = [];
|
|
|
|
|
emit('update:modelValue', element);
|
|
|
|
|
};
|
|
|
|
|
function select(e: MouseEvent) {
|
|
|
|
|
const target = (<HTMLInputElement>e.target);
|
|
|
|
|
const valueAttribute = target.attributes.getNamedItem("value");
|
|
|
|
|
let selectedID = "";
|
|
|
|
|
if (valueAttribute != null)
|
|
|
|
|
selectedID = valueAttribute.value;
|
|
|
|
|
const selected = Suggestions.value.filter(x => x.ID == selectedID)[0];
|
|
|
|
|
selectElement(selected);
|
|
|
|
|
};
|
|
|
|
|
function clear() {
|
|
|
|
|
Selected.value = undefined;
|
|
|
|
|
emit('update:modelValue', { ID: null, Name: SearchQuery.value });
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<div>
|
|
|
|
|
<input class="border-b-2 border-black" @keypress="keypress" v-if="Selected == undefined" v-model="SearchQuery" />
|
|
|
|
|
<span @click="clear" v-if="Selected != undefined" class="bg-gray-300">{{Selected.Name}}</span>
|
|
|
|
|
<input
|
|
|
|
|
class="border-b-2 border-black"
|
|
|
|
|
@keypress="keypress"
|
|
|
|
|
v-if="Selected == undefined"
|
|
|
|
|
v-model="SearchQuery"
|
|
|
|
|
/>
|
|
|
|
|
<span @click="clear" v-if="Selected != undefined" class="bg-gray-300">{{ Selected.Name }}</span>
|
|
|
|
|
<div v-if="Suggestions.length > 0" class="absolute bg-gray-400 w-64 p-2">
|
|
|
|
|
<span v-for="suggestion in Suggestions" class="block" @click="select" :value="suggestion.ID">
|
|
|
|
|
{{suggestion.Name}}
|
|
|
|
|
</span>
|
|
|
|
|
<span
|
|
|
|
|
v-for="suggestion in Suggestions"
|
|
|
|
|
class="block"
|
|
|
|
|
@click="select"
|
|
|
|
|
:value="suggestion.ID"
|
|
|
|
|
>{{ suggestion.Name }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|