Zaklad pro zadavani novych letu

This commit is contained in:
Michal Kváček
2023-06-06 07:35:04 +02:00
parent 9d843c62a6
commit 25bf93589e
19 changed files with 413 additions and 197 deletions
+11 -143
View File
@@ -1,55 +1,33 @@
<script setup>
import {computed, onMounted, reactive, ref, watch} from "vue";
import LocationInput from "components/inputs/LocationInput.vue";
import {onMounted, ref} from "vue";
import {useAircraftsStore} from "stores/Aircrafts";
import {useFlightsStore} from "stores/Flights";
import {useRouter} from "vue-router";
import {usePointsOfInterestStore} from "stores/PointsOfInterest";
import {storeToRefs} from "pinia";
import {isRequired} from "src/composables/form/rules";
import {useMeta} from "quasar";
import TabsStepper from "components/TabsStepper.vue";
import FlightForm from "components/flights/FlightForm.vue";
import {useAirportsStore} from "stores/Airports";
const aircraftsStore = useAircraftsStore();
const poiStore = usePointsOfInterestStore();
const flightsStore = useFlightsStore();
const airportStore = useAirportsStore();
useMeta({title: "New flight"});
onMounted(() => {
aircraftsStore.fetch();
poiStore.fetch();
flightsStore.fetch();
airportStore.fetch();
});
const rules = {
aircraft: [isRequired],
takeOffLocation: [isRequired],
LandingLocation: [isRequired],
}
const aircrafts = storeToRefs(aircraftsStore).items;
const locations = storeToRefs(poiStore).items;
const airports = storeToRefs(airportStore).items;
const turnPointsCount = ref(1);
const formData = reactive({
aircraftId: null,
takeOffLocation: null,
landingLocation: null,
turnPoints: [],
solo: true,
secondPilot: "",
instructor: false,
picTime: 0,
date: new Date(),
takeOffTime: "",
landingTime: "",
flightDurationMinutes: 0,
landings: 1,
note: ""
})
const formSteps = ["aircraft", "basic", "track", "copilot", "photos", "notes"]
const formStep = ref(formSteps[0]);
// watch(() => formData.takeOffLocation, (newVal) => {
// if (!formData.landingLocation) {
@@ -58,15 +36,12 @@ const formStep = ref(formSteps[0]);
// })
const router = useRouter();
const saveForm = () => {
flightsStore.create(this.formData).then(() => {
const handleSave = (formData) => {
flightsStore.create(formData).then(() => {
router.push({name: "myFlights"});
});
}
const basicInfoFilled = computed(() => {
return formData.aircraftId && formData.takeOffLocation && formData.landingLocation && formData.date && formData.flightDurationMinutes > 0
})
const removeTurnPoint = (idx) => {
formData.turnPoints.splice(idx, 1);
@@ -77,120 +52,13 @@ const removeTurnPoint = (idx) => {
<template>
<q-breadcrumbs>
<q-breadcrumbs-el :to="{name: 'myFlights'}">My Flights</q-breadcrumbs-el>
<q-breadcrumbs-el>Add new</q-breadcrumbs-el>
<q-breadcrumbs-el :to="{name: 'myFlights'}">Moje lety</q-breadcrumbs-el>
<q-breadcrumbs-el>Nový</q-breadcrumbs-el>
</q-breadcrumbs>
<!-- {{ formData }}-->
<q-form @submit.prevent="saveForm" class="q-my-lg">
<q-tabs
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="track" icon="route" label="Route"/>
<q-tab name="copilot" icon="person_add" label="Copilot"/>
<q-tab name="photos" icon="add_a_photo" label="Photos"/>
<q-tab name="notes" icon="edit_note" label="Notes"/>
</q-tabs>
<FlightForm @save="handleSave" :aircrafts="aircrafts" :airports="airports" :locations="locations"/>
<q-tab-panels v-model="formStep" animated>
<q-tab-panel name="aircraft">
<q-select
v-model="formData.aircraftId"
option-label="name"
option-value="id"
emit-value
map-options
:rules="rules.aircraft"
:options="aircrafts"
label="Aircraft"
>
<template #prepend>
<q-icon name="flight"></q-icon>
</template>
</q-select>
<TabsStepper v-model="formStep" next-step="basic"/>
</q-tab-panel>
<q-tab-panel name="basic">
<q-input type="date" v-model="formData.date" label="Date"/>
<q-input type="time" v-model="formData.time" label="Take-off time"/>
<LocationInput label="Take-off location" :rules="rules.takeOffLocation" :locations="locations" v-model="formData.takeOffLocation" prepend-icon="flight_takeoff"/>
<LocationInput label="Landing location" :rules="rules.landingLocation" :locations="locations" v-model="formData.landingLocation" prepend-icon="flight_land"/>
<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>
<q-tab-panel name="track">
<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-uploader
label="Upload GPX track"
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-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>
<TabsStepper v-model="formStep" previous-step="track" next-step="photos"/>
</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-editor v-model="formData.note" height="60vh" label="Notes"/>
<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>
</q-form>
</template>
@@ -10,9 +10,6 @@ const $q = useQuasar();
const router = useRouter();
const handleSave = (formData) => {
isRequestPending.value = true;
console.log("handlesave", formData);
useAircraftsStore().create(formData).then(() => {
$q.notify({message: "Letadlo úspěšně vytvořeno", position: "top", color: "positive"});
+43
View File
@@ -0,0 +1,43 @@
<script setup>
import {onMounted, ref} from "vue";
import {useFlightsStore} from "stores/Flights";
import {useMeta} from "quasar";
import FlightsList from "components/flights/FlightsList.vue";
import FlightsListSkeleton from "components/flights/FlightsListSkeleton.vue";
import {storeToRefs} from "pinia";
import AddFAB from "components/AddFAB.vue";
useMeta({title: "Moje lety"});
const flightsStore = useFlightsStore();
const flights = storeToRefs(flightsStore).items;
const loading = ref(false);
onMounted(() => {
loading.value = true;
flightsStore.fetch().finally(() => {
loading.value = false;
});
})
</script>
<template>
<FlightsListSkeleton v-if="loading"/>
<div class="q-pa-md q-gutter-sm" v-else-if="!loading && flights.length === 0">
<q-banner class="bg-light-blue text-white ">
<template v-slot:avatar>
<q-icon name="info"/>
</template>
Nemáš zaznamenaný žádný let.
<template v-slot:action>
<q-btn flat color="white" :to="{name: 'addFlight'}" label="Přidat let"/>
</template>
</q-banner>
</div>
<FlightsList :items="flights" v-else/>
<AddFAB :router-link="{name: 'addFlight'}"/>
</template>
-76
View File
@@ -1,76 +0,0 @@
<script setup>
import {computed, onMounted} from "vue";
import {useFlightsStore} from "stores/Flights";
import {minutesToHumanReadable} from "src/composables/timeUtils";
import {useMeta, useQuasar} from "quasar";
useMeta({title: "Moje lety"});
const flightsStore = useFlightsStore();
onMounted(() => {
flightsStore.fetch();
})
const totalFlightTime = computed(() => {
return flightsStore.items.reduce((acc, flight) => acc + flight.flightDurationMinutes, 0);
})
const $q = useQuasar();
const deleteFlight = (flightId) => {
$q.dialog({
title: 'Potvrzení',
message: 'Opravdu chceš smazat tento let?',
cancel: true,
persistent: true
}).onOk(() => {
flightsStore.deleteItem(flightId);
})
}
</script>
<template>
<div class="row">
<div class="col-12 col-md-4 col-lg-3" v-for="flight of flightsStore.items" :key="flight">
<q-card class="q-my-sm q-mx-sm">
<q-img :src="flight.titlePhotoUrl" v-if="flight.titlePhotoUrl">
<div class="absolute-bottom text-center text-h6">
<router-link :to="{name: 'flightDetail', params:{id: flight.id}}" class="text-white">
{{ flight.takeOffLocation }} - {{ flight.landingLocation }}
</router-link>
</div>
</q-img>
<q-card-section>
<div class="text-h6" v-if="!flight.titlePhotoUrl">
<router-link :to="{name: 'flightDetail', params:{id: flight.id}}">
{{ flight.takeOffLocation }} - {{ flight.landingLocation }}
</router-link>
</div>
<div class="text-subtitle2">{{ minutesToHumanReadable(flight.flightDurationMinutes) }}</div>
<div class="text-secondary">
<q-icon name="today"/>
{{ flight.date }}
</div>
<div class="text-secondary">
<q-icon name="plane"/>
{{ flight.aircraft.name }}
</div>
</q-card-section>
<q-separator/>
<q-card-actions align="right">
<!-- <q-btn flat icon="visibility"></q-btn>-->
<!-- <q-btn flat icon="edit" :to="{name: 'flightEdit', params:{id: flight.id}}"></q-btn>-->
<q-btn flat icon="delete" color="red" @click="deleteFlight(flight.id)"></q-btn>
</q-card-actions>
</q-card>
</div>
</div>
Total: {{ minutesToHumanReadable(totalFlightTime) }}
<q-page-sticky location="bottom" :offset="[30, 30]">
<q-fab icon="add" color="primary" label="Add flight" @click="$router.push({name: 'addFlight'})"/>
</q-page-sticky>
</template>