Many improvements. Still no reactivity on List

This commit is contained in:
2024-06-02 08:48:14 -04:00
parent 387af2e6ce
commit 9104ccab0f
16 changed files with 395 additions and 289 deletions

View File

@@ -166,7 +166,7 @@ watch(reservation, (newReservation) => {
interval: {
start: newReservation.start,
end: newReservation.end,
boatId: newReservation.resource,
resource: newReservation.resource,
},
};
bookingForm.value = updatedReservation;
@@ -190,7 +190,7 @@ const bookingName = computed(() =>
);
const boat = computed((): Boat | null => {
const boatId = bookingForm.value.interval?.boatId;
const boatId = bookingForm.value.interval?.resource;
console.log('Boat Lookup:', boatId);
return boatStore.getBoatById(boatId);
});
@@ -203,18 +203,18 @@ const onReset = () => {
interval: {
start: reservation.value.start,
end: reservation.value.end,
boatId: reservation.value.resource,
resource: reservation.value.resource,
},
}
: { ...newForm };
};
const onSubmit = () => {
const onSubmit = async () => {
const booking = bookingForm.value;
if (
!(
booking.interval &&
booking.interval.boatId &&
booking.interval.resource &&
booking.interval.start &&
booking.interval.end &&
auth.currentUser
@@ -224,7 +224,7 @@ const onSubmit = () => {
return;
}
const reservation = <Reservation>{
resource: booking.interval.boatId,
resource: booking.interval.resource,
start: booking.interval.start,
end: booking.interval.end,
user: auth.currentUser.$id,
@@ -232,15 +232,34 @@ const onSubmit = () => {
reason: booking.reason,
comment: booking.comment,
};
// TODO: Fix this. It will always look successful
reservationStore.createReservation(reservation); // Probably should pass the notify as a callback to the reservation creation.
$q.notify({
color: 'green-4',
const status = $q.notify({
color: 'secondary',
textColor: 'white',
icon: 'cloud_done',
message: 'Submitted',
timeout: 3000,
message: 'Submitting Reservation',
spinner: true,
closeBtn: 'Dismiss',
position: 'top',
timeout: 0,
group: false,
});
try {
const r = await reservationStore.createReservation(reservation);
status({
color: 'positive',
icon: 'cloud_done',
message: `Booking successful: ${
boatStore.getBoatById(r.resource)?.name
} at ${formatDate(r.start)}`,
spinner: false,
});
} catch (e) {
status({
color: 'negative',
icon: 'error',
spinner: false,
message: 'Failed to book!' + e,
});
}
router.go(-1);
};
</script>

View File

@@ -21,7 +21,11 @@
<q-icon :name="link.icon" />
</q-item-section>
<q-item-section>{{ link.name }}</q-item-section>
<q-item-section>
<span :class="link.color ? `text-${link.color}` : ''">
{{ link.name }}
</span>
</q-item-section>
</q-item>
<q-list v-if="link.sublinks">
<div
@@ -36,7 +40,11 @@
<q-icon :name="sublink.icon" />
</q-item-section>
<q-item-section>{{ sublink.name }}</q-item-section>
<q-item-section>
<span :class="sublink.color ? `text-${sublink.color}` : ''">
{{ sublink.name }}
</span>
</q-item-section>
</q-item>
</div>
</q-list>

View File

@@ -3,8 +3,7 @@
expand-icon-toggle
draggable="true"
@dragstart="onDragStart($event, template)"
v-model="expanded"
>
v-model="expanded">
<template v-slot:header>
<q-item-section>
<q-input
@@ -12,17 +11,21 @@
:borderless="!edit"
dense
v-model="template.name"
v-if="edit"
/><q-item-label v-if="!edit" class="cursor-pointer">{{
template.name
}}</q-item-label></q-item-section
>
v-if="edit" />
<q-item-label
v-if="!edit"
class="cursor-pointer">
{{ template.name }}
</q-item-label>
</q-item-section>
</template>
<q-card flat>
<q-card-section horizontal>
<q-card-section class="q-pt-xs">
<q-list dense>
<q-item v-for="(item, index) in template.timeTuples" :key="item[0]">
<q-item
v-for="(item, index) in template.timeTuples"
:key="item[0]">
<q-input
class="q-mx-sm"
dense
@@ -38,8 +41,7 @@
type="time"
label="End"
:borderless="!edit"
:readonly="!edit"
>
:readonly="!edit">
<template v-slot:after>
<q-btn
v-if="edit"
@@ -47,46 +49,44 @@
dense
flat
icon="delete"
@click="template.timeTuples.splice(index, 1)"
/> </template></q-input></q-item
></q-list>
@click="template.timeTuples.splice(index, 1)" />
</template>
</q-input>
</q-item>
</q-list>
<q-btn
v-if="edit"
dense
color="primary"
size="sm"
label="Add interval"
@click="template.timeTuples.push(['00:00', '00:00'])"
/></q-card-section>
@click="template.timeTuples.push(['00:00', '00:00'])" />
</q-card-section>
<q-card-actions vertical>
<q-btn
v-if="!edit"
color="primary"
icon="edit"
label="Edit"
@click="toggleEdit"
/>
@click="toggleEdit" />
<q-btn
v-if="edit"
color="primary"
icon="save"
label="Save"
@click="saveTemplate($event, template)"
/>
@click="saveTemplate($event, template)" />
<q-btn
v-if="edit"
color="secondary"
icon="cancel"
label="Cancel"
@click="revert"
/>
@click="revert" />
<q-btn
color="negative"
icon="delete"
label="Delete"
v-if="template.$id !== ''"
@click="deleteTemplate($event, template)"
/>
@click="deleteTemplate($event, template)" />
</q-card-actions>
</q-card-section>
</q-card>
@@ -101,25 +101,29 @@
square
icon="schedule"
v-for="item in overlapped"
:key="item.start"
>
{{ item.start }}-{{ item.end }}</q-chip
>
:key="item.start">
{{ item.start }}-{{ item.end }}
</q-chip>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="OK" color="primary" v-close-popup />
</q-card-actions> </q-card
></q-dialog>
<q-btn
flat
label="OK"
color="primary"
v-close-popup />
</q-card-actions>
</q-card>
</q-dialog>
</template>
<script setup lang="ts">
import { useScheduleStore } from 'src/stores/schedule';
import { useIntervalTemplateStore } from 'src/stores/intervalTemplate';
import { IntervalTemplate } from 'src/stores/schedule.types';
import { copyIntervalTemplate, timeTuplesOverlapped } from 'src/utils/schedule';
import { ref } from 'vue';
const alert = ref(false);
const overlapped = ref();
const scheduleStore = useScheduleStore();
const intervalTemplateStore = useIntervalTemplateStore();
const props = defineProps<{ edit?: boolean; modelValue: IntervalTemplate }>();
const edit = ref(props.edit);
const expanded = ref(props.edit);
@@ -141,7 +145,7 @@ const deleteTemplate = (
event: Event,
template: IntervalTemplate | undefined
) => {
if (template?.$id) scheduleStore.deleteIntervalTemplate(template.$id);
if (template?.$id) intervalTemplateStore.deleteIntervalTemplate(template.$id);
};
function onDragStart(e: DragEvent, template: IntervalTemplate) {
@@ -159,9 +163,9 @@ const saveTemplate = (evt: Event, template: IntervalTemplate | undefined) => {
} else {
edit.value = false;
if (template.$id && template.$id !== 'unsaved') {
scheduleStore.updateIntervalTemplate(template, template.$id);
intervalTemplateStore.updateIntervalTemplate(template, template.$id);
} else {
scheduleStore.createIntervalTemplate(template);
intervalTemplateStore.createIntervalTemplate(template);
emit('saved');
}
}

View File

@@ -35,7 +35,10 @@
<template #day-body="{ scope }">
<div
v-for="block in getBoatBlocks(scope)"
v-for="block in getAvailableIntervals(
scope.timestamp,
boats[scope.columnIndex]
)"
:key="block.$id">
<div
class="timeblock"
@@ -95,23 +98,24 @@ import CalendarHeaderComponent from './CalendarHeaderComponent.vue';
import { ref, computed, onMounted } from 'vue';
import { useBoatStore } from 'src/stores/boat';
import { useScheduleStore } from 'src/stores/schedule';
import { useAuthStore } from 'src/stores/auth';
import { Interval, Reservation } from 'src/stores/schedule.types';
import { storeToRefs } from 'pinia';
import { useReservationStore } from 'src/stores/reservation';
import { useIntervalTemplateStore } from 'src/stores/intervalTemplate';
import { useIntervalStore } from 'src/stores/interval';
const scheduleStore = useScheduleStore();
const intervalTemplateStore = useIntervalTemplateStore();
const reservationStore = useReservationStore();
const { boats } = storeToRefs(useBoatStore());
const selectedBlock = defineModel<Interval | null>();
const selectedDate = ref(today());
const { getAvailableIntervals } = useIntervalStore();
const calendar = ref<QCalendarDay | null>(null);
onMounted(async () => {
await useBoatStore().fetchBoats();
await scheduleStore.fetchIntervalTemplates();
await intervalTemplateStore.fetchIntervalTemplates();
});
function handleSwipe({ ...event }) {
@@ -194,23 +198,6 @@ function selectBlock(event: MouseEvent, scope: DayBodyScope, block: Interval) {
: (selectedBlock.value = block);
}
const boatBlocks = computed((): Record<string, Interval[]> => {
return scheduleStore
.getIntervals(selectedDate.value)
.reduce((result, interval) => {
if (!result[interval.boatId]) result[interval.boatId] = [];
if (
!reservationStore.isResourceTimeOverlapped(
interval.boatId,
new Date(interval.start),
new Date(interval.end)
)
)
result[interval.boatId].push(interval);
return result;
}, <Record<string, Interval[]>>{});
});
const boatReservations = computed((): Record<string, Reservation[]> => {
return reservationStore
.getReservationsByDate(selectedDate.value)
@@ -220,11 +207,6 @@ const boatReservations = computed((): Record<string, Reservation[]> => {
return result;
}, <Record<string, Reservation[]>>{});
});
function getBoatBlocks(scope: DayBodyScope): Interval[] {
const boat = boats.value[scope.columnIndex];
return boat ? boatBlocks.value[boat.$id] : [];
}
function getBoatReservations(scope: DayBodyScope): Reservation[] {
const boat = boats.value[scope.columnIndex];
return boat ? boatReservations.value[boat.$id] : [];