Combobox, POI
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
<script setup>
|
||||
import DatetimePicker from "components/inputs/DatetimePicker.vue";
|
||||
import {onMounted, reactive, ref, watch} from "vue";
|
||||
import FormWrapper from "components/FormWrapper.vue";
|
||||
import {setDefaultData} from "src/composables/form/formHandling";
|
||||
import {formatDatetime, parseDate} from "src/composables/datetimeUtils";
|
||||
import AnotherDatetimePicker from "components/inputs/AnotherDatetimePicker.vue";
|
||||
import DatetimePicker from "components/inputs/DatetimePicker.vue";
|
||||
import AirportLocationInput from "components/inputs/AirportLocationInput.vue";
|
||||
|
||||
const props = defineProps({
|
||||
@@ -77,7 +75,7 @@ onMounted(() => {
|
||||
label="Letadlo"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon name="flight"></q-icon>
|
||||
<q-icon name="flight" />
|
||||
</template>
|
||||
</q-select>
|
||||
</div>
|
||||
@@ -87,13 +85,13 @@ onMounted(() => {
|
||||
<div class="row">
|
||||
<div class="col col-12 col-md-6">
|
||||
<h3>Vzlet</h3>
|
||||
<AnotherDatetimePicker v-model="formData.takeoffDatetime" label="Datum a čas vzletu: "/>
|
||||
<DatetimePicker v-model="formData.takeoffDatetime" label="Datum a čas vzletu: "/>
|
||||
<AirportLocationInput v-model="formData.takeoffAirportId" :airports="airports" label="Letiště vzletu" takeoff/>
|
||||
</div>
|
||||
<div class="col col-12 col-md-6" v-if="!!formData.takeoffDatetime && !!formData.takeoffAirportId">
|
||||
|
||||
<h3>Přistání</h3>
|
||||
<AnotherDatetimePicker v-model="formData.landingDatetime" label="Datum a čas přistání"/>
|
||||
<DatetimePicker v-model="formData.landingDatetime" label="Datum a čas přistání"/>
|
||||
<AirportLocationInput v-model="formData.landingAirportId" :airports="airports" label="Letiště přistání" landing/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive} from "vue";
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import FormWrapper from "components/FormWrapper.vue";
|
||||
import {setDefaultData} from "src/composables/form/formHandling";
|
||||
import ComboboxInput from "components/inputs/ComboboxInput.vue";
|
||||
|
||||
const props = defineProps({
|
||||
flight: {
|
||||
@@ -17,7 +18,7 @@ const props = defineProps({
|
||||
const formData = reactive({
|
||||
solo: true,
|
||||
withInstructor: false,
|
||||
copilotId: null,
|
||||
copilot: null,
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
@@ -25,18 +26,22 @@ onMounted(() => {
|
||||
setDefaultData(formData, props.flight);
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormWrapper v-model="formData">
|
||||
<FormWrapper v-model="formData">
|
||||
|
||||
<q-btn-toggle spread no-caps v-model="formData.solo" toggle-color="primary" :options="[{label: 'Solo', value: true}, {label: 'S někým', value: false}]"/>
|
||||
<q-btn-toggle spread no-caps v-model="formData.solo" toggle-color="primary" :options="[{label: 'Solo', value: true}, {label: 'S někým', value: false}]"/>
|
||||
|
||||
<div v-if="!formData.solo">
|
||||
<q-input type="text" v-model="formData.secondPilot" label="Druhý pilot"/>
|
||||
<q-checkbox v-model="formData.withInstructor" v-if="formData.secondPilot !== ''" label="Instruktor"/>
|
||||
<!-- <q-input v-model="formData.picTime" label="PIC time"/>-->
|
||||
</div>
|
||||
{{ formData.copilot }}
|
||||
|
||||
</FormWrapper>
|
||||
<div v-if="!formData.solo">
|
||||
<ComboboxInput :options="copilots" v-model="formData.copilot" :key="formData.copilot" label="Druhy pilot" />
|
||||
|
||||
<q-checkbox v-model="formData.withInstructor" v-if="formData.copilot" label="Instruktor"/>
|
||||
<!-- <q-input v-model="formData.picTime" label="PIC time"/>-->
|
||||
</div>
|
||||
|
||||
</FormWrapper>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<script setup>
|
||||
import FormWrapper from "components/FormWrapper.vue";
|
||||
import {onMounted, reactive, ref} from "vue";
|
||||
import ComboboxInput from "components/inputs/ComboboxInput.vue";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Number, String],
|
||||
},
|
||||
locations: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
flight: {
|
||||
type: Object,
|
||||
required: false
|
||||
}
|
||||
});
|
||||
|
||||
const formData = reactive({
|
||||
track: []
|
||||
});
|
||||
const removeTrackItem = (index) => {
|
||||
formData.track.splice(index, 1);
|
||||
}
|
||||
|
||||
const poi = ref(null);
|
||||
const addTrackItem = (item) => {
|
||||
formData.track.push(item);
|
||||
poi.value = null;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
for (const i in props.flight.track) {
|
||||
const poiInfo = props.flight.track[i].pointOfInterest;
|
||||
formData.track.push({
|
||||
id: poiInfo.id,
|
||||
name: poiInfo.name
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormWrapper v-model="formData">
|
||||
|
||||
{{ flight.track }}
|
||||
|
||||
<q-list>
|
||||
<q-item>{{ flight.takeoffAirport.name }}</q-item>
|
||||
|
||||
<q-item v-for="(item, index) in formData.track" :key="item">
|
||||
{{ index + 1 }}. {{ item.name }}
|
||||
|
||||
<q-btn @click="removeTrackItem(index)" icon="delete" text-color="red"/>
|
||||
</q-item>
|
||||
|
||||
<q-item>{{ flight.landingAirport.name }}</q-item>
|
||||
|
||||
</q-list>
|
||||
|
||||
<ComboboxInput v-model="poi" :options="locations" clearable label="Location">
|
||||
<template #after>
|
||||
<q-btn @click="addTrackItem(poi)" v-if="poi" rounded>+</q-btn>
|
||||
</template>
|
||||
</ComboboxInput>
|
||||
</FormWrapper>
|
||||
</template>
|
||||
@@ -1,139 +0,0 @@
|
||||
<script setup>
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {FORMAT_DATETIME_LONG, FORMAT_ISO, formatDatetime, parseDate} from "src/composables/datetimeUtils";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [String, Date]
|
||||
},
|
||||
mask: {
|
||||
type: [String, Boolean],
|
||||
required: false,
|
||||
default: FORMAT_DATETIME_LONG
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
let dateModel = ref("");
|
||||
let timeModel = ref("");
|
||||
|
||||
let originalTime, originalDate;
|
||||
onMounted(() => {
|
||||
let emitDefaultValue = false;
|
||||
if (props.modelValue) {
|
||||
let modelVal = props.modelValue;
|
||||
if (typeof modelVal === 'string') {
|
||||
modelVal = parseDate(props.modelValue);
|
||||
emitDefaultValue = true;
|
||||
}
|
||||
|
||||
dateModel.value = formatDatetime(modelVal, "YYYY-MM-DD");
|
||||
timeModel.value = formatDatetime(modelVal, "HH:mm:ss");
|
||||
}
|
||||
|
||||
setOriginalValues();
|
||||
if (emitDefaultValue) {
|
||||
emitModelUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const publicModel = computed(() => {
|
||||
if (!dateModel.value) {
|
||||
return "";
|
||||
}
|
||||
const dateObject = parseDate(model.value, FORMAT_ISO);
|
||||
return formatDatetime(dateObject, props.mask);
|
||||
});
|
||||
|
||||
const popupProxy = ref(null);
|
||||
|
||||
const model = computed(() => dateModel.value + "T" + timeModel.value);
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const emitModelUpdate = () => {
|
||||
const val = parseDate(model.value);
|
||||
emit("update:modelValue", val);
|
||||
popupProxy.value.hide();
|
||||
}
|
||||
|
||||
const containsAnyOf = (needles, haystack) => {
|
||||
for (const i in needles) {
|
||||
if (haystack.includes(needles[i])) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const showDatePicker = computed(() => containsAnyOf(["YY", "M", "D"], props.mask));
|
||||
const showTimePicker = computed(() => containsAnyOf(["H", "h", "m"], props.mask));
|
||||
|
||||
const setOriginalValues = () => {
|
||||
originalDate = dateModel.value;
|
||||
originalTime = timeModel.value;
|
||||
}
|
||||
|
||||
const cancelSelection = () => {
|
||||
dateModel.value = originalDate;
|
||||
timeModel.value = originalTime;
|
||||
popupProxy.value.hide();
|
||||
}
|
||||
|
||||
const myLocale = {
|
||||
/* starting with Sunday */
|
||||
days: ["Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Neděle"],
|
||||
daysShort: ["Po", "Út", "St", "Čt", "Pá", "So", "Ne"],
|
||||
months: [
|
||||
"Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad",
|
||||
"Prosinec"
|
||||
],
|
||||
monthsShort: ["led.", "úno.", "bře.", "dub.", "kvě.", "čvn.", "čvc.", "srp.", "zář.", "říj.", "lis.", "pro."],
|
||||
firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
|
||||
format24h: true,
|
||||
pluralDay: 'dny'
|
||||
}
|
||||
|
||||
// https://quasar.dev/vue-composables/use-form-child - mozna resi ohack s onMounted()?
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-input readonly v-model="publicModel">
|
||||
<template #append>
|
||||
<q-icon name="event"/>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<q-popup-proxy ref="popupProxy" @hide="emitModelUpdate" @show="setOriginalValues">
|
||||
<div class="proxy-wrapper">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6" v-if="showDatePicker">
|
||||
<q-date square v-model="dateModel" :today-btn="true" flat mask="YYYY-MM-DD" :locale="myLocale"/>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6" v-if="showTimePicker">
|
||||
<q-time square v-model="timeModel" format24h flat mask="HH:mm"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row q-mb-sm">
|
||||
<div class="col">
|
||||
<q-btn color="secondary" class="q-ml-sm" @click="cancelSelection">Zrušit</q-btn>
|
||||
</div>
|
||||
<div class="col text-right">
|
||||
<q-btn color="primary" class="q-mr-sm" @click="emitModelUpdate">Nastavit</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-popup-proxy>
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.proxy-wrapper {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.q-date, .q-time {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,89 @@
|
||||
<script setup>
|
||||
import {onMounted, ref, watch} from "vue";
|
||||
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Object, Array]
|
||||
},
|
||||
rules: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
options: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
let model = ref({});
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
model.value = newVal;
|
||||
console.log("zmena!", newVal);
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
model.value = props.modelValue;
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
watch(model, (val) => {
|
||||
if (!val) return;
|
||||
const value = val.name ? val : {name: val};
|
||||
emit("update:modelValue", value);
|
||||
})
|
||||
|
||||
let availableOptions = ref([]);
|
||||
const filterFn = (val, update, abort) => {
|
||||
update(() => {
|
||||
if (!val || val === "") {
|
||||
availableOptions.value = props.options;
|
||||
} else {
|
||||
const needle = val.toLowerCase();
|
||||
availableOptions.value = props.options.filter(v => {
|
||||
return v.name.toLowerCase().indexOf(needle) > -1;
|
||||
});
|
||||
}
|
||||
|
||||
availableOptions.value = availableOptions.value.map(i => ({id: i.id, name: i.name}))
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-select
|
||||
v-model="model"
|
||||
use-input
|
||||
input-debounce="100"
|
||||
:display-value="`${model.name}`"
|
||||
:rules="rules"
|
||||
@filter="filterFn"
|
||||
:options="availableOptions"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
new-value-mode="add"
|
||||
>
|
||||
<template #before>
|
||||
<slot name="before"/>
|
||||
</template>
|
||||
<template #after>
|
||||
<slot name="after"/>
|
||||
</template>
|
||||
<template #append>
|
||||
<slot name="append"/>
|
||||
</template>
|
||||
|
||||
<!-- <template>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
Add new option
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
</template>
|
||||
@@ -1,31 +1,25 @@
|
||||
<script setup>
|
||||
import {computed, onMounted, ref, watch} from "vue";
|
||||
import {parseDate} from "src/composables/datetimeUtils";
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {FORMAT_DATETIME_LONG, FORMAT_ISO, formatDatetime, parseDate} from "src/composables/datetimeUtils";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [String, Date]
|
||||
},
|
||||
dateMask: {
|
||||
mask: {
|
||||
type: [String, Boolean],
|
||||
required: false,
|
||||
default: "YYYY-MM-DD"
|
||||
},
|
||||
timeMask: {
|
||||
type: [String, Boolean],
|
||||
required: false,
|
||||
default: "HH:mm"
|
||||
default: FORMAT_DATETIME_LONG
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
let dateModel = ref("");
|
||||
let timeModel = ref("");
|
||||
|
||||
let originalTime, originalDate;
|
||||
onMounted(() => {
|
||||
let date = "";
|
||||
let time = "";
|
||||
let emitDefaultValue = false;
|
||||
|
||||
if (props.modelValue) {
|
||||
let modelVal = props.modelValue;
|
||||
if (typeof modelVal === 'string') {
|
||||
@@ -33,56 +27,113 @@ onMounted(() => {
|
||||
emitDefaultValue = true;
|
||||
}
|
||||
|
||||
date = props.dateMask
|
||||
.replace("YYYY", modelVal.getFullYear().toString())
|
||||
.replace("MM", ('0' + modelVal.getMonth()).slice(-2))
|
||||
.replace("DD", ('0' + modelVal.getDate()).slice(-2));
|
||||
|
||||
time = props.timeMask
|
||||
.replace("HH", ('0' + modelVal.getHours()).slice(-2))
|
||||
.replace("mm", ('0' + modelVal.getMinutes()).slice(-2))
|
||||
.replace("ss", ('0' + modelVal.getSeconds()).slice(-2))
|
||||
|
||||
// if (time === '') {
|
||||
// time = "00:00";
|
||||
// }
|
||||
dateModel.value = formatDatetime(modelVal, "YYYY-MM-DD");
|
||||
timeModel.value = formatDatetime(modelVal, "HH:mm:ss");
|
||||
}
|
||||
|
||||
dateModel.value = date;
|
||||
timeModel.value = time;
|
||||
|
||||
setOriginalValues();
|
||||
if (emitDefaultValue) {
|
||||
emitModelUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const model = computed(() => dateModel.value + " " + timeModel.value);
|
||||
const publicModel = computed(() => {
|
||||
if (!dateModel.value) {
|
||||
return "";
|
||||
}
|
||||
const dateObject = parseDate(model.value, FORMAT_ISO);
|
||||
return formatDatetime(dateObject, props.mask);
|
||||
});
|
||||
|
||||
const popupProxy = ref(null);
|
||||
|
||||
const model = computed(() => dateModel.value + "T" + timeModel.value);
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const emitModelUpdate = () => {
|
||||
const now = new Date();
|
||||
const val = parseDate(model.value);
|
||||
// val.setHours(val.getHours() + now.getTimezoneOffset());
|
||||
emit("update:modelValue", val);
|
||||
popupProxy.value.hide();
|
||||
}
|
||||
watch([dateModel, timeModel], emitModelUpdate)
|
||||
|
||||
const containsAnyOf = (needles, haystack) => {
|
||||
for (const i in needles) {
|
||||
if (haystack.includes(needles[i])) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const showDatePicker = computed(() => containsAnyOf(["YY", "M", "D"], props.mask));
|
||||
const showTimePicker = computed(() => containsAnyOf(["H", "h", "m"], props.mask));
|
||||
|
||||
const setOriginalValues = () => {
|
||||
originalDate = dateModel.value;
|
||||
originalTime = timeModel.value;
|
||||
}
|
||||
|
||||
const cancelSelection = () => {
|
||||
dateModel.value = originalDate;
|
||||
timeModel.value = originalTime;
|
||||
popupProxy.value.hide();
|
||||
}
|
||||
|
||||
const myLocale = {
|
||||
/* starting with Sunday */
|
||||
days: ["Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Neděle"],
|
||||
daysShort: ["Po", "Út", "St", "Čt", "Pá", "So", "Ne"],
|
||||
months: [
|
||||
"Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad",
|
||||
"Prosinec"
|
||||
],
|
||||
monthsShort: ["led.", "úno.", "bře.", "dub.", "kvě.", "čvn.", "čvc.", "srp.", "zář.", "říj.", "lis.", "pro."],
|
||||
firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
|
||||
format24h: true,
|
||||
pluralDay: 'dny'
|
||||
}
|
||||
|
||||
// https://quasar.dev/vue-composables/use-form-child - mozna resi ohack s onMounted()?
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-input v-model="model" readonly>
|
||||
<q-input readonly v-model="publicModel">
|
||||
<template #append>
|
||||
<q-icon name="event">
|
||||
<q-popup-proxy cover>
|
||||
<q-icon name="event"/>
|
||||
</template>
|
||||
|
||||
<template #default>
|
||||
<q-popup-proxy ref="popupProxy" @hide="emitModelUpdate" @show="setOriginalValues">
|
||||
<div class="proxy-wrapper">
|
||||
<div class="row">
|
||||
<div class="col" v-if="dateMask">
|
||||
<q-date v-model="dateModel" :mask="dateMask"/>
|
||||
<div class="col-12 col-sm-6" v-if="showDatePicker">
|
||||
<q-date square v-model="dateModel" :today-btn="true" flat mask="YYYY-MM-DD" :locale="myLocale"/>
|
||||
</div>
|
||||
<div class="col" v-if="timeMask">
|
||||
<q-time v-model="timeModel" format24h :mask="timeMask"/>
|
||||
<div class="col-12 col-sm-6" v-if="showTimePicker">
|
||||
<q-time square v-model="timeModel" format24h flat mask="HH:mm"/>
|
||||
</div>
|
||||
</div>
|
||||
</q-popup-proxy>
|
||||
</q-icon>
|
||||
<div class="row q-mb-sm">
|
||||
<div class="col">
|
||||
<q-btn color="secondary" class="q-ml-sm" @click="cancelSelection">Zrušit</q-btn>
|
||||
</div>
|
||||
<div class="col text-right">
|
||||
<q-btn color="primary" class="q-mr-sm" @click="emitModelUpdate">Nastavit</q-btn>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</q-popup-proxy>
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.proxy-wrapper {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.q-date, .q-time {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
<script setup>
|
||||
import {onMounted, ref, toRefs, watch} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
type: [Number, String]
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
rules: {
|
||||
type: Array,
|
||||
required: false,
|
||||
default: () => []
|
||||
},
|
||||
locations: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
prependIcon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
},
|
||||
appendIcon: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: null
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
let selectedLocationModel = ref("");
|
||||
onMounted(() => {
|
||||
selectedLocationModel.value = props.modelValue;
|
||||
});
|
||||
watch(selectedLocationModel, (newVal) => {
|
||||
// TODO: rozdelit emit na dva modely - jeden na emit existujici lokality, druhy na emit nove vytvarene
|
||||
if (!newVal) return;
|
||||
|
||||
let value, eventName;
|
||||
if (newVal instanceof String) {
|
||||
eventName = "update:modelValue";
|
||||
value = newVal;
|
||||
} else {
|
||||
eventName = "update:modelValue";
|
||||
value = newVal.id;
|
||||
}
|
||||
|
||||
emit(eventName, value);
|
||||
})
|
||||
|
||||
const {locations} = toRefs(props);
|
||||
let availableLocations = ref([]);
|
||||
|
||||
const filterFn = (val, update, abort) => {
|
||||
update(() => {
|
||||
if (!val || val === "") {
|
||||
availableLocations.value = locations.value;
|
||||
} else {
|
||||
const needle = val.toLowerCase();
|
||||
availableLocations.value = locations.value.filter(v => {
|
||||
return v.name.toLowerCase().indexOf(needle) > -1;
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-select
|
||||
v-model="selectedLocationModel"
|
||||
:label=label
|
||||
use-input
|
||||
input-debounce="100"
|
||||
:rules="rules"
|
||||
:options="availableLocations"
|
||||
option-label="name"
|
||||
option-value="id"
|
||||
clearable
|
||||
new-value-mode="add"
|
||||
use-chips
|
||||
@filter="filterFn"
|
||||
>
|
||||
<template #before v-if="prependIcon">
|
||||
<q-icon :name="prependIcon"/>
|
||||
</template>
|
||||
<template #after v-if="appendIcon">
|
||||
<q-icon :name="appendIcon"/>
|
||||
</template>
|
||||
<template v-slot:selected v-if="!props.multiple">
|
||||
<q-chip
|
||||
v-if="selectedLocationModel"
|
||||
square
|
||||
>
|
||||
<q-avatar color="primary" text-color="white" :icon="selectedLocationModel.type === 'airport' ? 'flight' : 'marker'"/>
|
||||
{{ selectedLocationModel.name }}
|
||||
</q-chip>
|
||||
</template>
|
||||
<template #append>
|
||||
<slot name="append"></slot>
|
||||
</template>
|
||||
<template v-slot:no-option>
|
||||
<q-item>
|
||||
<q-item-section class="text-grey">
|
||||
Add new option
|
||||
</q-item-section>
|
||||
</q-item>
|
||||
</template>
|
||||
</q-select>
|
||||
|
||||
<!-- @input-value u q-select - nelze pouzit misto watche?-->
|
||||
</template>
|
||||
@@ -18,6 +18,13 @@ fragment flightFullInfo on Flight {
|
||||
...airportInfo
|
||||
}
|
||||
|
||||
track {
|
||||
pointOfInterest {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
|
||||
landingAirport {
|
||||
...airportInfo
|
||||
}
|
||||
@@ -71,6 +78,10 @@ fragment flightEditIds on Flight {
|
||||
takeoffAirportId
|
||||
aircraftId
|
||||
copilotId
|
||||
copilot {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import gql from "graphql-tag";
|
||||
|
||||
export const FRAGMENT_POI_LIST_INFO = gql`
|
||||
fragment pointOfInterestListInfo on PointOfInterest {
|
||||
id
|
||||
name
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,12 @@
|
||||
import gql from "graphql-tag";
|
||||
import {FRAGMENT_POI_LIST_INFO} from "src/graphql/fragments/poi";
|
||||
|
||||
export const CREATE_POI = gql`
|
||||
mutation createPointOfInterest($input: CreatePointOfInterestInput!) {
|
||||
createPointOfInterest(input: $input) {
|
||||
...pointOfInterestListInfo
|
||||
}
|
||||
}
|
||||
|
||||
${FRAGMENT_POI_LIST_INFO}
|
||||
`;
|
||||
@@ -0,0 +1,12 @@
|
||||
import gql from "graphql-tag";
|
||||
import {FRAGMENT_POI_LIST_INFO} from "src/graphql/fragments/poi";
|
||||
|
||||
export const POI_LIST = gql`
|
||||
query poiList {
|
||||
pointsOfInterest {
|
||||
...pointOfInterestListInfo
|
||||
}
|
||||
}
|
||||
|
||||
${FRAGMENT_POI_LIST_INFO}
|
||||
`;
|
||||
@@ -18,6 +18,7 @@ import {usePhotosStore} from "stores/Photo";
|
||||
import PhotosList from "components/photos/PhotosList.vue";
|
||||
import {confirmObject, successObject} from "src/composables/dialog";
|
||||
import PhotoForm from "components/flights/PhotoForm.vue";
|
||||
import FlightFormTrack from "components/flights/form/FlightFormTrack.vue";
|
||||
|
||||
useMeta({title: "Editace letu"});
|
||||
|
||||
@@ -56,6 +57,7 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
const handleFlightEdit = (data) => {
|
||||
console.log(data);
|
||||
useFlightsStore().update(flightId, data).then(() => {
|
||||
$q.notify(successObject("Úspěšně upraveno"));
|
||||
fetchFlight(flightId);
|
||||
@@ -129,6 +131,15 @@ const openPhotoEdit = (photo) => {
|
||||
<FlightFormCopilot @save="handleFlightEdit" :flight="flight" :copilots="copilots"/>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="track">
|
||||
<FlightFormTrack
|
||||
v-if="locations"
|
||||
:flight="flight"
|
||||
:locations="locations"
|
||||
@save="handleFlightEdit"
|
||||
/>
|
||||
</q-tab-panel>
|
||||
|
||||
<q-tab-panel name="photos">
|
||||
<PhotosList
|
||||
:photos="flight.photos"
|
||||
|
||||
@@ -36,7 +36,6 @@ export const useFlightsStore = defineStore('Flights', {
|
||||
return apolloWrapper.query(FLIGHT_DETAIL, {id}).then(result => result.data.flight);
|
||||
},
|
||||
fetch() {
|
||||
console.log("flights fetch");
|
||||
return apolloWrapper
|
||||
.query(FLIGHTS_LIST)
|
||||
.then((result) => {
|
||||
@@ -44,17 +43,6 @@ export const useFlightsStore = defineStore('Flights', {
|
||||
|
||||
return result.data.flights;
|
||||
});
|
||||
// if (this.items.length > 0) return;
|
||||
//
|
||||
// this.$patch({
|
||||
// items: [
|
||||
// {id: 1, takeOffLocation: "LKLT", titlePhotoUrl: null, landingLocation: "LKLC", date: "2023-03-03", aircraft: {id: 1, name: "OK-AUR28"}, flightDurationMinutes: 63},
|
||||
// {id: 2, takeOffLocation: "LKLT", titlePhotoUrl: "https://cdn.quasar.dev/img/mountains.jpg", landingLocation: "LKLT", date: "2023-02-01", aircraft: {id: 1, name: "OK-AUR28"}, flightDurationMinutes: 76},
|
||||
// {id: 3, takeOffLocation: "LKLT", titlePhotoUrl: null, landingLocation: "LKLC", date: "2023-04-03", aircraft: {id: 1, name: "OK-AUR28"}, flightDurationMinutes: 53},
|
||||
// {id: 4, takeOffLocation: "LKLT", titlePhotoUrl: null, landingLocation: "LKMB", date: "2023-03-04", aircraft: {id: 1, name: "OK-AUR28"}, flightDurationMinutes: 75},
|
||||
// {id: 5, takeOffLocation: "LKLT", titlePhotoUrl: null, landingLocation: "LKMH", date: "2023-01-46", aircraft: {id: 1, name: "OK-AUR28"}, flightDurationMinutes: 23},
|
||||
// ]
|
||||
// });
|
||||
},
|
||||
deleteItem(id) {
|
||||
const idx = this.items.indexOf(this.items.find(f => f.id === id));
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import {defineStore} from 'pinia'
|
||||
import {apolloWrapper} from "src/graphql/apollo";
|
||||
import {POI_LIST} from "src/graphql/queries/poi";
|
||||
|
||||
export const usePointsOfInterestStore = defineStore('PointsOfInterest', {
|
||||
state: () => ({
|
||||
@@ -16,23 +18,23 @@ export const usePointsOfInterestStore = defineStore('PointsOfInterest', {
|
||||
console.log('item', item);
|
||||
return item;
|
||||
},
|
||||
pointTypeName() {
|
||||
return (typeName) => {
|
||||
const typeToNameMap = {
|
||||
poi: "General POI",
|
||||
airport: "Airport",
|
||||
}
|
||||
return typeToNameMap[typeName] || "Unknown";
|
||||
}
|
||||
},
|
||||
groupByTypes() {
|
||||
const groupedByType = {};
|
||||
for (const item of this.items) {
|
||||
if (!groupedByType[item.type]) groupedByType[item.type] = [];
|
||||
groupedByType[item.type].push(item);
|
||||
}
|
||||
return groupedByType;
|
||||
}
|
||||
// pointTypeName() {
|
||||
// return (typeName) => {
|
||||
// const typeToNameMap = {
|
||||
// poi: "General POI",
|
||||
// airport: "Airport",
|
||||
// }
|
||||
// return typeToNameMap[typeName] || "Unknown";
|
||||
// }
|
||||
// },
|
||||
// groupByTypes() {
|
||||
// const groupedByType = {};
|
||||
// for (const item of this.items) {
|
||||
// if (!groupedByType[item.type]) groupedByType[item.type] = [];
|
||||
// groupedByType[item.type].push(item);
|
||||
// }
|
||||
// return groupedByType;
|
||||
// }
|
||||
},
|
||||
|
||||
actions: {
|
||||
@@ -41,12 +43,17 @@ export const usePointsOfInterestStore = defineStore('PointsOfInterest', {
|
||||
this.items.push({id: poiId, "name": "Zamek " + poiId, "type": "poi", "location": {"lat": 50, "lng": 10}});
|
||||
},
|
||||
fetch() {
|
||||
console.log("fetch poi");
|
||||
this.items = [
|
||||
{id: 1, "name": "LKLT", private: false, "type": "airport", "location": {"lat": 50, "lng": 10}},
|
||||
{id: 2, "name": "Hrad", "type": "poi", "location": {"lat": 50, "lng": 10}},
|
||||
{id: 3, "name": "Zamek", "type": "poi", "location": {"lat": 50, "lng": 10}},
|
||||
]
|
||||
return apolloWrapper.query(POI_LIST).then(result => {
|
||||
this.items = result.data.pointsOfInterest;
|
||||
return result.data.pointsOfInterest;
|
||||
});
|
||||
|
||||
// console.log("fetch poi");
|
||||
// this.items = [
|
||||
// {id: 1, "name": "LKLT", private: false, "type": "airport", "location": {"lat": 50, "lng": 10}},
|
||||
// {id: 2, "name": "Hrad", "type": "poi", "location": {"lat": 50, "lng": 10}},
|
||||
// {id: 3, "name": "Zamek", "type": "poi", "location": {"lat": 50, "lng": 10}},
|
||||
// ]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user