Updates to booking
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 1m58s

This commit is contained in:
2024-04-30 13:56:42 -04:00
parent 0de9991a49
commit 2f68877ce6
4 changed files with 106 additions and 73 deletions

View File

@@ -1,15 +0,0 @@
<template>
<q-banner :class="$q.dark.isActive ? 'bg-grey-9' : 'bg-grey-3'">
Use the calendar to pick a date. Select an available boat and timeslot
below.
</q-banner>
<BoatScheduleTableComponent v-model="reservation" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import BoatScheduleTableComponent from './boat/BoatScheduleTableComponent.vue';
import { Reservation } from 'src/stores/schedule.types';
const reservation = ref<Reservation | null>(null);
</script>

View File

@@ -38,7 +38,25 @@
:id="block.id" :id="block.id"
@click="selectBlock($event, scope, block)" @click="selectBlock($event, scope, block)"
> >
Available {{ boatData[scope.columnIndex].name }}<br />
{{ selectedBlock?.id === block.id ? 'Selected' : 'Available' }}
</div>
</div>
<div
v-for="r in boatData[scope.columnIndex].reservations"
:key="r.id"
>
<div
class="reservation"
:style="
reservationStyles(
r,
scope.timeStartPos,
scope.timeDurationHeight
)
"
>
{{ r.user }}
</div> </div>
</div> </div>
</template> </template>
@@ -55,6 +73,7 @@ import {
today, today,
parsed, parsed,
parseTimestamp, parseTimestamp,
parseDate,
addToDate, addToDate,
} from '@quasar/quasar-ui-qcalendar'; } from '@quasar/quasar-ui-qcalendar';
import CalendarHeaderComponent from './CalendarHeaderComponent.vue'; import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
@@ -66,44 +85,67 @@ import { Reservation, Timeblock } from 'src/stores/schedule.types';
interface BoatData extends Boat { interface BoatData extends Boat {
blocks?: Timeblock[]; blocks?: Timeblock[];
reservations?: Reservation[];
} }
const scheduleStore = useScheduleStore(); const scheduleStore = useScheduleStore();
const boatStore = useBoatStore(); const boatStore = useBoatStore();
const selectedBlock = ref<Timeblock | null>(null); const selectedBlock = ref<Timeblock | null>(null);
const selectedDate = ref(today()); const selectedDate = ref(today());
const reservation = ref<Reservation | null>(null);
const boatData = ref<BoatData[]>(boatStore.boats); const boatData = ref<BoatData[]>(boatStore.boats);
const calendar = ref<QCalendarDay | null>(null); const calendar = ref<QCalendarDay | null>(null);
const emit = defineEmits<{
updateBoatTime: [block: Timeblock];
}>();
function handleSwipe({ ...event }) { function handleSwipe({ ...event }) {
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next(); 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( function blockStyles(
block: Timeblock, block: Timeblock,
timeStartPos: (t: string) => string, timeStartPos: (t: string) => string,
timeDurationHeight: (d: number) => 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 = { const s = {
top: '', top: '',
height: '', height: '',
opacity: '', opacity: '',
}; };
if (block && timeStartPos && timeDurationHeight) { if (timeStartPos && timeDurationHeight) {
s.top = timeStartPos(parsed(block.start)?.time || '00:00') + 'px'; s.top = timeStartPos(start.time) + 'px';
s.height = s.height =
parseInt( parseInt(
timeDurationHeight( timeDurationHeight(diffTimestamp(start, end, false) / 1000 / 60)
diffTimestamp(
parsed(block.start) as Timestamp,
parsed(block.end) as Timestamp,
false
) /
1000 /
60
)
) - ) -
1 + 1 +
'px'; 'px';
@@ -124,13 +166,21 @@ interface DayBodyScope {
function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Timeblock) { function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Timeblock) {
// TODO: Disable blocks before today with updateDisabled and/or comparison // TODO: Disable blocks before today with updateDisabled and/or comparison
selectedBlock.value = block; selectedBlock.value = block;
emit('updateBoatTime', block);
} }
function changeEvent({ start }: { start: string }) { function changeEvent({ start }: { start: string }) {
const newBlocks = scheduleStore.getTimeblocksForDate(start); const newBlocks = scheduleStore.getTimeblocksForDate(start);
const reservations = scheduleStore.getBoatReservations(
parsed(start) as Timestamp
);
boatData.value.map((b) => { 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... 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 .boat-schedule-table-component
display: flex display: flex
max-height: 60vh 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 .timeblock
display: flex display: flex
position: absolute position: absolute
justify-content: center justify-content: center
align-items: center align-items: center
width: 99% width: 100%
opacity: 0.5 opacity: 0.5
margin: 0px margin: 0px
text-overflow: ellipsis text-overflow: ellipsis

View File

@@ -20,7 +20,11 @@
:caption="bookingSummary" :caption="bookingSummary"
> >
<q-separator /> <q-separator />
<boat-selection /> <q-banner :class="$q.dark.isActive ? 'bg-grey-9' : 'bg-grey-3'">
Use the calendar to pick a date. Select an available boat and
timeslot below.
</q-banner>
<BoatScheduleTableComponent @updateBoatTime="updateBoat" />
<q-banner <q-banner
rounded rounded
@@ -69,14 +73,14 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, computed, watch } from 'vue'; import { reactive, ref, computed, watch } from 'vue';
import { useAuthStore } from 'src/stores/auth'; 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 { Dialog, date } from 'quasar';
import BoatSelection from 'src/components/scheduling/BoatSelection.vue'; import { useScheduleStore } from 'src/stores/schedule';
import { makeDateTime } from '@quasar/quasar-ui-qcalendar'; import { Reservation, Timeblock } from 'src/stores/schedule.types';
import { useScheduleStore, Reservation } from 'src/stores/schedule'; import BoatScheduleTableComponent from 'src/components/scheduling/boat/BoatScheduleTableComponent.vue';
const auth = useAuthStore(); 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 resourceView = ref(true);
const scheduleStore = useScheduleStore(); const scheduleStore = useScheduleStore();
const bookingForm = reactive({ const bookingForm = reactive({
@@ -84,15 +88,7 @@ const bookingForm = reactive({
name: auth.currentUser?.name, name: auth.currentUser?.name,
boat: <Boat | undefined>undefined, boat: <Boat | undefined>undefined,
startDate: date.formatDate(new Date(), dateFormat), startDate: date.formatDate(new Date(), dateFormat),
endDate: computed(() => endDate: date.formatDate(new Date(), dateFormat),
date.formatDate(
date.addToDate(bookingForm.startDate, {
hours: bookingForm.duration,
}),
dateFormat
)
),
duration: 1,
}); });
watch(bookingForm, (b, a) => { watch(bookingForm, (b, a) => {
@@ -119,12 +115,10 @@ const onSubmit = () => {
// TODO // TODO
}; };
const onClickTime = (data) => { const updateBoat = (block: Timeblock) => {
bookingForm.boat = data.scope.resource; bookingForm.boat = useBoatStore().boats.find((b) => b.$id === block.boatId);
bookingForm.startDate = date.formatDate( bookingForm.startDate = date.formatDate(block.start, dateFormat);
date.addToDate(makeDateTime(data.scope.timestamp), { hours: 5 }), // A terrible hack to convert back to EST. TODO: FIX!!!! bookingForm.endDate = date.formatDate(block.end, dateFormat);
dateFormat
);
console.log(bookingForm.startDate); console.log(bookingForm.startDate);
}; };
const bookingDuration = computed(() => { const bookingDuration = computed(() => {
@@ -144,13 +138,4 @@ const bookingSummary = computed(() => {
? `${bookingForm.boat.name} @ ${bookingForm.startDate} for ${bookingDuration.value}` ? `${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 }
);
};
</script> </script>

View File

@@ -1,6 +1,5 @@
import { DateOptions, date } from 'quasar'; import { DateOptions, date } from 'quasar';
import { Boat, useBoatStore } from '../boat'; import { Boat, useBoatStore } from '../boat';
import { ID } from 'src/boot/appwrite';
import { import {
parseTimestamp, parseTimestamp,
today, today,
@@ -43,7 +42,7 @@ export function getSampleTimeBlocks(): Timeblock[] {
const tsToday: Timestamp = parseTimestamp(today()) as Timestamp; const tsToday: Timestamp = parseTimestamp(today()) as Timestamp;
for (let i = 0; i <= 30; i++) { for (let i = 0; i <= 30; i++) {
const template = Math.random() < 0.5 ? templateA : templateB; const template = templateB;
result.push( result.push(
...boats ...boats
.map((b): Timeblock[] => { .map((b): Timeblock[] => {
@@ -67,16 +66,16 @@ export function getSampleReservations(): Reservation[] {
{ {
id: 1, id: 1,
user: 'John Smith', user: 'John Smith',
start: '12:00', start: '7:00',
end: '15:00', end: '10:00',
boat: '1', boat: '1',
status: 'confirmed', status: 'confirmed',
}, },
{ {
id: 2, id: 2,
user: 'Bob Barker', user: 'Bob Barker',
start: '18:00', start: '16:00',
end: '21:00', end: '19:00',
boat: '1', boat: '1',
status: 'confirmed', status: 'confirmed',
}, },
@@ -91,24 +90,24 @@ export function getSampleReservations(): Reservation[] {
{ {
id: 4, id: 4,
user: 'Vince McMahon', user: 'Vince McMahon',
start: '15:00', start: '10:00',
end: '18:00', end: '13:00',
boat: '2', boat: '2',
status: 'pending', status: 'pending',
}, },
{ {
id: 5, id: 5,
user: 'Heather Graham', user: 'Heather Graham',
start: '09:00', start: '13:00',
end: '12:00', end: '19:00',
boat: '3', boat: '4',
status: 'confirmed', status: 'confirmed',
}, },
{ {
id: 6, id: 6,
user: 'Lawrence Fishburne', user: 'Lawrence Fishburne',
start: '18:00', start: '13:00',
end: '21:00', end: '16:00',
boat: '3', boat: '3',
}, },
]; ];