feat: add realtime updates of interval and reservation

This commit is contained in:
2024-06-21 23:12:35 -04:00
parent 64a59e856f
commit ff8e54449a
4 changed files with 62 additions and 30 deletions

View File

@@ -1,18 +1,9 @@
import { defineStore } from 'pinia';
import {
ID,
account,
functions,
teams,
client,
AppwriteIds,
} from 'boot/appwrite';
import { ID, account, functions, teams } from 'boot/appwrite';
import { ExecutionMethod, OAuthProvider, type Models } from 'appwrite';
import { computed, ref } from 'vue';
import { useBoatStore } from './boat';
import { useReservationStore } from './reservation';
import { useIntervalStore } from './interval';
import { Interval } from './schedule.types';
export const useAuthStore = defineStore('auth', () => {
const currentUser = ref<Models.User<Models.Preferences> | null>(null);
@@ -27,32 +18,12 @@ export const useAuthStore = defineStore('auth', () => {
currentUserTeams.value = await teams.list();
await useBoatStore().fetchBoats();
await useReservationStore().fetchUserReservations();
setupSubscriptions();
} catch {
currentUser.value = null;
currentUserTeams.value = null;
}
}
const setupSubscriptions = () => {
const intervalStore = useIntervalStore();
client.subscribe(
[
`databases.${AppwriteIds.databaseId}.collections.${AppwriteIds.collection.interval}.documents`,
],
(response) => {
// Callback will be executed on changes for documents A and all files.
if (
response.events.includes(
'databases.65ee1cbf9c2493faf15f.collections.interval.documents.*'
)
) {
const interval = response.payload as Interval;
if (interval.$id) intervalStore.intervals.set(interval.$id, interval);
}
}
);
};
const currentUserTeamNames = computed(() =>
currentUserTeams.value
? currentUserTeams.value.teams.map((team) => team.name)

View File

@@ -7,6 +7,7 @@ import { AppwriteIds, databases } from 'src/boot/appwrite';
import { ID, Query } from 'appwrite';
import { useReservationStore } from './reservation';
import { LoadingTypes } from 'src/utils/misc';
import { useRealtimeStore } from './realtime';
export const useIntervalStore = defineStore('interval', () => {
const intervals = ref(new Map<string, Interval>()); // Intervals by DocID
@@ -16,6 +17,23 @@ export const useIntervalStore = defineStore('interval', () => {
const reservationStore = useReservationStore();
const realtimeStore = useRealtimeStore();
realtimeStore.register(
`databases.${AppwriteIds.databaseId}.collections.${AppwriteIds.collection.interval}.documents`,
(response) => {
const payload = response.payload as Interval;
if (!payload.$id) return;
if (
response.events.includes('databases.*.collections.*.documents.*.delete')
) {
intervals.value.delete(payload.$id);
} else {
intervals.value.set(payload.$id, payload);
}
}
);
const getIntervals = (date: Timestamp | string, boat?: Boat) => {
const searchDate = typeof date === 'string' ? date : date.date;
const dayStart = new Date(searchDate + 'T00:00');

21
src/stores/realtime.ts Normal file
View File

@@ -0,0 +1,21 @@
import { defineStore } from 'pinia';
import { client } from 'src/boot/appwrite';
import { Interval } from './schedule.types';
import { ref } from 'vue';
import { RealtimeResponseEvent } from 'appwrite';
export const useRealtimeStore = defineStore('realtime', () => {
const subscriptions = ref<Map<string, () => void>>(new Map());
const register = (
channel: string,
fn: (response: RealtimeResponseEvent<Interval>) => void
) => {
if (subscriptions.value.has(channel)) return; // Already subscribed. But maybe different callback fn?
subscriptions.value.set(channel, client.subscribe(channel, fn));
};
return {
register,
};
});

View File

@@ -8,6 +8,7 @@ import { Timestamp, parseDate, today } from '@quasar/quasar-ui-qcalendar';
import { LoadingTypes } from 'src/utils/misc';
import { useAuthStore } from './auth';
import { isPast } from 'src/utils/schedule';
import { useRealtimeStore } from './realtime';
export const useReservationStore = defineStore('reservation', () => {
const reservations = ref<Map<string, Reservation>>(new Map());
@@ -16,7 +17,28 @@ export const useReservationStore = defineStore('reservation', () => {
// TODO: Come up with a better way of storing reservations by date & reservations for user
const authStore = useAuthStore();
const $q = useQuasar();
const realtimeStore = useRealtimeStore();
realtimeStore.register(
`databases.${AppwriteIds.databaseId}.collections.${AppwriteIds.collection.reservation}.documents`,
(response) => {
const payload = response.payload as Reservation;
if (payload.$id) {
if (
response.events.includes(
'databases.*.collections.*.documents.*.delete'
)
) {
reservations.value.delete(payload.$id);
userReservations.value.delete(payload.$id);
} else {
reservations.value.set(payload.$id, payload);
if (payload.user === authStore.currentUser?.$id)
userReservations.value.set(payload.$id, payload);
}
}
}
);
// Fetch reservations for a specific date range
const fetchReservationsForDateRange = async (
start: string = today(),