Many tweaks to booking form.

This commit is contained in:
2023-12-01 00:08:29 -05:00
parent aed0462e05
commit 8600000e24
7 changed files with 312 additions and 242 deletions

View File

@@ -1,47 +1,36 @@
<template>
<q-page padding>
<q-card>
<q-list>
<q-form @submit="onSubmit" @reset="onReset" class="q-gutter-md">
<q-input bottom-slots v-model="bookingForm.name" label="Name" readonly>
<q-input
bottom-slots
v-model="bookingForm.name"
label="Creating reservation for"
readonly
>
<template v-slot:prepend>
<q-icon name="person" />
</template>
</q-input>
<q-select
v-model="bookingForm.boat"
:options="boats"
option-value="id"
option-label="name"
label="Boat"
<q-expansion-item
expand-separator
v-model="resourceView"
icon="calendar_month"
label="Boat and Time"
default-opened
:caption="bookingSummary"
>
<template v-slot:prepend>
<q-item-section avatar>
<q-img
v-if="bookingForm.boat?.iconsrc"
:src="bookingForm.boat?.iconsrc"
/>
<q-icon v-else name="sailing" />
</q-item-section>
</template>
<q-separator />
<resource-schedule-viewer-component
@on-click-time="onClickTime"
@on-close-section="() => (resourceView = !resourceView)"
@on-update-duration="
(value) => {
bookingForm.duration = value;
}
"
/></q-expansion-item>
<template v-slot:option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section avatar>
<q-img :src="scope.opt.iconsrc" />
</q-item-section>
<q-item-section>
<q-item-label>{{ scope.opt.name }}</q-item-label>
<q-item-label caption>{{ scope.opt.class }}</q-item-label>
</q-item-section>
<q-item-section avatar v-if="scope.opt.defects">
<q-icon name="warning" color="warning" />
<q-tooltip class="bg-amber text-black shadow-7"
>This boat has defects. Select it to see details.
</q-tooltip>
</q-item-section>
</q-item>
</template>
</q-select>
<q-banner
rounded
class="bg-warning text-grey-10"
@@ -50,7 +39,7 @@
<template v-slot:avatar>
<q-icon name="warning" color="grey-10" />
</template>
This boat currently has the following defects:
This boat currently has the following notices:
<ol>
<li
v-for="defect in bookingForm.boat.defects"
@@ -60,145 +49,65 @@
</li>
</ol>
</q-banner>
<q-btn
label="View Schedule"
color="primary"
flat
@click="showSchedule = true"
>
<q-dialog
v-model="showSchedule"
full-width
cover
transition-show="scale"
transition-hide="scale"
>
<q-card>
<resource-schedule-viewer-component
@on-click-date="onClickDate"
@on-click-time="onClickTime"
/>
</q-card>
</q-dialog>
</q-btn>
<q-input
v-model="bookingForm.startDate"
label="Check-Out"
label-color="accent"
readonly
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer"> </q-icon>
</template>
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
@before-show="startDateOrTime = true"
>
<q-date
v-model="bookingForm.startDate"
mask="ddd MMM D, YYYY h:mm A"
:options="limitDate"
v-if="startDateOrTime"
>
<div class="row items-center justify-end">
<q-btn
label="Next"
color="primary"
flat
@click="startDateOrTime = false"
/>
</div>
</q-date>
<q-time
v-model="bookingForm.startDate"
mask="ddd MMM D, YYYY h:mm A"
:minute-options="minOpts"
v-else
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-input>
<q-input
v-model="bookingForm.endDate"
label="Check-In"
label-color="accent"
readonly
>
<template v-slot:prepend>
<q-icon name="event" class="cursor-pointer"> </q-icon>
</template>
<q-popup-proxy
cover
transition-show="scale"
transition-hide="scale"
@before-show="endDateOrTime = true"
>
<q-date
v-model="bookingForm.startDate"
mask="ddd MMM D, YYYY h:mm A"
:options="limitDate"
v-if="endDateOrTime"
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="Cancel" color="accent" flat />
<q-btn
label="Next"
color="primary"
flat
@click="endDateOrTime = !endDateOrTime"
/>
</div>
</q-date>
<q-time
v-model="bookingForm.endDate"
mask="ddd MMM D, YYYY h:mm A"
:minute-options="minOpts"
v-else
>
<div class="row items-center justify-end">
<q-btn v-close-popup label="Close" color="primary" flat />
</div>
</q-time>
</q-popup-proxy>
</q-input>
<q-chip icon="timelapse"
>Booking Duration: {{ bookingDuration }}</q-chip
<q-expansion-item
expand-separator
icon="people"
label="Crew and Passengers"
default-opened
>
<q-separator />
</q-expansion-item>
<q-item-section>
<q-btn label="Submit" type="submit" color="primary" />
</q-item-section>
</q-form>
</q-card>
</q-item-section> </q-form
></q-list>
</q-page>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { reactive, ref, computed, watch } from 'vue';
import { useAuthStore } from 'src/stores/auth';
import { Boat, useBoatStore } from 'src/stores/boat';
import { date } from 'quasar';
import { Dialog, date } from 'quasar';
import ResourceScheduleViewerComponent from 'src/components/ResourceScheduleViewerComponent.vue';
import { makeDateTime } from '@quasar/quasar-ui-qcalendar';
import { useScheduleStore, Reservation } from 'src/stores/schedule';
const auth = useAuthStore();
const boats = useBoatStore().boats;
const dateFormat = 'ddd MMM D, YYYY h:mm A';
const startDateOrTime = ref(true);
const endDateOrTime = ref(true);
const showSchedule = ref(false);
const bookingForm = ref({
const resourceView = ref(true);
const scheduleStore = useScheduleStore();
const bookingForm = reactive({
bookingId: scheduleStore.getNewId(),
name: auth.currentUser?.name,
boat: <Boat | undefined>undefined,
startDate: date.formatDate(new Date(), dateFormat),
endDate: date.formatDate(
date.addToDate(new Date(), { hours: 2 }),
dateFormat
endDate: computed(() =>
date.formatDate(
date.addToDate(bookingForm.startDate, {
hours: bookingForm.duration,
}),
dateFormat
)
),
duration: 1,
});
watch(bookingForm, (b, a) => {
const newRes = <Reservation>{
id: b.bookingId,
user: b.name,
resource: b.boat,
start: date.extractDate(b.startDate, dateFormat),
end: date.extractDate(b.endDate, dateFormat),
reservationDate: new Date(),
status: 'tentative',
};
//TODO: Turn this into a validator.
scheduleStore.isOverlapped(newRes)
? Dialog.create({ message: 'This booking overlaps another!' })
: scheduleStore.addOrCreateReservation(newRes);
});
const onReset = () => {
@@ -209,22 +118,18 @@ const onSubmit = () => {
// TODO
};
const onClickDate = (data) => {
console.log(data);
};
const onClickTime = (data) => {
bookingForm.value.boat = data.scope.resource;
bookingForm.value.startDate = date.formatDate(
bookingForm.boat = data.scope.resource;
bookingForm.startDate = date.formatDate(
date.addToDate(makeDateTime(data.scope.timestamp), { hours: 5 }), // A terrible hack to convert back to EST. TODO: FIX!!!!
dateFormat
);
showSchedule.value = false;
console.log(bookingForm.value.startDate);
console.log(bookingForm.startDate);
};
const bookingDuration = computed(() => {
const diff = date.getDateDiff(
bookingForm.value.endDate,
bookingForm.value.startDate,
bookingForm.endDate,
bookingForm.startDate,
'minutes'
);
return diff <= 0
@@ -233,6 +138,12 @@ const bookingDuration = computed(() => {
(diff % 60 > 0 ? ' ' + (diff % 60) + ' minutes' : '');
});
const bookingSummary = computed(() => {
return bookingForm.boat && bookingForm.startDate && bookingForm.endDate
? `${bookingForm.boat.name} @ ${bookingForm.startDate} for ${bookingDuration.value}`
: '';
});
const limitDate = (startDate: string) => {
return date.isBetweenDates(
startDate,
@@ -241,6 +152,4 @@ const limitDate = (startDate: string) => {
{ inclusiveFrom: true, inclusiveTo: true, onlyDate: true }
);
};
const minOpts = [0, 15, 30, 45, 60];
</script>