162 lines
5.0 KiB
TypeScript
162 lines
5.0 KiB
TypeScript
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<string, Interval>()); // Intervals by DocID
|
|
const dateStatus = ref(new Map<string, LoadingTypes>()); // State of load by date
|
|
|
|
const selectedDate = ref<string>(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<Interval> {
|
|
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,
|
|
};
|
|
});
|