Sorted out a bunch of reactivity issues
This commit is contained in:
@@ -5,6 +5,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent, onMounted } from 'vue';
|
import { defineComponent, onMounted } from 'vue';
|
||||||
import { useAuthStore } from './stores/auth';
|
import { useAuthStore } from './stores/auth';
|
||||||
|
import { useBoatStore } from './stores/boat';
|
||||||
|
import { useReservationStore } from './stores/reservation';
|
||||||
|
|
||||||
defineComponent({
|
defineComponent({
|
||||||
name: 'OYS Borrow-a-Boat',
|
name: 'OYS Borrow-a-Boat',
|
||||||
@@ -12,5 +14,7 @@ defineComponent({
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await useAuthStore().init();
|
await useAuthStore().init();
|
||||||
|
await useBoatStore().fetchBoats();
|
||||||
|
await useReservationStore().fetchUserReservations();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
246
src/components/BoatReservationComponent.vue
Normal file
246
src/components/BoatReservationComponent.vue
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
<template>
|
||||||
|
<div class="q-pa-xs row q-gutter-xs">
|
||||||
|
<q-card
|
||||||
|
flat
|
||||||
|
class="col-lg-4 col-md-6 col-sm-8 col-xs-12">
|
||||||
|
<q-card-section>
|
||||||
|
<div class="text-h5 q-mt-none q-mb-xs">
|
||||||
|
{{ reservation?.value ? 'Modify Booking' : 'New Booking' }}
|
||||||
|
</div>
|
||||||
|
<div class="text-caption text-grey-8">for: {{ bookingName }}</div>
|
||||||
|
</q-card-section>
|
||||||
|
<q-list class="q-px-xs">
|
||||||
|
<q-item
|
||||||
|
class="q-pa-none"
|
||||||
|
clickable
|
||||||
|
@click="boatSelect = true">
|
||||||
|
<q-card
|
||||||
|
v-if="boat"
|
||||||
|
class="col-12">
|
||||||
|
<q-card-section>
|
||||||
|
<q-img
|
||||||
|
:src="boat.imgSrc"
|
||||||
|
:fit="'scale-down'">
|
||||||
|
<div class="row absolute-top">
|
||||||
|
<div class="col text-h7 text-left">
|
||||||
|
{{ boat.name }}
|
||||||
|
</div>
|
||||||
|
<div class="col text-right text-caption">
|
||||||
|
{{ boat.class }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-img>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator />
|
||||||
|
<q-card-section horizontal>
|
||||||
|
<q-card-section class="col-9">
|
||||||
|
<q-list
|
||||||
|
dense
|
||||||
|
class="row">
|
||||||
|
<q-item class="q-ma-none col-12">
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-badge
|
||||||
|
color="primary"
|
||||||
|
label="Start" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section class="text-body2">
|
||||||
|
{{ formatDate(bookingForm.interval?.start) }}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-ma-none col-12">
|
||||||
|
<q-item-section avatar>
|
||||||
|
<q-badge
|
||||||
|
color="primary"
|
||||||
|
label="End" />
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section
|
||||||
|
class="text-body2"
|
||||||
|
style="min-width: 150px">
|
||||||
|
{{ formatDate(bookingForm.interval?.end) }}
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</q-card-section>
|
||||||
|
<q-separator vertical />
|
||||||
|
<q-card-section class="col-3 flex flex-center bg-grey-4">
|
||||||
|
{{ bookingDuration.hours }} hours
|
||||||
|
<div v-if="bookingDuration.minutes">
|
||||||
|
<q-separator />
|
||||||
|
{{ bookingDuration.minutes }} mins
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="col-12">
|
||||||
|
<q-field filled>Tap to Select a Boat / Time</q-field>
|
||||||
|
</div>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-px-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-select
|
||||||
|
filled
|
||||||
|
v-model="bookingForm.reason"
|
||||||
|
:options="reason_options"
|
||||||
|
label="Reason for sail" />
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="q-px-none">
|
||||||
|
<q-item-section>
|
||||||
|
<q-input
|
||||||
|
v-model="bookingForm.comment"
|
||||||
|
clearable
|
||||||
|
autogrow
|
||||||
|
filled
|
||||||
|
label="Additional Comments (optional)" />
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn
|
||||||
|
label="Reset"
|
||||||
|
@click="onReset"
|
||||||
|
color="secondary"
|
||||||
|
size="md" />
|
||||||
|
<q-btn
|
||||||
|
label="Submit"
|
||||||
|
@click="onSubmit"
|
||||||
|
color="primary" />
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
<q-dialog
|
||||||
|
v-model="boatSelect"
|
||||||
|
full-width>
|
||||||
|
<BoatScheduleTableComponent v-model="bookingForm.interval" />
|
||||||
|
</q-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref, watch } from 'vue';
|
||||||
|
import { useAuthStore } from 'src/stores/auth';
|
||||||
|
import { Boat, useBoatStore } from 'src/stores/boat';
|
||||||
|
import { Interval, Reservation } from 'src/stores/schedule.types';
|
||||||
|
import BoatScheduleTableComponent from 'src/components/scheduling/boat/BoatScheduleTableComponent.vue';
|
||||||
|
import { formatDate } from 'src/utils/schedule';
|
||||||
|
import { useReservationStore } from 'src/stores/reservation';
|
||||||
|
import { useQuasar } from 'quasar';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
interface BookingForm {
|
||||||
|
$id?: string;
|
||||||
|
user?: string;
|
||||||
|
interval?: Interval | null;
|
||||||
|
reason?: string;
|
||||||
|
members?: string[];
|
||||||
|
guests?: string[];
|
||||||
|
comment?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reason_options = ['Open Sail', 'Private Sail', 'Racing', 'Other'];
|
||||||
|
|
||||||
|
const boatStore = useBoatStore();
|
||||||
|
const auth = useAuthStore();
|
||||||
|
const newForm = {
|
||||||
|
user: auth.currentUser?.$id,
|
||||||
|
interval: {} as Interval,
|
||||||
|
reason: 'Open Sail',
|
||||||
|
members: [],
|
||||||
|
guests: [],
|
||||||
|
comment: '',
|
||||||
|
};
|
||||||
|
const reservation = defineModel<Reservation>();
|
||||||
|
const reservationStore = useReservationStore();
|
||||||
|
const boatSelect = ref(false);
|
||||||
|
const bookingForm = ref<BookingForm>({ ...newForm });
|
||||||
|
const $q = useQuasar();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
watch(reservation, (newReservation) => {
|
||||||
|
if (!newReservation) {
|
||||||
|
bookingForm.value = newForm;
|
||||||
|
} else {
|
||||||
|
const updatedReservation = {
|
||||||
|
...newReservation,
|
||||||
|
interval: {
|
||||||
|
start: newReservation.start,
|
||||||
|
end: newReservation.end,
|
||||||
|
boatId: newReservation.resource,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
bookingForm.value = updatedReservation;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const bookingDuration = computed((): { hours: number; minutes: number } => {
|
||||||
|
if (bookingForm.value.interval?.start && bookingForm.value.interval?.end) {
|
||||||
|
const start = new Date(bookingForm.value.interval.start).getTime();
|
||||||
|
const end = new Date(bookingForm.value.interval.end).getTime();
|
||||||
|
const delta = Math.abs(end - start) / 1000;
|
||||||
|
const hours = Math.floor(delta / 3600) % 24;
|
||||||
|
const minutes = Math.floor(delta - hours * 3600) % 60;
|
||||||
|
return { hours: hours, minutes: minutes };
|
||||||
|
}
|
||||||
|
return { hours: 0, minutes: 0 };
|
||||||
|
});
|
||||||
|
|
||||||
|
const bookingName = computed(() =>
|
||||||
|
auth.getUserNameById(bookingForm.value?.user)
|
||||||
|
);
|
||||||
|
|
||||||
|
const boat = computed((): Boat | null => {
|
||||||
|
const boatId = bookingForm.value.interval?.boatId;
|
||||||
|
console.log('Boat Lookup:', boatId);
|
||||||
|
return boatStore.getBoatById(boatId);
|
||||||
|
});
|
||||||
|
|
||||||
|
const onReset = () => {
|
||||||
|
bookingForm.value.interval = null;
|
||||||
|
bookingForm.value = reservation.value
|
||||||
|
? {
|
||||||
|
...reservation.value,
|
||||||
|
interval: {
|
||||||
|
start: reservation.value.start,
|
||||||
|
end: reservation.value.end,
|
||||||
|
boatId: reservation.value.resource,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: { ...newForm };
|
||||||
|
};
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
const booking = bookingForm.value;
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
booking.interval &&
|
||||||
|
booking.interval.boatId &&
|
||||||
|
booking.interval.start &&
|
||||||
|
booking.interval.end &&
|
||||||
|
auth.currentUser
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// TODO: Make a proper validator
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const reservation = <Reservation>{
|
||||||
|
resource: booking.interval.boatId,
|
||||||
|
start: booking.interval.start,
|
||||||
|
end: booking.interval.end,
|
||||||
|
user: auth.currentUser.$id,
|
||||||
|
status: 'confirmed',
|
||||||
|
reason: booking.reason,
|
||||||
|
comment: booking.comment,
|
||||||
|
};
|
||||||
|
// TODO: Fix this. It will always look successful
|
||||||
|
reservationStore.createReservation(reservation); // Probably should pass the notify as a callback to the reservation creation.
|
||||||
|
$q.notify({
|
||||||
|
color: 'green-4',
|
||||||
|
textColor: 'white',
|
||||||
|
icon: 'cloud_done',
|
||||||
|
message: 'Submitted',
|
||||||
|
timeout: 3000,
|
||||||
|
});
|
||||||
|
router.go(-1);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
Start: {{ formatDate(reservation.start) }}
|
Start: {{ formatDate(reservation.start) }}
|
||||||
<br />
|
<br />
|
||||||
End: {{ formatDate(reservation.end) }}
|
End: {{ formatDate(reservation.end) }}
|
||||||
|
<br />
|
||||||
|
Type: {{ reservation.reason }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -50,7 +52,7 @@
|
|||||||
<q-card-actions v-if="!isPast(reservation.end)">
|
<q-card-actions v-if="!isPast(reservation.end)">
|
||||||
<q-btn
|
<q-btn
|
||||||
flat
|
flat
|
||||||
@click="modifyReservation()">
|
:to="{ name: 'edit-reservation', params: { id: reservation.$id } }">
|
||||||
Modify
|
Modify
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-btn
|
<q-btn
|
||||||
@@ -107,8 +109,4 @@ const reservation = defineModel<Reservation>({ required: true });
|
|||||||
const cancelReservation = () => {
|
const cancelReservation = () => {
|
||||||
cancelDialog.value = true;
|
cancelDialog.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const modifyReservation = () => {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,217 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="q-pa-xs row q-gutter-xs">
|
<BoatReservationComponent v-model="newReservation" />
|
||||||
<q-card
|
|
||||||
flat
|
|
||||||
class="col-lg-4 col-md-6 col-sm-8 col-xs-12">
|
|
||||||
<q-card-section>
|
|
||||||
<div class="text-h5 q-mt-none q-mb-xs">New Booking</div>
|
|
||||||
<div class="text-caption text-grey-8">for: {{ bookingForm.name }}</div>
|
|
||||||
</q-card-section>
|
|
||||||
<q-list class="q-px-xs">
|
|
||||||
<q-separator />
|
|
||||||
<q-item
|
|
||||||
class="q-px-none"
|
|
||||||
clickable
|
|
||||||
@click="boatSelect = true">
|
|
||||||
<q-item-section>
|
|
||||||
<q-card
|
|
||||||
v-if="bookingForm.boat"
|
|
||||||
flat>
|
|
||||||
<q-card-section>
|
|
||||||
<q-img
|
|
||||||
:src="bookingForm.boat?.imgSrc"
|
|
||||||
:fit="'scale-down'">
|
|
||||||
<div class="row absolute-top">
|
|
||||||
<div class="col text-h7 text-left">
|
|
||||||
{{ bookingForm.boat?.name }}
|
|
||||||
</div>
|
|
||||||
<div class="col text-right text-caption">
|
|
||||||
{{ bookingForm.boat?.class }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</q-img>
|
|
||||||
</q-card-section>
|
|
||||||
<q-separator />
|
|
||||||
<q-card-section horizontal>
|
|
||||||
<q-card-section>
|
|
||||||
<q-list
|
|
||||||
dense
|
|
||||||
class="row">
|
|
||||||
<q-item>
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-badge
|
|
||||||
color="primary"
|
|
||||||
label="Start" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section class="text-body2">
|
|
||||||
{{ formatDate(bookingForm.startDate) }}
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item class="q-ma-none">
|
|
||||||
<q-item-section avatar>
|
|
||||||
<q-badge
|
|
||||||
color="primary"
|
|
||||||
label="End" />
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section class="text-body2">
|
|
||||||
{{ formatDate(bookingForm.endDate) }}
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</q-card-section>
|
|
||||||
<q-separator vertical />
|
|
||||||
<q-card-section class="col-3 flex flex-center bg-grey-4">
|
|
||||||
{{ bookingDuration.hours }} hours
|
|
||||||
<div v-if="bookingDuration.minutes">
|
|
||||||
<q-separator />
|
|
||||||
{{ bookingDuration.minutes }} mins
|
|
||||||
</div>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card-section>
|
|
||||||
</q-card>
|
|
||||||
<q-field
|
|
||||||
readonly
|
|
||||||
filled
|
|
||||||
v-else>
|
|
||||||
Tap to Select a Boat / Time
|
|
||||||
</q-field>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item class="q-px-none">
|
|
||||||
<q-item-section>
|
|
||||||
<q-select
|
|
||||||
filled
|
|
||||||
v-model="bookingForm.reason"
|
|
||||||
:options="reason_options"
|
|
||||||
label="Reason for sail" />
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item class="q-px-none">
|
|
||||||
<q-item-section>
|
|
||||||
<q-input
|
|
||||||
v-model="bookingForm.comment"
|
|
||||||
clearable
|
|
||||||
autogrow
|
|
||||||
filled
|
|
||||||
label="Additional Comments (optional)" />
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
<q-card-actions align="right">
|
|
||||||
<q-btn
|
|
||||||
label="Reset"
|
|
||||||
@click="onReset"
|
|
||||||
color="secondary"
|
|
||||||
size="md" />
|
|
||||||
<q-btn
|
|
||||||
label="Submit"
|
|
||||||
@click="onSubmit"
|
|
||||||
color="primary" />
|
|
||||||
</q-card-actions>
|
|
||||||
</q-card>
|
|
||||||
<q-dialog
|
|
||||||
v-model="boatSelect"
|
|
||||||
full-width>
|
|
||||||
<BoatScheduleTableComponent v-model="interval" />
|
|
||||||
</q-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, watch } from 'vue';
|
import BoatReservationComponent from 'src/components/BoatReservationComponent.vue';
|
||||||
import { useAuthStore } from 'src/stores/auth';
|
import { Reservation } from 'src/stores/schedule.types';
|
||||||
import { Boat, useBoatStore } from 'src/stores/boat';
|
import { ref } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
import { Interval, Reservation } from 'src/stores/schedule.types';
|
|
||||||
import BoatScheduleTableComponent from 'src/components/scheduling/boat/BoatScheduleTableComponent.vue';
|
|
||||||
import { getNewId } from 'src/utils/misc';
|
|
||||||
import { formatDate } from 'src/utils/schedule';
|
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { useReservationStore } from 'src/stores/reservation';
|
|
||||||
|
|
||||||
interface BookingForm {
|
const newReservation = ref<Reservation>();
|
||||||
bookingId: string;
|
|
||||||
name?: string;
|
|
||||||
boat?: Boat;
|
|
||||||
startDate?: string;
|
|
||||||
endDate?: string;
|
|
||||||
reason: string;
|
|
||||||
members: { name: string }[];
|
|
||||||
guests: { name: string }[];
|
|
||||||
comment?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const reason_options = ['Open Sail', 'Private Sail', 'Racing', 'Other'];
|
|
||||||
|
|
||||||
const auth = useAuthStore();
|
|
||||||
const interval = ref<Interval>();
|
|
||||||
const newForm = {
|
|
||||||
bookingId: getNewId(),
|
|
||||||
name: auth.currentUser?.name,
|
|
||||||
boat: <Boat | undefined>undefined,
|
|
||||||
startDate: '',
|
|
||||||
endDate: '',
|
|
||||||
reason: 'Open Sail',
|
|
||||||
members: [],
|
|
||||||
guests: [],
|
|
||||||
comment: '',
|
|
||||||
};
|
|
||||||
const bookingForm = ref<BookingForm>({ ...newForm });
|
|
||||||
const router = useRouter();
|
|
||||||
const reservationStore = useReservationStore();
|
|
||||||
const $q = useQuasar();
|
|
||||||
const boatSelect = ref(false);
|
|
||||||
|
|
||||||
watch(interval, (new_interval) => {
|
|
||||||
bookingForm.value.boat = useBoatStore().boats.find(
|
|
||||||
(b) => b.$id === new_interval?.boatId
|
|
||||||
);
|
|
||||||
bookingForm.value.startDate = new_interval?.start;
|
|
||||||
bookingForm.value.endDate = new_interval?.end;
|
|
||||||
});
|
|
||||||
|
|
||||||
const bookingDuration = computed((): { hours: number; minutes: number } => {
|
|
||||||
if (bookingForm.value.startDate && bookingForm.value.endDate) {
|
|
||||||
const start = new Date(bookingForm.value.startDate).getTime();
|
|
||||||
const end = new Date(bookingForm.value.endDate).getTime();
|
|
||||||
const delta = Math.abs(end - start) / 1000;
|
|
||||||
const hours = Math.floor(delta / 3600) % 24;
|
|
||||||
const minutes = Math.floor(delta - hours * 3600) % 60;
|
|
||||||
return { hours: hours, minutes: minutes };
|
|
||||||
}
|
|
||||||
return { hours: 0, minutes: 0 };
|
|
||||||
});
|
|
||||||
|
|
||||||
const onReset = () => {
|
|
||||||
interval.value = undefined;
|
|
||||||
bookingForm.value = { ...newForm };
|
|
||||||
};
|
|
||||||
const onSubmit = () => {
|
|
||||||
const booking = bookingForm.value;
|
|
||||||
if (
|
|
||||||
!(booking.boat && booking.startDate && booking.endDate && auth.currentUser)
|
|
||||||
) {
|
|
||||||
// TODO: Make a proper validator
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const reservation = <Reservation>{
|
|
||||||
resource: booking.boat.$id,
|
|
||||||
start: booking.startDate,
|
|
||||||
end: booking.endDate,
|
|
||||||
user: auth.currentUser.$id,
|
|
||||||
status: 'confirmed',
|
|
||||||
reason: booking.reason,
|
|
||||||
comment: booking.comment,
|
|
||||||
};
|
|
||||||
console.log(reservation);
|
|
||||||
// TODO: Fix this. It will always look successful
|
|
||||||
reservationStore.createReservation(reservation); // Probably should pass the notify as a callback to the reservation creation.
|
|
||||||
$q.notify({
|
|
||||||
color: 'green-4',
|
|
||||||
textColor: 'white',
|
|
||||||
icon: 'cloud_done',
|
|
||||||
message: 'Submitted',
|
|
||||||
});
|
|
||||||
router.go(-1);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -59,13 +59,11 @@
|
|||||||
</q-tab-panels>
|
</q-tab-panels>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useBoatStore } from 'src/stores/boat';
|
|
||||||
import { useReservationStore } from 'src/stores/reservation';
|
import { useReservationStore } from 'src/stores/reservation';
|
||||||
import ReservationCardComponent from 'src/components/scheduling/ReservationCardComponent.vue';
|
import ReservationCardComponent from 'src/components/scheduling/ReservationCardComponent.vue';
|
||||||
import { onMounted, ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
const reservationStore = useReservationStore();
|
const reservationStore = useReservationStore();
|
||||||
const boatStore = useBoatStore();
|
|
||||||
const tab = ref('upcoming');
|
const tab = ref('upcoming');
|
||||||
|
|
||||||
// const showMarker = (
|
// const showMarker = (
|
||||||
@@ -82,9 +80,4 @@ const tab = ref('upcoming');
|
|||||||
// isPast(currentItemDate) && (nextItemDate === null || !isPast(nextItemDate))
|
// isPast(currentItemDate) && (nextItemDate === null || !isPast(nextItemDate))
|
||||||
// );
|
// );
|
||||||
// };
|
// };
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
boatStore.fetchBoats();
|
|
||||||
reservationStore.fetchUserReservations();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
18
src/pages/schedule/ModifyBoatReservation.vue
Normal file
18
src/pages/schedule/ModifyBoatReservation.vue
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<BoatReservationComponent v-model="reservation" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import BoatReservationComponent from 'src/components/BoatReservationComponent.vue';
|
||||||
|
import { useReservationStore } from 'src/stores/reservation';
|
||||||
|
import { Reservation } from 'src/stores/schedule.types';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
|
||||||
|
const reservation = ref<Reservation>();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const id = useRoute().params.id as string;
|
||||||
|
reservation.value = await useReservationStore().getReservationById(id);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -42,8 +42,15 @@ const routes: RouteRecordRaw[] = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'list',
|
path: 'list',
|
||||||
component: () => import('src/pages/schedule/ListBookingsPage.vue'),
|
component: () =>
|
||||||
name: 'list-bookings',
|
import('src/pages/schedule/ListReservationsPage.vue'),
|
||||||
|
name: 'list-reservations',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'edit/:id',
|
||||||
|
component: () =>
|
||||||
|
import('src/pages/schedule/ModifyBoatReservation.vue'),
|
||||||
|
name: 'edit-reservation',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'manage',
|
path: 'manage',
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
currentUser.value = await account.get();
|
currentUser.value = await account.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUserNameById(id: string) {
|
function getUserNameById(id: string | undefined | null): string {
|
||||||
|
if (!id) return 'No User';
|
||||||
try {
|
try {
|
||||||
if (!userNames.value[id]) {
|
if (!userNames.value[id]) {
|
||||||
userNames.value[id] = '';
|
userNames.value[id] = '';
|
||||||
|
|||||||
@@ -47,6 +47,19 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
setDateLoaded(startDate, endDate, 'error');
|
setDateLoaded(startDate, endDate, 'error');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const getReservationById = async (id: string) => {
|
||||||
|
try {
|
||||||
|
const response = await databases.getDocument(
|
||||||
|
AppwriteIds.databaseId,
|
||||||
|
AppwriteIds.collection.reservation,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
return response as Reservation;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch reservation: ', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const createReservation = async (reservation: Reservation) => {
|
const createReservation = async (reservation: Reservation) => {
|
||||||
try {
|
try {
|
||||||
const response = await databases.createDocument(
|
const response = await databases.createDocument(
|
||||||
@@ -75,7 +88,6 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(id);
|
|
||||||
try {
|
try {
|
||||||
await databases.deleteDocument(
|
await databases.deleteDocument(
|
||||||
AppwriteIds.databaseId,
|
AppwriteIds.databaseId,
|
||||||
@@ -203,6 +215,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
getReservationsByDate,
|
getReservationsByDate,
|
||||||
|
getReservationById,
|
||||||
createReservation,
|
createReservation,
|
||||||
deleteReservation,
|
deleteReservation,
|
||||||
fetchReservationsForDateRange,
|
fetchReservationsForDateRange,
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ export type Reservation = Partial<Models.Document> & {
|
|||||||
status?: StatusTypes;
|
status?: StatusTypes;
|
||||||
reason: string;
|
reason: string;
|
||||||
comment: string;
|
comment: string;
|
||||||
|
members?: string[];
|
||||||
|
guests?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 24 hrs in advance only 2 weekday, and 1 weekend slot
|
// 24 hrs in advance only 2 weekday, and 1 weekend slot
|
||||||
|
|||||||
Reference in New Issue
Block a user