Prace na sprave letu
This commit is contained in:
@@ -1,19 +1,20 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
|
||||||
import {isRequestPending} from "src/composables/form/props";
|
import {isRequestPending} from "src/composables/form/props";
|
||||||
|
import {useSlots} from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
|
||||||
resetAfterSubmit: {
|
resetAfterSubmit: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
isRequestPending,
|
isRequestPending,
|
||||||
|
|
||||||
saveButton: {
|
saveButton: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: false,
|
required: false,
|
||||||
@@ -37,7 +38,9 @@ const saveForm = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-form @submit.prevent="saveForm" ref="form">
|
<q-form @submit.prevent="saveForm" ref="form">
|
||||||
<slot/>
|
<slot name="default"/>
|
||||||
|
|
||||||
|
<slot name="saveButton" />
|
||||||
|
|
||||||
<q-btn type="submit" color="primary" :icon="props.saveButton.icon" :loading="props.isRequestPending">
|
<q-btn type="submit" color="primary" :icon="props.saveButton.icon" :loading="props.isRequestPending">
|
||||||
{{ props.saveButton.label }}
|
{{ props.saveButton.label }}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<template>
|
||||||
|
skeleton
|
||||||
|
</template>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import LocationInput from "components/inputs/LocationInput.vue";
|
import LocationInput from "components/inputs/LocationInput.vue";
|
||||||
import TabsStepper from "components/TabsStepper.vue";
|
import TabsStepper from "components/TabsStepper.vue";
|
||||||
import FormWrapper from "components/FormWrapper.vue";
|
import FormWrapper from "components/FormWrapper.vue";
|
||||||
import {computed, reactive, ref} from "vue";
|
import {computed, reactive, ref, watch} from "vue";
|
||||||
import {isRequired} from "src/composables/form/rules";
|
import {isRequired} from "src/composables/form/rules";
|
||||||
import DatetimePicker from "components/inputs/DatetimePicker.vue";
|
import DatetimePicker from "components/inputs/DatetimePicker.vue";
|
||||||
|
|
||||||
@@ -23,18 +23,20 @@ const props = defineProps({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const formData = reactive({
|
const formData = reactive({
|
||||||
aircraftId: null,
|
aircraftId: 43,
|
||||||
takeoffAirportId: null,
|
takeoffAirportId: 3,
|
||||||
landingAirportId: null,
|
landingAirportId: 3,
|
||||||
takeoffDatetime: null,
|
takeoffDatetime: new Date("2023-06-05T09:55:01"),
|
||||||
landingDatetime: null,
|
landingDatetime: new Date("2023-06-05T10:41:51"),
|
||||||
|
|
||||||
|
photos: [],
|
||||||
|
|
||||||
// turnPoints: [],
|
// turnPoints: [],
|
||||||
copilotId: null,
|
copilotId: null,
|
||||||
solo: true,
|
solo: true,
|
||||||
withInstructor: false,
|
withInstructor: false,
|
||||||
durationPic: 0,
|
durationPic: 0,
|
||||||
// flightDurationMinutes: 0,
|
durationTotal: null,
|
||||||
landings: 1,
|
landings: 1,
|
||||||
|
|
||||||
name: "",
|
name: "",
|
||||||
@@ -46,7 +48,16 @@ const rules = {
|
|||||||
landingAirport: [],
|
landingAirport: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
const formSteps = ["aircraft", "basic", "copilot", "track", "photos", "notes"]
|
const recalculateDuration = () => {
|
||||||
|
const diff = formData.landingDatetime - formData.takeoffDatetime;
|
||||||
|
|
||||||
|
formData.durationTotal = diff / 1000 / 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => formData.takeoffDatetime, () => recalculateDuration())
|
||||||
|
watch(() => formData.landingDatetime, () => recalculateDuration())
|
||||||
|
|
||||||
|
const formSteps = ["basic", "copilot", "track", "photos", "notes"]
|
||||||
const formStep = ref(formSteps[0]);
|
const formStep = ref(formSteps[0]);
|
||||||
const basicInfoFilled = computed(() => {
|
const basicInfoFilled = computed(() => {
|
||||||
return (
|
return (
|
||||||
@@ -59,119 +70,144 @@ const basicInfoFilled = computed(() => {
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
<FormWrapper v-model="formData">
|
<FormWrapper v-model="formData">
|
||||||
{{ formData }}
|
<template #default>
|
||||||
|
|
||||||
<q-tabs
|
<pre>{{ formData }}</pre>
|
||||||
v-model="formStep"
|
|
||||||
outside-arrows
|
|
||||||
mobile-arrows
|
|
||||||
left-icon="chevron_left"
|
|
||||||
right-icon="chevron_right"
|
|
||||||
active-color="primary"
|
|
||||||
class="q-mb-lg"
|
|
||||||
>
|
|
||||||
<q-tab name="aircraft" icon="flight" label="Aircraft"/>
|
|
||||||
<q-tab name="basic" icon="flight_takeoff" label="Basic"/>
|
|
||||||
<q-tab name="copilot" icon="person_add" label="Copilot"/>
|
|
||||||
<q-tab name="track" icon="route" label="Route"/>
|
|
||||||
<q-tab name="photos" icon="add_a_photo" label="Photos"/>
|
|
||||||
<q-tab name="notes" icon="edit_note" label="Notes"/>
|
|
||||||
</q-tabs>
|
|
||||||
|
|
||||||
<q-tab-panels v-model="formStep" animated>
|
<q-tabs
|
||||||
<q-tab-panel name="aircraft">
|
v-model="formStep"
|
||||||
<q-select
|
outside-arrows
|
||||||
v-model="formData.aircraftId"
|
mobile-arrows
|
||||||
option-label="name"
|
left-icon="chevron_left"
|
||||||
option-value="id"
|
right-icon="chevron_right"
|
||||||
emit-value
|
active-color="primary"
|
||||||
map-options
|
class="q-mb-lg"
|
||||||
:rules="rules.aircraft"
|
>
|
||||||
:options="aircrafts"
|
<q-tab name="basic" icon="flight_takeoff" label="Základní informace"/>
|
||||||
label="Letadlo"
|
<q-tab name="copilot" icon="person_add" label="Spolucestující"/>
|
||||||
>
|
<q-tab name="track" icon="route" label="Trasa"/>
|
||||||
<template #prepend>
|
<q-tab name="photos" icon="add_a_photo" label="Fotky"/>
|
||||||
<q-icon name="flight"></q-icon>
|
<q-tab name="notes" icon="edit_note" label="Poznámky"/>
|
||||||
|
</q-tabs>
|
||||||
|
|
||||||
|
<q-tab-panels v-model="formStep" animated>
|
||||||
|
|
||||||
|
<q-tab-panel name="basic">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<q-select
|
||||||
|
v-model="formData.aircraftId"
|
||||||
|
option-label="name"
|
||||||
|
option-value="id"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
:rules="rules.aircraft"
|
||||||
|
:options="aircrafts"
|
||||||
|
label="Letadlo"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<q-icon name="flight"></q-icon>
|
||||||
|
</template>
|
||||||
|
</q-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="formData.aircraftId">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3>Vzlet</h3>
|
||||||
|
|
||||||
|
<DatetimePicker v-model="formData.takeoffDatetime" label="Datum a čas vzletu"/>
|
||||||
|
<LocationInput label="Letiště vzletu" :rules="rules.takeoffAirport" :locations="airports" v-model="formData.takeoffAirportId" prepend-icon="flight_takeoff"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" v-if="!!formData.takeoffDatetime && !!formData.takeoffAirportId">
|
||||||
|
<div class="col">
|
||||||
|
|
||||||
|
<h3>Přistání</h3>
|
||||||
|
|
||||||
|
<LocationInput label="Letiště přistání" :rules="rules.landingAirport" :locations="airports" v-model="formData.landingAirportId" prepend-icon="flight_land"/>
|
||||||
|
<DatetimePicker v-model="formData.landingDatetime" label="Datum a čas přistání"/>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<q-input v-model="formData.landings" label="Počet přistání" type="number" min="1"/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-input v-model="formData.durationTotal" readonly min=0 label="Délka letu (v minutách)" type="number"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TabsStepper v-model="formStep" next-step="track" v-if="formData.landingAirportId"/>
|
||||||
</template>
|
</template>
|
||||||
</q-select>
|
</q-tab-panel>
|
||||||
|
|
||||||
<TabsStepper v-model="formStep" next-step="basic"/>
|
<q-tab-panel name="copilot">
|
||||||
</q-tab-panel>
|
<q-btn-toggle spread no-caps v-model="formData.solo" toggle-color="primary" :options="[{label: 'Solo flight', value: true}, {label: 'Flight with someone', value: false}]"/>
|
||||||
<q-tab-panel name="basic">
|
|
||||||
<!-- <q-input type="date" v-model="formData.date" label="Date"/>-->
|
|
||||||
|
|
||||||
<DatetimePicker v-model="formData.takeoffDatetime" label="Datum a čas vzletu" />
|
<div v-if="!formData.solo">
|
||||||
|
<q-input type="text" v-model="formData.secondPilot" label="Second pilot"/>
|
||||||
|
<q-checkbox v-model="formData.instructor" v-if="formData.secondPilot !== ''" label="Instructor"/>
|
||||||
|
<!-- <q-input v-model="formData.picTime" label="PIC time"/>-->
|
||||||
|
</div>
|
||||||
|
|
||||||
<LocationInput label="Take-off location" :rules="rules.takeoffAirport" :locations="airports" v-model="formData.takeoffAirportId" prepend-icon="flight_takeoff"/>
|
<TabsStepper v-model="formStep" previous-step="basic" next-step="track"/>
|
||||||
<LocationInput label="Landing location" :rules="rules.landingAirport" :locations="airports" v-model="formData.landingAirportId" prepend-icon="flight_land"/>
|
</q-tab-panel>
|
||||||
<q-input type="datetime-local" v-model="formData.landingDatetime" label="Landing date & time"/>
|
|
||||||
<q-input v-model="formData.landings" label="Landings" type="number" min="1"/>
|
|
||||||
<q-input v-model="formData.flightDurationMinutes" min=0 label="Flight duration (minutes)" type="number"/>
|
|
||||||
|
|
||||||
<TabsStepper v-model="formStep" previous-step="aircraft" next-step="track"/>
|
<q-tab-panel name="track">
|
||||||
</q-tab-panel>
|
<!-- <template v-for="i in turnPointsCount" :key="`${i}-${turnPointsCount}`">-->
|
||||||
|
<!-- <LocationInput label="Turn point" :locations="locations" v-model="formData.turnPoints[i-1]">-->
|
||||||
|
<!-- <template #append v-if="i > 1">-->
|
||||||
|
<!-- <q-btn @click="removeTurnPoint(i - 1)">-</q-btn>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- </LocationInput>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
<!-- <q-btn @click="turnPointsCount++">-->
|
||||||
|
<!-- Add turn point-->
|
||||||
|
<!-- </q-btn>-->
|
||||||
|
|
||||||
<q-tab-panel name="track">
|
<q-uploader
|
||||||
<!-- <template v-for="i in turnPointsCount" :key="`${i}-${turnPointsCount}`">-->
|
label="Upload GPX track"
|
||||||
<!-- <LocationInput label="Turn point" :locations="locations" v-model="formData.turnPoints[i-1]">-->
|
url="http://localhost:4444/upload"
|
||||||
<!-- <template #append v-if="i > 1">-->
|
class="q-mx-sm"
|
||||||
<!-- <q-btn @click="removeTurnPoint(i - 1)">-</q-btn>-->
|
style="width: 100%"
|
||||||
<!-- </template>-->
|
auto-upload
|
||||||
<!-- </LocationInput>-->
|
color="secondary"
|
||||||
<!-- </template>-->
|
/>
|
||||||
<!-- <q-btn @click="turnPointsCount++">-->
|
|
||||||
<!-- Add turn point-->
|
|
||||||
<!-- </q-btn>-->
|
|
||||||
|
|
||||||
<q-uploader
|
<TabsStepper v-model="formStep" previous-step="copilot" next-step="photos"/>
|
||||||
label="Upload GPX track"
|
</q-tab-panel>
|
||||||
url="http://localhost:4444/upload"
|
|
||||||
class="q-mx-sm"
|
|
||||||
style="width: 100%"
|
|
||||||
auto-upload
|
|
||||||
color="secondary"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TabsStepper v-model="formStep" previous-step="basic" next-step="copilot"/>
|
|
||||||
</q-tab-panel>
|
|
||||||
|
|
||||||
<q-tab-panel name="copilot">
|
|
||||||
<q-btn-toggle spread no-caps v-model="formData.solo" toggle-color="primary" :options="[{label: 'Solo flight', value: true}, {label: 'Flight with someone', value: false}]"/>
|
|
||||||
|
|
||||||
<div v-if="!formData.solo">
|
<q-tab-panel name="photos">
|
||||||
<q-input type="text" v-model="formData.secondPilot" label="Second pilot"/>
|
<q-file
|
||||||
<q-checkbox v-model="formData.instructor" v-if="formData.secondPilot !== ''" label="Instructor"/>
|
label="Upload photos"
|
||||||
<q-input v-model="formData.picTime" label="PIC time"/>
|
multiple
|
||||||
|
style="width: 100%;"
|
||||||
|
color="secondary"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<TabsStepper v-model="formStep" previous-step="copilot" next-step="notes"/>
|
||||||
|
</q-tab-panel>
|
||||||
|
|
||||||
|
<q-tab-panel name="notes">
|
||||||
|
<q-input type="text" v-model="formData.name" label="Nazev"/>
|
||||||
|
<q-editor v-model="formData.description" height="60vh" label="Poznámky"/>
|
||||||
|
|
||||||
|
<TabsStepper v-model="formStep" previous-step="photos"/>
|
||||||
|
</q-tab-panel>
|
||||||
|
</q-tab-panels>
|
||||||
|
</template>
|
||||||
|
<template #saveButton>
|
||||||
|
<q-page-sticky expand position="bottom" :offset="[10, 10]" v-if="basicInfoFilled">
|
||||||
|
<div>
|
||||||
|
<q-btn type="submit" size="lg" class="full-width" color="primary" icon="save" label="Save flight"/>
|
||||||
</div>
|
</div>
|
||||||
|
</q-page-sticky>
|
||||||
<TabsStepper v-model="formStep" previous-step="track" next-step="photos"/>
|
</template>
|
||||||
</q-tab-panel>
|
|
||||||
|
|
||||||
<q-tab-panel name="photos">
|
|
||||||
<q-uploader
|
|
||||||
label="Upload photos"
|
|
||||||
url="http://localhost:4444/upload"
|
|
||||||
multiple
|
|
||||||
auto-upload
|
|
||||||
style="width: 100%;"
|
|
||||||
color="secondary"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TabsStepper v-model="formStep" previous-step="copilot" next-step="notes"/>
|
|
||||||
</q-tab-panel>
|
|
||||||
|
|
||||||
<q-tab-panel name="notes">
|
|
||||||
<q-input type="text" v-model="formData.name" label="Nazev" />
|
|
||||||
<q-editor v-model="formData.description" height="60vh" label="Poznámky"/>
|
|
||||||
|
|
||||||
<TabsStepper v-model="formStep" previous-step="photos"/>
|
|
||||||
</q-tab-panel>
|
|
||||||
</q-tab-panels>
|
|
||||||
|
|
||||||
<q-page-sticky expand position="bottom" :offset="[10, 10]" v-if="basicInfoFilled">
|
|
||||||
<div>
|
|
||||||
<q-btn type="submit" size="lg" class="full-width" color="primary" icon="save" label="Save flight"/>
|
|
||||||
</div>
|
|
||||||
</q-page-sticky>
|
|
||||||
</FormWrapper>
|
</FormWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {minutesToHumanReadable} from "src/composables/timeUtils";
|
import {formatDate, minutesToHumanReadable} from "src/composables/datetimeUtils";
|
||||||
import {computed} from "vue";
|
import {computed} from "vue";
|
||||||
import {useQuasar} from "quasar";
|
import {useQuasar} from "quasar";
|
||||||
|
|
||||||
@@ -47,10 +47,10 @@ const totalFlightTime = computed(() => {
|
|||||||
{{ flight.takeoffAirport.name }} - {{ flight.landingAirport.name }}
|
{{ flight.takeoffAirport.name }} - {{ flight.landingAirport.name }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-subtitle2">{{ minutesToHumanReadable(flight.flightDurationMinutes) }}</div>
|
<div class="text-subtitle2">{{ minutesToHumanReadable(flight.durationMinCalculated) }}</div>
|
||||||
<div class="text-secondary">
|
<div class="text-secondary">
|
||||||
<q-icon name="today"/>
|
<q-icon name="today"/>
|
||||||
{{ flight.date }}
|
{{ formatDate(flight.takeoffDatetime) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-secondary">
|
<div class="text-secondary">
|
||||||
<q-icon name="plane"/>
|
<q-icon name="plane"/>
|
||||||
|
|||||||
@@ -1,24 +1,73 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted, ref, watch} from "vue";
|
import {computed, onMounted, ref, watch} from "vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: String,
|
type: Date,
|
||||||
required: true
|
},
|
||||||
|
dateMask: {
|
||||||
|
type: String, Boolean,
|
||||||
|
required: false,
|
||||||
|
default: "YYYY-MM-DD"
|
||||||
|
},
|
||||||
|
timeMask: {
|
||||||
|
type: String, Boolean,
|
||||||
|
required: false,
|
||||||
|
default: "HH:mm"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['update:modelValue']);
|
|
||||||
|
|
||||||
let model = ref("");
|
let dateModel = ref("");
|
||||||
|
let timeModel = ref("");
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
model.value = props.modelValue;
|
let date = "";
|
||||||
|
let time = "";
|
||||||
|
|
||||||
|
if (props.modelValue) {
|
||||||
|
|
||||||
|
date = props.dateMask.replace("YYYY", props.modelValue.getFullYear())
|
||||||
|
.replace("MM", ('0' + props.modelValue.getMonth()).slice(-2))
|
||||||
|
.replace("DD", ('0' + props.modelValue.getDate()).slice(-2));
|
||||||
|
|
||||||
|
time = props.timeMask.replace("HH", ('0' + props.modelValue.getHours()).slice(-2))
|
||||||
|
.replace("mm", ('0' + props.modelValue.getMinutes()).slice(-2))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time === '') {
|
||||||
|
time = "00:00";
|
||||||
|
}
|
||||||
|
|
||||||
|
dateModel.value = date;
|
||||||
|
timeModel.value = time;
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(model, (newVal) => {
|
const model = computed(() => dateModel.value + " " + timeModel.value);
|
||||||
emit("update:modelValue", newVal);
|
|
||||||
})
|
const emit = defineEmits(['update:modelValue']);
|
||||||
|
const emitModelUpdate = () => {
|
||||||
|
const now = new Date();
|
||||||
|
const val = new Date(model.value);
|
||||||
|
val.setHours(val.getHours() + now.getTimezoneOffset());
|
||||||
|
emit("update:modelValue", val);
|
||||||
|
}
|
||||||
|
watch([dateModel, timeModel], emitModelUpdate)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-input type="datetime-local" v-model="model" v-bind="$attrs"/>
|
<q-input v-model="model" readonly>
|
||||||
|
<template #append>
|
||||||
|
<q-icon name="event">
|
||||||
|
<q-popup-proxy cover>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col" v-if="dateMask">
|
||||||
|
<q-date v-model="dateModel" :mask="dateMask"/>
|
||||||
|
</div>
|
||||||
|
<div class="col" v-if="timeMask">
|
||||||
|
<q-time v-model="timeModel" format24h :mask="timeMask"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-popup-proxy>
|
||||||
|
</q-icon>
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ watch(selectedLocationModel, (newVal) => {
|
|||||||
// TODO: rozdelit emit na dva modely - jeden na emit existujici lokality, druhy na emit nove vytvarene
|
// TODO: rozdelit emit na dva modely - jeden na emit existujici lokality, druhy na emit nove vytvarene
|
||||||
if (!newVal) return;
|
if (!newVal) return;
|
||||||
|
|
||||||
console.log(newVal);
|
|
||||||
|
|
||||||
let value, eventName;
|
let value, eventName;
|
||||||
if (newVal instanceof String) {
|
if (newVal instanceof String) {
|
||||||
eventName = "update:modelValue";
|
eventName = "update:modelValue";
|
||||||
|
|||||||
@@ -3,3 +3,10 @@ export const minutesToHumanReadable = (totalMinutes) => {
|
|||||||
const minutes = totalMinutes % 60;
|
const minutes = totalMinutes % 60;
|
||||||
return `${hours}h ${minutes}min`
|
return `${hours}h ${minutes}min`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const formatDate = (date) => {
|
||||||
|
if (typeof date === 'string') {
|
||||||
|
date = new Date(date);
|
||||||
|
}
|
||||||
|
return date.getDate()+". "+date.getMonth()+". "+date.getFullYear();
|
||||||
|
}
|
||||||
@@ -4,8 +4,12 @@ export const FRAGMENT_FLIGHT_FULL_INFO = gql`
|
|||||||
fragment flightFullInfo on Flight {
|
fragment flightFullInfo on Flight {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
description
|
||||||
takeoffDatetime
|
takeoffDatetime
|
||||||
landingDatetime
|
landingDatetime
|
||||||
|
durationMinCalculated
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
takeoffAirport {
|
takeoffAirport {
|
||||||
id
|
id
|
||||||
|
|||||||
@@ -7,7 +7,16 @@ query FlightsList {
|
|||||||
...flightFullInfo
|
...flightFullInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
${FRAGMENT_FLIGHT_FULL_INFO}
|
${FRAGMENT_FLIGHT_FULL_INFO}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FLIGHT_DETAIL = gql`
|
||||||
|
query FlightDetail($id: Int!) {
|
||||||
|
flight(id: $id) {
|
||||||
|
...flightFullInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${FRAGMENT_FLIGHT_FULL_INFO}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ const route = useRoute();
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const aircraftId = computed(() => parseInt(route.params.id));
|
const aircraftId = computed(() => parseInt(route.params.id));
|
||||||
let loading = ref(false);
|
const loading = ref(false);
|
||||||
let aircraft = reactive({});
|
let aircraft = reactive({});
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|||||||
@@ -1,34 +1,41 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {useFlightsStore} from "stores/Flights";
|
import {useFlightsStore} from "stores/Flights";
|
||||||
import {useRoute} from "vue-router";
|
import {useRoute} from "vue-router";
|
||||||
import {computed, onMounted} from "vue";
|
import {onMounted, reactive, ref} from "vue";
|
||||||
import {minutesToHumanReadable} from "src/composables/timeUtils";
|
import {formatDate, minutesToHumanReadable} from "src/composables/datetimeUtils";
|
||||||
|
import FlightDetailSkeleton from "components/flights/FlightDetailSkeleton.vue";
|
||||||
|
import AddFAB from "components/AddFAB.vue";
|
||||||
|
|
||||||
const flightsStore = useFlightsStore();
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const loading = ref(false)
|
||||||
|
let flight = reactive({});
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
flightsStore.fetchDetail(route.params.id);
|
loading.value = true;
|
||||||
|
useFlightsStore().fetchDetail(parseInt(route.params.id))
|
||||||
|
.then(respFlight => flight = respFlight)
|
||||||
|
.finally(() => loading.value = false);
|
||||||
})
|
})
|
||||||
|
|
||||||
const flight = computed(() => flightsStore.getDetail(route.params.id) || {});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1>{{flight.takeOffLocation}} - {{flight.landingLocation}}</h1>
|
<FlightDetailSkeleton v-if="loading || Object.keys(flight).length === 0"/>
|
||||||
|
|
||||||
<q-icon name="calendar">{{flight.date}}</q-icon>
|
<template v-else>
|
||||||
<q-icon name="weather">
|
<h1>{{ flight.name }}</h1>
|
||||||
Clouds: few
|
<h2>{{ flight.takeoffAirport.name }} - {{ flight.landingAirport.name }}</h2>
|
||||||
Wind: 220/12kt
|
|
||||||
Temp: 12°C
|
|
||||||
</q-icon>
|
|
||||||
|
|
||||||
Track: {{ flight.turnPoints }}
|
<article v-html="flight.description" />
|
||||||
|
|
||||||
{{ minutesToHumanReadable(flight.flightDurationMinutes) }}
|
<q-icon name="calendar"/>
|
||||||
|
{{ formatDate(flight.takeoffDatetime) }}
|
||||||
|
{{ minutesToHumanReadable(flight.durationMinCalculated) }}
|
||||||
|
|
||||||
<q-page-sticky location="bottom-right" :offset="[30, 30]">
|
<!-- <q-icon name="weather"/>-->
|
||||||
<q-fab color="primary" icon="edit" label="Edit" @click="$router.push({name: 'flightEdit', params:{id: flight.id}})"/>
|
<!-- Clouds: few-->
|
||||||
</q-page-sticky>
|
<!-- Wind: 220/12kt-->
|
||||||
|
<!-- Temp: 12°C-->
|
||||||
|
|
||||||
|
|
||||||
|
<AddFAB :router-link="{name: 'flightEdit', params:{id: flight.id}}" label="Upravit"/>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {useRoute} from "vue-router";
|
|||||||
import {useFlightsStore} from "stores/Flights";
|
import {useFlightsStore} from "stores/Flights";
|
||||||
import {computed, onMounted} from "vue";
|
import {computed, onMounted} from "vue";
|
||||||
import {storeToRefs} from "pinia";
|
import {storeToRefs} from "pinia";
|
||||||
import {minutesToHumanReadable} from "src/composables/timeUtils";
|
import {minutesToHumanReadable} from "src/composables/datetimeUtils";
|
||||||
|
|
||||||
const secondPilotStore = useSecondPilotsStore();
|
const secondPilotStore = useSecondPilotsStore();
|
||||||
const flightsStore = useFlightsStore();
|
const flightsStore = useFlightsStore();
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ const password = ref("");
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const logUser = () => {
|
const logUser = () => {
|
||||||
useUserStore().login({email: email.value, password: password.value}).then(() => {
|
useUserStore().login({email: email.value, password: password.value}).then(() => {
|
||||||
console.log("tu ok");
|
|
||||||
router.push({name: "myFlights"});
|
router.push({name: "myFlights"});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ export const useAircraftsStore = defineStore('Aircrafts', {
|
|||||||
fetchDetail(id) {
|
fetchDetail(id) {
|
||||||
return apolloWrapper
|
return apolloWrapper
|
||||||
.query(AIRCRAFT_DETAIL, {id})
|
.query(AIRCRAFT_DETAIL, {id})
|
||||||
.then((result) => {
|
.then((result) => result.data.aircraft);
|
||||||
return result.data.aircraft;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
create(formData) {
|
create(formData) {
|
||||||
delete formData['id'];
|
delete formData['id'];
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {apolloWrapper} from "src/graphql/apollo"
|
import {apolloWrapper} from "src/graphql/apollo"
|
||||||
import {FLIGHTS_LIST} from "src/graphql/queries/flights";
|
import {FLIGHT_DETAIL, FLIGHTS_LIST} from "src/graphql/queries/flights";
|
||||||
import {CREATE_FLIGHT} from "src/graphql/mutations/flight";
|
import {CREATE_FLIGHT} from "src/graphql/mutations/flight";
|
||||||
|
|
||||||
export const useFlightsStore = defineStore('Flights', {
|
export const useFlightsStore = defineStore('Flights', {
|
||||||
@@ -24,7 +24,7 @@ export const useFlightsStore = defineStore('Flights', {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
fetchDetail(id) {
|
fetchDetail(id) {
|
||||||
this.items.push({id: id, takeOffLocation: "LKLT", landingLocation: "LKLT", date: "2023-02-01", aircraft: {id: 1, name: "OK-AUR28"}, flightDurationMinutes: 76})
|
return apolloWrapper.query(FLIGHT_DETAIL, {id}).then(result => result.data.flight);
|
||||||
},
|
},
|
||||||
fetch() {
|
fetch() {
|
||||||
return apolloWrapper
|
return apolloWrapper
|
||||||
|
|||||||
Reference in New Issue
Block a user