diff --git a/src/stores/auth.ts b/src/stores/auth.ts index fd7b4d1..03a1906 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -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 | 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) diff --git a/src/stores/interval.ts b/src/stores/interval.ts index 77b766e..5df970a 100644 --- a/src/stores/interval.ts +++ b/src/stores/interval.ts @@ -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()); // 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'); diff --git a/src/stores/realtime.ts b/src/stores/realtime.ts new file mode 100644 index 0000000..fc0609a --- /dev/null +++ b/src/stores/realtime.ts @@ -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 void>>(new Map()); + + const register = ( + channel: string, + fn: (response: RealtimeResponseEvent) => void + ) => { + if (subscriptions.value.has(channel)) return; // Already subscribed. But maybe different callback fn? + subscriptions.value.set(channel, client.subscribe(channel, fn)); + }; + + return { + register, + }; +}); diff --git a/src/stores/reservation.ts b/src/stores/reservation.ts index 994792d..e4d6ac5 100644 --- a/src/stores/reservation.ts +++ b/src/stores/reservation.ts @@ -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>(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(),