Converted some schedule to use backend

This commit is contained in:
2024-05-04 23:17:05 -04:00
parent fa4d83e42d
commit 634cff507c
7 changed files with 83 additions and 60 deletions

View File

@@ -14,7 +14,7 @@
}, },
"dependencies": { "dependencies": {
"@quasar/extras": "^1.16.11", "@quasar/extras": "^1.16.11",
"appwrite": "^13.0.0", "appwrite": "^14.0.1",
"pinia": "^2.1.7", "pinia": "^2.1.7",
"vue": "3", "vue": "3",
"vue-router": "4" "vue-router": "4"

View File

@@ -20,18 +20,15 @@
> >
<template #head-day="{ scope }"> <template #head-day="{ scope }">
<div style="text-align: center; font-weight: 800"> <div style="text-align: center; font-weight: 800">
{{ boatData[scope.columnIndex].displayName }} {{ getBoatDisplayName(scope) }}
</div> </div>
</template> </template>
<template #day-body="{ scope }"> <template #day-body="{ scope }">
<div <div v-for="block in getBoatBlocks(scope)" :key="block.$id">
v-for="block in boatData[scope.columnIndex].blocks"
:key="block.id"
>
<div <div
class="timeblock" class="timeblock"
:class="selectedBlock?.id === block.id ? 'selected' : ''" :class="selectedBlock?.$id === block.$id ? 'selected' : ''"
:style=" :style="
blockStyles(block, scope.timeStartPos, scope.timeDurationHeight) blockStyles(block, scope.timeStartPos, scope.timeDurationHeight)
" "
@@ -39,10 +36,10 @@
@click="selectBlock($event, scope, block)" @click="selectBlock($event, scope, block)"
> >
{{ boatData[scope.columnIndex].name }}<br /> {{ boatData[scope.columnIndex].name }}<br />
{{ selectedBlock?.id === block.id ? 'Selected' : 'Available' }} {{ selectedBlock?.$id === block.$id ? 'Selected' : 'Available' }}
</div> </div>
</div> </div>
<div <!-- <div
v-for="r in boatData[scope.columnIndex].reservations" v-for="r in boatData[scope.columnIndex].reservations"
:key="r.id" :key="r.id"
> >
@@ -58,7 +55,7 @@
> >
{{ r.user }} {{ r.user }}
</div> </div>
</div> </div> -->
</template> </template>
</QCalendarDay> </QCalendarDay>
</div> </div>
@@ -71,7 +68,6 @@ import {
Timestamp, Timestamp,
diffTimestamp, diffTimestamp,
today, today,
parsed,
parseTimestamp, parseTimestamp,
parseDate, parseDate,
addToDate, addToDate,
@@ -79,26 +75,26 @@ import {
} from '@quasar/quasar-ui-qcalendar'; } from '@quasar/quasar-ui-qcalendar';
import CalendarHeaderComponent from './CalendarHeaderComponent.vue'; import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
import { ref, computed } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { Boat, useBoatStore } from 'src/stores/boat'; import { Boat, useBoatStore } from 'src/stores/boat';
import { useScheduleStore } from 'src/stores/schedule'; import { useScheduleStore } from 'src/stores/schedule';
import { Reservation, Timeblock } from 'src/stores/schedule.types'; import { Reservation, Timeblock } from 'src/stores/schedule.types';
import { date } from 'quasar'; import { date } from 'quasar';
interface BoatData extends Boat {
blocks?: Timeblock[];
reservations?: Reservation[];
}
const scheduleStore = useScheduleStore(); const scheduleStore = useScheduleStore();
const boatStore = useBoatStore(); const boatStore = useBoatStore();
const boatData = boatStore.boats;
const selectedBlock = defineModel<Timeblock | null>(); const selectedBlock = defineModel<Timeblock | null>();
const selectedDate = ref(today()); const selectedDate = ref(today());
const boatData = ref<BoatData[]>(boatStore.boats);
const calendar = ref<QCalendarDay | null>(null); const calendar = ref<QCalendarDay | null>(null);
onMounted(async () => {
await boatStore.fetchBoats();
await scheduleStore.fetchTimeBlocks();
// useScheduleStore().fetchReservations()
}); // TODO: Probably need this to be more sophisticated.
function handleSwipe({ ...event }) { function handleSwipe({ ...event }) {
event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next(); event.direction === 'right' ? calendar.value?.prev() : calendar.value?.next();
} }
@@ -121,13 +117,19 @@ function blockStyles(
timeDurationHeight: (d: number) => string timeDurationHeight: (d: number) => string
) { ) {
return genericBlockStyle( return genericBlockStyle(
parsed(block.start) as Timestamp, parseDate(new Date(block.start)) as Timestamp,
parsed(block.end) as Timestamp, parseDate(new Date(block.end)) as Timestamp,
timeStartPos, timeStartPos,
timeDurationHeight timeDurationHeight
); );
} }
function getBoatDisplayName(scope: DayBodyScope) {
return boatData && boatData.value[scope.columnIndex]
? boatData.value[scope.columnIndex].displayName
: '';
}
function genericBlockStyle( function genericBlockStyle(
start: Timestamp, start: Timestamp,
end: Timestamp, end: Timestamp,
@@ -168,33 +170,52 @@ function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Timeblock) {
: (selectedBlock.value = block); : (selectedBlock.value = block);
} }
function changeEvent({ start }: { start: string }) { interface BoatBlocks {
const newBlocks = scheduleStore.getTimeblocksForDate(start); [key: string]: Timeblock[];
const reservations = scheduleStore.getBoatReservations( }
parsed(start) as Timestamp
);
boatData.value.map((boat) => {
boat.reservations = reservations.filter(
(reservation) => reservation.resource === boat
);
boat.blocks = newBlocks.filter(
(block) =>
block.boatId === boat.$id &&
boat.reservations?.filter(
(r) =>
r.start <
date.addToDate(makeDateTime(parsed(block.end) as Timestamp), {
hours: 4,
}) &&
r.end >
date.addToDate(makeDateTime(parsed(block.start) as Timestamp), {
hours: 4,
})
).length == 0
);
});
setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout... const boatBlocks = computed((): BoatBlocks => {
return scheduleStore
.getTimeblocksForDate(selectedDate.value)
.reduce((result, tb) => {
if (!result[tb.boatId]) result[tb.boatId] = [];
result[tb.boatId].push(tb);
return result;
}, <BoatBlocks>{});
});
function getBoatBlocks(scope: DayBodyScope): Timeblock[] {
return boatData.value[scope.columnIndex]
? boatBlocks.value[boatData.value[scope.columnIndex].$id]
: [];
}
function changeEvent({ start }: { start: string }) {
// const newBlocks = scheduleStore.getTimeblocksForDate(start);
// const reservations = scheduleStore.getBoatReservations(
// parsed(start) as Timestamp
// );
// boatData.value.map((boat) => {
// boat.reservations = reservations.filter(
// (reservation) => reservation.resource === boat
// );
// boat.blocks = newBlocks.filter(
// (block) =>
// block.boatId === boat.$id &&
// boat.reservations?.filter(
// (r: Reservation) =>
// r.start <
// date.addToDate(makeDateTime(parsed(block.end) as Timestamp), {
// hours: 4,
// }) &&
// r.end >
// date.addToDate(makeDateTime(parsed(block.start) as Timestamp), {
// hours: 4,
// })
// ).length == 0
// );
// });
// setTimeout(() => calendar.value?.scrollToTime('09:00'), 100); // Should figure out why we need this setTimeout...
} }
const disabledBefore = computed(() => { const disabledBefore = computed(() => {

View File

@@ -9,9 +9,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps } from 'vue';
import type { Task } from 'src/stores/task'; import type { Task } from 'src/stores/task';
import TaskCardComponent from './TaskCardComponent.vue'; import TaskCardComponent from './TaskCardComponent.vue';
const props = defineProps<{ tasks: Task[] }>(); defineProps<{ tasks: Task[] }>();
</script> </script>

View File

@@ -131,8 +131,7 @@ const bookingForm = ref<BookingForm>({
}); });
watch(timeblock, (tb_new) => { watch(timeblock, (tb_new) => {
console.log('Hi'); bookingForm.value.boat = useBoatStore().boats.value.find(
bookingForm.value.boat = useBoatStore().boats.find(
(b) => b.$id === tb_new?.boatId (b) => b.$id === tb_new?.boatId
); );
bookingForm.value.startDate = date.formatDate(tb_new?.start, dateFormat); bookingForm.value.startDate = date.formatDate(tb_new?.start, dateFormat);

View File

@@ -21,9 +21,12 @@ export const useScheduleStore = defineStore('schedule', () => {
if (!timeblocks.value) { if (!timeblocks.value) {
fetchTimeBlocks(); fetchTimeBlocks();
} }
return timeblocks.value.filter((b) => return timeblocks.value.filter((b) => {
compareDate(parsed(b.start) as Timestamp, parsed(date) as Timestamp) return compareDate(
); parseDate(new Date(b.start)) as Timestamp,
parsed(date) as Timestamp
);
});
}; };
const getBoatReservations = ( const getBoatReservations = (
@@ -113,9 +116,11 @@ export const useScheduleStore = defineStore('schedule', () => {
return { return {
reservations, reservations,
timeblocks,
getBoatReservations, getBoatReservations,
getConflictingReservations, getConflictingReservations,
getTimeblocksForDate, getTimeblocksForDate,
fetchTimeBlocks,
getNewId, getNewId,
addOrCreateReservation, addOrCreateReservation,
isReservationOverlapped, isReservationOverlapped,

View File

@@ -86,13 +86,12 @@ export const useTaskStore = defineStore('tasks', {
return; return;
} }
try { try {
const response = await databases.deleteDocument( await databases.deleteDocument(
AppwriteIds.databaseId, AppwriteIds.databaseId,
AppwriteIds.collection.task, AppwriteIds.collection.task,
docId docId
); );
this.tasks = this.tasks.filter((task) => docId !== task.$id); this.tasks = this.tasks.filter((task) => docId !== task.$id);
console.log(response);
} catch (error) { } catch (error) {
// Need some better error handling, here. // Need some better error handling, here.
console.error('Failed to delete task:', error); console.error('Failed to delete task:', error);

View File

@@ -1620,10 +1620,10 @@ anymatch@~3.1.2:
normalize-path "^3.0.0" normalize-path "^3.0.0"
picomatch "^2.0.4" picomatch "^2.0.4"
appwrite@^13.0.0: appwrite@^14.0.1:
version "13.0.2" version "14.0.1"
resolved "https://registry.yarnpkg.com/appwrite/-/appwrite-13.0.2.tgz#225f38225a012bb7dc2a70ea777fae363f9188fa" resolved "https://registry.yarnpkg.com/appwrite/-/appwrite-14.0.1.tgz#8a7e653597b370f0b9472c007e29ca0be8af182a"
integrity sha512-ISkUXO8pojDWGx5XqknCwwikgAQye4Ni4FL+Ns8Hg42rXeyehLlmvHGjFOmpS+odT6nsWYUaXzVjV4SZuDorog== integrity sha512-ORlvfqVif/2K3qKGgGiGfMP33Zwm+xxB1fIC4Lm3sojOkDd8u8YvgKQO0Meq5UXb8Dc0Rl66Z7qlGBAfRQ04bA==
dependencies: dependencies:
cross-fetch "3.1.5" cross-fetch "3.1.5"
isomorphic-form-data "2.0.0" isomorphic-form-data "2.0.0"