import { defineStore } from 'pinia'; import { computed, ref } from 'vue'; import { Boat } from './boat'; import { Timestamp, today } from '@quasar/quasar-ui-qcalendar'; import { Interval } from './schedule.types'; 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 const dateStatus = ref(new Map()); // State of load by date const selectedDate = ref(today()); 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'); const dayEnd = new Date(searchDate + 'T23:59'); if (dateStatus.value.get(searchDate) === undefined) { dateStatus.value.set(searchDate, 'pending'); fetchIntervals(searchDate); } return computed(() => { return Array.from(intervals.value.values()).filter((interval) => { const intervalStart = new Date(interval.start); const intervalEnd = new Date(interval.end); const isWithinDay = intervalStart < dayEnd && intervalEnd > dayStart; const matchesBoat = boat ? boat.$id === interval.resource : true; return isWithinDay && matchesBoat; }); }); }; const getAvailableIntervals = (date: Timestamp | string, boat?: Boat) => { return computed(() => getIntervals(date, boat).value.filter((interval) => { return !reservationStore.isResourceTimeOverlapped( interval.resource, new Date(interval.start), new Date(interval.end) ); }) ); }; async function fetchInterval(id: string): Promise { return (await databases.getDocument( AppwriteIds.databaseId, AppwriteIds.collection.interval, id )) as Interval; } async function fetchIntervals(dateString: string) { try { const response = await databases.listDocuments( AppwriteIds.databaseId, AppwriteIds.collection.interval, [ Query.greaterThanEqual( 'end', new Date(dateString + 'T00:00').toISOString() ), Query.lessThanEqual( 'start', new Date(dateString + 'T23:59').toISOString() ), Query.limit(50), // We are asuming that we won't have more than 50 intervals per day. ] ); response.documents.forEach((d) => intervals.value.set(d.$id, d as Interval) ); dateStatus.value.set(dateString, 'loaded'); console.info(`Loaded ${response.documents.length} intervals from server`); } catch (error) { console.error('Failed to fetch intervals', error); dateStatus.value.set(dateString, 'error'); } } const createInterval = async (interval: Interval) => { try { const response = await databases.createDocument( AppwriteIds.databaseId, AppwriteIds.collection.interval, ID.unique(), interval ); intervals.value.set(response.$id, response as Interval); } catch (e) { console.error('Error creating Interval: ' + e); } }; const updateInterval = async (interval: Interval) => { try { if (interval.$id) { const response = await databases.updateDocument( AppwriteIds.databaseId, AppwriteIds.collection.interval, interval.$id, { ...interval, $id: undefined } ); intervals.value.set(response.$id, response as Interval); console.info(`Saved Interval: ${interval.$id}`); } else { console.error('Update interval called without an ID'); } } catch (e) { console.error('Error updating Interval: ' + e); } }; const deleteInterval = async (id: string) => { try { await databases.deleteDocument( AppwriteIds.databaseId, AppwriteIds.collection.interval, id ); intervals.value.delete(id); console.info(`Deleted interval: ${id}`); } catch (e) { console.error('Error deleting Interval: ' + e); } }; return { getIntervals, getAvailableIntervals, fetchIntervals, fetchInterval, createInterval, updateInterval, deleteInterval, selectedDate, intervals, }; });