Verejna cast, hezci 404ka, refaktoring
This commit is contained in:
+23
-1
@@ -1,3 +1,25 @@
|
||||
<script setup>
|
||||
import {useRoute} from "vue-router";
|
||||
import {computed} from "vue";
|
||||
import ErrorNotFound from "pages/ErrorNotFound.vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {useAppStore} from "stores/App";
|
||||
|
||||
const route = useRoute();
|
||||
|
||||
|
||||
const layoutComponent = computed(() => {
|
||||
if (!route.meta) return null;
|
||||
return route.meta.layout;
|
||||
});
|
||||
|
||||
const appStatus = storeToRefs(useAppStore()).appStatus;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<router-view />
|
||||
<ErrorNotFound v-if="appStatus === 404"/>
|
||||
<template v-else>
|
||||
<component :is="layoutComponent" v-if="layoutComponent"/>
|
||||
<router-view v-else/>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<script setup>
|
||||
import {flight} from "src/composables/objects/flight";
|
||||
import MapWithMarkers from "components/map/MapWithMarkers.vue";
|
||||
import {computed} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
flight: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
const trackWithGPS = computed(() => {
|
||||
return flight.value.track.filter(poi => poi.pointOfInterest.gpsLatitude && poi.pointOfInterest.gpsLongitude)
|
||||
});
|
||||
|
||||
const pointsOfInterests = computed(() => {
|
||||
const path = [{
|
||||
label: flight.value.takeoffAirport.name,
|
||||
position:
|
||||
{
|
||||
lat: flight.value.takeoffAirport.gpsLatitude,
|
||||
lng: flight.value.takeoffAirport.gpsLongitude
|
||||
}
|
||||
}];
|
||||
|
||||
for (const poi of trackWithGPS.value) {
|
||||
path.push({
|
||||
label: poi.pointOfInterest.name,
|
||||
position: {lat: poi.pointOfInterest.gpsLatitude, lng: poi.pointOfInterest.gpsLongitude}
|
||||
});
|
||||
}
|
||||
|
||||
path.push({
|
||||
label: flight.value.takeoffAirport.name,
|
||||
position: {
|
||||
lat: flight.value.landingAirport.gpsLatitude,
|
||||
lng: flight.value.landingAirport.gpsLongitude
|
||||
}
|
||||
});
|
||||
|
||||
return path;
|
||||
});
|
||||
|
||||
|
||||
const mapPhotos = computed(() => {
|
||||
return flight.value.photos.filter(photo => photo.gpsLatitude && photo.gpsLongitude)
|
||||
});
|
||||
|
||||
const displayMap = computed(() => {
|
||||
return (
|
||||
!!flight.value.gpsTrackUrl ||
|
||||
mapPhotos.value.length > 0 ||
|
||||
trackWithGPS.value.length > 0 ||
|
||||
flight.value.landingAirport.id !== flight.value.takeoffAirport.id
|
||||
)
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MapWithMarkers
|
||||
v-if="displayMap"
|
||||
style="width: 100%; height: 500px;"
|
||||
:gpx-track-url="flight.gpxTrackUrl"
|
||||
:markers="pointsOfInterests"
|
||||
:photos="mapPhotos"
|
||||
/>
|
||||
</template>
|
||||
@@ -18,7 +18,7 @@ const props = defineProps({
|
||||
displayVisibilityInfo: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
default: true
|
||||
}
|
||||
});
|
||||
|
||||
@@ -33,12 +33,12 @@ const props = defineProps({
|
||||
:to="{name: routeDetail.name, params:{...routeDetail.params, id: flight.id}}"
|
||||
>
|
||||
<q-item-section avatar>
|
||||
<q-avatar size="100px">
|
||||
<div v-if="flight.coverPhoto" :style="`width: 100px; height: 100px; background-image: url('${flight.coverPhoto.thumbnailUrl}'); background-size: cover`"></div>
|
||||
<q-avatar size="150px">
|
||||
<div v-if="flight.coverPhoto" :style="`width: 150px; height: 150px; background-image: url('${flight.coverPhoto.thumbnailUrl}'); background-size: cover`"></div>
|
||||
</q-avatar>
|
||||
</q-item-section>
|
||||
<q-item-section>
|
||||
{{ flightName(flight) }}
|
||||
<h5>{{ flightName(flight) }}</h5>
|
||||
<div class="text-secondary">
|
||||
<q-icon name="flight_takeoff"/>
|
||||
{{ formatDatetime(flight.takeoffDatetime) }}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<script setup>
|
||||
import PhotoDetail from "components/photos/PhotoDetail.vue";
|
||||
import { ref, watch} from "vue";
|
||||
|
||||
const props = defineProps({
|
||||
photos: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
coverPhotoUrl: {
|
||||
type: String,
|
||||
required: false
|
||||
}
|
||||
})
|
||||
|
||||
const displayedPhoto = ref(null);
|
||||
const openPhotoDetail = ref(false);
|
||||
const photoData = ref(null);
|
||||
const openDetail = ({photo, idx, allPhotos}) => {
|
||||
openPhotoDetail.value = true;
|
||||
photoData.value = {photo, idx, allPhotos}
|
||||
}
|
||||
|
||||
watch(() => props.photos, (newVal) => {
|
||||
if (newVal.length === 0) return;
|
||||
displayedPhoto.value = props.coverPhotoUrl || newVal[0].url;
|
||||
}, {immediate: true});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-carousel
|
||||
v-if="photos.length > 0"
|
||||
animated
|
||||
v-model="displayedPhoto"
|
||||
arrows
|
||||
swipeable
|
||||
height="auto"
|
||||
infinite
|
||||
>
|
||||
<q-carousel-slide style="padding: 0" v-for="(photo, idx) in photos" :key="photo.url" :name="photo.url">
|
||||
<q-img :src="photo.url" @click="openDetail({photo, idx, allPhotos: photos})"/>
|
||||
</q-carousel-slide>
|
||||
</q-carousel>
|
||||
|
||||
<PhotoDetail
|
||||
v-if="photoData"
|
||||
v-model="openPhotoDetail"
|
||||
:photo="photoData.photo"
|
||||
:photos="photoData.allPhotos"
|
||||
:opened-index="photoData.idx"
|
||||
/>
|
||||
</template>
|
||||
@@ -21,6 +21,7 @@ const props = defineProps({
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const formData = reactive({
|
||||
aircraft: null,
|
||||
takeoffAirport: null,
|
||||
@@ -28,89 +29,107 @@ const formData = reactive({
|
||||
takeoffDatetime: null,
|
||||
landingDatetime: null,
|
||||
landings: 1,
|
||||
isPublic: false,
|
||||
name: "",
|
||||
description: "",
|
||||
})
|
||||
|
||||
const recalculateDuration = (data) => {
|
||||
const diff = data.landingDatetime - data.takeoffDatetime;
|
||||
data.durationTotal = diff / 1000 / 60;
|
||||
}
|
||||
|
||||
watch(() => [formData.takeoffDatetime, formData.landingDatetime], () => recalculateDuration(formData))
|
||||
});
|
||||
|
||||
const rules = {};
|
||||
const isMounted = ref(false);
|
||||
// tohle je blby ohack kvuli tomu, ze DatetimeInput se renderuje jeste pred mounted a do props nedostane hodnotu
|
||||
// modelu. A neumi se s tim smirit...
|
||||
onMounted(() => {
|
||||
if (props.flight) {
|
||||
setDefaultData(formData, props.flight);
|
||||
formData.aircraft = {id: formData.aircraft.id, name: formData.aircraft.callSign};
|
||||
formData.takeoffAirport = {id: formData.takeoffAirport.id, name: formData.takeoffAirport.name}
|
||||
formData.landingAirport = {id: formData.landingAirport.id, name: formData.landingAirport.name}
|
||||
watch(() => props.flight, (newVal) => {
|
||||
if (newVal) {
|
||||
setDefaultData(formData, newVal);
|
||||
formData.aircraft = {id: newVal.aircraft.id, name: newVal.aircraft.callSign};
|
||||
formData.takeoffAirport = {id: newVal.takeoffAirport.id, name: newVal.takeoffAirport.name}
|
||||
formData.landingAirport = {id: newVal.landingAirport.id, name: newVal.landingAirport.name}
|
||||
}
|
||||
isMounted.value = true;
|
||||
});
|
||||
}, {immediate: true});
|
||||
|
||||
const aircrafts = computed(() => {
|
||||
return props.aircrafts.map(a => ({id: a.id, name: a.callSign}));
|
||||
});
|
||||
|
||||
watch(() => formData.takeoffDatetime, () => {
|
||||
if (!formData.landingDatetime) {
|
||||
formData.landingDatetime = formData.takeoffDatetime;
|
||||
}
|
||||
});
|
||||
watch(() => formData.takeoffAirport, () => {
|
||||
if (!formData.landingAirport) {
|
||||
formData.landingAirport = {...formData.takeoffAirport};
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FormWrapper v-model="formData" v-if="isMounted">
|
||||
<FormWrapper v-model="formData">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<ComboboxInput
|
||||
v-bind="commonProps"
|
||||
:options="aircrafts"
|
||||
v-model="formData.aircraft"
|
||||
:key="formData.aircraft"
|
||||
label="Letadlo"
|
||||
/>
|
||||
<q-card class="q-mx-md q-my-md">
|
||||
<q-card-section>
|
||||
<div class="text-h6">Vyber letadlo</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section>
|
||||
<ComboboxInput
|
||||
v-bind="commonProps"
|
||||
:options="aircrafts"
|
||||
v-model="formData.aircraft"
|
||||
:key="formData.aircraft"
|
||||
label="Letadlo"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col col-12 col-md-6">
|
||||
<h3>Vzlet</h3>
|
||||
<DatetimePicker
|
||||
v-model="formData.takeoffDatetime"
|
||||
label="Datum a čas vzletu: "
|
||||
v-bind="commonProps"
|
||||
/>
|
||||
<ComboboxInput
|
||||
:options="airports"
|
||||
v-model="formData.takeoffAirport"
|
||||
label="Letiště vzletu"
|
||||
v-bind="commonProps"
|
||||
:enable-new-values="false"
|
||||
/>
|
||||
<q-card class="q-mx-md q-my-md">
|
||||
<q-card-section>
|
||||
<div class="text-h6">Vzlet</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<DatetimePicker
|
||||
v-model="formData.takeoffDatetime"
|
||||
label="Datum a čas vzletu: "
|
||||
v-bind="commonProps"
|
||||
/>
|
||||
|
||||
<ComboboxInput
|
||||
:options="airports"
|
||||
v-model="formData.takeoffAirport"
|
||||
label="Letiště vzletu"
|
||||
v-bind="commonProps"
|
||||
:enable-new-values="false"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
|
||||
<div class="col col-12 col-md-6">
|
||||
|
||||
<h3>Přistání</h3>
|
||||
<DatetimePicker
|
||||
v-model="formData.landingDatetime"
|
||||
:min-date="formData.takeoffDatetime"
|
||||
label="Datum a čas přistání"
|
||||
v-bind="commonProps"
|
||||
/>
|
||||
<q-card class="q-mx-md q-my-md">
|
||||
<q-card-section>
|
||||
<div class="text-h6">Přistání</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<DatetimePicker
|
||||
v-model="formData.landingDatetime"
|
||||
:min-date="formData.takeoffDatetime"
|
||||
label="Datum a čas přistání"
|
||||
v-bind="commonProps"
|
||||
/>
|
||||
|
||||
<ComboboxInput
|
||||
:options="airports"
|
||||
v-model="formData.landingAirport"
|
||||
label="Letiště přistání"
|
||||
v-bind="commonProps"
|
||||
:enable-new-values="false"
|
||||
/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
|
||||
<ComboboxInput
|
||||
:options="airports"
|
||||
v-model="formData.landingAirport"
|
||||
label="Letiště přistání"
|
||||
v-bind="commonProps"
|
||||
:enable-new-values="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</FormWrapper>
|
||||
|
||||
@@ -51,6 +51,11 @@ onMounted(() => {
|
||||
<template>
|
||||
<FormWrapper v-model="formData">
|
||||
|
||||
<q-banner class="bg-green text-white" v-if="flight.gpxTrackUrl">
|
||||
<q-icon name="check"/>
|
||||
Trasa nahrána
|
||||
</q-banner>
|
||||
|
||||
<q-file
|
||||
accept=".gpx"
|
||||
v-model="formData.gpxTrack"
|
||||
@@ -59,14 +64,10 @@ onMounted(() => {
|
||||
hint="Slouží pro vykreslení kompletní a detailní trasy"
|
||||
>
|
||||
<template #prepend>
|
||||
<q-icon name="upload" />
|
||||
<q-icon name="upload"/>
|
||||
</template>
|
||||
</q-file>
|
||||
|
||||
<template v-if="flight.gpxTrackUrl">
|
||||
<q-icon name="check" color="green" /> Trasa nahrána
|
||||
</template>
|
||||
|
||||
<ComboboxInput
|
||||
v-bind="commonProps"
|
||||
v-model="poi"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import {computed, onMounted, ref} from "vue";
|
||||
import {computed, onMounted, ref, watch} from "vue";
|
||||
import {FORMAT_DATETIME_LONG, FORMAT_ISO, formatDatetime, parseDate} from "src/composables/datetimeUtils";
|
||||
import {commonProps} from "src/composables/inputs";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
@@ -21,24 +22,25 @@ 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();
|
||||
}
|
||||
});
|
||||
// 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();
|
||||
// }
|
||||
// });
|
||||
// TODO: ^^ by asi slo prepsat do watchera, viz ComboboxInput
|
||||
|
||||
|
||||
@@ -57,7 +59,9 @@ const emit = defineEmits(['update:modelValue']);
|
||||
const emitModelUpdate = () => {
|
||||
const val = parseDate(model.value);
|
||||
emit("update:modelValue", val);
|
||||
popupProxy.value.hide();
|
||||
|
||||
if (popupProxy.value)
|
||||
popupProxy.value.hide();
|
||||
}
|
||||
|
||||
const containsAnyOf = (needles, haystack) => {
|
||||
@@ -103,10 +107,28 @@ const isDateValid = (date) => {
|
||||
return date >= minDate;
|
||||
}
|
||||
|
||||
watch(() => props.modelValue, (newVal) => {
|
||||
let emitDefaultValue = false;
|
||||
if (newVal) {
|
||||
let modelVal = newVal;
|
||||
if (typeof modelVal === 'string') {
|
||||
modelVal = parseDate(newVal);
|
||||
emitDefaultValue = true;
|
||||
}
|
||||
|
||||
dateModel.value = formatDatetime(modelVal, "YYYY-MM-DD");
|
||||
timeModel.value = formatDatetime(modelVal, "HH:mm:ss");
|
||||
}
|
||||
|
||||
setOriginalValues();
|
||||
if (emitDefaultValue) {
|
||||
emitModelUpdate();
|
||||
}
|
||||
}, {immediate: true});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-input readonly v-model="publicModel">
|
||||
<q-input readonly v-bind="commonProps" v-model="publicModel">
|
||||
<template #append>
|
||||
<q-icon name="event"/>
|
||||
</template>
|
||||
|
||||
@@ -30,7 +30,7 @@ const openDetail = (photo, idx) => {
|
||||
<div class="col-12 col-sm-4 col-md-4 col-lg-3" v-for="(photo, idx) in photos" :key="photo.id">
|
||||
<q-card class="q-my-sm q-mx-sm">
|
||||
<q-img :src="photo.thumbnailUrl" @click="openDetail(photo, idx)">
|
||||
<div class="absolute-bottom">
|
||||
<div class="absolute-bottom" v-if="photo.name !== '' || photo.description !== ''">
|
||||
<div class="text-h6" v-if="photo.name !== ''">
|
||||
{{ photo.name }}
|
||||
</div>
|
||||
|
||||
@@ -13,9 +13,9 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
const formData = reactive({
|
||||
name: null,
|
||||
publicUsername: null,
|
||||
description: null,
|
||||
name: '',
|
||||
publicUsername: '',
|
||||
description: '',
|
||||
avatarImage: null,
|
||||
titleImage: null,
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ const openDetail = ref(false);
|
||||
|
||||
<template>
|
||||
|
||||
<q-btn rounded @click="openDetail = true" v-bind="$attrs">
|
||||
<q-btn rounded flat @click="openDetail = true" v-bind="$attrs">
|
||||
<CloudCoverIcon :cloudcover="weather.cloudcoverTotal"/>
|
||||
|
||||
<q-icon name="navigation" :style="`transform: rotate(${weather.windDirectionSurface}deg)`"/>
|
||||
|
||||
@@ -3,6 +3,7 @@ import {useFlightsStore} from "stores/Flights";
|
||||
import {ref} from "vue";
|
||||
import {storeToRefs} from "pinia";
|
||||
import {confirmObject} from "src/composables/dialog";
|
||||
import {useAppStore} from "stores/App";
|
||||
|
||||
export const flightName = (flight) => {
|
||||
const date = formatDatetime(flight.takeoffDatetime, FORMAT_DATE);
|
||||
@@ -15,9 +16,9 @@ export const flightName = (flight) => {
|
||||
|
||||
export const loading = ref(true);
|
||||
export const flight = ref(null);
|
||||
export const fetchFlight = (flightId) => {
|
||||
export const fetchFlight = (flightId, username) => {
|
||||
loading.value = true;
|
||||
return useFlightsStore().fetchDetail(parseInt(flightId))
|
||||
return useFlightsStore().fetchDetail(parseInt(flightId), username)
|
||||
.then(respFlight => {
|
||||
flight.value = respFlight;
|
||||
return respFlight;
|
||||
@@ -42,4 +43,3 @@ export const handleDeleteFlight = ($q, flightId, onOkCallback = () => {
|
||||
useFlightsStore().delete(flightId).then(onOkCallback);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
// app global css in SCSS form
|
||||
|
||||
.flight-detail-card {
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
+21
-3
@@ -3,7 +3,8 @@ import {createApolloProvider} from "@vue/apollo-option";
|
||||
import {createUploadLink} from 'apollo-upload-client';
|
||||
import {onError} from "@apollo/client/link/error";
|
||||
import {useUserStore} from "stores/User";
|
||||
import {useRouter} from "vue-router";
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {useAppStore} from "stores/App";
|
||||
|
||||
|
||||
const uploadLink = createUploadLink({
|
||||
@@ -15,7 +16,7 @@ const errorLink = onError(
|
||||
if (networkError?.statusCode === 401) {
|
||||
return fromPromise(
|
||||
useUserStore().refreshAccessToken().catch((error) => {
|
||||
useRouter().push({to: "login"});
|
||||
useAppStore().appStatus = 401;
|
||||
})
|
||||
)
|
||||
.filter((value) => Boolean(value))
|
||||
@@ -32,6 +33,21 @@ const errorLink = onError(
|
||||
return forward(operation);
|
||||
});
|
||||
}
|
||||
|
||||
if (graphQLErrors) {
|
||||
const messages = [];
|
||||
|
||||
for (const error of graphQLErrors) {
|
||||
if (error.message === "Not found") {
|
||||
useAppStore().appStatus = 404;
|
||||
}
|
||||
|
||||
if (error.message === "Not authenticated") {
|
||||
window.location = "/login";
|
||||
}
|
||||
}
|
||||
console.log(graphQLErrors)
|
||||
}
|
||||
});
|
||||
|
||||
const authLink = new ApolloLink((operation, forward) => {
|
||||
@@ -60,7 +76,9 @@ export const apolloWrapper = {
|
||||
})
|
||||
.then((response) => response)
|
||||
.catch(err => {
|
||||
console.error("Error during query: ", err)
|
||||
console.log(err.message);
|
||||
// console.error("Error during query: ", err)
|
||||
return err;
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import gql from "graphql-tag";
|
||||
|
||||
export const FRAGMENT_AIRPORT_INFO = gql`
|
||||
fragment airportInfo on Airport {
|
||||
id
|
||||
name
|
||||
icaoCode
|
||||
gpsLatitude
|
||||
|
||||
@@ -37,6 +37,11 @@ fragment flightFullInfo on Flight {
|
||||
...airportInfo
|
||||
}
|
||||
|
||||
copilot {
|
||||
id
|
||||
name
|
||||
}
|
||||
|
||||
gpxTrackUrl
|
||||
track {
|
||||
pointOfInterest {
|
||||
@@ -103,15 +108,3 @@ ${FRAGMENT_AIRPORT_INFO}
|
||||
${FRAGMENT_AIRCRAFT_BASIC_INFO}
|
||||
`
|
||||
|
||||
export const FRAGMENT_FLIGHT_EDIT_IDS = gql`
|
||||
fragment flightEditIds on Flight {
|
||||
landingAirportId
|
||||
takeoffAirportId
|
||||
aircraftId
|
||||
copilotId
|
||||
copilot {
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import gql from "graphql-tag";
|
||||
import {FRAGMENT_FLIGHT_EDIT_IDS, FRAGMENT_FLIGHT_FULL_INFO, FRAGMENT_FLIGHT_LIST_INFO} from "src/graphql/fragments/flight";
|
||||
import {FRAGMENT_FLIGHT_FULL_INFO, FRAGMENT_FLIGHT_LIST_INFO} from "src/graphql/fragments/flight";
|
||||
|
||||
export const FLIGHTS_LIST = gql`
|
||||
query FlightsList {
|
||||
@@ -14,11 +14,9 @@ export const FLIGHT_DETAIL = gql`
|
||||
query FlightDetail($id: Int!) {
|
||||
flight(id: $id) {
|
||||
...flightFullInfo
|
||||
...flightEditIds
|
||||
}
|
||||
}
|
||||
|
||||
${FRAGMENT_FLIGHT_FULL_INFO}
|
||||
${FRAGMENT_FLIGHT_EDIT_IDS}
|
||||
`;
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<q-layout view="lHh Lpr lFf">
|
||||
<q-page-container>
|
||||
<router-view :loggedUser="loggedUser" class="q-py-md"/>
|
||||
</q-page-container>
|
||||
</q-layout>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {storeToRefs} from "pinia";
|
||||
import {useUserStore} from "stores/User";
|
||||
import {onMounted} from "vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import {useMeta} from "quasar";
|
||||
|
||||
const {pageTitle} = storeToRefs(useAppStore());
|
||||
const loggedUser = storeToRefs(useUserStore()).user;
|
||||
|
||||
useMeta(() => ({
|
||||
title: pageTitle.value !== '' ? `${pageTitle.value} - Polétání.cz` : 'Polétání.cz'
|
||||
}));
|
||||
|
||||
onMounted(() => {
|
||||
if (useUserStore().getAccessToken()) {
|
||||
useUserStore().fetchLoggedUserDetail();
|
||||
}
|
||||
})
|
||||
|
||||
</script>
|
||||
@@ -3,7 +3,7 @@
|
||||
<q-header>
|
||||
<q-toolbar>
|
||||
<q-toolbar-title>
|
||||
Polétání.cz
|
||||
{{ pageTitle ? `${pageTitle} | Polétání.cz` : "Polétání.cz" }}
|
||||
</q-toolbar-title>
|
||||
|
||||
<template v-if="loggedUser.id">
|
||||
@@ -26,7 +26,8 @@
|
||||
</q-header>
|
||||
|
||||
<q-page-container>
|
||||
<router-view :loggedUser="loggedUser" class="q-py-md"/>
|
||||
<BreadcrumbsNavigation class="q-mx-md q-my-md" :items="breadcrumbs"/>
|
||||
<router-view :loggedUser="loggedUser" class="q-my-lg"/>
|
||||
</q-page-container>
|
||||
</q-layout>
|
||||
</template>
|
||||
@@ -37,8 +38,9 @@ import {useUserStore} from "stores/User";
|
||||
import {onMounted} from "vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import {useMeta} from "quasar";
|
||||
import BreadcrumbsNavigation from "components/BreadcrumbsNavigation.vue";
|
||||
|
||||
const {pageTitle} = storeToRefs(useAppStore());
|
||||
const {pageTitle, breadcrumbs} = storeToRefs(useAppStore());
|
||||
const loggedUser = storeToRefs(useUserStore()).user;
|
||||
|
||||
useMeta(() => ({
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<template>
|
||||
<div class="fullscreen bg-blue text-white text-center q-pa-md flex flex-center">
|
||||
<div class="fullscreen text-center q-pa-md flex flex-center">
|
||||
<div>
|
||||
<div style="font-size: 30vh">
|
||||
404
|
||||
</div>
|
||||
|
||||
<div class="text-h2" style="opacity:.4">
|
||||
Oops. Nothing here...
|
||||
<q-img src="/plane-crash.svg" width="75%" />
|
||||
|
||||
<div style="font-size: 20vh">
|
||||
404
|
||||
</div>
|
||||
|
||||
<q-btn
|
||||
@@ -14,8 +13,8 @@
|
||||
color="white"
|
||||
text-color="blue"
|
||||
unelevated
|
||||
to="/"
|
||||
label="Go Home"
|
||||
:to="{name: 'homepage'}"
|
||||
label="Zpět na titulní stranu"
|
||||
no-caps
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
<script setup>
|
||||
import {useRoute, useRouter} from "vue-router";
|
||||
import {computed, onMounted, ref, watch} from "vue";
|
||||
import {onMounted, watch} from "vue";
|
||||
import FlightDetailSkeleton from "components/flights/FlightDetailSkeleton.vue";
|
||||
import {fetchFlight, flight, flightName, handleDeleteFlight, loading} from "src/composables/objects/flight";
|
||||
import {useAppStore} from "stores/App";
|
||||
import FlightBasicInfo from "components/flights/FlightBasicInfo.vue";
|
||||
import {useQuasar} from "quasar";
|
||||
import {copyToClipboard, useQuasar} from "quasar";
|
||||
import {successObject} from "src/composables/dialog";
|
||||
import MapWithMarkers from "components/map/MapWithMarkers.vue";
|
||||
import FAB from "components/FAB.vue";
|
||||
import PhotoDetail from "components/photos/PhotoDetail.vue";
|
||||
import {useFlightsStore} from "stores/Flights";
|
||||
import PhotoCarousel from "components/flights/PhotoCarousel.vue";
|
||||
import FlightTrackMap from "components/flights/FlightTrackMap.vue";
|
||||
import {useUserStore} from "stores/User";
|
||||
|
||||
|
||||
const $q = useQuasar();
|
||||
const $router = useRouter();
|
||||
const displayedPhoto = ref(null);
|
||||
const flightId = parseInt(useRoute().params.id);
|
||||
|
||||
onMounted(() => {
|
||||
fetchFlight(flightId).then(() => {
|
||||
if (flight.value.photos.length === 0) return;
|
||||
displayedPhoto.value = flight.value.coverPhoto.url || flight.value.photos[0].url;
|
||||
})
|
||||
fetchFlight(flightId);
|
||||
})
|
||||
|
||||
watch(flight, (newVal) => {
|
||||
@@ -43,62 +39,29 @@ const handleDeleteAndRedirect = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const trackWithGPS = computed(() => {
|
||||
return flight.value.track.filter(poi => poi.pointOfInterest.gpsLatitude && poi.pointOfInterest.gpsLongitude)
|
||||
});
|
||||
|
||||
const pointsOfInterests = computed(() => {
|
||||
const path = [{
|
||||
label: flight.value.takeoffAirport.name,
|
||||
position:
|
||||
{
|
||||
lat: flight.value.takeoffAirport.gpsLatitude,
|
||||
lng: flight.value.takeoffAirport.gpsLongitude
|
||||
}
|
||||
}];
|
||||
|
||||
for (const poi of trackWithGPS.value) {
|
||||
path.push({
|
||||
label: poi.pointOfInterest.name,
|
||||
position: {lat: poi.pointOfInterest.gpsLatitude, lng: poi.pointOfInterest.gpsLongitude}
|
||||
});
|
||||
}
|
||||
|
||||
path.push({
|
||||
label: flight.value.takeoffAirport.name,
|
||||
position: {
|
||||
lat: flight.value.landingAirport.gpsLatitude,
|
||||
lng: flight.value.landingAirport.gpsLongitude
|
||||
}
|
||||
});
|
||||
|
||||
return path;
|
||||
});
|
||||
|
||||
const openPhotoDetail = ref(false);
|
||||
const photoData = ref(null);
|
||||
const openDetail = ({photo, idx, allPhotos}) => {
|
||||
openPhotoDetail.value = true;
|
||||
photoData.value = {photo, idx, allPhotos}
|
||||
}
|
||||
const mapPhotos = computed(() => {
|
||||
return flight.value.photos.filter(photo => photo.gpsLatitude && photo.gpsLongitude)
|
||||
});
|
||||
|
||||
const displayMap = computed(() => {
|
||||
return (
|
||||
!!flight.value.gpsTrackUrl ||
|
||||
mapPhotos.value.length > 0 ||
|
||||
trackWithGPS.value.length > 0 ||
|
||||
flight.value.landingAirport.id !== flight.value.takeoffAirport.id
|
||||
)
|
||||
});
|
||||
|
||||
const togglePublicVisibility = () => {
|
||||
useFlightsStore().update(flightId, {isPublic: !flight.value.isPublic}).then(() => {
|
||||
$q.notify(successObject("Uspesne nastaveno"));
|
||||
})
|
||||
}
|
||||
const newVisibility = !flight.value.isPublic;
|
||||
useFlightsStore()
|
||||
.update(flightId, {isPublic: newVisibility})
|
||||
.then((updatedFlight) => {
|
||||
flight.value = updatedFlight;
|
||||
$q.notify(successObject(newVisibility ? "Úspěšně publikováno" : "Úspěšně skryto"));
|
||||
});
|
||||
};
|
||||
|
||||
const copyLinkToClipboard = () => {
|
||||
const loggedUser = useUserStore().user;
|
||||
const url = $router.resolve({
|
||||
name: "publicFlightDetail",
|
||||
params: {id: flightId, username: loggedUser.publicUsername}
|
||||
});
|
||||
copyToClipboard(window.location.origin + url.href).then(() => {
|
||||
$q.notify(successObject("Odkaz zkopírován"))
|
||||
});
|
||||
;
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@@ -107,63 +70,43 @@ const togglePublicVisibility = () => {
|
||||
|
||||
<template v-else>
|
||||
<q-card class="q-mx-md q-my-md flight-detail-card">
|
||||
<q-carousel
|
||||
v-if="flight.photos.length > 0"
|
||||
animated
|
||||
v-model="displayedPhoto"
|
||||
arrows
|
||||
swipeable
|
||||
height="auto"
|
||||
infinite
|
||||
>
|
||||
<q-carousel-slide style="padding: 0" v-for="(photo, idx) in flight.photos" :key="photo.url" :name="photo.url">
|
||||
<q-img :src="photo.url" @click="openDetail({photo, idx, allPhotos: flight.photos})"/>
|
||||
</q-carousel-slide>
|
||||
</q-carousel>
|
||||
<PhotoCarousel :cover-photo-url="flight.coverPhoto?.url" :photos="flight.photos"/>
|
||||
|
||||
<q-card-actions class="q-my-md">
|
||||
<div class="col-grow">
|
||||
<q-btn
|
||||
flat
|
||||
:to="{name: 'flightEdit', params:{id: flight.id}}"
|
||||
icon="edit"
|
||||
text-color="primary"
|
||||
label="Upravit"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
@click="togglePublicVisibility"
|
||||
:icon="flight.isPublic ? 'visibility_off' : 'visibility'"
|
||||
flat
|
||||
:label="flight.isPublic ? 'Skrýt' : 'Zveřejnit'"
|
||||
/>
|
||||
|
||||
<q-btn
|
||||
icon="link"
|
||||
@click="copyLinkToClipboard()"
|
||||
flat
|
||||
v-if="flight.isPublic"
|
||||
label="Získat odkaz"
|
||||
/>
|
||||
</div>
|
||||
<q-btn @click="handleDeleteAndRedirect" icon="delete" flat text-color="red" label="Smazat"/>
|
||||
</q-card-actions>
|
||||
|
||||
<q-card-section>
|
||||
<FlightBasicInfo :flight="flight"/>
|
||||
|
||||
<article class="q-my-lg" v-html="flight.description"/>
|
||||
|
||||
<MapWithMarkers
|
||||
v-if="displayMap"
|
||||
style="width: 100%; height: 500px;"
|
||||
:gpx-track-url="flight.gpxTrackUrl"
|
||||
:markers="pointsOfInterests"
|
||||
:photos="mapPhotos"
|
||||
/>
|
||||
<FlightTrackMap :flight="flight"/>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="right">
|
||||
<q-btn @click="togglePublicVisibility" :icon="flight.isPublic ? 'visibility' : 'visibility_off'" rounded flat text-color="primary">
|
||||
<q-tooltip>
|
||||
|
||||
{{ flight.isPublic ? 'je verejny' : 'neni verejny'}}
|
||||
|
||||
</q-tooltip>
|
||||
</q-btn>
|
||||
|
||||
<q-btn @click="handleDeleteAndRedirect" icon="delete" rounded flat text-color="red"/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
|
||||
<PhotoDetail
|
||||
v-if="photoData"
|
||||
v-model="openPhotoDetail"
|
||||
:photo="photoData.photo"
|
||||
:photos="photoData.allPhotos"
|
||||
:opened-index="photoData.idx"
|
||||
/>
|
||||
|
||||
<FAB :router-link="{name: 'flightEdit', params:{id: flight.id}}" mode="edit"/>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.flight-detail-card {
|
||||
width: 100%;
|
||||
max-width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,50 @@
|
||||
<script setup>
|
||||
import {onMounted, watch} from "vue";
|
||||
import {fetchFlight, flight, flightName, loading} from "src/composables/objects/flight";
|
||||
import {useRoute} from "vue-router";
|
||||
import PhotoCarousel from "components/flights/PhotoCarousel.vue";
|
||||
import FlightTrackMap from "components/flights/FlightTrackMap.vue";
|
||||
import FlightBasicInfo from "components/flights/FlightBasicInfo.vue";
|
||||
import {useAppStore} from "stores/App";
|
||||
import FlightDetailSkeleton from "components/flights/FlightDetailSkeleton.vue";
|
||||
|
||||
const routeParams = useRoute().params
|
||||
|
||||
onMounted(() => {
|
||||
fetchFlight(routeParams.id, routeParams.username);
|
||||
})
|
||||
|
||||
watch(flight, (newVal) => {
|
||||
const flightNameFormatted = flightName(newVal);
|
||||
useAppStore().setPageTitle(flightNameFormatted);
|
||||
useAppStore().setBreadcrumbs([
|
||||
{to: {name: "publicProfileDetail", params: {username: routeParams.username}}, label: `@${routeParams.username}`},
|
||||
{label: flightNameFormatted}
|
||||
]);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
Detail letu
|
||||
</div>
|
||||
|
||||
<FlightDetailSkeleton v-if="loading || !flight"/>
|
||||
|
||||
<template v-else>
|
||||
|
||||
<q-banner class="bg-warning text-white q-mx-md q-my-md" v-if="!flight.isPublic">
|
||||
Pozor! Tento let není publikován a nebude tak dostupný pro ostatní!
|
||||
</q-banner>
|
||||
|
||||
|
||||
<q-card class="q-mx-md q-my-md flight-detail-card">
|
||||
<PhotoCarousel :cover-photo-url="flight.coverPhoto.url" :photos="flight.photos"/>
|
||||
<q-card-section>
|
||||
<FlightBasicInfo :flight="flight"/>
|
||||
|
||||
<article class="q-my-lg" v-html="flight.description"/>
|
||||
|
||||
<FlightTrackMap :flight="flight"/>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Pochlub se svým polétáním!</h1>
|
||||
|
||||
<router-link :to='{"name": "login"}'>Login</router-link>
|
||||
<router-link :to='{"name": "registration"}'>Register</router-link>
|
||||
|
||||
<p>Létáš? Kam si archivuješ fotky a trasy? Polétání.cz je aplikace pro sdílení informací o tvých výletech vzduchem.</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -17,7 +17,7 @@ const logUser = () => {
|
||||
<template>
|
||||
<q-page class="window-height window-width row justify-center">
|
||||
<q-card square style="width:95%; max-width: 450px; height:400px;" class="q-mt-lg">
|
||||
<q-card-section class="bg-accent">
|
||||
<q-card-section class="bg-primary">
|
||||
<h4 class="text-h5 q-my-md text-white">Login</h4>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
@@ -36,10 +36,10 @@ const logUser = () => {
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions class="q-px-lg">
|
||||
<q-btn unelevated size="lg" class="full-width" label="Sign In" @click.prevent="logUser()"/>
|
||||
<q-btn unelevated size="lg" class="full-width" label="Přihlásit se" @click.prevent="logUser()"/>
|
||||
</q-card-actions>
|
||||
<q-card-section class="text-center q-pa-sm">
|
||||
<p class="text-grey-6">Forgot your password?</p>
|
||||
<router-link :to="{name: 'forgottenPassword'}" class="text-grey-6">Zapomenuté heslo</router-link>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
|
||||
|
||||
@@ -45,13 +45,11 @@ const flights = storeToRefs(useFlightsStore()).items;
|
||||
</q-banner>
|
||||
|
||||
<template v-else>
|
||||
<h3>Lety</h3>
|
||||
|
||||
<FlightsList
|
||||
:items="flights"
|
||||
:displayVisibilityInfo="false"
|
||||
:route-detail="{name: 'publicFlightDetail', params: {username: username}}"
|
||||
/>
|
||||
<FlightsList
|
||||
:items="flights"
|
||||
:displayVisibilityInfo="loggedUser.id === pilot.id"
|
||||
:route-detail="{name: 'publicFlightDetail', params: {username: username}}"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
@@ -63,10 +61,11 @@ const flights = storeToRefs(useFlightsStore()).items;
|
||||
</div>
|
||||
|
||||
<h3>{{ pilot.name }}</h3>
|
||||
<div class="text-subtitle1">
|
||||
Registrován: {{ formatDatetime(pilot.createdAt, FORMAT_DATE) }}
|
||||
</div>
|
||||
|
||||
<div class="q-my-lg" v-html="pilot.description"/>
|
||||
|
||||
Registrován: {{ formatDatetime(pilot.createdAt, FORMAT_DATE) }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -37,43 +37,37 @@ const registerUser = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<q-page
|
||||
class="window-height window-width row justify-center items-center"
|
||||
>
|
||||
<div class="column q-pa-lg">
|
||||
<div class="row">
|
||||
<q-card square class="shadow-24" style="width:300px;height:485px;">
|
||||
<q-card-section class="bg-deep-purple-7">
|
||||
<h4 class="text-h5 text-white q-my-md">Registration</h4>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-form class="q-px-sm q-pt-xl q-pb-lg" @submit.prevent="registerUser">
|
||||
<q-input square clearable v-model="name" type="text" label="Name">
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="person"/>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-page class="row justify-center">
|
||||
<q-card style="width:95%; max-width: 450px; height: 500px" >
|
||||
<q-card-section class="bg-primary">
|
||||
<h4 class="text-h5 text-white q-my-md">Registrace</h4>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<q-form class="q-px-sm q-pt-xl q-pb-lg" @submit.prevent="registerUser">
|
||||
<q-input square clearable v-model="name" type="text" label="Name">
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="person"/>
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<q-input square clearable v-model="email" type="email" label="E-mail">
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="email"/>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input square clearable v-model="password" type="password" label="Password">
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="lock"/>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
<q-card-actions class="q-px-lg">
|
||||
<q-btn @click="registerUser" unelevated size="lg" color="purple-4" class="full-width text-white" label="Get Started"/>
|
||||
</q-card-actions>
|
||||
<q-card-section class="text-center q-pa-sm">
|
||||
<router-link :to="{name: 'login'}" class="text-grey-6">Return to login</router-link>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
<q-input square clearable v-model="email" type="email" label="E-mail">
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="email"/>
|
||||
</template>
|
||||
</q-input>
|
||||
<q-input square clearable v-model="password" type="password" label="Password">
|
||||
<template v-slot:prepend>
|
||||
<q-icon name="lock"/>
|
||||
</template>
|
||||
</q-input>
|
||||
</q-form>
|
||||
</q-card-section>
|
||||
<q-card-actions class="q-px-lg">
|
||||
<q-btn @click="registerUser" unelevated size="lg" class="full-width" label="Registrovat"/>
|
||||
</q-card-actions>
|
||||
<q-card-section class="text-center q-pa-sm">
|
||||
<router-link :to="{name: 'login'}" class="text-grey-6">Zpět na login</router-link>
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</q-page>
|
||||
</template>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import PlainLayout from "layouts/PlainLayout.vue";
|
||||
|
||||
const routes = [
|
||||
{path: '/login', name: "login", component: () => import('pages/public/LoginPage.vue'), meta: {layout: PlainLayout}},
|
||||
{path: '/register', name: "registration", component: () => import('pages/public/RegisterPage.vue'), meta: {layout: PlainLayout}},
|
||||
{path: '/forgotten-password', name: "forgottenPassword", component: () => import('pages/public/RegisterPage.vue'), meta: {layout: PlainLayout}},
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('layouts/PublicLayout.vue'),
|
||||
children: [
|
||||
{path: '', name: "homepage", component: () => import('pages/public/IndexPage.vue')},
|
||||
{path: 'login', name: "login", component: () => import('pages/public/LoginPage.vue')},
|
||||
{path: 'register', name: "registration", component: () => import('pages/public/RegisterPage.vue')},
|
||||
{path: 'about', name: "about", component: () => import('pages/public/AboutPage.vue')},
|
||||
{path: ':username', name: "publicProfileDetail", component: () => import('pages/public/PilotProfilePage.vue')},
|
||||
{path: ':username/:id', name: "publicFlightDetail", component: () => import('pages/public/FlightDetailPage.vue')},
|
||||
|
||||
+3
-1
@@ -3,12 +3,14 @@ import {defineStore} from 'pinia'
|
||||
export const useAppStore = defineStore('App', {
|
||||
state: () => ({
|
||||
pageTitle: null,
|
||||
breadcrumbs: []
|
||||
breadcrumbs: [],
|
||||
appStatus: 200
|
||||
}),
|
||||
actions: {
|
||||
resetAfterRouteChange() {
|
||||
this.setPageTitle("");
|
||||
this.setBreadcrumbs([]);
|
||||
this.appStatus = 200;
|
||||
},
|
||||
setPageTitle(pageTitle) {
|
||||
this.pageTitle = pageTitle;
|
||||
|
||||
+11
-4
@@ -25,15 +25,22 @@ export const useFlightsStore = defineStore('Flights', {
|
||||
},
|
||||
update(id, formData) {
|
||||
return apolloWrapper.mutate(EDIT_FLIGHT, {id: id, input: formData}).then(({data}) => {
|
||||
console.log("Pridat update ve storu")
|
||||
return data.editFlight;
|
||||
const flight = data.editFlight;
|
||||
const idx = this.items.findIndex(item => item.id === id);
|
||||
if (idx < 0) {
|
||||
this.items.push(flight)
|
||||
} else {
|
||||
this.items[idx] = flight;
|
||||
}
|
||||
|
||||
return flight;
|
||||
});
|
||||
},
|
||||
fetchDetail(id) {
|
||||
fetchDetail(id, username) {
|
||||
if (typeof id !== "number") {
|
||||
id = parseInt(id);
|
||||
}
|
||||
return apolloWrapper.query(FLIGHT_DETAIL, {id}).then(result => result.data.flight);
|
||||
return apolloWrapper.query(FLIGHT_DETAIL, {id, username}).then(result => result.data.flight);
|
||||
},
|
||||
fetch(username) {
|
||||
return apolloWrapper
|
||||
|
||||
+10
-8
@@ -12,22 +12,24 @@ export const useUserStore = defineStore('LoggedUser', {
|
||||
|
||||
actions: {
|
||||
update(id, formData) {
|
||||
apolloWrapper.mutate(EDIT_USER, {id, input: formData}).then(({data}) => {
|
||||
this.user = data.editLoggedUser;
|
||||
return data.editLoggedUser;
|
||||
apolloWrapper.mutate(EDIT_USER, {id, input: formData}).then((response) => {
|
||||
const user = response.data?.editLoggedUser;
|
||||
this.user = user;
|
||||
return user;
|
||||
});
|
||||
},
|
||||
|
||||
fetchLoggedUserDetail() {
|
||||
return apolloWrapper.query(LOGGED_USER_DETAIL).then(({data}) => {
|
||||
this.user = data.loggedUser;
|
||||
return data.loggedUser;
|
||||
return apolloWrapper.query(LOGGED_USER_DETAIL).then((response) => {
|
||||
const user = response.data?.loggedUser;
|
||||
this.user = user;
|
||||
return user;
|
||||
})
|
||||
},
|
||||
|
||||
fetchDetail(username) {
|
||||
return apolloWrapper.query(USER_DETAIL, {username}).then(({data}) => {
|
||||
return data.user
|
||||
return apolloWrapper.query(USER_DETAIL, {username}).then((response) => {
|
||||
return response.data?.user;
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user