fix: Improve reactivity in intervals

This commit is contained in:
2024-06-20 21:52:00 -04:00
parent b7a3608e67
commit e97949cab3
5 changed files with 31 additions and 36 deletions

View File

@@ -38,7 +38,7 @@
v-for="block in getAvailableIntervals( v-for="block in getAvailableIntervals(
scope.timestamp, scope.timestamp,
boats[scope.columnIndex] boats[scope.columnIndex]
)" ).value"
:key="block.$id"> :key="block.$id">
<div <div
class="timeblock" class="timeblock"

View File

@@ -92,7 +92,7 @@ const currentUser = useAuthStore().currentUser;
const getSortedIntervals = (timestamp: Timestamp, boat?: Boat): Interval[] => { const getSortedIntervals = (timestamp: Timestamp, boat?: Boat): Interval[] => {
return getAvailableIntervals(timestamp, boat) return getAvailableIntervals(timestamp, boat)
.concat(boatReservationEvents(timestamp, boat)) .value.concat(boatReservationEvents(timestamp, boat))
.sort((a, b) => Date.parse(a.start) - Date.parse(b.start)); .sort((a, b) => Date.parse(a.start) - Date.parse(b.start));
}; };
// Method declarations // Method declarations

View File

@@ -26,7 +26,9 @@
cell-width="150px"> cell-width="150px">
<template #day="{ scope }"> <template #day="{ scope }">
<div <div
v-if="filteredIntervals(scope.timestamp, scope.resource).length" v-if="
filteredIntervals(scope.timestamp, scope.resource).value.length
"
style=" style="
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@@ -35,10 +37,8 @@
font-size: 12px; font-size: 12px;
"> ">
<template <template
v-for="block in sortedIntervals( v-for="block in sortedIntervals(scope.timestamp, scope.resource)
scope.timestamp, .value"
scope.resource
)"
:key="block.id"> :key="block.id">
<q-chip class="cursor-pointer"> <q-chip class="cursor-pointer">
{{ date.formatDate(block.start, 'HH:mm') }} - {{ date.formatDate(block.start, 'HH:mm') }} -
@@ -163,7 +163,7 @@ import {
} from '@quasar/quasar-ui-qcalendar'; } from '@quasar/quasar-ui-qcalendar';
import { Boat, useBoatStore } from 'src/stores/boat'; import { Boat, useBoatStore } from 'src/stores/boat';
import { useIntervalStore } from 'src/stores/interval'; import { useIntervalStore } from 'src/stores/interval';
import { onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import type { import type {
Interval, Interval,
IntervalTemplate, IntervalTemplate,
@@ -208,8 +208,10 @@ const filteredIntervals = (date: Timestamp, boat: Boat) => {
}; };
const sortedIntervals = (date: Timestamp, boat: Boat) => { const sortedIntervals = (date: Timestamp, boat: Boat) => {
return filteredIntervals(date, boat).sort( return computed(() =>
filteredIntervals(date, boat).value.sort(
(a, b) => Date.parse(a.start) - Date.parse(b.start) (a, b) => Date.parse(a.start) - Date.parse(b.start)
)
); );
}; };
@@ -293,7 +295,7 @@ function onDrop(
overlapped.value = boatsToApply overlapped.value = boatsToApply
.map((boat) => .map((boat) =>
intervalsOverlapped( intervalsOverlapped(
existingIntervals.concat( existingIntervals.value.concat(
intervalsFromTemplate(boat, templateId, date) intervalsFromTemplate(boat, templateId, date)
) )
) )

View File

@@ -2,25 +2,26 @@ import { defineStore } from 'pinia';
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import { Boat } from './boat'; import { Boat } from './boat';
import { Timestamp, today } from '@quasar/quasar-ui-qcalendar'; import { Timestamp, today } from '@quasar/quasar-ui-qcalendar';
import { Interval } from './schedule.types';
import { Interval, IntervalRecord } from './schedule.types';
import { AppwriteIds, databases } from 'src/boot/appwrite'; import { AppwriteIds, databases } from 'src/boot/appwrite';
import { ID, Query } from 'appwrite'; import { ID, Query } from 'appwrite';
import { useReservationStore } from './reservation'; import { useReservationStore } from './reservation';
import { LoadingTypes } from 'src/utils/misc';
export const useIntervalStore = defineStore('interval', () => { export const useIntervalStore = defineStore('interval', () => {
// TODO: Implement functions to dynamically pull this data. const intervals = ref(new Map<string, Interval>()); // Intervals by DocID
const intervals = ref<Map<string, Interval>>(new Map()); const dateStatus = ref(new Map<string, LoadingTypes>()); // State of load by date
const intervalDates = ref<IntervalRecord>({});
const reservationStore = useReservationStore();
const selectedDate = ref<string>(today()); const selectedDate = ref<string>(today());
const getIntervals = (date: Timestamp | string, boat?: Boat): Interval[] => { const reservationStore = useReservationStore();
const getIntervals = (date: Timestamp | string, boat?: Boat) => {
const searchDate = typeof date === 'string' ? date : date.date; const searchDate = typeof date === 'string' ? date : date.date;
const dayStart = new Date(searchDate + 'T00:00'); const dayStart = new Date(searchDate + 'T00:00');
const dayEnd = new Date(searchDate + 'T23:59'); const dayEnd = new Date(searchDate + 'T23:59');
if (!intervalDates.value[searchDate]) { if (dateStatus.value.get(searchDate) === undefined) {
intervalDates.value[searchDate] = 'pending'; dateStatus.value.set(searchDate, 'pending');
fetchIntervals(searchDate); fetchIntervals(searchDate);
} }
return computed(() => { return computed(() => {
@@ -32,22 +33,19 @@ export const useIntervalStore = defineStore('interval', () => {
const matchesBoat = boat ? boat.$id === interval.resource : true; const matchesBoat = boat ? boat.$id === interval.resource : true;
return isWithinDay && matchesBoat; return isWithinDay && matchesBoat;
}); });
}).value; });
}; };
const getAvailableIntervals = ( const getAvailableIntervals = (date: Timestamp | string, boat?: Boat) => {
date: Timestamp | string, return computed(() =>
boat?: Boat getIntervals(date, boat).value.filter((interval) => {
): Interval[] => {
return computed(() => {
return getIntervals(date, boat).filter((interval) => {
return !reservationStore.isResourceTimeOverlapped( return !reservationStore.isResourceTimeOverlapped(
interval.resource, interval.resource,
new Date(interval.start), new Date(interval.start),
new Date(interval.end) new Date(interval.end)
); );
}); })
}).value; );
}; };
async function fetchInterval(id: string): Promise<Interval> { async function fetchInterval(id: string): Promise<Interval> {
@@ -78,11 +76,11 @@ export const useIntervalStore = defineStore('interval', () => {
response.documents.forEach((d) => response.documents.forEach((d) =>
intervals.value.set(d.$id, d as Interval) intervals.value.set(d.$id, d as Interval)
); );
intervalDates.value[dateString] = 'loaded'; dateStatus.value.set(dateString, 'loaded');
console.info(`Loaded ${response.documents.length} intervals from server`); console.info(`Loaded ${response.documents.length} intervals from server`);
} catch (error) { } catch (error) {
console.error('Failed to fetch intervals', error); console.error('Failed to fetch intervals', error);
intervalDates.value[dateString] = 'error'; dateStatus.value.set(dateString, 'error');
} }
} }

View File

@@ -1,5 +1,4 @@
import { Models } from 'appwrite'; import { Models } from 'appwrite';
import { LoadingTypes } from 'src/utils/misc';
export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined; export type StatusTypes = 'tentative' | 'confirmed' | 'pending' | undefined;
export type Reservation = Interval & { export type Reservation = Interval & {
@@ -29,7 +28,3 @@ export type IntervalTemplate = Partial<Models.Document> & {
name: string; name: string;
timeTuples: TimeTuple[]; timeTuples: TimeTuple[];
}; };
export interface IntervalRecord {
[key: string]: LoadingTypes;
}