Compare commits
2 Commits
e1a784ef45
...
c297f1f287
| Author | SHA1 | Date | |
|---|---|---|---|
|
c297f1f287
|
|||
|
43e68c8ae7
|
@@ -3,108 +3,13 @@
|
|||||||
Use the calendar to pick a date. Select an available boat and timeslot
|
Use the calendar to pick a date. Select an available boat and timeslot
|
||||||
below.
|
below.
|
||||||
</q-banner>
|
</q-banner>
|
||||||
<BoatScheduleTableComponent />
|
<BoatScheduleTableComponent v-model="reservation" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import {
|
|
||||||
today,
|
|
||||||
parseTimestamp,
|
|
||||||
addToDate,
|
|
||||||
Timestamp,
|
|
||||||
} from '@quasar/quasar-ui-qcalendar';
|
|
||||||
import { Boat, useBoatStore } from 'src/stores/boat';
|
|
||||||
import { useScheduleStore, Timeblock } from 'src/stores/schedule';
|
|
||||||
import { computed } from 'vue';
|
|
||||||
import { date } from 'quasar';
|
|
||||||
import BoatScheduleTableComponent from './boat/BoatScheduleTableComponent.vue';
|
import BoatScheduleTableComponent from './boat/BoatScheduleTableComponent.vue';
|
||||||
|
import { Reservation } from 'src/stores/schedule.types';
|
||||||
|
|
||||||
interface EventData {
|
const reservation = ref<Reservation | null>(null);
|
||||||
event: object;
|
|
||||||
scope: {
|
|
||||||
timestamp: object;
|
|
||||||
columnindex: number;
|
|
||||||
activeDate: boolean;
|
|
||||||
droppable: boolean;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const calendar = ref();
|
|
||||||
const scheduleStore = useScheduleStore();
|
|
||||||
const selectedDate = ref(today());
|
|
||||||
const selectedBoatTime = ref();
|
|
||||||
|
|
||||||
const disabledBefore = computed(() => {
|
|
||||||
const todayTs = parseTimestamp(today()) as Timestamp;
|
|
||||||
return addToDate(todayTs, { day: -1 }).date;
|
|
||||||
});
|
|
||||||
|
|
||||||
function monthFormatter() {
|
|
||||||
try {
|
|
||||||
return new Intl.DateTimeFormat('en-CA' || undefined, {
|
|
||||||
month: 'long',
|
|
||||||
timeZone: 'UTC',
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const disabledDays = () => {
|
|
||||||
// Placeholder. This should actually compute days when boats aren't available.
|
|
||||||
const days = [];
|
|
||||||
const todayTs = parseTimestamp(today()) as Timestamp;
|
|
||||||
days.push(addToDate(todayTs, { day: 2 }).date);
|
|
||||||
return days;
|
|
||||||
};
|
|
||||||
|
|
||||||
const boatoptions = (boat: Boat) => {
|
|
||||||
const options = useScheduleStore()
|
|
||||||
.getTimeblocksForDate(date.extractDate(selectedDate.value, 'YYYY-MM-DD'))
|
|
||||||
.map((x: Timeblock) => {
|
|
||||||
const conflicts = getConflicts(x, boat);
|
|
||||||
return {
|
|
||||||
label: x.start.time + ' to ' + x.end.time,
|
|
||||||
value: boat.id + ':' + x.start.time,
|
|
||||||
disable: conflicts.length > 0,
|
|
||||||
user: conflicts[0]?.user,
|
|
||||||
boat: boat,
|
|
||||||
timeblock: x,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
return options;
|
|
||||||
};
|
|
||||||
|
|
||||||
const emit = defineEmits(['onClickTime', 'onUpdateDuration']);
|
|
||||||
|
|
||||||
function onPrev() {
|
|
||||||
calendar.value.prev();
|
|
||||||
}
|
|
||||||
function onNext() {
|
|
||||||
calendar.value.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onClickDate(data: EventData) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
function onChange(data: EventData) {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const getConflicts = (timeblock: Timeblock, boat: Boat) => {
|
|
||||||
const start = date.buildDate({
|
|
||||||
hour: timeblock.start.hour,
|
|
||||||
minute: timeblock.start.minute,
|
|
||||||
second: 0,
|
|
||||||
millisecond: 0,
|
|
||||||
});
|
|
||||||
const end = date.buildDate({
|
|
||||||
hour: timeblock.end.hour,
|
|
||||||
minute: timeblock.end.minute,
|
|
||||||
second: 0,
|
|
||||||
millisecond: 0,
|
|
||||||
});
|
|
||||||
return scheduleStore.getConflictingReservations(boat, start, end);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -14,18 +14,21 @@
|
|||||||
interval-start="06:00"
|
interval-start="06:00"
|
||||||
:short-interval-label="true"
|
:short-interval-label="true"
|
||||||
v-model="selectedDate"
|
v-model="selectedDate"
|
||||||
:column-count="boats.length"
|
:column-count="boatData.length"
|
||||||
@change="scrollToEvent()"
|
@change="changeEvent"
|
||||||
v-touch-swipe.left.right="handleSwipe"
|
v-touch-swipe.left.right="handleSwipe"
|
||||||
>
|
>
|
||||||
<template #head-day="{ scope }">
|
<template #head-day="{ scope }">
|
||||||
<div style="text-align: center; font-weight: 800">
|
<div style="text-align: center; font-weight: 800">
|
||||||
{{ boats[scope.columnIndex].displayName }}
|
{{ boatData[scope.columnIndex].displayName }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #day-body="{ scope }">
|
<template #day-body="{ scope }">
|
||||||
<div v-for="block in blocklist" :key="block.id">
|
<div
|
||||||
|
v-for="block in boatData[scope.columnIndex].blocks"
|
||||||
|
:key="block.id"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="timeblock"
|
class="timeblock"
|
||||||
:style="
|
:style="
|
||||||
@@ -54,24 +57,26 @@ import {
|
|||||||
} from '@quasar/quasar-ui-qcalendar';
|
} from '@quasar/quasar-ui-qcalendar';
|
||||||
import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
|
import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
|
||||||
|
|
||||||
import { ref, reactive, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useBoatStore } from 'src/stores/boat';
|
import { Boat, useBoatStore } from 'src/stores/boat';
|
||||||
import { Timeblock, useScheduleStore } from 'src/stores/schedule';
|
import { useScheduleStore } from 'src/stores/schedule';
|
||||||
import { TouchSwipeValue } from 'quasar';
|
import { Reservation, Timeblock } from 'src/stores/schedule.types';
|
||||||
|
|
||||||
|
interface BoatData extends Boat {
|
||||||
|
blocks?: Timeblock[];
|
||||||
|
}
|
||||||
|
|
||||||
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 blocklist = reactive<Timeblock[]>(
|
const boatData = ref<BoatData[]>(boatStore.boats);
|
||||||
scheduleStore.getTimeblocksForDate(parsed(today()) as Timestamp)
|
|
||||||
);
|
|
||||||
const boats = boatStore.boats;
|
|
||||||
|
|
||||||
const calendar = ref<QCalendarDay | null>(null);
|
const calendar = ref<QCalendarDay | null>(null);
|
||||||
|
|
||||||
function handleSwipe(event: Event) {
|
function handleSwipe({ ...event }) {
|
||||||
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
|
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
|
||||||
}
|
}
|
||||||
function blockStyles(
|
function blockStyles(
|
||||||
@@ -84,16 +89,26 @@ function blockStyles(
|
|||||||
height: '',
|
height: '',
|
||||||
opacity: '',
|
opacity: '',
|
||||||
};
|
};
|
||||||
if (timeStartPos && timeDurationHeight) {
|
if (block && timeStartPos && timeDurationHeight) {
|
||||||
s.top = timeStartPos(block.start.time) + 'px';
|
s.top = timeStartPos(parsed(block.start)?.time || '00:00') + 'px';
|
||||||
s.height =
|
s.height =
|
||||||
timeDurationHeight(
|
parseInt(
|
||||||
diffTimestamp(block.start, block.end, false) / 1000 / 60
|
timeDurationHeight(
|
||||||
) + 'px';
|
diffTimestamp(
|
||||||
}
|
parsed(block.start) as Timestamp,
|
||||||
if (selectedBlock.value?.id === block.id) {
|
parsed(block.end) as Timestamp,
|
||||||
s.opacity = '1.0';
|
false
|
||||||
|
) /
|
||||||
|
1000 /
|
||||||
|
60
|
||||||
|
)
|
||||||
|
) -
|
||||||
|
1 +
|
||||||
|
'px';
|
||||||
}
|
}
|
||||||
|
// if (selectedBlock.value?.id === block.id) {
|
||||||
|
// s.opacity = '1.0';
|
||||||
|
// }
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,38 +124,42 @@ function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Timeblock) {
|
|||||||
selectedBlock.value = block;
|
selectedBlock.value = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
function scrollToEvent() {
|
function changeEvent({ start }: { start: string }) {
|
||||||
|
const newBlocks = scheduleStore.getTimeblocksForDate(start);
|
||||||
|
boatData.value.map((b) => {
|
||||||
|
return (b.blocks = newBlocks.filter((block) => block.boatId === b.$id));
|
||||||
|
});
|
||||||
setTimeout(() => calendar.value?.scrollToTime('09:00'), 10); // Should figure out why we need this setTimeout...
|
setTimeout(() => calendar.value?.scrollToTime('09:00'), 10); // Should figure out why we need this setTimeout...
|
||||||
}
|
}
|
||||||
|
|
||||||
const disabledBefore = computed(() => {
|
const disabledBefore = computed(() => {
|
||||||
let ts = parseTimestamp(today());
|
const todayTs = parseTimestamp(today()) as Timestamp;
|
||||||
ts = addToDate(ts, { day: -1 });
|
return addToDate(todayTs, { day: -1 }).date;
|
||||||
return ts.date;
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="sass">
|
<style lang="sass">
|
||||||
.boat-schedule-table-component
|
.boat-schedule-table-component
|
||||||
display: flex
|
display: flex
|
||||||
height: 60vh
|
max-height: 60vh
|
||||||
.timeblock
|
.timeblock
|
||||||
display: flex
|
display: flex
|
||||||
position: absolute
|
position: absolute
|
||||||
justify-content: center
|
justify-content: center
|
||||||
align-items: center
|
align-items: center
|
||||||
width: 100%
|
width: 99%
|
||||||
opacity: 0.25
|
opacity: 0.5
|
||||||
margin: 0 1px
|
margin: 0px
|
||||||
text-overflow: ellipsis
|
text-overflow: ellipsis
|
||||||
overflow: hidden
|
|
||||||
font-size: 0.8em
|
font-size: 0.8em
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
background: $primary
|
background: $primary
|
||||||
color: white
|
color: white
|
||||||
border: 2px solid black
|
border: 1px solid black
|
||||||
.selected
|
.selected
|
||||||
opacity: 1 !important
|
opacity: 1 !important
|
||||||
.q-calendar-day__interval--text
|
.q-calendar-day__interval--text
|
||||||
font-size: 0.8em
|
font-size: 0.8em
|
||||||
|
.q-calendar-day__day.q-current-day
|
||||||
|
padding: 1px
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,22 +2,21 @@
|
|||||||
<q-page>
|
<q-page>
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-form @submit="onSubmit" @reset="onReset" class="q-gutter-sm">
|
<q-form @submit="onSubmit" @reset="onReset" class="q-gutter-sm">
|
||||||
<q-input
|
<q-item>
|
||||||
bottom-slots
|
<q-item-section :avatar="true">
|
||||||
v-model="bookingForm.name"
|
<q-icon name="person"
|
||||||
label="Creating reservation for"
|
/></q-item-section>
|
||||||
readonly
|
<q-item-section>
|
||||||
>
|
<q-item-label> Name: {{ bookingForm.name }} </q-item-label>
|
||||||
<template v-slot:prepend>
|
</q-item-section>
|
||||||
<q-icon name="person" />
|
</q-item>
|
||||||
</template>
|
|
||||||
</q-input>
|
|
||||||
<q-expansion-item
|
<q-expansion-item
|
||||||
expand-separator
|
expand-separator
|
||||||
v-model="resourceView"
|
v-model="resourceView"
|
||||||
icon="calendar_month"
|
icon="calendar_month"
|
||||||
label="Boat and Time"
|
label="Boat and Time"
|
||||||
default-opened
|
default-opened
|
||||||
|
class="q-mt-none"
|
||||||
:caption="bookingSummary"
|
:caption="bookingSummary"
|
||||||
>
|
>
|
||||||
<q-separator />
|
<q-separator />
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ and rough engine performance.`,
|
|||||||
imgsrc: '/tmpimg/capri25.png',
|
imgsrc: '/tmpimg/capri25.png',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
$id: '3',
|
$id: '4',
|
||||||
name: 'Just My Imagination',
|
name: 'Just My Imagination',
|
||||||
displayName: 'JMI',
|
displayName: 'JMI',
|
||||||
class: 'Capri 25',
|
class: 'Capri 25',
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
import { DateOptions, date } from 'quasar';
|
||||||
|
import { Boat, useBoatStore } from '../boat';
|
||||||
|
import { ID } from 'src/boot/appwrite';
|
||||||
|
import {
|
||||||
|
parseTimestamp,
|
||||||
|
today,
|
||||||
|
Timestamp,
|
||||||
|
addToDate,
|
||||||
|
} from '@quasar/quasar-ui-qcalendar';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
StatusTypes,
|
||||||
|
Reservation,
|
||||||
|
TimeBlockTemplate,
|
||||||
|
Timeblock,
|
||||||
|
} from '../schedule.types';
|
||||||
|
|
||||||
|
export const templateA: TimeBlockTemplate = {
|
||||||
|
id: '1',
|
||||||
|
name: 'WeekdayBlocks',
|
||||||
|
blocks: [
|
||||||
|
['08:00', '12:00'],
|
||||||
|
['12:00', '16:00'],
|
||||||
|
['17:00', '21:00'],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const templateB: TimeBlockTemplate = {
|
||||||
|
id: '2',
|
||||||
|
name: 'WeekendBlocks',
|
||||||
|
blocks: [
|
||||||
|
['07:00', '10:00'],
|
||||||
|
['10:00', '13:00'],
|
||||||
|
['13:00', '16:00'],
|
||||||
|
['16:00', '19:00'],
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getSampleTimeBlocks(): Timeblock[] {
|
||||||
|
// Hard-code 30 days worth of blocks, for now. Make them random templates
|
||||||
|
const boats = useBoatStore().boats;
|
||||||
|
const result: Timeblock[] = [];
|
||||||
|
const tsToday: Timestamp = parseTimestamp(today()) as Timestamp;
|
||||||
|
|
||||||
|
for (let i = 0; i <= 30; i++) {
|
||||||
|
const template = Math.random() < 0.5 ? templateA : templateB;
|
||||||
|
result.push(
|
||||||
|
...boats
|
||||||
|
.map((b): Timeblock[] => {
|
||||||
|
return template.blocks.map((t): Timeblock => {
|
||||||
|
return {
|
||||||
|
id: 'id' + Math.random().toString(32).slice(2),
|
||||||
|
boatId: b.$id,
|
||||||
|
start: addToDate(tsToday, { day: i }).date + ' ' + t[0],
|
||||||
|
end: addToDate(tsToday, { day: i }).date + ' ' + t[1],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.flat(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSampleReservations(): Reservation[] {
|
||||||
|
const sampleData = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
user: 'John Smith',
|
||||||
|
start: '12:00',
|
||||||
|
end: '15:00',
|
||||||
|
boat: '1',
|
||||||
|
status: 'confirmed',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
user: 'Bob Barker',
|
||||||
|
start: '18:00',
|
||||||
|
end: '21:00',
|
||||||
|
boat: '1',
|
||||||
|
status: 'confirmed',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
user: 'Peter Parker',
|
||||||
|
start: '9:00',
|
||||||
|
end: '12:00',
|
||||||
|
boat: '2',
|
||||||
|
status: 'tentative',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
user: 'Vince McMahon',
|
||||||
|
start: '15:00',
|
||||||
|
end: '18:00',
|
||||||
|
boat: '2',
|
||||||
|
status: 'pending',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
user: 'Heather Graham',
|
||||||
|
start: '09:00',
|
||||||
|
end: '12:00',
|
||||||
|
boat: '3',
|
||||||
|
status: 'confirmed',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
user: 'Lawrence Fishburne',
|
||||||
|
start: '18:00',
|
||||||
|
end: '21:00',
|
||||||
|
boat: '3',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const boatStore = useBoatStore();
|
||||||
|
const now = new Date();
|
||||||
|
const splitTime = (x: string): string[] => {
|
||||||
|
return x.split(':');
|
||||||
|
};
|
||||||
|
const makeOpts = (x: string[]): DateOptions => {
|
||||||
|
return {
|
||||||
|
hour: parseInt(x[0]),
|
||||||
|
minute: parseInt(x[1]),
|
||||||
|
seconds: 0,
|
||||||
|
milliseconds: 0,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return sampleData.map((entry): Reservation => {
|
||||||
|
const boat = <Boat>boatStore.boats.find((b) => b.$id == entry.boat);
|
||||||
|
return {
|
||||||
|
id: entry.id,
|
||||||
|
user: entry.user,
|
||||||
|
start: date.adjustDate(now, makeOpts(splitTime(entry.start))),
|
||||||
|
end: date.adjustDate(now, makeOpts(splitTime(entry.end))),
|
||||||
|
resource: boat,
|
||||||
|
reservationDate: now,
|
||||||
|
status: entry.status as StatusTypes,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,158 +1,27 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { Boat, useBoatStore } from './boat';
|
import { Boat } from './boat';
|
||||||
import { date } from 'quasar';
|
import {
|
||||||
import { DateOptions } from 'quasar';
|
Timestamp,
|
||||||
import { Timestamp, parseDate } from '@quasar/quasar-ui-qcalendar';
|
parseDate,
|
||||||
|
parsed,
|
||||||
|
compareDate,
|
||||||
|
} from '@quasar/quasar-ui-qcalendar';
|
||||||
|
|
||||||
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
|
import { Reservation, Timeblock } from './schedule.types';
|
||||||
export interface Reservation {
|
import {
|
||||||
id: number;
|
getSampleReservations,
|
||||||
user: string;
|
getSampleTimeBlocks,
|
||||||
start: Date;
|
} from './sampledata/schedule';
|
||||||
end: Date;
|
|
||||||
resource: Boat;
|
|
||||||
reservationDate: Date;
|
|
||||||
status?: StatusTypes;
|
|
||||||
}
|
|
||||||
// 24 hrs in advance only 2 weekday, and 1 weekend slot
|
|
||||||
// Within 24 hrs, any available slot
|
|
||||||
/* TODO: Figure out how best to separate out where qcalendar bits should be.
|
|
||||||
e.g.: Should there be any qcalendar stuff in this store? Or should we have just JS Date
|
|
||||||
objects in here? */
|
|
||||||
|
|
||||||
export interface Timeblock {
|
|
||||||
start: Timestamp;
|
|
||||||
end: Timestamp;
|
|
||||||
selected?: false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const weekdayBlocks = [
|
|
||||||
{
|
|
||||||
start: { time: '08:00', hour: 8, minute: 0 },
|
|
||||||
end: { time: '12:00', hour: 12, minute: 0 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: { time: '12:00', hour: 12, minute: 0 },
|
|
||||||
end: { time: '16:00', hour: 16, minute: 0 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: { time: '17:00', hour: 17, minute: 0 },
|
|
||||||
end: { time: '21:00', hour: 21, minute: 0 },
|
|
||||||
},
|
|
||||||
] as Timeblock[];
|
|
||||||
|
|
||||||
const weekendBlocks = [
|
|
||||||
{
|
|
||||||
start: { time: '07:00', hour: 7, minute: 0 },
|
|
||||||
end: { time: '10:00', hour: 10, minute: 0 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: { time: '10:00', hour: 10, minute: 0 },
|
|
||||||
end: { time: '13:00', hour: 13, minute: 0 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: { time: '13:00', hour: 13, minute: 0 },
|
|
||||||
end: { time: '16:00', hour: 16, minute: 0 },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
start: { time: '16:00', hour: 16, minute: 0 },
|
|
||||||
end: { time: '19:00', hour: 19, minute: 0 },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function getSampleReservations(): Reservation[] {
|
|
||||||
const sampleData = [
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
user: 'John Smith',
|
|
||||||
start: '12:00',
|
|
||||||
end: '15:00',
|
|
||||||
boat: '1',
|
|
||||||
status: 'confirmed',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
user: 'Bob Barker',
|
|
||||||
start: '18:00',
|
|
||||||
end: '21:00',
|
|
||||||
boat: '1',
|
|
||||||
status: 'confirmed',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
user: 'Peter Parker',
|
|
||||||
start: '9:00',
|
|
||||||
end: '12:00',
|
|
||||||
boat: '2',
|
|
||||||
status: 'tentative',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
user: 'Vince McMahon',
|
|
||||||
start: '15:00',
|
|
||||||
end: '18:00',
|
|
||||||
boat: '2',
|
|
||||||
status: 'pending',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
user: 'Heather Graham',
|
|
||||||
start: '09:00',
|
|
||||||
end: '12:00',
|
|
||||||
boat: '3',
|
|
||||||
status: 'confirmed',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
user: 'Lawrence Fishburne',
|
|
||||||
start: '18:00',
|
|
||||||
end: '21:00',
|
|
||||||
boat: '3',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const boatStore = useBoatStore();
|
|
||||||
const now = new Date();
|
|
||||||
const splitTime = (x: string): string[] => {
|
|
||||||
return x.split(':');
|
|
||||||
};
|
|
||||||
const makeOpts = (x: string[]): DateOptions => {
|
|
||||||
return {
|
|
||||||
hour: parseInt(x[0]),
|
|
||||||
minute: parseInt(x[1]),
|
|
||||||
seconds: 0,
|
|
||||||
milliseconds: 0,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return sampleData.map((entry): Reservation => {
|
|
||||||
const boat = <Boat>boatStore.boats.find((b) => b.$id == entry.boat);
|
|
||||||
return {
|
|
||||||
id: entry.id,
|
|
||||||
user: entry.user,
|
|
||||||
start: date.adjustDate(now, makeOpts(splitTime(entry.start))),
|
|
||||||
end: date.adjustDate(now, makeOpts(splitTime(entry.end))),
|
|
||||||
resource: boat,
|
|
||||||
reservationDate: now,
|
|
||||||
status: entry.status as StatusTypes,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useScheduleStore = defineStore('schedule', () => {
|
export const useScheduleStore = defineStore('schedule', () => {
|
||||||
// TODO: Implement functions to dynamically pull this data.
|
// TODO: Implement functions to dynamically pull this data.
|
||||||
const reservations = ref<Reservation[]>(getSampleReservations());
|
const reservations = ref<Reservation[]>(getSampleReservations());
|
||||||
const timeblocks = weekdayBlocks;
|
|
||||||
|
|
||||||
const getTimeblocksForDate = (date: Timestamp): Timeblock[] => {
|
const getTimeblocksForDate = (date: string): Timeblock[] => {
|
||||||
return timeblocks.map((t) => {
|
return getSampleTimeBlocks().filter((b) =>
|
||||||
return {
|
compareDate(parsed(b.start) as Timestamp, parsed(date) as Timestamp)
|
||||||
// Update all the start/end times with the passed in date
|
);
|
||||||
...t,
|
|
||||||
start: { ...date, ...t.start },
|
|
||||||
end: { ...date, ...t.end },
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getBoatReservations = (
|
const getBoatReservations = (
|
||||||
@@ -160,7 +29,6 @@ export const useScheduleStore = defineStore('schedule', () => {
|
|||||||
boat?: string
|
boat?: string
|
||||||
): Reservation[] => {
|
): Reservation[] => {
|
||||||
return reservations.value.filter((x) => {
|
return reservations.value.filter((x) => {
|
||||||
console.log(searchDate);
|
|
||||||
return (
|
return (
|
||||||
((parseDate(x.start)?.date == searchDate.date ||
|
((parseDate(x.start)?.date == searchDate.date ||
|
||||||
parseDate(x.end)?.date == searchDate.date) && // Part of reservation falls on day
|
parseDate(x.end)?.date == searchDate.date) && // Part of reservation falls on day
|
||||||
@@ -171,6 +39,21 @@ export const useScheduleStore = defineStore('schedule', () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const getConflicts = (timeblock: Timeblock, boat: Boat) => {
|
||||||
|
// const start = date.buildDate({
|
||||||
|
// hour: timeblock.start.hour,
|
||||||
|
// minute: timeblock.start.minute,
|
||||||
|
// second: 0,
|
||||||
|
// millisecond: 0,
|
||||||
|
// });
|
||||||
|
// const end = date.buildDate({
|
||||||
|
// hour: timeblock.end.hour,
|
||||||
|
// minute: timeblock.end.minute,
|
||||||
|
// second: 0,
|
||||||
|
// millisecond: 0,
|
||||||
|
// });
|
||||||
|
// return scheduleStore.getConflictingReservations(boat, start, end);
|
||||||
|
// };
|
||||||
const getConflictingReservations = (
|
const getConflictingReservations = (
|
||||||
resource: Boat,
|
resource: Boat,
|
||||||
start: Date,
|
start: Date,
|
||||||
|
|||||||
32
src/stores/schedule.types.ts
Normal file
32
src/stores/schedule.types.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import type { Boat } from './boat';
|
||||||
|
|
||||||
|
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
|
||||||
|
export interface Reservation {
|
||||||
|
id: number;
|
||||||
|
user: string;
|
||||||
|
start: Date;
|
||||||
|
end: Date;
|
||||||
|
resource: Boat;
|
||||||
|
reservationDate: Date;
|
||||||
|
status?: StatusTypes;
|
||||||
|
}
|
||||||
|
// 24 hrs in advance only 2 weekday, and 1 weekend slot
|
||||||
|
// Within 24 hrs, any available slot
|
||||||
|
/* TODO: Figure out how best to separate out where qcalendar bits should be.
|
||||||
|
e.g.: Should there be any qcalendar stuff in this store? Or should we have just JS Date
|
||||||
|
objects in here? */
|
||||||
|
|
||||||
|
export type timeTuple = [start: string, end: string];
|
||||||
|
export interface Timeblock {
|
||||||
|
id: string;
|
||||||
|
boatId: string;
|
||||||
|
start: string;
|
||||||
|
end: string;
|
||||||
|
selected?: false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TimeBlockTemplate {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
blocks: timeTuple[];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user