Merge branch 'master' of kvacek.cz:poletani.cz/app into ssr

This commit is contained in:
Michal Kváček
2023-11-20 16:28:02 +01:00
79 changed files with 1464 additions and 1498 deletions
+43
View File
@@ -0,0 +1,43 @@
<script setup>
import {computed} from "vue";
import {useQuasar} from "quasar";
const props = defineProps({
saveButton: {
type: [Object, Boolean],
required: false,
default: () => ({
label: "Uložit",
icon: "save",
align: "left"
})
}
})
const $q = useQuasar();
const fullwidthBtn = computed(() => $q.screen.width <= $q.screen.sizes.md);
</script>
<template>
<div class="text-right">
<q-btn
color="primary"
type="submit"
size="lg"
:class="{'q-my-lg': true, 'btn--fullwidth': fullwidthBtn}"
:icon="props.saveButton.icon"
:loading="props.isRequestPending"
>
{{ props.saveButton.label }}
<template v-slot:loading>
<q-spinner/>
</template>
</q-btn>
</div>
</template>
<style>
.btn--fullwidth {
width: 100%;
}
</style>
+2 -28
View File
@@ -2,6 +2,7 @@
import {isRequestPending} from "src/composables/form/props";
import {computed, useSlots} from "vue";
import {useQuasar} from "quasar";
import FormSubmitButton from "components/FormSubmitButton.vue";
const props = defineProps({
modelValue: {
@@ -23,38 +24,11 @@ const emits = defineEmits(["save"]);
const saveForm = () => {
emits("save", props.modelValue);
}
const $q = useQuasar();
const fullwidthBtn = computed(() => $q.screen.width <= $q.screen.sizes.md);
</script>
<template>
<q-form @submit.prevent="saveForm" ref="form">
<slot name="default"/>
<div class="text-right">
<q-btn
color="primary"
type="submit"
size="lg"
:class="{'q-my-lg': true, 'btn--fullwidth': fullwidthBtn}"
v-if="saveButton"
:icon="props.saveButton.icon"
:loading="props.isRequestPending"
>
{{ props.saveButton.label }}
<template v-slot:loading>
<q-spinner />
</template>
</q-btn>
</div>
<FormSubmitButton v-if="saveButton" :save-button="saveButton" />
</q-form>
</template>
<style>
.btn--fullwidth {
width: 100%;
}
</style>
@@ -1,5 +1,4 @@
<script setup>
import {aircraft} from "src/composables/objects/aircraft";
import {confirmObject} from "src/composables/dialog";
import {useQuasar} from "quasar";
import {storeToRefs} from "pinia";
@@ -17,7 +16,6 @@ const $q = useQuasar();
const loggedUser = storeToRefs(useUserStore()).user;
const confirmDelete = (aircraftId) => {
$q.dialog(confirmObject('Opravdu chceš smazat toto letadlo?'))
.onOk(() => {
@@ -1,6 +1,4 @@
<script setup>
import {poi} from "src/composables/objects/poi";
const props = defineProps({
routeBack: {
type: Object,
@@ -1,6 +1,6 @@
<script setup>
import {randomInt} from "src/composables/random";
import {onBeforeMount, onMounted, ref} from "vue";
import {computed} from "vue";
const props = defineProps({
itemsCountMin: {
@@ -12,19 +12,18 @@ const props = defineProps({
type: Number,
required:false,
default: 5
},
items: {
type: Number, required: false,
}
});
const items = ref(0);
onMounted(() => {
items.value = randomInt(props.itemsCountMin, props.itemsCountMax);
})
const renderedItems = computed(() => props.items || randomInt(props.itemsCountMin, props.itemsCountMax));
</script>
<template>
<q-list bordered separator>
<q-item v-ripple v-for="i in items" :key="i">
<q-item v-ripple v-for="i in renderedItems" :key="i">
<q-item-section avatar>
<q-skeleton type="QAvatar" />
</q-item-section>
+2 -2
View File
@@ -19,14 +19,14 @@ const getCoverPhotos = (item) => item.flights.filter(f => !!f.coverPhoto).map(f
<template>
<q-list bordered separator>
<q-item
v-for="event of items" :key="event"
clickable
:to="{name: routeDetail.name, params: {...routeDetail.params, id: event.id}}"
v-ripple
v-for="event of items" :key="event"
>
<q-item-section>
<q-item-label>
<q-avatar icon="event" color="primary" text-color="white" v-if="event.flights.length === 0"/>
<q-avatar icon="event" color="primary" text-color="white" v-if="!event.flights || event.flights.length === 0"/>
<AvatarsGroup :avatars="getCoverPhotos(event)" v-else/>
{{ event.name }}
@@ -1,5 +1,4 @@
<script setup>
import {flight} from "src/composables/objects/flight";
import {FORMAT_DATE, FORMAT_TIME, formatDatetime, minutesToHumanReadable} from "src/composables/datetimeUtils";
import WeatherInfo from "components/weather/WeatherInfo.vue";
@@ -1,5 +1,4 @@
<script setup>
import {randomInt} from "src/composables/random";
import ListItemSkeleton from "components/basicSkeletons/ListItemSkeleton.vue";
import BasicTextSkeleton from "components/basicSkeletons/BasicTextSkeleton.vue";
</script>
@@ -16,7 +15,7 @@ import BasicTextSkeleton from "components/basicSkeletons/BasicTextSkeleton.vue";
<q-item>
<q-list>
<ListItemSkeleton v-for="i in randomInt(1, 3)" :key="i"/>
<ListItemSkeleton v-for="i in 3" :key="i"/>
</q-list>
</q-item>
+7 -8
View File
@@ -1,7 +1,6 @@
<script setup>
import {flight} from "src/composables/objects/flight";
import MapWithMarkers from "components/map/MapWithMarkers.vue";
import {computed, ref} from "vue";
import {computed, reactive, ref} from "vue";
import {Line} from "vue-chartjs"
const props = defineProps({
@@ -12,23 +11,23 @@ const props = defineProps({
})
const mapPhotos = computed(() => flight.value.photos.filter(photo => photo.gpsLatitude && photo.gpsLongitude));
const poisWithGPS = computed(() => flight.value.track.map(poi => poi.pointOfInterest || poi.airport));
const mapPhotos = computed(() => props.flight.photos.filter(photo => photo.gpsLatitude && photo.gpsLongitude));
const poisWithGPS = computed(() => props.flight.track.map(poi => poi.pointOfInterest || poi.airport));
const mapMarkers = [flight.value.takeoffAirport].concat(poisWithGPS.value).concat([flight.value.landingAirport]);
const mapMarkers = [props.flight.takeoffAirport].concat(poisWithGPS.value).concat([props.flight.landingAirport]);
const pointsOfInterests = computed(() => mapMarkers
.filter(marker => marker.gpsLatitude && marker.gpsLongitude)
.map(
marker => ({label: marker.name, position: {lat: marker.gpsLatitude, lng: marker.gpsLongitude}})
));
const gpxTrack = flight.value.gpxTrack;
const gpxTrack = props.flight.gpxTrack ? reactive(props.flight.gpxTrack) : null;
const displayMap = computed(() => {
return (
!!gpxTrack ||
mapPhotos.value.length > 0 ||
poisWithGPS.value.length > 0 ||
flight.value.landingAirport.id !== flight.value.takeoffAirport.id
props.flight.landingAirport.id !== props.flight.takeoffAirport.id
)
});
@@ -82,7 +81,7 @@ const drawCurrentPositionMarker = (e) => {
return;
}
const idx = res[0].index;
currentPositionMarker.value = flight.value.gpxTrack.coordinates[idx];
currentPositionMarker.value = props.flight.gpxTrack.coordinates[idx];
}
const chartOptions = {
+1 -1
View File
@@ -1,6 +1,6 @@
<script setup>
import {minutesToHumanReadable} from "src/composables/datetimeUtils";
import {flightName} from "src/composables/objects/flight";
import {flightName} from "src/composables/flight";
import AvatarFromPhoto from "components/avatars/AvatarFromPhoto.vue";
const props = defineProps({
@@ -5,7 +5,6 @@ import {setDefaultData} from "src/composables/form/formHandling";
import RichTextEditor from "components/inputs/RichTextEditor.vue";
import {commonProps} from "src/composables/inputs";
import ComboboxInput from "components/inputs/ComboboxInput.vue";
import {isRequestPending} from "src/composables/objects/flight";
const props = defineProps({
flight: {
+1 -1
View File
@@ -24,7 +24,7 @@ const props = defineProps({
const formData = reactive({
name: null,
description: null,
description: "",
gpsLatitude: null,
gpsLongitude: null,
type: null,
+7 -1
View File
@@ -1,7 +1,13 @@
<script setup>
import {user as pilot} from "src/composables/objects/user";
import {FORMAT_DATE, formatDatetime} from "src/composables/datetimeUtils";
import AvatarFromPhoto from "components/avatars/AvatarFromPhoto.vue";
const props = defineProps({
pilot: {
type: Object,
required: true
}
});
</script>
<template>