diff --git a/src/components/flightPlans/FlightPlanForm.vue b/src/components/flightPlans/FlightPlanForm.vue new file mode 100644 index 0000000..bbc11b8 --- /dev/null +++ b/src/components/flightPlans/FlightPlanForm.vue @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + km/h + + + diff --git a/src/components/flightPlans/FlightPlanRouteTable.vue b/src/components/flightPlans/FlightPlanRouteTable.vue new file mode 100644 index 0000000..07bb182 --- /dev/null +++ b/src/components/flightPlans/FlightPlanRouteTable.vue @@ -0,0 +1,92 @@ + + + + + + + + + {{ minutesToHumanReadable(getTotalTime(flightPlan, plannedSpeed)) }} + + + {{ getTotalDistance(flightPlan) }} km + + + + + + + + + diff --git a/src/components/flightPlans/FlightPlanSideControls.vue b/src/components/flightPlans/FlightPlanSideControls.vue index 0981a34..8d4f3e7 100644 --- a/src/components/flightPlans/FlightPlanSideControls.vue +++ b/src/components/flightPlans/FlightPlanSideControls.vue @@ -1,19 +1,14 @@ @@ -73,13 +57,15 @@ const totalTime = computed(() => { {{ segment.bearing }}°, {{ segment.distance }} km, - {{ minutesToHumanReadable(getDuration(segment.distance, props.plannedSpeed)) }} + {{ minutesToHumanReadable(getDuration(segment.distance, props.flightPlan.plannedSpeed)) }} @@ -123,7 +109,7 @@ const totalTime = computed(() => { Celková vzdálenost: {{ totalDistance }} km - Plánovaná doba letu: {{ minutesToHumanReadable(totalTime) }} + Plánovaná doba letu: {{ minutesToHumanReadable(getTotalTime(props.flightPlan, props.flightPlan.plannedSpeed)) }} diff --git a/src/composables/flightPlan.js b/src/composables/flightPlan.js index ac3aeb7..6ee1532 100644 --- a/src/composables/flightPlan.js +++ b/src/composables/flightPlan.js @@ -23,6 +23,24 @@ export const useFlightPlanUtils = () => { return {getIcon, getMarkersFrom} } +export const useFlightPlanCalculations = () => { + const getDuration = (distance, speed) => Math.round(distance / speed * 60) + + const getTotalDistance = (flightPlan) => { + if (!flightPlan.track.length) return null; + + return Math.round(flightPlan.track.map(t => t.distance).reduce((a, b) => a + b)); + } + + const getTotalTime = (flightPlan, plannedSpeed) => { + if (!flightPlan.track.length) return null; + + return flightPlan.track.map(t => getDuration(t.distance, plannedSpeed)).reduce((a, b) => a + b) + } + + return {getDuration, getTotalDistance, getTotalTime} +} + export const useFlightPlanObjects = () => { const editableNameTypes = ["geocode", "mapPoint"]; diff --git a/src/composables/utils.js b/src/composables/utils.js index d1f2661..d8ff1b1 100644 --- a/src/composables/utils.js +++ b/src/composables/utils.js @@ -8,3 +8,18 @@ export const pluralize = (count, singular, plural, pluralMore) => { else if (count < 5) return plural; else return pluralMore; } + +export const textEllipsis = (text, maxLength) => { + if (text.length <= maxLength) { + return text; + } + + let words = text.split(' '); + + const maxWords = 2; + if (words.length <= maxWords + 1) { + return text; + } + + return words[0] + ' ... ' + words[words.length - 1]; +} diff --git a/src/pages/profile/flightPlanner/FlightPlanEditPage.vue b/src/pages/profile/flightPlanner/FlightPlanEditPage.vue index 8f03838..4c9b8bc 100644 --- a/src/pages/profile/flightPlanner/FlightPlanEditPage.vue +++ b/src/pages/profile/flightPlanner/FlightPlanEditPage.vue @@ -14,28 +14,23 @@ import {usePointsOfInterestStore} from "stores/PointsOfInterest"; import {storeToRefs} from "pinia"; import {useAirspacesStore} from "stores/Airspaces"; import {useAirportsStore} from "stores/Airports"; -import {commonProps} from "src/composables/inputs"; import {useAppStore} from "stores/App"; import {useFlightPlanObjects, useFlightPlanUtils} from "src/composables/flightPlan"; import FlightPlanMap from "components/flightPlans/FlightPlanMap.vue"; import FlightPlanRoute from "components/flightPlans/FlightPlanRoute.vue"; import FlightPlanSideControls from "components/flightPlans/FlightPlanSideControls.vue"; -import DatetimePicker from "components/inputs/DatetimePicker.vue"; import {useAircraftsStore} from "stores/Aircrafts"; -import ComboboxInput from "components/inputs/ComboboxInput.vue"; -import FormWrapper from "components/FormWrapper.vue"; import {successObject} from "src/composables/dialog"; import {useQuasar} from "quasar"; -import {useCopilotsStore} from "stores/Copilots"; +import FlightPlanRouteTable from "components/flightPlans/FlightPlanRouteTable.vue"; +import FlightPlanForm from "components/flightPlans/FlightPlanForm.vue"; const {flightPlan} = storeToRefs(useFlightPlansStore()); - const flightPlanName = computed(() => flightPlan.value.name || "Nepojmenovaný plán"); useAppStore().setPageTitle(`${flightPlanName.value} - plánovnání`); useAppStore().setBreadcrumbs([ {to: {name: "flightPlans"}, label: "Moje plány"}, {label: flightPlanName.value}, - {label: "Editace"} ]); onMounted(() => { @@ -51,20 +46,9 @@ const {airports} = storeToRefs(useAirportsStore()); const {aircrafts: aircraftsData} = storeToRefs(useAircraftsStore()); const aircrafts = computed(() => aircraftsData.value.map(a => ({id: a.id, name: a.callSign}))); - const {getMarkersFrom} = useFlightPlanUtils(); const {markerObject} = useFlightPlanObjects(); -const formData = ref({ - name: flightPlan.value?.name || null, - isDefaultName: flightPlan.value ? flightPlan.value.isDefaultName : true, - isEditableByCopilot: flightPlan.value?.isEditableByCopilot || false, - isPublic: flightPlan.value?.isPublic || false, - plannedTakeoffDatetime: flightPlan.value?.plannedTakeoffDatetime || null, - aircraft: flightPlan.value && flightPlan.value.aircraft ? {id: flightPlan.value.aircraft.id, name: flightPlan.value.aircraft.callSign} : null, - plannedSpeed: flightPlan.value?.plannedSpeed || 150, -}) - const openedTab = ref("route"); const flightPlannerDialogOpen = ref(false); const flightPlanMarkers = ref(getMarkersFrom(flightPlan.value)); @@ -73,7 +57,6 @@ const handleMarkersChanges = (markers) => { flightPlanMarkers.value = markers; useFlightPlansStore().update(flightPlan.value.id, { - name: formData.value.name, markers: markers.map(m => markerObject({ name: m.name, type: m.type, @@ -85,9 +68,9 @@ const handleMarkersChanges = (markers) => { const $q = useQuasar(); -const handleFlightPlanInfoSave = () => { - useFlightPlansStore().update(flightPlan.value.id, formData.value).then(() => { - $q.notify(successObject("Ulozeno")); +const handleFlightPlanInfoSave = (formData) => { + useFlightPlansStore().update(flightPlan.value.id, formData).then(() => { + $q.notify(successObject("Informace úspěšně uloženy")); }) } const insertAtPosition = ref(flightPlanMarkers.value.length); @@ -95,6 +78,7 @@ const fullscreen = ref(false); + {{ flightPlan.plannedSpeed }} @@ -105,6 +89,12 @@ const fullscreen = ref(false); Informace + + + + Navigační štítek + + @@ -136,25 +126,22 @@ const fullscreen = ref(false); - - - - - - - - - - - - km/h - - + - + + + + diff --git a/src/pages/profile/flightPlanner/FlightPlansPage.vue b/src/pages/profile/flightPlanner/FlightPlansPage.vue index 09bd853..cbaf2ff 100644 --- a/src/pages/profile/flightPlanner/FlightPlansPage.vue +++ b/src/pages/profile/flightPlanner/FlightPlansPage.vue @@ -11,15 +11,13 @@ import FlightPlansList from "components/flightPlans/FlightPlansList.vue"; useAppStore().setPageTitle("Nový plán"); useAppStore().setBreadcrumbs([ {to: {name: "myFlights"}, label: "Moje lety"}, - {to: {name: "flightPlans"}, label: "Plány"}, - {label: "Nový"} + {label: "Plánované lety"}, ]); onMounted(() => { useFlightPlansStore().fetch(); }); - const {flightPlans, isQueryRunning} = storeToRefs(useFlightPlansStore()); diff --git a/src/pages/public/AboutPage.vue b/src/pages/public/AboutPage.vue index 8f986e5..4cf38cf 100644 --- a/src/pages/public/AboutPage.vue +++ b/src/pages/public/AboutPage.vue @@ -31,9 +31,9 @@ useMeta(() => metaData({ Pro obohacení informací používá Polétání.cz data z následujících zdrojů: - Open Meteo API - pro stahování informací o počasí při vzletu a přistání + Open Meteo API - pro stahování informací o počasí při vzletu a přistání, pro stahování informací o elevaci terénu Elevation API - pro stažení informací o výšce terénu. Tato informace se používá u fotografií a trasy letu - VFR příručka - pro aktualizaci informací o letištích + OpenAIP - primární zdroj dat o vzdušném prostoru a letištích O autorovi diff --git a/src/pages/public/ContactPage.vue b/src/pages/public/ContactPage.vue index 57fc675..c26467d 100644 --- a/src/pages/public/ContactPage.vue +++ b/src/pages/public/ContactPage.vue @@ -25,10 +25,10 @@ const sendMessage = () => { email_from: formData.value.email, content: formData.value.content }).then((e) => { - $q.notify(successObject("Zpráva byla jakoby odeslána")); + $q.notify(successObject("Zpráva byla odeslána")); formData.value = {email: "", content: ""}; }).catch(() => { - $q.notify(errorObject("Zprávu se nepodařilo odeslat. Zkus to znovu za chvíli.")); + $q.notify(errorObject("Zprávu se nepodařilo odeslat. Zkus to znovu za chvíli.")); }) } diff --git a/src/pages/public/FeaturesPage.vue b/src/pages/public/FeaturesPage.vue index dfe8809..b78ad2b 100644 --- a/src/pages/public/FeaturesPage.vue +++ b/src/pages/public/FeaturesPage.vue @@ -18,6 +18,7 @@ useAppStore().setBreadcrumbs([ Sdílet zážitky s kamarády Upravovat fotky Zobrazovat je v kontextu polohy + Planovat let Debriefing letu: https://www.easa.europa.eu/community/topics/post-flight-debrief