Converted some schedule to use backend
This commit is contained in:
@@ -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"
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user