import { defineStore } from 'pinia'; import { computed, ref } from 'vue'; import { Boat } from './boat'; import { Timestamp, today } from '@quasar/quasar-ui-qcalendar'; import { Interval, IntervalRecord } from './schedule.types'; import { AppwriteIds, databases } from 'src/boot/appwrite'; import { ID, Query } from 'appwrite'; import { useReservationStore } from './reservation'; export const useIntervalStore = defineStore('interval', () => { // TODO: Implement functions to dynamically pull this data. const intervals = ref>(new Map()); const intervalDates = ref({}); const reservationStore = useReservationStore(); const selectedDate = ref(today()); const getIntervals = (date: Timestamp | string, boat?: Boat): Interval[] => { const searchDate = typeof date === 'string' ? date : date.date; const dayStart = new Date(searchDate + 'T00:00'); const dayEnd = new Date(searchDate + 'T23:59'); if (!intervalDates.value[searchDate]) { intervalDates.value[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; }); }).value; }; const getAvailableIntervals = ( date: Timestamp | string, boat?: Boat ): Interval[] => { return computed(() => { return getIntervals(date, boat).filter((interval) => { return !reservationStore.isResourceTimeOverlapped( interval.resource, new Date(interval.start), new Date(interval.end) ); }); }).value; }; 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) ); intervalDates.value[dateString] = 'loaded'; console.info(`Loaded ${response.documents.length} intervals from server`); } catch (error) { console.error('Failed to fetch intervals', error); intervalDates.value[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, }; });