From 2f68877ce6605cd40aea6e8440efb09b0fa6383c Mon Sep 17 00:00:00 2001 From: Patrick Toal Date: Tue, 30 Apr 2024 13:56:42 -0400 Subject: [PATCH] Updates to booking --- src/components/scheduling/BoatSelection.vue | 15 --- .../boat/BoatScheduleTableComponent.vue | 94 ++++++++++++++++--- src/pages/schedule/BoatReservationPage.vue | 45 +++------ src/stores/sampledata/schedule.ts | 25 +++-- 4 files changed, 106 insertions(+), 73 deletions(-) diff --git a/src/components/scheduling/BoatSelection.vue b/src/components/scheduling/BoatSelection.vue index d1b847c..e69de29 100644 --- a/src/components/scheduling/BoatSelection.vue +++ b/src/components/scheduling/BoatSelection.vue @@ -1,15 +0,0 @@ - - - diff --git a/src/components/scheduling/boat/BoatScheduleTableComponent.vue b/src/components/scheduling/boat/BoatScheduleTableComponent.vue index 06ea358..b8fda5e 100644 --- a/src/components/scheduling/boat/BoatScheduleTableComponent.vue +++ b/src/components/scheduling/boat/BoatScheduleTableComponent.vue @@ -38,7 +38,25 @@ :id="block.id" @click="selectBlock($event, scope, block)" > - Available + {{ boatData[scope.columnIndex].name }}
+ {{ selectedBlock?.id === block.id ? 'Selected' : 'Available' }} + + +
+
+ {{ r.user }}
@@ -55,6 +73,7 @@ import { today, parsed, parseTimestamp, + parseDate, addToDate, } from '@quasar/quasar-ui-qcalendar'; import CalendarHeaderComponent from './CalendarHeaderComponent.vue'; @@ -66,44 +85,67 @@ import { Reservation, Timeblock } from 'src/stores/schedule.types'; interface BoatData extends Boat { blocks?: Timeblock[]; + reservations?: Reservation[]; } const scheduleStore = useScheduleStore(); const boatStore = useBoatStore(); const selectedBlock = ref(null); const selectedDate = ref(today()); -const reservation = ref(null); const boatData = ref(boatStore.boats); const calendar = ref(null); +const emit = defineEmits<{ + updateBoatTime: [block: Timeblock]; +}>(); + function handleSwipe({ ...event }) { event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next(); } +function reservationStyles( + reservation: Reservation, + timeStartPos: (t: string) => string, + timeDurationHeight: (d: number) => string +) { + return genericBlockStyle( + parseDate(reservation.start) as Timestamp, + parseDate(reservation.end) as Timestamp, + timeStartPos, + timeDurationHeight + ); +} + function blockStyles( block: Timeblock, timeStartPos: (t: string) => string, timeDurationHeight: (d: number) => string +) { + return genericBlockStyle( + parsed(block.start) as Timestamp, + parsed(block.end) as Timestamp, + timeStartPos, + timeDurationHeight + ); +} + +function genericBlockStyle( + start: Timestamp, + end: Timestamp, + timeStartPos: (t: string) => string, + timeDurationHeight: (d: number) => string ) { const s = { top: '', height: '', opacity: '', }; - if (block && timeStartPos && timeDurationHeight) { - s.top = timeStartPos(parsed(block.start)?.time || '00:00') + 'px'; + if (timeStartPos && timeDurationHeight) { + s.top = timeStartPos(start.time) + 'px'; s.height = parseInt( - timeDurationHeight( - diffTimestamp( - parsed(block.start) as Timestamp, - parsed(block.end) as Timestamp, - false - ) / - 1000 / - 60 - ) + timeDurationHeight(diffTimestamp(start, end, false) / 1000 / 60) ) - 1 + 'px'; @@ -124,13 +166,21 @@ interface DayBodyScope { function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Timeblock) { // TODO: Disable blocks before today with updateDisabled and/or comparison selectedBlock.value = block; + emit('updateBoatTime', block); } function changeEvent({ start }: { start: string }) { const newBlocks = scheduleStore.getTimeblocksForDate(start); + const reservations = scheduleStore.getBoatReservations( + parsed(start) as Timestamp + ); boatData.value.map((b) => { - return (b.blocks = newBlocks.filter((block) => block.boatId === b.$id)); + b.blocks = newBlocks.filter((block) => block.boatId === b.$id); + b.reservations = reservations.filter( + (reservation) => reservation.resource === b + ); // TODO: search by id, not item. }); + setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout... } @@ -144,12 +194,26 @@ const disabledBefore = computed(() => { .boat-schedule-table-component display: flex max-height: 60vh +.reservation + display: flex + position: absolute + justify-content: center + align-items: center + width: 100% + opacity: 1 + margin: 0px + text-overflow: ellipsis + font-size: 0.8em + cursor: pointer + background: $accent + color: white + border: 1px solid black .timeblock display: flex position: absolute justify-content: center align-items: center - width: 99% + width: 100% opacity: 0.5 margin: 0px text-overflow: ellipsis diff --git a/src/pages/schedule/BoatReservationPage.vue b/src/pages/schedule/BoatReservationPage.vue index 2675b2c..120aa6c 100644 --- a/src/pages/schedule/BoatReservationPage.vue +++ b/src/pages/schedule/BoatReservationPage.vue @@ -20,7 +20,11 @@ :caption="bookingSummary" > - + + Use the calendar to pick a date. Select an available boat and + timeslot below. + + import { reactive, ref, computed, watch } from 'vue'; import { useAuthStore } from 'src/stores/auth'; -import { Boat } from 'src/stores/boat'; +import { Boat, useBoatStore } from 'src/stores/boat'; import { Dialog, date } from 'quasar'; -import BoatSelection from 'src/components/scheduling/BoatSelection.vue'; -import { makeDateTime } from '@quasar/quasar-ui-qcalendar'; -import { useScheduleStore, Reservation } from 'src/stores/schedule'; +import { useScheduleStore } from 'src/stores/schedule'; +import { Reservation, Timeblock } from 'src/stores/schedule.types'; +import BoatScheduleTableComponent from 'src/components/scheduling/boat/BoatScheduleTableComponent.vue'; const auth = useAuthStore(); -const dateFormat = 'ddd MMM D, YYYY h:mm A'; +const dateFormat = 'MMM D, YYYY h:mm A'; const resourceView = ref(true); const scheduleStore = useScheduleStore(); const bookingForm = reactive({ @@ -84,15 +88,7 @@ const bookingForm = reactive({ name: auth.currentUser?.name, boat: undefined, startDate: date.formatDate(new Date(), dateFormat), - endDate: computed(() => - date.formatDate( - date.addToDate(bookingForm.startDate, { - hours: bookingForm.duration, - }), - dateFormat - ) - ), - duration: 1, + endDate: date.formatDate(new Date(), dateFormat), }); watch(bookingForm, (b, a) => { @@ -119,12 +115,10 @@ const onSubmit = () => { // TODO }; -const onClickTime = (data) => { - 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 - ); +const updateBoat = (block: Timeblock) => { + bookingForm.boat = useBoatStore().boats.find((b) => b.$id === block.boatId); + bookingForm.startDate = date.formatDate(block.start, dateFormat); + bookingForm.endDate = date.formatDate(block.end, dateFormat); console.log(bookingForm.startDate); }; const bookingDuration = computed(() => { @@ -144,13 +138,4 @@ const bookingSummary = computed(() => { ? `${bookingForm.boat.name} @ ${bookingForm.startDate} for ${bookingDuration.value}` : ''; }); - -const limitDate = (startDate: string) => { - return date.isBetweenDates( - startDate, - new Date(), - date.addToDate(new Date(), { days: 21 }), - { inclusiveFrom: true, inclusiveTo: true, onlyDate: true } - ); -}; diff --git a/src/stores/sampledata/schedule.ts b/src/stores/sampledata/schedule.ts index 806bb6d..82afbb8 100644 --- a/src/stores/sampledata/schedule.ts +++ b/src/stores/sampledata/schedule.ts @@ -1,6 +1,5 @@ import { DateOptions, date } from 'quasar'; import { Boat, useBoatStore } from '../boat'; -import { ID } from 'src/boot/appwrite'; import { parseTimestamp, today, @@ -43,7 +42,7 @@ export function getSampleTimeBlocks(): Timeblock[] { const tsToday: Timestamp = parseTimestamp(today()) as Timestamp; for (let i = 0; i <= 30; i++) { - const template = Math.random() < 0.5 ? templateA : templateB; + const template = templateB; result.push( ...boats .map((b): Timeblock[] => { @@ -67,16 +66,16 @@ export function getSampleReservations(): Reservation[] { { id: 1, user: 'John Smith', - start: '12:00', - end: '15:00', + start: '7:00', + end: '10:00', boat: '1', status: 'confirmed', }, { id: 2, user: 'Bob Barker', - start: '18:00', - end: '21:00', + start: '16:00', + end: '19:00', boat: '1', status: 'confirmed', }, @@ -91,24 +90,24 @@ export function getSampleReservations(): Reservation[] { { id: 4, user: 'Vince McMahon', - start: '15:00', - end: '18:00', + start: '10:00', + end: '13:00', boat: '2', status: 'pending', }, { id: 5, user: 'Heather Graham', - start: '09:00', - end: '12:00', - boat: '3', + start: '13:00', + end: '19:00', + boat: '4', status: 'confirmed', }, { id: 6, user: 'Lawrence Fishburne', - start: '18:00', - end: '21:00', + start: '13:00', + end: '16:00', boat: '3', }, ];