fix: reactivity bug with ListReservationsPage
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m32s
All checks were successful
Build BAB Application Deployment Artifact / build (push) Successful in 2m32s
This commit is contained in:
@@ -184,7 +184,7 @@ function getEvents(scope: ResourceIntervalScope) {
|
|||||||
scope.resource.$id
|
scope.resource.$id
|
||||||
);
|
);
|
||||||
|
|
||||||
return resourceEvents.map((event) => {
|
return resourceEvents.value.map((event) => {
|
||||||
return {
|
return {
|
||||||
left: scope.timeStartPosX(parsed(event.start)),
|
left: scope.timeStartPosX(parsed(event.start)),
|
||||||
width: scope.timeDurationWidth(
|
width: scope.timeDurationWidth(
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Interval) {
|
|||||||
const boatReservations = computed((): Record<string, Reservation[]> => {
|
const boatReservations = computed((): Record<string, Reservation[]> => {
|
||||||
return reservationStore
|
return reservationStore
|
||||||
.getReservationsByDate(selectedDate.value)
|
.getReservationsByDate(selectedDate.value)
|
||||||
.reduce((result, reservation) => {
|
.value.reduce((result, reservation) => {
|
||||||
if (!result[reservation.resource]) result[reservation.resource] = [];
|
if (!result[reservation.resource]) result[reservation.resource] = [];
|
||||||
result[reservation.resource].push(reservation);
|
result[reservation.resource].push(reservation);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@@ -134,16 +134,16 @@ const createReservationFromInterval = (interval: Interval | Reservation) => {
|
|||||||
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 boatReservationEvents(
|
const boatReservationEvents = (
|
||||||
timestamp: Timestamp,
|
timestamp: Timestamp,
|
||||||
resource: Boat | undefined
|
resource: Boat | undefined
|
||||||
) {
|
): Reservation[] => {
|
||||||
if (!resource) return [];
|
if (!resource) return [] as Reservation[];
|
||||||
return reservationStore.getReservationsByDate(
|
return reservationStore.getReservationsByDate(
|
||||||
getDate(timestamp),
|
getDate(timestamp),
|
||||||
(resource as Boat).$id
|
(resource as Boat).$id
|
||||||
);
|
).value;
|
||||||
}
|
};
|
||||||
function onToday() {
|
function onToday() {
|
||||||
calendar.value.moveToToday();
|
calendar.value.moveToToday();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
class="q-pa-none">
|
class="q-pa-none">
|
||||||
<q-card
|
<q-card
|
||||||
clas="q-ma-md"
|
clas="q-ma-md"
|
||||||
v-if="!futureUserReservations.length">
|
v-if="!reservationStore.futureUserReservations.length">
|
||||||
<q-card-section>
|
<q-card-section>
|
||||||
<div class="text-h6">You don't have any upcoming bookings!</div>
|
<div class="text-h6">You don't have any upcoming bookings!</div>
|
||||||
<div class="text-h8">Why don't you go make one?</div>
|
<div class="text-h8">Why don't you go make one?</div>
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
</q-card>
|
</q-card>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<div
|
<div
|
||||||
v-for="reservation in futureUserReservations"
|
v-for="reservation in reservationStore.futureUserReservations"
|
||||||
:key="reservation.$id">
|
:key="reservation.$id">
|
||||||
<ReservationCardComponent :modelValue="reservation" />
|
<ReservationCardComponent :modelValue="reservation" />
|
||||||
</div>
|
</div>
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
name="past"
|
name="past"
|
||||||
class="q-pa-none">
|
class="q-pa-none">
|
||||||
<div
|
<div
|
||||||
v-for="reservation in pastUserReservations"
|
v-for="reservation in reservationStore.pastUserReservations"
|
||||||
:key="reservation.$id">
|
:key="reservation.$id">
|
||||||
<ReservationCardComponent :modelValue="reservation" />
|
<ReservationCardComponent :modelValue="reservation" />
|
||||||
</div>
|
</div>
|
||||||
@@ -63,7 +63,7 @@ import { useReservationStore } from 'src/stores/reservation';
|
|||||||
import ReservationCardComponent from 'src/components/scheduling/ReservationCardComponent.vue';
|
import ReservationCardComponent from 'src/components/scheduling/ReservationCardComponent.vue';
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
const { futureUserReservations, pastUserReservations } = useReservationStore();
|
const reservationStore = useReservationStore();
|
||||||
|
|
||||||
onMounted(() => useReservationStore().fetchUserReservations());
|
onMounted(() => useReservationStore().fetchUserReservations());
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import type { Reservation } from './schedule.types';
|
import type { Reservation } from './schedule.types';
|
||||||
import { computed, ref, watch } from 'vue';
|
import { ComputedRef, computed, reactive } from 'vue';
|
||||||
import { AppwriteIds, databases } from 'src/boot/appwrite';
|
import { AppwriteIds, databases } from 'src/boot/appwrite';
|
||||||
import { ID, Query } from 'appwrite';
|
import { ID, Query } from 'appwrite';
|
||||||
import { date, useQuasar } from 'quasar';
|
import { date, useQuasar } from 'quasar';
|
||||||
@@ -11,10 +11,10 @@ import { isPast } from 'src/utils/schedule';
|
|||||||
import { useRealtimeStore } from './realtime';
|
import { useRealtimeStore } from './realtime';
|
||||||
|
|
||||||
export const useReservationStore = defineStore('reservation', () => {
|
export const useReservationStore = defineStore('reservation', () => {
|
||||||
const reservations = ref<Map<string, Reservation>>(new Map());
|
const reservations = reactive<Map<string, Reservation>>(new Map());
|
||||||
const datesLoaded = ref<Record<string, LoadingTypes>>({});
|
const datesLoaded = reactive<Record<string, LoadingTypes>>({});
|
||||||
const userReservations = ref<Map<string, Reservation>>(new Map());
|
const userReservations = reactive<Map<string, Reservation>>(new Map());
|
||||||
// TODO: Come up with a better way of storing reservations by date & reservations for user
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
const realtimeStore = useRealtimeStore();
|
const realtimeStore = useRealtimeStore();
|
||||||
@@ -29,12 +29,12 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
'databases.*.collections.*.documents.*.delete'
|
'databases.*.collections.*.documents.*.delete'
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
reservations.value.delete(payload.$id);
|
reservations.delete(payload.$id);
|
||||||
userReservations.value.delete(payload.$id);
|
userReservations.delete(payload.$id);
|
||||||
} else {
|
} else {
|
||||||
reservations.value.set(payload.$id, payload);
|
reservations.set(payload.$id, payload);
|
||||||
if (payload.user === authStore.currentUser?.$id)
|
if (payload.user === authStore.currentUser?.$id)
|
||||||
userReservations.value.set(payload.$id, payload);
|
userReservations.set(payload.$id, payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
response.documents.forEach((d) =>
|
response.documents.forEach((d) =>
|
||||||
reservations.value.set(d.$id, d as Reservation)
|
reservations.set(d.$id, d as Reservation)
|
||||||
);
|
);
|
||||||
setDateLoaded(startDate, endDate, 'loaded');
|
setDateLoaded(startDate, endDate, 'loaded');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -103,8 +103,8 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
reservation
|
reservation
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
reservations.value.set(response.$id, response as Reservation);
|
reservations.set(response.$id, response as Reservation);
|
||||||
userReservations.value.set(response.$id, response as Reservation);
|
userReservations.set(response.$id, response as Reservation);
|
||||||
console.info('Reservation booked: ', response);
|
console.info('Reservation booked: ', response);
|
||||||
return response as Reservation;
|
return response as Reservation;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -117,14 +117,8 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
reservation: string | Reservation | null | undefined
|
reservation: string | Reservation | null | undefined
|
||||||
) => {
|
) => {
|
||||||
if (!reservation) return false;
|
if (!reservation) return false;
|
||||||
let id;
|
const id = typeof reservation === 'string' ? reservation : reservation.$id;
|
||||||
if (typeof reservation === 'string') {
|
if (!id) return false;
|
||||||
id = reservation;
|
|
||||||
} else if ('$id' in reservation && typeof reservation.$id === 'string') {
|
|
||||||
id = reservation.$id;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const status = $q.notify({
|
const status = $q.notify({
|
||||||
color: 'secondary',
|
color: 'secondary',
|
||||||
@@ -142,8 +136,8 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
AppwriteIds.collection.reservation,
|
AppwriteIds.collection.reservation,
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
reservations.value.delete(id);
|
reservations.delete(id);
|
||||||
userReservations.value.delete(id);
|
userReservations.delete(id);
|
||||||
console.info(`Deleted reservation: ${id}`);
|
console.info(`Deleted reservation: ${id}`);
|
||||||
status({
|
status({
|
||||||
color: 'warning',
|
color: 'warning',
|
||||||
@@ -168,7 +162,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
if (start > end) return [];
|
if (start > end) return [];
|
||||||
let curDate = start;
|
let curDate = start;
|
||||||
while (curDate < end) {
|
while (curDate < end) {
|
||||||
datesLoaded.value[(parseDate(curDate) as Timestamp).date] = state;
|
datesLoaded[(parseDate(curDate) as Timestamp).date] = state;
|
||||||
curDate = date.addToDate(curDate, { days: 1 });
|
curDate = date.addToDate(curDate, { days: 1 });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -179,8 +173,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
const unloaded = [];
|
const unloaded = [];
|
||||||
while (curDate < end) {
|
while (curDate < end) {
|
||||||
const parsedDate = (parseDate(curDate) as Timestamp).date;
|
const parsedDate = (parseDate(curDate) as Timestamp).date;
|
||||||
if (datesLoaded.value[parsedDate] === undefined)
|
if (datesLoaded[parsedDate] === undefined) unloaded.push(parsedDate);
|
||||||
unloaded.push(parsedDate);
|
|
||||||
curDate = date.addToDate(curDate, { days: 1 });
|
curDate = date.addToDate(curDate, { days: 1 });
|
||||||
}
|
}
|
||||||
return unloaded;
|
return unloaded;
|
||||||
@@ -190,15 +183,15 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
const getReservationsByDate = (
|
const getReservationsByDate = (
|
||||||
searchDate: string,
|
searchDate: string,
|
||||||
boat?: string
|
boat?: string
|
||||||
): Reservation[] => {
|
): ComputedRef<Reservation[]> => {
|
||||||
if (!datesLoaded.value[searchDate]) {
|
if (!datesLoaded[searchDate]) {
|
||||||
fetchReservationsForDateRange(searchDate);
|
fetchReservationsForDateRange(searchDate);
|
||||||
}
|
}
|
||||||
const dayStart = new Date(searchDate + 'T00:00');
|
const dayStart = new Date(searchDate + 'T00:00');
|
||||||
const dayEnd = new Date(searchDate + 'T23:59');
|
const dayEnd = new Date(searchDate + 'T23:59');
|
||||||
|
|
||||||
return computed(() => {
|
return computed(() => {
|
||||||
return Array.from(reservations.value.values()).filter((reservation) => {
|
return Array.from(reservations.values()).filter((reservation) => {
|
||||||
const reservationStart = new Date(reservation.start);
|
const reservationStart = new Date(reservation.start);
|
||||||
const reservationEnd = new Date(reservation.end);
|
const reservationEnd = new Date(reservation.end);
|
||||||
|
|
||||||
@@ -207,7 +200,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
const matchesBoat = boat ? boat === reservation.resource : true;
|
const matchesBoat = boat ? boat === reservation.resource : true;
|
||||||
return isWithinDay && matchesBoat;
|
return isWithinDay && matchesBoat;
|
||||||
});
|
});
|
||||||
}).value;
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get conflicting reservations for a resource within a time range
|
// Get conflicting reservations for a resource within a time range
|
||||||
@@ -216,7 +209,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
start: Date,
|
start: Date,
|
||||||
end: Date
|
end: Date
|
||||||
): Reservation[] => {
|
): Reservation[] => {
|
||||||
return Array.from(reservations.value.values()).filter(
|
return Array.from(reservations.values()).filter(
|
||||||
(entry) =>
|
(entry) =>
|
||||||
entry.resource === resource &&
|
entry.resource === resource &&
|
||||||
new Date(entry.start) < end &&
|
new Date(entry.start) < end &&
|
||||||
@@ -251,7 +244,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
[Query.equal('user', authStore.currentUser.$id)]
|
[Query.equal('user', authStore.currentUser.$id)]
|
||||||
);
|
);
|
||||||
response.documents.forEach((d) =>
|
response.documents.forEach((d) =>
|
||||||
userReservations.value.set(d.$id, d as Reservation)
|
userReservations.set(d.$id, d as Reservation)
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to fetch reservations for user: ', error);
|
console.error('Failed to fetch reservations for user: ', error);
|
||||||
@@ -259,7 +252,7 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const sortedUserReservations = computed((): Reservation[] =>
|
const sortedUserReservations = computed((): Reservation[] =>
|
||||||
[...userReservations.value?.values()].sort(
|
[...userReservations.values()].sort(
|
||||||
(a, b) => new Date(b.start).getTime() - new Date(a.start).getTime()
|
(a, b) => new Date(b.start).getTime() - new Date(a.start).getTime()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -274,27 +267,6 @@ export const useReservationStore = defineStore('reservation', () => {
|
|||||||
return sortedUserReservations.value?.filter((b) => isPast(b.end));
|
return sortedUserReservations.value?.filter((b) => isPast(b.end));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ensure reactivity for computed properties when Map is modified
|
|
||||||
watch(
|
|
||||||
reservations,
|
|
||||||
() => {
|
|
||||||
sortedUserReservations.value;
|
|
||||||
futureUserReservations.value;
|
|
||||||
pastUserReservations.value;
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
watch(
|
|
||||||
userReservations,
|
|
||||||
() => {
|
|
||||||
sortedUserReservations.value;
|
|
||||||
futureUserReservations.value;
|
|
||||||
pastUserReservations.value;
|
|
||||||
},
|
|
||||||
{ deep: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getReservationsByDate,
|
getReservationsByDate,
|
||||||
getReservationById,
|
getReservationById,
|
||||||
|
|||||||
Reference in New Issue
Block a user